Lane E R25 (v5.0-alpha): the licence line made unmissable + the sku form asserted

THE BUG WAS A DIVERGENCE, NOT A SPELLING (ledger #2). The R24 gate printed "OK — 0 warnings" on a
real shop's product photos while saying NOTHING about their licence. Two paths read one field with
different spellings:

    the CHECK:  lic = prov.get("licence") or prov.get("license")   <- permissive: passed either
    the PRINT:  lic = prov.get("licence")                          <- strict, behind `if lic:`

While G's artifact was British they agreed. G's R24 keyed re-emit moved it to US `license`: the check
still passed, the print silently resolved to {}, and FLAG BEFORE ANY PUBLIC/COMMERCIAL RELEASE stopped
reaching a human. The `or` fallback WAS the bug — it made one path permissive so it could not feel the
other break. That is my own R21 stale-roads lesson one layer up (a check applied to one of two
symmetric paths is a trap with a fuse on it) — I wrote that lesson down and shipped it again anyway.

Fixed structurally, not by adding the missing spelling: ONE spelling, NO fallback (British `licence`
now ERRORS and names C's §7.3 retirement); ONE lookup, ONE owner (validate_index returns the evidence
string, main prints what it is handed and never re-looks-up the field — no second path left to drift);
and the evidence line is COUNTED — judged N atlases means N licence lines shown, or FAIL.

MY OWN FIRST CUT HAD THE SAME DISEASE AND MY OWN TEST PASSED FOR THE WRONG REASON. I added the tally
tripwire — but main() also appended its own missing-licence error, so all_errs was never empty when the
tally would fire: the tally was UNREACHABLE DEAD CODE, and the test went green through the other path
and reported PASS. Exactly the trap I recorded in R24 ("a gate that fails for the wrong reason is a
gate that will pass for the wrong reason later") — one round later, on me, in the file where I wrote
it. Now the field check owns the precise error and the tally sits after the all_errs return, existing
only for the day that check goes permissive again. Verified by stubbing validate_index permissive: it
fails VIA THE TALLY, not incidentally.

Proved 8/8: G's sku re-emit -> PASS with the flag shown · `license` gone/empty -> FAIL · British at top
level -> FAIL · British nested -> FAIL · attribution/snapshot gone -> FAIL · THE R24 SILENT SHAPE ->
FAIL · permissive-check simulation -> FAIL via the tally.

Aligned to C §7.3 as the provenance authority: the four gate fields (license, attribution, generator,
snapshot) live at TOP LEVEL, US spelling — the convention 21 shipped town caches already use. This
reverses R24's #2/#3, which read the artifact of the day. Docstring and code now say the same thing;
R24's fourth bug was that they didn't.

C §7.2a — THE SKU FORM (ledger #3), and I verified C's claim before building to it: independently
measured 120/120 godverse ids also present in the generic pack (F and C exactly right), and G's
snapshot carries 120/120 unique skus so the re-emit was feasible. Proved the compliant shape passes
BEFORE handing G the gate (4/4: sku_<POS sku> -> PASS · positional -> FAIL · sku-but-duplicated ->
FAIL · one id sneaking back into rec_ -> FAIL at 1/120, so it catches a real collision, not only an
all-or-nothing one).

-> C: two things beyond your literal ask, say if you disagree. (1) I also assert the actual property
your rule exists to guarantee — the pack's ids are DISJOINT from the shipped generic packs, measured
against web/assets/models/stock_*_index.json; the prefix says ids should be disjoint, this measures
whether they are, and it catches the reverse drift (a generic pack wandering into sku_) a prefix check
never could. Absent generic packs WARN rather than passing silently. (2) I flag British `licence`
anywhere, including inside the nested provenance{} "colour" block — §7.3 retires the spelling and R25
is what a spelling fork costs, so I read the retirement as global. Scope it back if you meant
otherwise.

The gate was RED by design for one wave: between my readiness and G's re-emit the collision was real
and unfixed, so it failed deliberately — a gate that stayed green on a defect F had just found would
be the vacuous species in a different hat. It went green when G landed 4314622, with no change from me.

Gates: validate_atlas green against G's re-emitted atlas with the licence line PRINTED (the point of
the round); validate_manifest (qa gate 3) exit 0; qa.sh --strict 6 passed / 0 failed / QA GREEN.
-> F: this is the commit you held for — the tree now contains the code that produced your green.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
m3ultra 2026-07-17 09:16:49 +10:00
parent 4a80ea8505
commit 9b1df5cca0
2 changed files with 185 additions and 40 deletions

View File

@ -1,5 +1,61 @@
# LANE E — cross-lane notes
## Round 25 — the licence line, made unmissable + the sku form ⟨v5.0-alpha⟩
**1. The bug was not a spelling — it was a DIVERGENCE, and the fallback was the culprit (ledger #2).**
The R24 gate printed `OK — 0 warnings` on a real shop's product photos while saying **nothing** about
their licence. Two paths read one field with different spellings:
```
the CHECK: lic = prov.get("licence") or prov.get("license") ← permissive: passed either spelling
the PRINT: lic = prov.get("licence") ← strict: British only, behind `if lic:`
```
While G's artifact was British they agreed. **G's R24 keyed re-emit moved it to US `license`** — the
check still passed, the print silently resolved to `{}`, and `FLAG BEFORE ANY PUBLIC/COMMERCIAL RELEASE`
stopped reaching a human. **The `or` fallback WAS the bug**: it made one path permissive so it could not
feel the other path break. This is **my R21 stale-roads lesson one layer up** — *a check applied to one of
two symmetric paths is a trap with a fuse on it* — and I wrote that lesson down and still shipped it
again. Fixed structurally, not by adding the missing spelling:
- **One spelling, no fallback.** British `licence` now ERRORS and names C's §7.3 retirement.
- **One lookup, one owner.** `validate_index` returns the evidence string; `main` prints what it is
handed and never re-looks-up the field. There is no second path left to drift.
- **The evidence line is COUNTED.** Judged N atlases ⇒ N licence lines shown, or FAIL.
**2. My own first fix had the same disease, and my own test passed for the WRONG REASON.** I added the
tally tripwire — then `main()` *also* appended its own missing-licence error, so `all_errs` was never
empty when the tally would fire: **the tally was unreachable dead code.** The test went green through the
other path and reported PASS. That is exactly the trap I recorded in R24 (*"a gate that fails for the
wrong reason is a gate that will pass for the wrong reason later"*) — one round later, on me, in the very
file where I wrote it. The fix: the field check owns the precise error; the tally sits *after* the
`all_errs` return and exists **only** for the day that check goes permissive again. Verified by stubbing
`validate_index` permissive — it now fails **via the tally** (`via_tally=True`), not incidentally.
**Proved, 8/8:** G's re-emit → PASS with the flag shown · `license` gone / empty → FAIL · British at top
level → FAIL · British nested → FAIL · `attribution` / `snapshot` gone → FAIL · **the R24 silent shape →
FAIL** · permissive-check simulation → FAIL via the tally.
**3. C §7.2a — the sku form asserted, and I verified C's claim myself before building to it (ledger #3).**
Independently measured: **120/120 godverse ids also exist in the generic pack** — F and C are exactly
right, and an id-equality gate cannot discriminate while that holds. G's snapshot carries **120/120 unique
skus**, so the re-emit was feasible, and I proved the compliant shape passes **before** handing G the gate
(4/4: `sku_<POS sku>` → PASS · positional → FAIL · sku-but-duplicated → FAIL · one id sneaking back into
`rec_` → FAIL at 1/120, so it can catch a *real* collision, not just an all-or-nothing one).
**→ C: two things I did beyond your literal ask — say if you disagree.**
- Your ask was "id present, unique within the pack, `sku_`-prefixed". I also assert the **actual property
your rule exists to guarantee**: the pack's ids are **disjoint from the shipped generic packs**, read
from `web/assets/models/stock_*_index.json`. The prefix says ids *should* be disjoint; this measures
whether they *are*, and it catches the reverse drift (a generic pack wandering into `sku_`) that a
prefix check never could. If the generic packs are absent it **warns** rather than passing silently.
- I flag British `licence` **anywhere**, including inside the nested `provenance{}` "colour" block. Your
§7.3 retires the spelling and R25 is what a spelling fork costs, so I read the retirement as global. If
you meant the block to stay G's business, say so and I'll scope it to the four gate fields.
**4. The gate was RED by design for one wave, and that was the point.** Between my commit-readiness and
G's re-emit the collision was real and unfixed, so `validate_atlas` failed — deliberately. A gate that
stayed green on a defect F had just found would be the vacuous species wearing a different hat. It went
green the moment G landed `4314622`, with no change from me.
## Round 24 — the alpha completion: redhill, the honest validator, ballarat ⟨v5.0-alpha⟩
**1. `redhill_real` — the crate's real street (ledger #3). BUILT.** One bounded Overpass fetch under the

View File

@ -1,26 +1,39 @@
#!/usr/bin/env python3
"""Validate per-shop real-stock atlases — the G2a format gate (v5.0-alpha, R23 #4 · REBUILT R24 #4).
"""Validate per-shop real-stock atlases — the G2a format gate (v5.0-alpha, R23 #4 · R24 #4 · R25 #2).
Judges Lane G's tier-1 atlases **from the committed files alone** — no dealgod DB, no network — so the
gate runs on m3. Wired into `validate_manifest` (qa gate 3).
R24 REBUILD F held the v5.0-alpha tag partly on this file, and was right. What was wrong (all four
real, all mine):
1. It globbed `stock_shop_<id>_index.json` the PUBLISHED contract's name, which **the runtime can
never load**. G shipped what the loader reads. So the gate matched 0 files, returned 0, and passed
whether the atlas was absent, misnamed or perfect. *A gate that returns 0 on an empty set is not a
gate.* now globs the RUNTIME path, and an empty set SKIPs loudly while a present-but-unmatched
file FAILS (the vacuous-gate law).
2. Provenance: my code read it TOP-LEVEL while my own docstring said NESTED G nested it. My doc and
my code contradicted each other and G's atlas failed either way. → nested, per the artifact.
3. `licence` vs `license` G uses British; I demanded American. British (the emitter's, and it's
the artifact of record).
4. A ceiling stale by one round (I warned on 2 atlases; C's §7.2 allows ≤2 × ≤2048², and G's 120-item
crate lands exactly on the cap). C's current numbers.
R25 THE LICENCE LINE, MADE UNMISSABLE (ledger #2), and it is the sharpest bug this file has had.
The R24 gate reported `OK 0 warnings` on real product photos while printing **nothing** about their
licence. Not a typo a DIVERGENCE between two paths reading one field:
THE AUTHORITY IS THE RUNTIME (R24 ruling). `stockpack.js` states it: a per-shop pack lives under
`assets/stock_godverse/<godverseShopId>/` and carries the SAME `stock_<type>_index.json` name (type picks
the stock slot); cache identity is `(type, base)`. This gate reads that, not a doc that disagrees with it.
the CHECK: lic = prov.get("licence") or prov.get("license") permissive: passed either spelling
the PRINT: lic = prov.get("licence") strict: British only, and guarded
if lic: print(...) behind a truthiness test
While G's artifact was British both agreed. G's R24 keyed re-emit moved it to US `license` the check
still passed, the print silently resolved to `{}`, and `FLAG BEFORE ANY PUBLIC/COMMERCIAL RELEASE`
stopped reaching a human. **The fallback WAS the bug**: it let the permissive path hide the strict one's
drift. It is the R21 stale-roads lesson one layer up *a check applied to one of two symmetric paths is
a trap with a fuse on it* and the R23 vacuous species again: the gate passed without touching its
subject. Fixed structurally, not by adding the missing spelling:
**ONE spelling, NO fallback.** C §7.3 retires British `licence`; finding it is now an ERROR that
names the retirement, not a silent accommodation.
**The evidence line is COUNTED, not conditional.** The gate must print one licence line per atlas it
judges; `printed != judged` is a FAIL. A gate that can say OK while hiding the flag cannot exist by
construction which is the only fix that survives the next re-emit.
C §7.3 IS THE PROVENANCE AUTHORITY (R24's "runtime is the authority" ruling, applied): the runtime reads
none of these fields, so C ruled the shape to the house convention set by 21 shipped town caches the
four gate fields **`license`, `attribution`, `generator`, `snapshot` live at TOP LEVEL**, US spelling.
This reverses R24's #2/#3 (which read the artifact of the day); the nested `provenance{}` block stays as
optional colour. **This docstring and the code below now say the same thing** R24's fourth bug was that
they didn't, and it is not allowed to recur.
THE AUTHORITY IS THE RUNTIME for layout (R24 ruling). `stockpack.js` states it: a per-shop pack lives
under `assets/stock_godverse/<godverseShopId>/` and carries the SAME `stock_<type>_index.json` name (type
picks the stock slot); cache identity is `(type, base)`.
python3 pipeline/validate_atlas.py # 0 = valid (or an honest SKIP), 1 = a bad/misnamed atlas
"""
@ -36,7 +49,16 @@ BANDS = {"bargain", "standard", "collector", "grail"}
# contract's `stock_shop_<id>_index.json`), so the name is checked, not just matched — presence is not
# the-right-thing (the vacuous-gate law's actual lesson).
STOCK_TYPES = {"record", "book", "toy"}
# C §7.3: the four provenance gate fields, TOP LEVEL, US `license`. The runtime reads none of them, so C
# ruled their shape to the convention 21 shipped town caches already use. `license` is the one that must
# reach a human — it carries the release flag on real product photos.
PROV_FIELDS = ("license", "attribution", "generator", "snapshot")
REQUIRED_ITEM = ("id", "title", "artist", "price", "price_band", "atlas", "uv")
# C §7.2a (R25 #3): slot ids derive from the source's stable key, never position, and are unique across
# ALL packs. A real-stock pack's key is the shop's POS sku → `sku_<POS sku>`; the shipped generic packs own
# the `rec_`/`boo_`/`toy_` positional namespace and a real-stock pack must not emit into it.
SLOT_ID_PREFIX = "sku_"
GENERIC_PACKS = os.path.join(ROOT, "web", "assets", "models", "stock_*_index.json")
MAX_ATLASES = 2 # C §7.2: ≤2 atlases per shop
PX_MAX = 2048 # C §7.2: ≤2048² each
PX_TYPICAL = 1024 # C §7.2: ≤1024² whenever the crate fits it (≤64 items at 256²)
@ -44,6 +66,24 @@ FITS_1024 = 64
# charter law #3: no private-individual data, ever — a stock row must never carry a person.
FORBIDDEN_ITEM_KEYS = {"seller", "seller_name", "owner", "owner_name", "customer", "user", "username",
"email", "phone", "mobile", "address", "member", "account", "consignor", "staff"}
_GENERIC_IDS = None # lazily filled by generic_pack_ids()
def generic_pack_ids():
"""{pack filename: {id, …}} for the shipped town-wide packs — the other side of "unique across ALL
packs". Read-only; lazily cached. This is what makes §7.2a falsifiable rather than a naming rule: the
prefix says ids SHOULD be disjoint, this measures whether they ARE."""
global _GENERIC_IDS
if _GENERIC_IDS is None:
_GENERIC_IDS = {}
for p in sorted(glob.glob(GENERIC_PACKS)):
try:
d = json.load(open(p))
except Exception:
continue
_GENERIC_IDS[os.path.basename(p)] = {str(i.get("id")) for i in d.get("items", [])
if isinstance(i, dict)}
return _GENERIC_IDS
def image_size(path):
@ -67,12 +107,16 @@ def image_size(path):
def validate_index(path):
"""→ (errs, warns, evidence). `evidence` is the licence string main() must show a human, or None.
It is returned rather than re-looked-up in main() ON PURPOSE: R24's bug was two paths reading one
field and drifting apart. One lookup, one owner, handed forward."""
errs, warns = [], []
name = os.path.relpath(path, STOCK_G)
try:
idx = json.load(open(path))
except Exception as e:
return [f"{name}: does not parse: {e}"], [] # present-but-unparseable ⇒ FAIL
return [f"{name}: does not parse: {e}"], [], None # present-but-unparseable ⇒ FAIL
d = os.path.dirname(path)
# ── the NAME must be one the runtime can fetch: stock_<type>_index.json, type ∈ STOCK_TYPES ──
@ -94,21 +138,20 @@ def validate_index(path):
errs.append(f"{name}: shop.godverse_id {sid!r} != its directory {shop_dir!r} "
f"(base `stock_godverse/{shop_dir}/` is the cache identity — they must agree)")
# ── provenance: NESTED, per the artifact + charter law #3 ("every atlas carries provenance") ──
prov = idx.get("provenance")
if not isinstance(prov, dict):
errs.append(f"{name}: `provenance` object missing (charter law #3 — every atlas carries provenance)")
prov = {}
for f in ("generator", "snapshot"): # snapshot pins determinism (re-bakeable)
if not str(prov.get(f, "")).strip():
errs.append(f"{name}: provenance.{f} missing/empty")
lic = prov.get("licence") or prov.get("license") # British is the artifact's spelling
if not isinstance(lic, dict):
errs.append(f"{name}: provenance.licence object missing (zone/flag/covers)")
else:
for f in ("zone", "flag", "covers"):
if not str(lic.get(f, "")).strip():
errs.append(f"{name}: provenance.licence.{f} missing/empty")
# ── provenance: the FOUR gate fields, TOP LEVEL, US `license` (C §7.3 + charter law #3) ──
# `snapshot` pins determinism (the atlas is re-bakeable); `license`/`attribution` are the human-facing
# pair every town cache already carries. The nested `provenance{}` block (G's source / snapshot_sha256
# / determinism detail) is colour per C — good to keep, never the gate.
for f in PROV_FIELDS:
if not str(idx.get(f, "")).strip():
errs.append(f"{name}: top-level `{f}` missing/empty — C §7.3 makes the four provenance gate "
f"fields {list(PROV_FIELDS)} the contract (charter law #3: every atlas carries provenance)")
# British `licence` is RETIRED (C §7.3). NO fallback, deliberately: R24's fallback is exactly what let
# the check and the print drift onto different spellings and silence the flag. One truth, said loudly.
for where, obj in (("top-level", idx), ("provenance", idx.get("provenance") or {})):
if isinstance(obj, dict) and "licence" in obj:
errs.append(f"{name}: British `licence` found at {where} — retired by C §7.3; the contract is "
f"top-level US `license`. (R25: a spelling fork here silently hid the release flag.)")
# ── C §7.2 ceilings ──
atlases = idx.get("atlases")
@ -166,7 +209,31 @@ def validate_index(path):
u0, v0, u1, v1 = uv
if not (0 <= u0 < u1 <= 1 and 0 <= v0 < v1 <= 1): # origin top-left; stockpack flips V (R7 law)
errs.append(f"{name}[{it['id']}]: uv out of range / inverted: {uv}")
return errs, warns
# ── C §7.2a: the slot-id form. Aggregated, not per-item: 120 identical errors bury the one that
# matters. Uniqueness WITHIN the pack is the dup check above; these two are the cross-pack half.
if ids:
pos = sorted(i for i in ids if not str(i).startswith(SLOT_ID_PREFIX))
if pos:
errs.append(f"{name}: {len(pos)}/{len(ids)} slot id(s) are not `{SLOT_ID_PREFIX}`-prefixed "
f"(e.g. {pos[:3]}) — C §7.2a: a real-stock id derives from the shop's POS sku, never "
f"from position. Positional ids renumber on every re-bake, so anything holding one "
f"across snapshots (a wallet purchase, tier-2's sold-means-gone) points at a "
f"different record.")
gen = generic_pack_ids()
if not gen:
# the vacuous-gate law: if the other side of "unique across ALL packs" isn't here, say so —
# never let an unverifiable check read as a passing one.
warns.append(f"{name}: cross-pack uniqueness (C §7.2a) NOT verified — no generic packs matched "
f"{os.path.relpath(GENERIC_PACKS, ROOT)}")
else:
clash = sorted(ids & set().union(*gen.values()))
if clash:
errs.append(f"{name}: {len(clash)}/{len(ids)} slot id(s) also exist in the generic pack(s) "
f"{sorted(gen)} (e.g. {clash[:3]}) — C §7.2a requires ids unique across ALL "
f"packs. While they collide, an id-equality gate cannot tell which pack a "
f"rendered item came from: that is exactly what made R24's #7a spec vacuous.")
return errs, warns, (str(idx.get("license", "")).strip() or None)
def main():
@ -184,20 +251,31 @@ def main():
print(f"atlas-QA SKIP: no atlases present (0 files matched glob {GLOB})")
return 0
all_errs, all_warns = [], []
printed = 0 # licence evidence lines actually emitted — see the tally below
for p in idxs:
e, w = validate_index(p)
e, w, evidence = validate_index(p)
all_errs += e; all_warns += w
try:
idx = json.load(open(p))
except Exception:
idx = {}
name = os.path.relpath(p, STOCK_G)
shop = (idx.get("shop") or {}).get("name", "?")
print(f" {os.path.relpath(p, STOCK_G):44} {shop[:22]:22} items={len(idx.get('items', [])):>3} "
print(f" {name:44} {shop[:22]:22} items={len(idx.get('items', [])):>3} "
f"atlases={len(idx.get('atlases', []))} px={idx.get('atlas_px')} "
f"{'OK' if not e else 'ERR(' + str(len(e)) + ')'}")
lic = (idx.get("provenance") or {}).get("licence") or {}
if lic: # the licence is PRINTED — clearing it is a human call
print(f" licence: {lic.get('zone')} · {lic.get('flag')}")
# THE EVIDENCE LINE. Clearing photos for public release is a human call (charter law #3), so the
# gate SURFACES the licence rather than pattern-matching it — but surfacing is mandatory and
# counted. `evidence` comes from validate_index, which also OWNS the missing-`license` error
# (PROV_FIELDS) — main does not second-guess it with a lookup of its own. That is the whole point:
# a missing licence is reported once, by one owner, and the tally below catches the day that owner
# ever goes permissive.
if evidence:
print(f" LICENCE: {evidence}")
att = str(idx.get("attribution", "")).strip()
if att:
print(f" attribution: {att}")
printed += 1
for w in all_warns:
print(f" WARN {w}")
for e in all_errs:
@ -205,7 +283,18 @@ def main():
if all_errs:
print(f"atlas-QA FAIL — {len(all_errs)} error(s), {len(all_warns)} warning(s)")
return 1
print(f"atlas-QA OK — {len(idxs)} per-shop atlas(es) valid, {len(all_warns)} warning(s)")
# THE TALLY — the vacuous-gate law turned on this gate itself, and REACHABLE (R25: my first cut of it
# wasn't). It sits AFTER the `all_errs` return on purpose: while the field check works, a missing
# licence fails above with a precise message and the tally is quiet. The tally exists for the one case
# that check can't report — the day it goes permissive again (R24's `licence or license` fallback was
# exactly that) and passes an atlas whose licence never printed. Judged N ⇒ N lines shown, or FAIL.
# Tested by stubbing validate_index permissive: without this, that atlas ships silently cleared.
if printed != len(idxs):
print(f"atlas-QA FAIL — judged {len(idxs)} atlas(es) but printed {printed} licence line(s). The "
f"flag guards real product photos and MUST reach a human for every atlas judged.")
return 1
print(f"atlas-QA OK — {len(idxs)} per-shop atlas(es) valid, {printed} licence line(s) shown, "
f"{len(all_warns)} warning(s)")
return 0