feat(nwsync): emit blobs and per-artifact NSYM, assemble merged manifests

Adds `crucible nwsync emit` and `crucible nwsync assemble`, the split
replacement for upstream nwn_nwsync_write, which cannot be used because it
wants every hak, the TLK and the module present in one run on one disk.

emit explodes one artifact — a .hak/.erf or a loose file such as the TLK —
into NWSync blobs (NWCompressedBuffer framing, magic NSYC, zstd) plus a NSYM
v3 manifest describing only that artifact, with the same .json sidecar
upstream writes. Blob names are the sha1 of the uncompressed bytes, restypes
nss/ndb/gic are always skipped, an unresolvable restype is a hard error, a
resource over 15 MB fails closed, and no latest or .origin file is ever
written.

assemble merges the per-artifact manifests into one, reading no bulk data.
The merge rule is resref shadowing, not concatenation: a resref present in
more than one artifact resolves to the earliest artifact in --order, the way
the game resolves it. It refuses to merge across mismatched emitter versions,
and takes --group-id from the caller (1 current, 2 testing; 0 is absent).

Refs #53.
This commit is contained in:
2026-07-29 12:12:22 +02:00
parent 4d03085996
commit 0de1c1e280
15 changed files with 1199 additions and 8 deletions
+9
View File
@@ -34,11 +34,20 @@ aliases.
| `depot` | `verify` | Existence sweep plus sampled download re-hash. |
| `depot` | `get` | Fetch one blob with sha re-verify. |
| `depot` | `pull` | Incremental verified pull of every referenced blob. |
| `nwsync` | `emit` | Explode one artifact into NWSync blobs plus its own NSYM manifest. |
| `nwsync` | `assemble` | Merge per-artifact NSYM manifests into one merged manifest. |
`depot status` and `depot get` pick their backend either with `--out DIR`, a
depot tree on disk, or with `--target bunny|cdn`, a remote backend. The two
flags are mutually exclusive.
`nwsync emit` runs where an artifact is born (a `.hak`/`.erf`, or a loose file
such as the TLK); `nwsync assemble` runs at module release and reads only the
small per-artifact manifests. `--order` lists artifact names highest priority
first: a resref in more than one artifact resolves to the earliest one, the way
the game resolves it. `--group-id` is per channel — 1 is current, 2 is testing,
and 0 leaves the field out of the sidecar.
## Hidden compatibility aliases
Existing scripts may continue using these names indefinitely. They are accepted