archvillainette 3f1e33a39a
build-binaries / build-binaries (push) Successful in 2m56s
fix(wiki): compare drift against what NodeBB stored, not what we rendered (#104)
Fixes #103.

## What was wrong

`crucible wiki deploy` decided a page had drifted by hashing NodeBB's stored
copy and comparing it to the hash of the text Crucible rendered. Those match
only if NodeBB gives our HTML back byte for byte. It does not, so every
`sow-topdata` tag deploy failed:

```
local pages: 1200, updated: 1, skipped: 1176, drifted: 23
remote managed wiki content drifted; rerun with --force to overwrite
```

Nobody had edited those pages. The operator's only way out was to leave
`--force` on, which removes the protection the guard exists for.

## What changed

- New manifest field `remote_hash`: the managed-region hash of the post NodeBB
  hands back right after we write it. Drift compares against that, so it means
  "the live page changed after we last wrote it".
- A post with no `sourceContent` is not drift. It predates `sourceContent`
  sync, reads back as rendered HTML, and belongs to the existing
  `SourceContentSynced` repair — which the drift refusal used to block.
- The error names the drifted pages, capped at ten plus a count.
- Deleted the dead `wikiDeployPlan.RemoteHash` field.

Old manifests keep the previous comparison until each page is next written, so
no re-seed is needed. Cost: one extra post read per page written. Pages that
skip are still never fetched.

## Tests

`internal/topdata/wiki_deploy_test.go`, same seam as the rest of the file
(`DeployWikiWithOptions` against the fake NodeBB): normalized remote copy is not
drift, a hand-edited page still is and the error names it, `--force` overwrites
it and re-records the hash, a post without `sourceContent` is repaired instead
of refused, and an old-format manifest deploys and gains a `remote_hash`.

`make check` passes.

🤖 Generated with [Claude Code](https://claude.com/claude-code)Reviewed-on: #104

Co-authored-by: vickydotbat <vickydotbat@tutamail.com>
2026-08-07 21:46:36 +00:00
2026-06-18 07:29:09 +00:00
2026-06-25 09:29:39 +00:00
2026-07-12 12:06:40 +00:00
2026-06-20 15:41:33 +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-nwsync crucible nwsync NWSync blob emit + manifest assemble + verify
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, then delete the assets of every release except the newest two — Gitea keeps them forever otherwise, and every binary is reproducible from its tag.
  • 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.41
Latest
2026-08-07 21:50:13 +00:00
Languages
Go 98.8%
Shell 0.9%
PowerShell 0.2%
Nix 0.1%