archvillainetteandClaude Opus 5 6b7d5ce693
ci / ci (pull_request) Successful in 3m34s
fix(erf): align restype numbers with upstream neverwinter.nim
Five entries in the restype table disagreed with upstream
neverwinter.nim's restype.nim, so HAKs written from those source
extensions were labelled with a type the game reads as something else:

  gff  0x07F7 (2039, upstream bte) -> 0x07F5 (2037)
  ltr  0x0813 (2067, upstream bak) -> 0x07F4 (2036)
  jpg  0x081C (2076, upstream tml) -> 0x0821 (2081)
  dfa                              -> dft (0x07FD/2045 was already right,
                                      only the name was a typo)
  mdb  0x0816 (2070, upstream xbc) -> removed

Upstream registers no restype for mdb, so there is no correct number to
give it; keeping it squatting on xbc silently mislabels the resource.
It is dropped from AssetExtensions too, which turns .mdb into a loud
"unsupported extension" build error instead of a corrupt HAK entry. No
asset in the current corpus uses any of these paths.

Root cause of the miss: the init() consistency guard only panicked when
a number was missing from the reverse map. Its `if canonicalExt == ext
{ continue }` branch did nothing when the two maps disagreed, so a
mismatch was never caught. The guard now panics on disagreement and
also checks the reverse direction.

Adds a conformance test pinning the shared numbers against upstream,
including the four numbers upstream reserves for other extensions, and
a test that the two maps are mutual inverses.

Refs ShadowsOverWestgate/sow-tools#64

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-07-28 18:36:03 +02:00
2026-06-18 07:29:09 +00:00
2026-07-12 12:51:17 +00:00
2026-07-12 12:51:17 +00:00
2026-06-25 09:29:39 +00:00
2026-07-12 12:06:40 +00:00
2026-06-25 09:29:39 +00:00
2026-06-13 09:49:29 +02:00
2026-06-13 09:49:29 +02:00
2026-06-20 15:41:33 +00:00
2026-07-22 16:54:26 +00:00
2026-06-12 10:14:38 +02:00

sow-tools — Crucible

Crucible is the Shadows Over Westgate build/conversion/sync toolchain: one Go module producing several small binaries plus a crucible dispatcher (D11). It is the only repo that owns builder logic; the artifact repos (sow-module, sow-topdata, sow-assets-manifest) invoke Crucible through wrapper scripts and never embed a toolkit.

Repos produce artifacts.  sow-platform deploys artifacts.
Crucible is how the artifact repos turn source into artifacts.

Binaries

Binary Dispatcher form Owns
crucible dispatcher: crucible <builder> [args]
crucible-depot crucible depot content-addressed depot blob verify/move
crucible-hak crucible hak ERF/HAK pack/unpack + hak manifests
crucible-module crucible module build/extract/validate/compare the .mod
crucible-topdata crucible topdata compile 2da/tlk topdata + packages
crucible-wiki crucible wiki render + deploy mechanical wiki pages

The dispatcher and the standalone shims share one registry (internal/dispatch); the shims exist so consumer wrapper scripts can resolve a single-token command. The full legacy nwn-tool command surface and where each command lands is mapped in docs/command-surface.md.

Status (cutover performed)

The internal app/pipeline/project/erf/gff/topdata/changelog/ validator packages from gitea/sow-tools have been migrated into this tree, and the module, topdata, hak, and wiki builders now delegate to the migrated nwn-tool command surface (mapped in docs/command-surface.md). config and changelog are global commands on the dispatcher. depot has no migrated logic yet, so it keeps the fail-closed path: exit 70, never a faked artifact.

See docs/migration-from-nwn-tool.md for what was done and what remains (the consumer --manifest/--source/--out flag contract is the open Phase-6 item).

Quick start (no Nix)

Teammates without Nix don't build anything — they run the bootstrap wrapper, which downloads the latest released crucible for your OS and runs it:

./crucible            # interactive menu (pick a command)
./crucible module build
./crucible topdata validate

Windows (PowerShell):

.\crucible.ps1 module build

The binary is cached under ~/.cache/crucible/<version>/ (%LOCALAPPDATA%\crucible on Windows); --repo-local caches inside the repo instead. Private releases: set CRUCIBLE_TOKEN or write the token to ~/.config/crucible/token.

Develop

Self-contained (D8) — a host with only Nix can run everything:

nix develop            # Go + shellcheck + yamllint + make
make check             # go vet + go test + shellcheck + yamllint
make build             # build every cmd/* into ./bin (gitignored)
make smoke             # build + assert the fail-closed contract

Binaries are never committed — they are CI artifacts (D19). This retires the old habit of checking in nwn-tool / sow-toolkit.

CI

PR-first (D7): checks run once on pull requests; the only publish event is a v* tag (see runbooks/ci-trigger-standard.md in sow-docs, https://git.westgate.pw/ShadowsOverWestgate/sow-docs).

  • ci.yml — vet, test, shellcheck, yamllint, binary smoke, and cross-build all targets once per pull request.
  • build-binaries.yml — on a v* tag, cross-build and upload the binaries, SHA256SUMS, and the wrappers to the Gitea release.
  • sync-wrappers.yml — on a main push that touches wrappers/, auto-PR the canonical wrappers to the consumer repos in wrappers/consumers.txt. Consumer drift checks run after those PRs merge to main, not on the PRs themselves, to avoid recursive cross-repo checks.

Consumers

How the artifact repos resolve a Crucible binary is documented in docs/consumer-contract.md.

S
Description
Contains Crucible, our toolkit for processing NWN data and assets into its final form.
Readme GPL-3.0
60 MiB
v0.3.36
Latest
2026-07-31 23:14:20 +00:00
Languages
Go 98.8%
Shell 0.9%
PowerShell 0.2%
Nix 0.1%