Lane C R25: sku-derived slot ids — F's id-collision finding made structural (ledger #3)
One contract line, published first so G re-emits against it. §7.2a added. THE COLLISION, MEASURED: both packs number items positionally from zero, so all 120 godverse ids are also generic-pack ids — 120/120 overlap. An id-equality gate cannot discriminate which pack a rendered item came from; that is exactly why the brief's own #7a spec was vacuous. (The vacuous-gate law's first application broke the law — and my own R23 metric had the same disease.) THE RULE (§7.2a): items[].id MUST derive from the source's stable key, never from position, and MUST be unique across ALL packs. Real-stock packs: id = "sku_" + <POS sku> (G's snapshot already carries `sku` per item, e.g. 20260314070442 — it's just dropped at emit, so this is index-only). Generic packs keep rec_NNNN as their namespace; real-stock must not emit into it. TWO REASONS, and the second outlives the gate: 1. positional ids collide by construction (the 120/120 above) -> id-equality gates can't discriminate. Sku ids fix that permanently, now, at two atlases instead of fifty. 2. POSITION IS NOT IDENTITY: a positional id renumbers on every re-bake — sell one record out of crate 550 and rec_0050 silently becomes a different record. Anything holding an id across snapshots (a wallet purchase, a saved dig, a gate assertion, and above all tier-2's sold-means-gone) would point at the wrong item. The POS sku is stable because it is the shop's own identity for that copy (release_id identifies the pressing, not the copy). So this is also the identity tier-2 will need, bought now for free. SCOPE: index-only — no atlas bytes, no town cache, no goldens, no C code (id isn't read by the loader, §7.3; the dig/buy consumers and gates read it). -> G: re-emit with sku_ ids. -> E: assert the form (present, unique within pack, sku_-prefixed). Committed by explicit pathspec — F's six staged files sit untouched, as its session left them. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
parent
2c1ae37160
commit
0d8d59a22a
@ -3,7 +3,39 @@
|
|||||||
*Status: **v1 complete & verified**. Standalone interiors library + test page. Every shop door opens
|
*Status: **v1 complete & verified**. Standalone interiors library + test page. Every shop door opens
|
||||||
into a unique, seeded, themed interior, generated on demand in ~4ms, byte-identical every revisit.*
|
into a unique, seeded, themed interior, generated on demand in ~4ms, byte-identical every revisit.*
|
||||||
|
|
||||||
Last updated: 2026-07-17 (round 24) · owner: PROCITY-C · reviewer: Fable
|
Last updated: 2026-07-17 (round 25) · owner: PROCITY-C · reviewer: Fable
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Update 2026-07-17 (round 25, the tag earned) — sku-derived slot ids (ledger #3, C's one line)
|
||||||
|
|
||||||
|
R25 §Lane C: one contract line, published first so G re-emits against it. **§7.2a added** — F's id-collision
|
||||||
|
finding made structural, while there are two atlases to migrate instead of fifty.
|
||||||
|
|
||||||
|
**The collision, measured:** both packs number items positionally from zero, so **all 120 godverse ids are
|
||||||
|
also generic-pack ids — 120/120 overlap.** An id-equality gate cannot discriminate which pack a rendered
|
||||||
|
item came from; that's exactly why the brief's own #7a spec was vacuous. (The vacuous-gate law's first
|
||||||
|
application broke the law — and my own R23 metric had the same disease. It's a persistent species.)
|
||||||
|
|
||||||
|
**The rule (§7.2a):** `items[].id` MUST derive from the source's stable key, never from position, and MUST
|
||||||
|
be unique across ALL packs. Real-stock packs: **`id = "sku_" + <POS sku>`** — G's snapshot already carries
|
||||||
|
`sku` per item (e.g. `20260314070442`), it's just dropped at emit, so this is index-only. Generic packs keep
|
||||||
|
`rec_NNNN` as their namespace; real-stock must not emit into it.
|
||||||
|
|
||||||
|
**I gave it two reasons, and the second is the one that outlives the gate.** The collision is the presenting
|
||||||
|
symptom. The deeper defect is that **position is not identity**: a positional id renumbers on every re-bake,
|
||||||
|
so selling one record out of crate 550 silently makes `rec_0050` a *different* record. Anything holding an
|
||||||
|
id across snapshots — a wallet purchase, a saved dig, a gate assertion, and above all **tier-2's
|
||||||
|
sold-means-gone** — would point at the wrong item. The POS sku is stable because it's the shop's own
|
||||||
|
identity for that copy (`release_id` identifies the pressing, not the copy). So this line isn't only a gate
|
||||||
|
fix; it's the identity tier-2 will need, bought now for free.
|
||||||
|
|
||||||
|
**Scope kept honest:** index-only, no atlas bytes, no town cache, no goldens. `id` isn't read by the loader
|
||||||
|
(§7.3) — the dig/buy consumers and the gates read it, so no C code changes. **→ G:** re-emit with `sku_`
|
||||||
|
ids. **→ E:** assert the form (present, unique within the pack, `sku_`-prefixed for real-stock).
|
||||||
|
|
||||||
|
*Process note:* F's six files were staged in the shared tree mid-flight; committed by explicit pathspec, so
|
||||||
|
F's session is untouched.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
@ -12,6 +12,9 @@
|
|||||||
> held F's tag. §7 now states what `stockpack.js` actually implements, extended per-shop, and the
|
> held F's tag. §7 now states what `stockpack.js` actually implements, extended per-shop, and the
|
||||||
> `type+base` cache keying is landed. **G's R23 atlas layout is ratified** (G re-emits provenance field
|
> `type+base` cache keying is landed. **G's R23 atlas layout is ratified** (G re-emits provenance field
|
||||||
> names only, §7.3). §0–§6 unchanged.
|
> names only, §7.3). §0–§6 unchanged.
|
||||||
|
> **v5.0-alpha amendment (2026-07-17, R25 ledger #3):** **§7.2a added — slot ids must be sku-derived,**
|
||||||
|
> unique across packs and stable across re-emits (F's id-collision finding, made structural). Index-only;
|
||||||
|
> no atlas bytes, no goldens. §0–§6 unchanged.
|
||||||
|
|
||||||
*The district ships **three** venue archetypes behind `?gigs=1` — `pub`, `band_room`, `rsl`. Lane A
|
*The district ships **three** venue archetypes behind `?gigs=1` — `pub`, `band_room`, `rsl`. Lane A
|
||||||
converts a chosen shop to a venue kind in place (`shop.type = kind`); C keys the interior recipe off
|
converts a chosen shop to a venue kind in place (`shop.type = kind`); C keys the interior recipe off
|
||||||
@ -257,6 +260,32 @@ The loader is `preloadStockPack(type, { base })` → it fetches **`<base>stock_<
|
|||||||
- **`uv: [u0,v0,u1,v1]`, origin TOP-LEFT** — the loader flips V itself (`uvRect`). Do not pre-flip.
|
- **`uv: [u0,v0,u1,v1]`, origin TOP-LEFT** — the loader flips V itself (`uvRect`). Do not pre-flip.
|
||||||
- Read by the dig/buy consumers (not by the loader): **`id`, `title`, `artist`, `price`, `price_band`**.
|
- Read by the dig/buy consumers (not by the loader): **`id`, `title`, `artist`, `price`, `price_band`**.
|
||||||
|
|
||||||
|
### 7.2a Slot ids — unique across packs, stable across re-emits (v5.0-alpha, R25 ledger #3)
|
||||||
|
**Rule: `items[].id` MUST derive from the source's own stable key — never from position — and MUST be
|
||||||
|
unique across ALL packs.** For a real-stock (godverse) pack that key is the shop's POS sku:
|
||||||
|
**`id = "sku_" + <POS sku>`** (e.g. `sku_20260314070442`; G's snapshot already carries `sku` per item, it's
|
||||||
|
just dropped at emit). The shipped generic packs keep `rec_NNNN` as their namespace — **a real-stock pack
|
||||||
|
must not emit into it.**
|
||||||
|
|
||||||
|
**Why — two reasons, both measured:**
|
||||||
|
1. **Positional ids collide by construction.** Both packs number from zero, so **all 120 godverse ids are
|
||||||
|
also generic-pack ids — 120/120 overlap (measured R25)**. An id-equality gate therefore cannot
|
||||||
|
discriminate which pack a rendered item came from: that is what made the brief's own #7a spec vacuous.
|
||||||
|
F caught it and replaced it with title-sets + texture-URL provenance (now the canonical honest-gate
|
||||||
|
pattern for stock). Sku ids make id-equality discriminating again — permanently, and while there are
|
||||||
|
two atlases to migrate instead of fifty.
|
||||||
|
2. **Position is not identity — and this one outlives the gate.** A positional id renumbers on every
|
||||||
|
re-bake: sell one record out of crate 550 and `rec_0050` silently becomes a *different* record. Anything
|
||||||
|
holding an id across snapshots — a wallet purchase, a saved dig, a gate assertion, and above all
|
||||||
|
**tier-2's sold-means-gone** — would then point at the wrong item. The POS sku is stable precisely
|
||||||
|
because it is the shop's own identity for that record: the same principle that makes `godverseShopId`
|
||||||
|
the POS shop id. *(`release_id` identifies the pressing, not the copy — the sku is the copy.)*
|
||||||
|
|
||||||
|
**Scope: index-only.** `id` is not read by the loader (§7.3) — the dig/buy consumers and the gates read it.
|
||||||
|
**No atlas bytes, no town cache, no golden moves.**
|
||||||
|
**→ Lane E:** assert the form — `id` present, **unique within the pack**, and `sku_`-prefixed for
|
||||||
|
real-stock packs.
|
||||||
|
|
||||||
### 7.3 Fields the runtime IGNORES — and the provenance ruling (the drift dies here)
|
### 7.3 Fields the runtime IGNORES — and the provenance ruling (the drift dies here)
|
||||||
`version`, `atlas_px`, `cell`/`cell_w`/`cell_h`, `count`, `kind`, `tier`, `shop`, `crate`,
|
`version`, `atlas_px`, `cell`/`cell_w`/`cell_h`, `count`, `kind`, `tier`, `shop`, `crate`,
|
||||||
`provenance` — **`stockpack.js` reads none of them.** So the authority for their shape is not C's
|
`provenance` — **`stockpack.js` reads none of them.** So the authority for their shape is not C's
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user