10 KiB
description, alwaysApply
| 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-toolkitCLI 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 ismodule/ - authored binary asset source (
content/) — that isassets/ - user-facing wrapper commands — those live in the consumer repos
2. Repository Layout
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.mdinternal/topdata/FAMILY_EXPANSION_CONTRACT.mdinternal/topdata/MASTERFEATS_CONTRACT.mdinternal/topdata/INHERITANCE_CONTRACT.mdinternal/topdata/CLASS_FEAT_GLOBAL_INJECTS_CONTRACT.mdinternal/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 automationCONFIGURATION_HARDENING_CONTRACT.md— YAML authority, config refactor progress, outstanding hardening workCONFIGURATION_REFACTOR_CONTRACT.md— config normalization scopeLOG_REFACTOR_CONTRACT.md— logging verbosity model, phase/summary presentation, remaining command gapsTOPDATA_HARDENING_CONTRACT.md— active topdata hardening priorities and findingsWIKI_DEPLOYMENT_CONTRACT.md— wiki build/deploy phase, current state, immediate goalsCHANGELOG_AUTOMATION_CONTRACT.md— changelog generator contract and consumer ownershipMUSIC_REFACTOR_CONTRACT.md— music pipeline refactor status and dataset modelMODEL_COMPILATION_ON_BUILDTIME_CONTRACT.md— outstanding model compilation build-time contractSCRIPT_WRAPPER_CONTRACT.md— wrapper contract status (largely complete)module/topdata/wiki/TEMPLATE_AUTHORITY_CONTRACT.mdinsow-module— wiki template/YAML ownership rules; mandatory before editing wiki rendering
4. Full Command Surface
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 <name>] # build one HAK by name
[--archive <name>] # build one archive
[--source-manifest <path>] # seed split state from prior manifest
[--plan-only] # show build plan without writing
[--skip-music] # skip music conversion for this run
[--music-dataset <id>] # process a single music dataset
sow-toolkit extract [<archive>...] # 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
[<manifest-path>]
sow-toolkit config validate # validate nwn-tool.yaml against schema
sow-toolkit config effective # dump effective merged config
sow-toolkit config inspect <key> # inspect one config value
sow-toolkit config explain <key> # 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 <path>]
[--endpoint <url>]
[--token <token>]
[--version <ver>]
[--namespace <ns>]
[--category <namespace=cid>]
[--manifest <path>]
[--stale-policy <report|archive|purge>]
[--dry-run]
[--create]
[--force]
[--reset-managed-namespaces]
sow-toolkit build-changelog # render release changelog from Gitea API
[--config <path>] # defaults to scripts/changelog.json
[--output <path>] # defaults to stdout
[--current-tag <tag>]
[--previous-tag <tag>]
[--api-base-url <url>]
[--token <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
nwn-tool.yamlnwn-tool.ymlnwn-tool.json(legacy, prints migration warning)
YAML is canonical. Inspect effective config with:
./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):
./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:
GOCACHE="$PWD/.cache/go-build" go run ./cmd/nwn-tool --help
After building, test it from a consumer repo:
cd ../module
SOW_TOOLS_DEV_BINARY=../toolkit/tools/sow-toolkit ./validate-topdata.sh
7. Key Tests
Run the full suite:
go test ./...
Determinism test — mandatory when changing topdata ID allocation, lockfile persistence, generated families, or null-and-relocate behavior:
go test ./internal/topdata -run TestBuildNativeKeepsGeneratedIDsStableAcrossRepeatedBuilds
App-level tests (CLI behavior, compact vs. verbose output):
go test ./internal/app/...
Changelog tests:
go test ./internal/changelog/...
8. Consumer Resolution
Consumer repos resolve the toolkit binary in this order:
- Pinned local binary:
tools/sow-toolkit/tools/sow-toolkit.exe - Dev override via
SOW_TOOLS_DEV_BINARY=<path> - Auto-install from latest
sow-toolsGitea release
Use SOW_TOOLS_DEV_BINARY to override for one invocation without replacing
the installed binary:
cd ../module
SOW_TOOLS_DEV_BINARY=../toolkit/tools/sow-toolkit ./build-topdata.sh
9. Release Artifacts
This repo publishes:
sow-toolkit-linux-amd64.tar.gzsow-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*:
- Read
module/topdata/wiki/TEMPLATE_AUTHORITY_CONTRACT.mdinsow-modulefirst. - Page structure, displayed values, headings, and wording belong in
module/topdata/wiki/templates/andmodule/topdata/wiki/data.yaml/tables.yaml. - Toolkit code owns only generic rendering mechanics, expression helpers, validation, deterministic ordering, and compatibility fallbacks.
- 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.yamldeclarations, 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 effectivein a consumer repo when changing config-loading logic.