Compare commits

...
2 Commits
Author SHA1 Message Date
gitea-botandarchvillainette 754375fb08 depot: report sweep progress to stderr instead of discarding it (#35)
test / test (push) Successful in 1m20s
build-binaries / build-binaries (push) Successful in 2m6s
build-image / publish (push) Successful in 38s
Sweep prints `probed N/M` every 1000 blobs, but every caller passed `io.Discard`, so a full ~71k-blob verify ran ~56 minutes with zero output and looked hung in CI (sow-assets-manifest run 245).

`go test ./internal/depot` passes; verified live against the cdn (progress lines now appear on stderr).

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

Co-authored-by: vickydotbat <vickydotbat@tutamail.com>
Reviewed-on: #35
Co-authored-by: gitea-bot <gitea-bot@noreply.git.westgate.pw>
Co-committed-by: gitea-bot <gitea-bot@noreply.git.westgate.pw>
2026-07-09 09:46:59 +00:00
gitea-botandarchvillainette 8a90713122 docs: agent-facing documentation pass (#34)
Documentation pass: AGENTS.md guidance map / purpose / usage sections; sibling-repo paths replaced with repo name + Gitea URL. Includes pending working-tree changes that were present before the pass.

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

Co-authored-by: vickydotbat <vickydotbat@tutamail.com>
Reviewed-on: #34
Co-authored-by: gitea-bot <gitea-bot@noreply.git.westgate.pw>
Co-committed-by: gitea-bot <gitea-bot@noreply.git.westgate.pw>
2026-07-09 08:09:34 +00:00
3 changed files with 47 additions and 5 deletions
+41
View File
@@ -9,6 +9,47 @@ This repo owns the **builder logic:** one Go module
(`git.westgate.pw/ShadowsOverWestgate/sow-tools`) producing the `crucible` (`git.westgate.pw/ShadowsOverWestgate/sow-tools`) producing the `crucible`
dispatcher and the `crucible-<name>` binaries. dispatcher and the `crucible-<name>` binaries.
## What it is / part it serves
Shadows Over Westgate (SoW) is a Neverwinter Nights: Enhanced Edition
persistent world, split into single-purpose repos. This repo is Crucible, the
Go build toolkit. The content repos hold game source (module areas, rules
data, binary assets) and call Crucible to turn that source into artifacts:
the `.mod` file, 2DA/TLK tables, HAKs, wiki pages. Crucible is the only place
builder logic lives; content repos only run it through thin wrapper scripts.
## Guidance map
| Where | What |
|-------|------|
| `cmd/crucible/`, `cmd/crucible-<name>/` | dispatcher + per-builder shims (thin `main.go` files) |
| `internal/dispatch/` | the command registry — single source of truth for the command surface |
| `internal/` (app, pipeline, project, erf, gff, topdata, changelog, validator, depot, menu, buildinfo) | the actual builder logic |
| `wrappers/` | canonical bootstrap wrappers (`crucible`, `crucible.ps1`) synced to consumer repos; `wrappers/consumers.txt` lists targets |
| `docs/command-surface.md` | every command, old `nwn-tool` name → new home |
| `docs/consumer-contract.md` | how consumer repos resolve/pin a Crucible binary |
| `docs/migration-from-nwn-tool.md` | migration status, what remains |
| `tests/`, `Makefile`, `flake.nix` | checks, targets, dev shell |
Task routing: adding/changing a command → read `docs/command-surface.md`
first, then `internal/dispatch`. Changing how consumers get binaries →
`docs/consumer-contract.md` + `wrappers/`. Release/CI questions → README "CI"
section and `.gitea/workflows/`.
## How it is used
- Dev loop: `nix develop`, then `make check` / `make build` / `make smoke`
(see Commands below).
- Release: push a `v*` tag. CI uploads cross-built binaries + wrappers to the
Gitea release and publishes the `crucible` container image.
- Consumers (they download released binaries via the wrapper; they never
vendor a toolkit):
- sow-module — https://git.westgate.pw/ShadowsOverWestgate/sow-module
- sow-topdata — https://git.westgate.pw/ShadowsOverWestgate/sow-topdata
- sow-assets-manifest — https://git.westgate.pw/ShadowsOverWestgate/sow-assets-manifest
- sow-platform (deploys the released image/pins) —
https://git.westgate.pw/ShadowsOverWestgate/sow-platform
## What this repo owns / does not own ## What this repo owns / does not own
Owns: build/extract/validate/compare pipeline, ERF/HAK packing, topdata 2da/tlk Owns: build/extract/validate/compare pipeline, ERF/HAK packing, topdata 2da/tlk
+2 -1
View File
@@ -80,7 +80,8 @@ This retires the old habit of checking in `nwn-tool` / `sow-toolkit`.
## CI ## CI
PR-first (D7): checks run on pull requests and on push to `main`; the only PR-first (D7): checks run on pull requests and on push to `main`; the only
publish event is a `v*` tag (see `sow-docs/runbooks/ci-trigger-standard.md`). publish event is a `v*` tag (see `runbooks/ci-trigger-standard.md` in sow-docs,
https://git.westgate.pw/ShadowsOverWestgate/sow-docs).
- `test.yml` — vet, test, shellcheck, yamllint, binary smoke (PR + main). - `test.yml` — vet, test, shellcheck, yamllint, binary smoke (PR + main).
- `test-image.yml` — build the OCI image to prove it compiles (PR + main, no push). - `test-image.yml` — build the OCI image to prove it compiles (PR + main, no push).
+4 -4
View File
@@ -143,7 +143,7 @@ func runStatus(args []string, stdout, stderr io.Writer, getenv func(string) stri
} }
shas := shaKeys(shaSizes) shas := shaKeys(shaSizes)
res, err := Sweep(context.Background(), backend, shas, cfg, io.Discard) res, err := Sweep(context.Background(), backend, shas, cfg, stderr)
if err != nil { if err != nil {
fmt.Fprintln(stderr, "depot status:", err) fmt.Fprintln(stderr, "depot status:", err)
return exitInternal return exitInternal
@@ -185,7 +185,7 @@ func runPush(args []string, stdout, stderr io.Writer, getenv func(string) string
} }
shas := shaKeys(shaSizes) shas := shaKeys(shaSizes)
res, err := Sweep(context.Background(), backend, shas, cfg, io.Discard) res, err := Sweep(context.Background(), backend, shas, cfg, stderr)
if err != nil { if err != nil {
fmt.Fprintln(stderr, "depot push:", err) fmt.Fprintln(stderr, "depot push:", err)
return exitInternal return exitInternal
@@ -266,7 +266,7 @@ func runVerify(args []string, stdout, stderr io.Writer, getenv func(string) stri
} }
shas := shaKeys(shaSizes) shas := shaKeys(shaSizes)
res, err := Sweep(context.Background(), backend, shas, cfg, io.Discard) res, err := Sweep(context.Background(), backend, shas, cfg, stderr)
if err != nil { if err != nil {
fmt.Fprintln(stderr, "depot verify:", err) fmt.Fprintln(stderr, "depot verify:", err)
return exitInternal return exitInternal
@@ -389,7 +389,7 @@ func runPull(args []string, stdout, stderr io.Writer, getenv func(string) string
// Sweep the source to distinguish "not there" (exit 1, listed) from // Sweep the source to distinguish "not there" (exit 1, listed) from
// "there, download it". // "there, download it".
res, err := Sweep(context.Background(), backend, toCheck, cfg, io.Discard) res, err := Sweep(context.Background(), backend, toCheck, cfg, stderr)
if err != nil { if err != nil {
fmt.Fprintln(stderr, "depot pull:", err) fmt.Fprintln(stderr, "depot pull:", err)
return exitInternal return exitInternal