crucible nwsync emit and assemble print their summary line to stdout. Any caller that captures a script's stdout as a value gets the summary glued onto it. This broke the first real tag release.
Evidence
sow-assets-manifest run 5009, tag v0.2.1-rc1, conclusion: failure after 17 minutes. Step Pack, publish, and link HAKs does:
release_dir="$(... scripts/pack-haks.sh)"
pack-haks.sh:115 calls nwsync_emit, which at scripts/lib.sh:815 runs crucible without redirecting stdout. All 11 emit summaries landed in $release_dir, so publish-release.sh:16 died:
[depot] ERROR: release dir not found: emitted 3046d008…: 9754 resources, 0 new blobs, index …
… (10 more) …
/var/lib/gitea-runner/…/sow-assets-pack/release
The last line is the correct path. lib.sh's own log "nwsync: emitted $key" goes to stderr correctly — only crucible's line leaks.
Fix
internal/nwsync/run.go, two lines to stderr:
:109 — emitted %s: %d resources, %d new blobs, index %s
:143 — assembled manifest %s: %d resources, %s
Neither is a machine-readable contract. sow-topdata's contract tests (tests/backfill-nwsync-contract.sh, tests/publish-topdata-release-contract.sh) grep an EMIT_LOG their own fake-crucible stub writes, not real stdout — so nothing parses these.
sow-topdata — latent. publish-topdata-release.sh doesn't capture stdout, so run 5011 passed and v0.2.3-rc1 published clean.
sow-module — latent, and :143 is the assemble path that sow-module#51 is about to build. Fixing now avoids repeating this.
Why not patch >&2 in sow-assets-manifest
It works, but leaves topdata and the unbuilt module assemble step still leaking into whatever captures them next. One line in crucible covers every caller.
Follow-up
Crucible reaches CI off the nix devshell, so after this lands sow-assets-manifest needs a flake.lock bump, then a re-run of the v0.2.1-rc1 tag.
State left by the failed run
Nothing to clean up. Haks and NWSync blobs uploaded (all 0 new blobs — backfill had them). publish-release.sh died before uploading anything, so no catalog landed and Promote channel was skipped. The tag stands; re-running is the break-glass republish path 23c15b6 added. No re-tag needed.
Part of #54.
## Question
`crucible nwsync emit` and `assemble` print their summary line to **stdout**. Any caller that captures a script's stdout as a value gets the summary glued onto it. This broke the first real tag release.
### Evidence
sow-assets-manifest [run 5009](https://git.westgate.pw/ShadowsOverWestgate/sow-assets-manifest/actions/runs/5009/jobs/5039), tag `v0.2.1-rc1`, `conclusion: failure` after 17 minutes. Step **Pack, publish, and link HAKs** does:
```bash
release_dir="$(... scripts/pack-haks.sh)"
```
`pack-haks.sh:115` calls `nwsync_emit`, which at `scripts/lib.sh:815` runs crucible without redirecting stdout. All 11 emit summaries landed in `$release_dir`, so `publish-release.sh:16` died:
```
[depot] ERROR: release dir not found: emitted 3046d008…: 9754 resources, 0 new blobs, index …
… (10 more) …
/var/lib/gitea-runner/…/sow-assets-pack/release
```
The last line is the correct path. `lib.sh`'s own `log "nwsync: emitted $key"` goes to stderr correctly — only crucible's line leaks.
### Fix
`internal/nwsync/run.go`, two lines to stderr:
- `:109` — `emitted %s: %d resources, %d new blobs, index %s`
- `:143` — `assembled manifest %s: %d resources, %s`
Neither is a machine-readable contract. sow-topdata's contract tests (`tests/backfill-nwsync-contract.sh`, `tests/publish-topdata-release-contract.sh`) grep an `EMIT_LOG` their own fake-crucible stub writes, not real stdout — so nothing parses these.
### Blast radius
- **sow-assets-manifest** — broken now, blocks #47's tag.
- **sow-topdata** — latent. `publish-topdata-release.sh` doesn't capture stdout, so [run 5011](https://git.westgate.pw/ShadowsOverWestgate/sow-topdata/actions/runs/5011/jobs/5041) passed and `v0.2.3-rc1` published clean.
- **sow-module** — latent, and `:143` is the assemble path that sow-module#51 is about to build. Fixing now avoids repeating this.
### Why not patch `>&2` in sow-assets-manifest
It works, but leaves topdata and the unbuilt module assemble step still leaking into whatever captures them next. One line in crucible covers every caller.
### Follow-up
Crucible reaches CI off the nix devshell, so after this lands sow-assets-manifest needs a `flake.lock` bump, then a re-run of the `v0.2.1-rc1` tag.
### State left by the failed run
Nothing to clean up. Haks and NWSync blobs uploaded (all `0 new blobs` — backfill had them). `publish-release.sh` died before uploading anything, so no catalog landed and **Promote channel** was skipped. The tag stands; re-running is the break-glass republish path `23c15b6` added. No re-tag needed.
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Part of #54.
Question
crucible nwsync emitandassembleprint their summary line to stdout. Any caller that captures a script's stdout as a value gets the summary glued onto it. This broke the first real tag release.Evidence
sow-assets-manifest run 5009, tag
v0.2.1-rc1,conclusion: failureafter 17 minutes. Step Pack, publish, and link HAKs does:pack-haks.sh:115callsnwsync_emit, which atscripts/lib.sh:815runs crucible without redirecting stdout. All 11 emit summaries landed in$release_dir, sopublish-release.sh:16died:The last line is the correct path.
lib.sh's ownlog "nwsync: emitted $key"goes to stderr correctly — only crucible's line leaks.Fix
internal/nwsync/run.go, two lines to stderr::109—emitted %s: %d resources, %d new blobs, index %s:143—assembled manifest %s: %d resources, %sNeither is a machine-readable contract. sow-topdata's contract tests (
tests/backfill-nwsync-contract.sh,tests/publish-topdata-release-contract.sh) grep anEMIT_LOGtheir own fake-crucible stub writes, not real stdout — so nothing parses these.Blast radius
publish-topdata-release.shdoesn't capture stdout, so run 5011 passed andv0.2.3-rc1published clean.:143is the assemble path that sow-module#51 is about to build. Fixing now avoids repeating this.Why not patch
>&2in sow-assets-manifestIt works, but leaves topdata and the unbuilt module assemble step still leaking into whatever captures them next. One line in crucible covers every caller.
Follow-up
Crucible reaches CI off the nix devshell, so after this lands sow-assets-manifest needs a
flake.lockbump, then a re-run of thev0.2.1-rc1tag.State left by the failed run
Nothing to clean up. Haks and NWSync blobs uploaded (all
0 new blobs— backfill had them).publish-release.shdied before uploading anything, so no catalog landed and Promote channel was skipped. The tag stands; re-running is the break-glass republish path23c15b6added. No re-tag needed.