--- description: alwaysApply: true --- # Toolkit Agent Guide `toolkit/` owns the shared `sow-toolkit` Go binary consumed by `module/` and `assets/`. It does not own authored game content — it owns the build, extract, validate, compare, topdata, wiki, music, and changelog machinery that those repos invoke through wrapper scripts. ## 1. Project Overview Repository name: `sow-tools` Go module: `gitea.westgate.pw/ShadowsOverWestgate/sow-tools` Language: Go 1.26+ Entry point: `cmd/nwn-tool/` Built binary: `tools/sow-toolkit` (Linux) / `tools/sow-toolkit.exe` (Windows) What this repo owns: - the `sow-toolkit` CLI implementation - all build, extract, compare, and validate pipeline logic - native topdata validation, build, compare, conversion, and packaging - wiki rendering and NodeBB deployment - music scanning, BMU generation, credits, and normalization - changelog generation from Gitea API - config loading and effective-config inspection - HAK archive reading and writing (ERF format) - GFF JSON conversion What this repo does not own: - authored module source (`src/`, `topdata/`) — that is `module/` - authored binary asset source (`content/`) — that is `assets/` - user-facing wrapper commands — those live in the consumer repos ## 2. Repository Layout ```text cmd/nwn-tool/ CLI entrypoint (flag parsing, command dispatch) internal/app/ command wiring, console UX, verbosity model internal/changelog/ changelog rendering from Gitea API internal/erf/ ERF/MOD/HAK reading and writing internal/gff/ canonical GFF JSON and binary conversion internal/music/ music scanning, BMU build, credits, normalization internal/pipeline/ build, extract, compare, and manifest workflows internal/project/ config loading, effective config, repo scanning internal/topdata/ native topdata, wiki, and autogen workflows internal/validator/ validation and diagnostics tools/ built development binary output docs/ additional implementation-level documentation ``` Key topdata-adjacent contracts in `internal/topdata/` (read before editing topdata logic): - `internal/topdata/FEAT_GENERATED_FAMILIES_CONTRACT.md` - `internal/topdata/FAMILY_EXPANSION_CONTRACT.md` - `internal/topdata/MASTERFEATS_CONTRACT.md` - `internal/topdata/INHERITANCE_CONTRACT.md` - `internal/topdata/CLASS_FEAT_GLOBAL_INJECTS_CONTRACT.md` - `internal/topdata/AUTO-INCLUDE_EXISTING_PART_MODELS_IN_2DA_GENERATION_CONTRACT.md` ## 3. Relevant Links And Documentation Read these before making significant changes: - `README.md` — full command surface, consumer resolution, release automation - `CONFIGURATION_HARDENING_CONTRACT.md` — YAML authority, config refactor progress, outstanding hardening work - `CONFIGURATION_REFACTOR_CONTRACT.md` — config normalization scope - `LOG_REFACTOR_CONTRACT.md` — logging verbosity model, phase/summary presentation, remaining command gaps - `TOPDATA_HARDENING_CONTRACT.md` — active topdata hardening priorities and findings - `WIKI_DEPLOYMENT_CONTRACT.md` — wiki build/deploy phase, current state, immediate goals - `CHANGELOG_AUTOMATION_CONTRACT.md` — changelog generator contract and consumer ownership - `MUSIC_REFACTOR_CONTRACT.md` — music pipeline refactor status and dataset model - `MODEL_COMPILATION_ON_BUILDTIME_CONTRACT.md` — outstanding model compilation build-time contract - `SCRIPT_WRAPPER_CONTRACT.md` — wrapper contract status (largely complete) - `module/topdata/wiki/TEMPLATE_AUTHORITY_CONTRACT.md` in `sow-module` — wiki template/YAML ownership rules; mandatory before editing wiki rendering ## 4. Full Command Surface ```bash sow-toolkit build # build module ERF from src/ sow-toolkit build-module # alias; builds module with HAK manifest refresh sow-toolkit build-haks # build HAKs and haks.json manifest [--hak ] # build one HAK by name [--archive ] # build one archive [--source-manifest ] # seed split state from prior manifest [--plan-only] # show build plan without writing [--skip-music] # skip music conversion for this run [--music-dataset ] # process a single music dataset sow-toolkit extract [...] # extract built archive back into src/ sow-toolkit validate # validate project structure and config sow-toolkit compare # compare built output against extracted source sow-toolkit apply-hak-manifest # apply haks.json to module HAK list [] sow-toolkit config validate # validate nwn-tool.yaml against schema sow-toolkit config effective # dump effective merged config sow-toolkit config inspect # inspect one config value sow-toolkit config explain # explain a config key's meaning and source sow-toolkit config sources # show config file discovery order sow-toolkit music list-datasets # list configured music datasets sow-toolkit music scan # scan and report music sources sow-toolkit music build # convert and package music BMUs sow-toolkit music credits # generate music credits sow-toolkit music validate # validate music dataset config sow-toolkit music manifest # emit music manifest sow-toolkit music normalize # normalize music metadata sow-toolkit validate-topdata # validate topdata authoring sow-toolkit build-topdata # compile topdata + optional wiki [--force] # force rebuild even if cache is fresh [--wiki] # also run wiki build sow-toolkit build-top-package # package sow_top.hak + sow_tlk.tlk only [--force] sow-toolkit compare-topdata # native self-check for topdata pipeline sow-toolkit convert-topdata # 2DA/JSON/module conversion utilities <2da-to-json|2da-to-module|json-to-2da> ... sow-toolkit build-wiki # render topdata wiki into .cache/wiki/ [--force] sow-toolkit deploy-wiki # deploy rendered wiki to NodeBB [--source-dir ] [--endpoint ] [--token ] [--version ] [--namespace ] [--category ] [--manifest ] [--stale-policy ] [--dry-run] [--create] [--force] [--reset-managed-namespaces] sow-toolkit build-changelog # render release changelog from Gitea API [--config ] # defaults to scripts/changelog.json [--output ] # defaults to stdout [--current-tag ] [--previous-tag ] [--api-base-url ] [--token ] # or env: GITEA_API_TOKEN, GITEA_TOKEN, SOW_TOOLS_TOKEN ``` Global flags (pass after the command name): `--quiet`, `--verbose`, `--debug` ## 5. Config Discovery Order 1. `nwn-tool.yaml` 2. `nwn-tool.yml` 3. `nwn-tool.json` (legacy, prints migration warning) YAML is canonical. Inspect effective config with: ```bash ./scripts/run-nwn-tool.sh config effective --json ./scripts/run-nwn-tool.sh config explain topdata.package_hak ./scripts/run-nwn-tool.sh config explain autogen.cache.root ./scripts/run-nwn-tool.sh config explain topdata.wiki.page_templates_dir ``` ## 6. Building The Toolkit Normal build (produces `tools/sow-toolkit`): ```bash ./build-tool.sh # Linux/macOS .\build-tool.ps1 # Windows ``` Both wrappers use `.cache/go-build` and skip rebuild when sources are older than the existing binary. Or run directly without building: ```bash GOCACHE="$PWD/.cache/go-build" go run ./cmd/nwn-tool --help ``` After building, test it from a consumer repo: ```bash cd ../module SOW_TOOLS_DEV_BINARY=../toolkit/tools/sow-toolkit ./validate-topdata.sh ``` ## 7. Key Tests Run the full suite: ```bash go test ./... ``` Determinism test — mandatory when changing topdata ID allocation, lockfile persistence, generated families, or null-and-relocate behavior: ```bash go test ./internal/topdata -run TestBuildNativeKeepsGeneratedIDsStableAcrossRepeatedBuilds ``` App-level tests (CLI behavior, compact vs. verbose output): ```bash go test ./internal/app/... ``` Changelog tests: ```bash go test ./internal/changelog/... ``` ## 8. Consumer Resolution Consumer repos resolve the toolkit binary in this order: 1. Pinned local binary: `tools/sow-toolkit` / `tools/sow-toolkit.exe` 2. Dev override via `SOW_TOOLS_DEV_BINARY=` 3. Auto-install from latest `sow-tools` Gitea release Use `SOW_TOOLS_DEV_BINARY` to override for one invocation without replacing the installed binary: ```bash cd ../module SOW_TOOLS_DEV_BINARY=../toolkit/tools/sow-toolkit ./build-topdata.sh ``` ## 9. Release Artifacts This repo publishes: - `sow-toolkit-linux-amd64.tar.gz` - `sow-toolkit-windows-amd64.exe` Consumer repos install them with `scripts/install-tool.sh` or `scripts/install-tool.ps1`. ## 10. Wiki Ownership Rule When a task touches `internal/topdata/wiki*`: 1. Read `module/topdata/wiki/TEMPLATE_AUTHORITY_CONTRACT.md` in `sow-module` first. 2. Page structure, displayed values, headings, and wording belong in `module/topdata/wiki/templates/` and `module/topdata/wiki/data.yaml` / `tables.yaml`. 3. Toolkit code owns only generic rendering mechanics, expression helpers, validation, deterministic ordering, and compatibility fallbacks. 4. Do not mention Shadows Over Westgate-specific categories, row keys, labels, or wording in toolkit Go code unless they are compatibility shims. ## 11. Repository Working Rules ### Git - Never create new branches or commit anything. - Allow the user to do it manually. - Suggest a single commit message, but do not commit yourself. - Never reset, discard, or overwrite user changes unless explicitly asked. ### Implementation Discipline - YAML is the authoritative config format. JSON is for generated artifacts only. - All repository-shaped behavior must flow through `nwn-tool.yaml` declarations, not through toolkit-internal hardcoded assumptions. - New config fields require validation; invalid config must fail early and clearly. - Outputs must be deterministic across runs given the same inputs. - Run `go test ./...` before claiming a change is complete. - Check `config effective` in a consumer repo when changing config-loading logic.