diff --git a/README.md b/README.md index 546b6d3..b685e0a 100644 --- a/README.md +++ b/README.md @@ -1,114 +1,101 @@ # HeimForge -A generator that produces standalone, hardened Valheim mod-suite repositories from a small set of identity parameters. It is not itself a Valheim mod. +HeimForge generates standalone Valheim mod-suite repositories built around +BepInEx and Jötunn. + +It provides a structured starting point for projects that need separate +client/server modules, repeatable builds, metadata-driven deployment, testing, +and deterministic packaging. HeimForge is an unofficial community project and is not affiliated with or endorsed by Iron Gate or Coffee Stain. ## What it generates -Each generated project is a complete, independent repository with: - -- BepInEx + Jötunn plugin scaffolding across `Common` (always present) and up to three optional runtime tiers: `ServerCore`, `Client`, and `Shared.Diagnostics`. -- Server-authoritative networking conventions and per-module Jötunn compatibility classification. -- WSL-first build/test/deploy/package tooling driven by a single authoritative `suite.config.json`. -- Metadata-driven client/server deployment and deterministic local packaging with SHA-256 checksums. -- Project-local OMP resources: domain skills (`valheim-modding`, `valheim-networking`, `harmony-reverse-engineering`, `valheim-release`), a `valheim-dev` extension, and a bootstrap prompt. -- A routed `.context/` task bundle (stable references, mutable state, version-sensitive findings) so agents load only what a task needs. - -The generated project imports nothing from this repository and can be moved, renamed, or open-sourced independently. - -## Licensing - -Unless otherwise noted, HeimForge source and documentation outside `template/` -are licensed under the Apache License 2.0. See `LICENSE`. - -Files under `template/` are licensed under MIT-0 because they are intended to -be copied into independently owned generated repositories. See -`template/LICENSES/MIT-0.txt`. - -A generated project does not automatically adopt MIT-0 as its project license. -It starts with `LICENSE.todo` plus `LICENSES/MIT-0.txt`; the latter covers only -the HeimForge scaffold material copied into that repository. Before public -distribution, choose the generated project's own license, add it as the root -`LICENSE`, remove `LICENSE.todo`, and retain any notices or terms required by -third-party material. - -## Supported topology - -Every module declares one compatibility category: +A generated project can include: -- `SERVER_ONLY` -- `SHARED_OPTIONAL` -- `SHARED_REQUIRED` -- `CLIENT_ONLY` +- `Common` shared code +- `ServerCore` server-only functionality +- `Client` client-only functionality +- `Shared.Diagnostics` shared optional diagnostics +- BepInEx + Jötunn project scaffolding +- build, test, deploy, and package scripts +- metadata-driven client/server deployment +- deterministic release packages with SHA-256 checksums +- development and architecture documentation -`ServerCore`, `Client`, and `Shared.Diagnostics` may each be individually included or omitted at generation time; `Common` is always generated. - -## WSL-first recommendation - -Generated projects are built, tested, and packaged from WSL/Linux; the Windows Valheim client is inspected and deployed to through `/mnt/c/...`. Keep both this repository and generated repositories inside the WSL filesystem rather than under `/mnt/c`. +Generated repositories are standalone and do not depend on HeimForge after +generation. ## Requirements -- WSL2 (or native Linux) with `bash`, `git`, and Python 3.10 or newer. -- .NET SDK (for the generated project's own build/test; not required merely to generate a project). - -No Valheim installation or game files are needed to run the generator itself. +To run HeimForge: -## Test +- WSL2 or native Linux +- Bash and Git +- Python 3.10 or newer -Run the full HeimForge test suite with: +A .NET SDK is required to build and test generated projects, but not merely to +run the generator. -```bash -./scripts/test.sh -``` +A Valheim installation is not required to generate a project. -The script runs the canonical Python `unittest` discovery command from the repository root. +## Quick start -## Interactive generation +Generate a project interactively: ```bash ./scripts/create-project.sh ``` -Prompts for suite name, root namespace, plugin GUID root, author, Thunderstore namespace, initial version, output directory, and which optional modules (`ServerCore`, `Client`, `Shared.Diagnostics`) to include. - -## Non-interactive generation +Or non-interactively: ```bash ./scripts/create-project.sh \ - --name Vibeheim --namespace Vibeheim --guid com.example.vibeheim \ - --author "Your Name" --thunderstore-namespace YourNS --version 0.1.0 \ - --output ~/src/vibeheim + --name MyMod \ + --namespace MyMod \ + --guid com.example.mymod \ + --author "Your Name" \ + --thunderstore-namespace YourName \ + --version 0.1.0 \ + --output ~/src/mymod ``` -Add `--no-server-core`, `--no-client`, or `--no-shared-diagnostics` to omit an optional module. Combining all three is rejected: `Common` is a shared library, not a runtime plugin, and at least one runtime module is required. Add `--force` to overwrite a non-empty output directory (refused for the bootstrapper's own repository, its ancestors, `/`, and `$HOME`). +`ServerCore`, `Client`, and `Shared.Diagnostics` can each be omitted when they +are not needed. -## Generated-project first steps +After generation: ```bash -cd ~/src/vibeheim +cd ~/src/mymod cp Environment.props.example Environment.props cp .valheim/dev.json.example .valheim/dev.json ./scripts/preflight.sh --portable ``` -## Generated example +## Example + +[heimforge-example](https://github.com/heimforge-dev/heimforge-example) is a +clean reference project generated with all supported module tiers enabled and +no added gameplay code. + +## Licensing + +HeimForge source and documentation outside `template/` are licensed under +Apache-2.0. -[HeimForge Example](https://github.com/heimforge-dev/heimforge-example) -is a clean reference repository generated by HeimForge with all supported -module tiers enabled and no added gameplay code. +Reusable scaffold material under `template/` is licensed under MIT-0 because +it is copied into independently owned generated repositories. -## Dogfood: Vibeheim +Generated projects choose their own project-level license before public +distribution. -Vibeheim is HeimForge's real-world dogfood project. Generic infrastructure -improvements discovered while developing Vibeheim should be upstreamed to -this repository's `template/`; Vibeheim-specific gameplay stays entirely -inside the Vibeheim repository. +See `LICENSE`, `template/LICENSES/MIT-0.txt`, and +`docs/TEMPLATE_MAINTENANCE.md` for details. ## Documentation -- `docs/GENERATOR_ARCHITECTURE.md`: how `bootstrap/` renders and validates a project. -- `docs/TEMPLATE_MAINTENANCE.md`: the token vocabulary and how to extend `template/`. -- `docs/TEST_PERFORMANCE_AUDIT.md`: certified test-suite performance audit and the safety boundaries it preserves. +- `docs/GENERATOR_ARCHITECTURE.md` — generator architecture +- `docs/TEMPLATE_MAINTENANCE.md` — maintaining the generated template +- `CONTRIBUTING.md` — development and contribution workflow +- `SECURITY.md` — reporting security issues diff --git a/template/README.md b/template/README.md index 7aa9f50..39f6537 100644 --- a/template/README.md +++ b/template/README.md @@ -1,210 +1,180 @@ # {{SUITE_NAME}} -Hardened WSL-first repository scaffold for an OMP/Pi coding harness and a modular Valheim mod suite, generated by HeimForge. +A modular Valheim mod-suite repository generated by HeimForge. This is an unofficial community project and is not affiliated with or endorsed by Iron Gate or Coffee Stain. -This package is a development/bootstrap repository, not a claim that Valheim runtime behavior has already been proven. It deliberately separates what can be validated statically from what must be verified against the user's actual Valheim client and dedicated server. +The repository provides standalone build, test, deployment, metadata, and +packaging workflows. Static validation does not replace runtime testing against +the actual Valheim client and server. -## Canonical development environment +## Quick start -Use **WSL/Linux as the primary development environment**. +Use WSL/Linux as the primary development environment and keep the repository in +the Linux filesystem rather than under `/mnt/c`. -```text -WSL repository + OMP/Pi + dotnet + optional Docker tooling - | - +-- build/test/package in WSL - +-- inspect Windows Valheim files through /mnt/c/... -{{DEPLOY_TOPOLOGY_LINES}} +Copy the local configuration templates: + +```bash +cp Environment.props.example Environment.props +cp .valheim/dev.json.example .valheim/dev.json ``` -Keep the repository in the WSL filesystem, for example `~/src/{{ROOT_NAMESPACE_LOWER}}`, rather than under `/mnt/c`. +Then run a portable repository-only check: -Windows remains the real Valheim client runtime. Bash scripts are authoritative. +```bash +./scripts/preflight.sh --portable +``` + +For full local validation after configuring a development Valheim installation: + +```bash +./scripts/preflight.sh +./scripts/bootstrap.sh +``` -## Runtime topology +See `docs/development.md` for local Valheim paths, server deployment, SSH, +Docker lifecycle configuration, and reference maintenance. -This list reflects the initial scaffold selection made when this repository was generated; `suite.config.json` plus the canonical `.sln` remain the machine-validated current structural authority afterward (see "Hardened metadata model" below). If a later structural edit adds or removes a project, update this list and `docs/module-catalog.md` by hand. +## Modules -`Common` is a shared library other plugins reference, not itself a runtime BepInEx plugin. `ServerCore`, `Client`, and `Shared.Diagnostics` may each be individually omitted, but at least one of the three must be enabled -- a generation request disabling all three is rejected before this repository is created. +This project was generated with the following modules: {{INCLUDED_MODULES_LIST}} -Current compatibility boundaries: +Compatibility boundaries: {{COMPATIBILITY_BOUNDARIES_LIST}} -## Hardened metadata model +`Common` is a shared library rather than a BepInEx runtime plugin; at least one of the three must be enabled -- a generation request disabling all three is rejected before this repository is created. -`suite.config.json` is the editable source of truth for supported **mutable** suite/project/package metadata -- values that can be edited and re-synchronized without renaming repository layout: +`suite.config.json` and the solution file are the current structural authority. -- version, author, Thunderstore namespace, plugin GUID root -- dependency pins -- C# language version -- project scopes and target frameworks, subject to exactly matching `.sln`'s real `src/` project membership (see below) -- client/server package membership +## Development environment -`suiteName` and `rootNamespace` are generation-time **identity**, not editable through `suite.config.json`: `rootNamespace` already determined the `.sln` filename, every project directory under `src/`, and every handwritten/generated C# namespace when this repository was rendered; `suiteName` already determined the deployment-manifest identity (`.{suiteName}.deploy-manifest.json`) that tracks which DLLs this suite owns at a deployment destination. `suite.identity.lock.json` records both generation-time values; `sync`/`check`/packaging/deployment reject any `suite.config.json` edit that disagrees with it, before touching any generated file or deployment destination. Changing repository identity requires regenerating the suite (or creating a new project), not editing the config. +The canonical workflow is: -`projects` may gain or lose entries after generation, but only in lockstep with `.sln` itself: add/remove the `.csproj`, add/remove the matching `.sln` entry, then update `suite.config.json` and run `sync`/`check`. The set of `src/` projects `suite.config.json` configures and the set the solution actually builds must always agree exactly; `sync`/`check`/packaging/deployment reject a mismatch in either direction before touching anything. +```text +WSL repository + dotnet + | + +-- build/test/package in WSL + +-- inspect Windows Valheim files through /mnt/c/... +{{DEPLOY_TOPOLOGY_LINES}} +``` -Generated committed outputs are synchronized with: +Windows remains the real Valheim client runtime. -```bash -python3 scripts/suite_metadata.py sync -``` +## Common commands -Validate them with: +Validate project metadata: ```bash python3 scripts/suite_metadata.py check ``` -`sync` regenerates `build/Suite.Generated.props`, the common module's `SuiteConstants.Generated.cs`, and `packaging/profile-lock.json` from the mutable fields above. `check` fails if any of those generated files drift from the authoritative config, if `suiteName`/`rootNamespace` no longer match the `suite.identity.lock.json` baseline, or if `projects` no longer matches `.sln`'s real project membership. - -## Start here - -1. Extract/copy this repository inside the WSL filesystem. -2. Copy `Environment.props.example` to `Environment.props` and edit the WSL-visible Windows Valheim path. -3. Copy `.valheim/dev.json.example` to `.valheim/dev.json` and edit development targets. -4. Ensure the development Windows Valheim installation contains the pinned BepInExPack and Jötunn runtime. -5. Run: +Synchronize supported metadata changes: ```bash -./scripts/preflight.sh -./scripts/bootstrap.sh +python3 scripts/suite_metadata.py sync ``` -6. Start OMP in the repository root. -7. Run `/bootstrap-valheim` or ask the harness to execute `BOOTSTRAP_PROMPT.md`. - -For a portable repository-only check without local Valheim paths: +Run tests: ```bash -./scripts/preflight.sh --portable +./scripts/test.sh ``` -## Game-stack maintenance - -Use one offline-first command to inspect the configured development stack: +Build: ```bash -python3 scripts/update-game-stack.py check +./scripts/build.sh Debug ``` -It reports Valheim's deterministic local Steam build ID when available, pinned and development-profile Jötunn/BepInExPack versions, pin/runtime drift, and whether Jötunn publicized assemblies are present. It does not query Thunderstore or change files. - -Apply only versions chosen explicitly: +Inspect the configured Valheim/Jötunn/BepInEx development stack: ```bash -python3 scripts/update-game-stack.py apply \ - --jotunn \ - --bepinex +python3 scripts/update-game-stack.py check ``` -`apply` synchronizes metadata, refreshes references for an explicit Jötunn update, then runs the ordinary parallel build and preflight. It never installs a runtime package into a profile or remote server, deploys plugins, or restarts a server. For a Valheim binary update without changing pins, run: +Refresh game references after a Valheim binary/reference update: ```bash -python3 scripts/update-game-stack.py check python3 scripts/update-game-stack.py refresh -./scripts/check-game-update.sh ``` -`update-game-stack.py` maintains dependency metadata, local runtime inspection, references, and builds. `check-game-update.sh` fingerprints the resolved gameplay assembly (`assembly_valheim.dll`, with `Assembly-CSharp.dll` fallback for older layouts) and lists Harmony targets requiring semantic revalidation; a successful build does not prove Harmony patches remain valid. Remote/server runtime is never inspected or changed by these commands. Deployment remains explicit: +Create deterministic Release packages: ```bash -{{DEPLOY_COMMANDS_LIST}} +./scripts/package.sh ``` -Add `--restart` only to an explicit server deployment. +See `docs/development.md`, `docs/dependencies.md`, and `docs/testing.md` for +details. ## Deployment -Both Bash deployment and OMP deployment use the same metadata-driven `scripts/deploy.py` implementation. Server artifact planning is independent of deployment transport (`local` or `ssh`) and lifecycle (`none` or `docker`), so changing where the server runs never changes module selection. +Deployment is explicit and metadata-driven: ```bash {{DEPLOY_COMMANDS_LIST}} ``` -Server deployment does not restart by default. Use `./scripts/deploy-server.sh Debug --restart` to invoke the configured lifecycle after a successful deployment. See `docs/development.md` for schema-v2 local/SSH examples, SSH aliases and executable overrides, remote platform selection, staging guarantees, and schema-v1 migration. - {{DEPLOY_SIDE_NOTES_LIST}} -No glob-based side classification is used. +Server deployment does not restart the server unless explicitly requested. -## Licensing +See `docs/development.md` for local and SSH deployment configuration, +transaction guarantees, and server lifecycle behavior. + +## Metadata -HeimForge does not choose a project-level license for this generated -repository. `LICENSE.todo` remains as a release reminder, while -`LICENSES/MIT-0.txt` covers only the HeimForge scaffold material copied into -the repository. +`suite.config.json` is the editable source of truth for supported mutable +project metadata, including: -Your own application and gameplay code may use the project license you choose, -subject to the terms of third-party dependencies or other incorporated -material. Before public distribution, add the chosen project license as the -root `LICENSE` and remove `LICENSE.todo`. +- version and publication metadata +- dependency pins +- project scopes and target frameworks +- client/server package membership -`python3 scripts/suite_metadata.py check --release` enforces that the root -`LICENSE` is a non-empty regular UTF-8 text file and that `LICENSE.todo` has -been removed. Local/test packaging remains available before that public-release -gate is satisfied. When a root `LICENSE` exists, generated package ZIPs include -it verbatim. +`suiteName` and `rootNamespace` are generation-time identity and are locked in +`suite.identity.lock.json`. -## Packaging +Use `scripts/suite_metadata.py` rather than hand-editing generated metadata +files. -`package.sh` is no longer a placeholder. It performs a Release build and creates deterministic local distribution ZIPs plus SHA-256 checksums under `artifacts/packages/`: +## Licensing -```bash -./scripts/package.sh -``` +HeimForge does not select a project-level license for generated repositories. -These are local/test distribution packages. Public Thunderstore publication still requires final branding, namespace, license, descriptions/icons, and a clean runtime validation pass. +`LICENSES/MIT-0.txt` covers the HeimForge scaffold material. Before public +distribution: -Run this before public publication metadata work: +1. choose a project license +2. add it as the root `LICENSE` +3. remove `LICENSE.todo` +4. run: ```bash python3 scripts/suite_metadata.py check --release ``` -It intentionally fails while GUID/author/Thunderstore-namespace placeholders remain. - -## Dependency pins - -Exact current versions are authoritative in `suite.config.json` and synchronized into `build/Suite.Generated.props` by `scripts/suite_metadata.py sync` -- not duplicated here, so this section cannot go stale when a pin changes: - -- Jötunn: `jotunnVersion` -- BepInExPack Valheim: `bepInExPackVersion` -- Microsoft.NETFramework.ReferenceAssemblies: `netFrameworkReferenceAssembliesVersion`, for cross-platform `net48` targeting -- runtime plugin language version: `csharpLanguageVersion` (`net48` target) +See `docs/release.md` for the complete release checklist. -Dependency changes must be deliberate and documented. Do not silently float them. +## Runtime validation -## OMP layout +Repository checks can prove structural consistency, build behavior, packaging, +and deployment rules, but some behavior still requires the user's actual +Valheim environment: -Project-local OMP resources use native discovery: - -- `.omp/skills/*/SKILL.md` -- `.omp/extensions/valheim-dev/index.ts` -- `.omp/prompts/bootstrap-valheim.md` - -No generic project planner/reviewer/scout agents are added. Use the harness's installed planning and subagent capabilities. - -## What is proven before local runtime validation - -The hardened scaffold includes automated checks for: - -- metadata consistency -- configured project existence and target frameworks -- client/server module separation -- Bash syntax and executable flags -- local secret/config ignore rules -- generated constants being authoritative -- cross-platform `net48` reference package inclusion -- original Jötunn compatibility boundaries -- real deterministic packaging implementation -- removal of arbitrary configured log-command execution from the OMP extension +{{PENDING_RUNTIME_PROOF_LIST}} -What still requires the user's machine: +## Documentation -{{PENDING_RUNTIME_PROOF_LIST}} +- `docs/development.md` — local environment, build, deployment, and server workflows +- `docs/dependencies.md` — dependency purposes and version maintenance +- `docs/module-catalog.md` — generated module topology +- `docs/networking.md` — networking conventions +- `docs/patch-ledger.md` — Harmony patch tracking +- `docs/release.md` — packaging and public-release checklist +- `docs/testing.md` — validation and test workflow