Phase 2 of the parts-row autogen design — Crucible (sow-tools) side only.
Resolves parts 2DA rows from the immutable `part.yml` published with the asset HAK release, over the anonymous Bunny CDN channel, with the parts consumer required (no fail-open).
Changes
Resolver (T3): generalize `resolveCDNChannelManifest` — derive manifest basename + provenance label from config; drop hardcoded `assets/vfxs.yml` so `part.yml` resolves through the same path. VFX behavior unchanged.
Parts filter (T4): `filterCDNChannelEntries` dispatches on consumer mode; new `filterPartsCDNChannelEntries` implements the inventory contract — `restype: mdl` under `part//`, row id from trailing digits, dedup l/r/race/gender variants by (category,rowID), sort by source, zero accepted rows = hard fail, reject row id 0 / non-numeric / malformed / no-assets.
Pipeline (T6): native build runs one explicit augment → normalize → override sequence under the configured `parts_rows` policy; overrides may update an existing/discovered row but never synthesize one (orphan override now errors).
Validation (T7): reject more than one `parts_rows` consumer.
Tests
9 new tests: parts filter contract, 12-dataset coverage, offline manifest-basename, orphan-override reject + discovered-row update, and a parity guard proving a bare CDN-only parts build needs no wrapper/token/NWN_ROOT/checkout.
Gate green: `go test ./internal/topdata/... ./internal/project/...` + full `go build ./... && go test ./...`.
Scope / ordering
Phase 2 is inert until Phase 1 (sow-assets-manifest publishes `part.yml`) ships and the operational Gate (release publish/promote) runs, then Phase 3 enables the sow-topdata consumer. Do not enable the consumer against a channel whose current release predates `part.yml`.
Phase 2 of the parts-row autogen design — Crucible (sow-tools) side only.
Resolves parts 2DA rows from the immutable \`part.yml\` published with the asset HAK release, over the anonymous Bunny CDN channel, with the parts consumer **required** (no fail-open).
## Changes
- **Resolver (T3):** generalize \`resolveCDNChannelManifest\` — derive manifest basename + provenance label from config; drop hardcoded \`assets/vfxs.yml\` so \`part.yml\` resolves through the same path. VFX behavior unchanged.
- **Parts filter (T4):** \`filterCDNChannelEntries\` dispatches on consumer mode; new \`filterPartsCDNChannelEntries\` implements the inventory contract — \`restype: mdl\` under \`part/<supported-cat>/\`, row id from trailing digits, dedup l/r/race/gender variants by (category,rowID), sort by source, **zero accepted rows = hard fail**, reject row id 0 / non-numeric / malformed / no-assets.
- **Category (T5):** add \`hand\` + \`parts/hand\` mapping (12 datasets; \`leg→legs\` already present).
- **Pipeline (T6):** native build runs one explicit augment → normalize → override sequence under the configured \`parts_rows\` policy; overrides may update an existing/discovered row but **never synthesize** one (orphan override now errors).
- **Validation (T7):** reject more than one \`parts_rows\` consumer.
## Tests
9 new tests: parts filter contract, 12-dataset coverage, offline manifest-basename, orphan-override reject + discovered-row update, and a parity guard proving a bare CDN-only parts build needs no wrapper/token/NWN_ROOT/checkout.
Gate green: \`go test ./internal/topdata/... ./internal/project/...\` + full \`go build ./... && go test ./...\`.
## Scope / ordering
Phase 2 is inert until **Phase 1** (sow-assets-manifest publishes \`part.yml\`) ships and the operational **Gate** (release publish/promote) runs, then **Phase 3** enables the sow-topdata consumer. Do not enable the consumer against a channel whose current release predates \`part.yml\`.
Plan: \`sow-topdata/docs/superpowers/plans/2026-06-25-topdata-parts-autogen-channel.md\`
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Phase 2 of the parts-row autogen design: Crucible resolves parts 2DA rows
from the immutable part.yml published with the asset HAK release, over the
anonymous Bunny CDN channel, with the parts consumer required (no fail-open).
- generalize resolveCDNChannelManifest: derive manifest basename + provenance
label from config; drop hardcoded assets/vfxs.yml so part.yml resolves too
- add filterPartsCDNChannelEntries + mode dispatch implementing the inventory
contract (restype mdl under part/<cat>/, trailing-digit row id, dedup
l/r/race/gender variants, sort by source, zero accepted rows = hard fail)
- support hand category + parts/hand dataset mapping (12 datasets total)
- native pipeline: single augment -> normalize -> override sequence with the
configured parts_rows policy; overrides may update but never synthesize a row
- reject multiple parts_rows consumers in project validation
- tests: parts filter contract, category coverage, offline basename, orphan
override reject, and a parity guard proving a bare CDN-only parts build
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
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.
Phase 2 of the parts-row autogen design — Crucible (sow-tools) side only.
Resolves parts 2DA rows from the immutable `part.yml` published with the asset HAK release, over the anonymous Bunny CDN channel, with the parts consumer required (no fail-open).
Changes
Tests
9 new tests: parts filter contract, 12-dataset coverage, offline manifest-basename, orphan-override reject + discovered-row update, and a parity guard proving a bare CDN-only parts build needs no wrapper/token/NWN_ROOT/checkout.
Gate green: `go test ./internal/topdata/... ./internal/project/...` + full `go build ./... && go test ./...`.
Scope / ordering
Phase 2 is inert until Phase 1 (sow-assets-manifest publishes `part.yml`) ships and the operational Gate (release publish/promote) runs, then Phase 3 enables the sow-topdata consumer. Do not enable the consumer against a channel whose current release predates `part.yml`.
Plan: `sow-topdata/docs/superpowers/plans/2026-06-25-topdata-parts-autogen-channel.md`
🤖 Generated with Claude Code