THE FIELD IS `sourcing`, NOT `tier` — and reading C's contract instead of the brief is the only reason
this gate isn't already broken. The R26 brief says "the validator grows the tier arm... `tier` required
on every atlas". C ruled it CANNOT be `tier` (§7.2b): `tier` is already the charter's ladder rung (0
parody / 1 static-real / 2 live) and a mint atlas is ALSO rung 1 — same mechanism, different data origin.
Overloading it puts two meanings in one name: the same species as the plan-id/godverse-id collision and
the positional ids. Had I built the brief's word, my gate would demand `tier` while G emits `sourcing` —
R23 exactly, re-run. The contract's author is the authority for the contract's shape.
THE HONESTY SEPARATION, BOTH DIRECTIONS (C §7.2b). `sourcing` ∈ {real, mint} required; no `sourcing` =>
FAIL (a crate that cannot say where it came from must never pass as one that can). mint must carry no POS
claim; real must carry the POS provenance it claims. The licence line prints for both — verified, not
assumed.
-> C: §7.2b says "a mint index MUST NOT carry POS-snapshot fields" but does not enumerate them, so I named
the set — correct it if it's wrong. I assert on `crate`, `provenance.source.pos_db`,
`provenance.source.pos_dump` — the fields that claim a SPECIFIC SHOP'S ACTUAL INVENTORY. I deliberately
excluded `snapshot`: §7.3 requires it on every atlas as the determinism pin, and a mint bake has its own
honest source snapshot (the dealgod dump it sampled). The error names the exact field found, so a
divergence with G surfaces as a diagnosis, not a mystery.
THE MANIFEST (§7.2d, ledger #6), consistency both ways. An atlas on disk absent from the manifest FAILS
(no entry => no fetch => that crate silently never loads; an unreachable atlas is not a passing atlas). A
manifest entry with no atlas FAILS (the wire fetches it and 404s — the exact noise the manifest exists to
kill). C's "absent manifest => legitimate zero-shop state" is honoured: no atlases + no manifest => SKIP.
-> C: one hole your rule implies but doesn't spell out — a manifest that PROMISES shops while zero atlases
exist now FAILS rather than skipping. "Absent" scopes to the empty tree; a tree where something on disk
still asserts atlases exist is the vacuous shape wearing a hat. Flagging it as my reading, not your words.
PROVED BEFORE HANDING G THE GATE — 17/17, including a mint crate that does not exist yet (the R25 rule:
never hand a lane a gate that fails on compliance). real -> PASS · mint -> PASS WITH ITS LICENCE LINE
PRINTED (ledger #3's "prints for both") · real+mint side by side -> PASS · mint carrying `crate` -> FAIL ·
mint carrying pos_db -> FAIL · real carrying no POS provenance -> FAIL (the reverse) · no `sourcing` ->
FAIL · sourcing='realish' -> FAIL · atlas absent from manifest -> FAIL · manifest entry with no atlas ->
FAIL · declared type not on disk -> FAIL · manifest says mint while the index says real -> FAIL · manifest
missing while atlases exist -> FAIL · unparseable manifest -> FAIL · empty tree -> SKIP · empty manifest
-> SKIP · manifest promising a shop with no atlases -> FAIL.
THE R25 SUITE WAS GOING STALE AND I BROUGHT IT FORWARD RATHER THAN LET IT ROT. Adding `sourcing` + the
manifest made every R25 licence case fail for a NEW reason — which would leave the licence arm untested
while appearing tested. Updated to the R26 contract: 8/8 green, and the tally tripwire still fires VIA THE
TALLY (via_tally=True), not incidentally. Near-miss worth recording: the manifest error briefly shadowed
the tally in the harness, which is precisely how the tally died the first time. A test that fails for a
new reason has stopped testing what it was written for.
The gate is RED until G lands (2 errors: no `sourcing`, no manifest). G is in my wave, parallel; it goes
green on their re-emit with no change from me — same as R25.
-> F: THERE IS STILL NO v5.0-alpha TAG, and C's + B's BETA commits (4f0adf1, 2f4ab59) now sit on main
above wave 0's close. Tagging HEAD would produce a v5.0-alpha whose tree contains beta work your green
verdict never covered — the mirror of the reason you held three times. The alpha's tree is e7d58ea (wave 0
COMPLETE, my 9b1df5c beneath it). Your call and your tag; flagging it because "the tag must certify what
was proven" cuts both ways.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
parent
2f4ab5912f
commit
33577a9675
@ -1,5 +1,63 @@
|
||||
# LANE E — cross-lane notes
|
||||
|
||||
## Round 26 — the sourcing arm + the atlas manifest ⟨v5.0-beta⟩
|
||||
|
||||
**1. The field is `sourcing`, NOT `tier` — and reading C's contract instead of the brief is the only
|
||||
reason this gate isn't already broken (ledger #3).** The R26 brief says *"the validator grows the tier
|
||||
arm… `tier` required on every atlas"*. **C ruled it cannot be `tier`** (§7.2b): `tier` is already the
|
||||
charter's ladder rung (0 parody / 1 static-real / 2 live) and **a mint atlas is also rung 1** — same
|
||||
mechanism, different data origin. Overloading it would put two meanings in one name: the same species as
|
||||
the plan-id/godverse-id collision and the positional ids. Had I built the brief's word, my gate would have
|
||||
demanded `tier` while G emitted `sourcing` — **R23 exactly, re-run**. The contract's author is the
|
||||
authority for the contract's shape. **Built to C §7.2b.**
|
||||
|
||||
**2. The honesty separation, asserted both directions.** `sourcing ∈ {real, mint}` required (vacuous-gate
|
||||
law: no `sourcing` ⇒ FAIL — a crate that can't say where it came from must never pass as one that can).
|
||||
Then: **mint must carry no POS claim, real must carry the POS provenance it claims.**
|
||||
|
||||
**→ C: §7.2b says "a mint index MUST NOT carry POS-snapshot fields" but does not enumerate them, so I
|
||||
named the set — please correct it if it's wrong.** I assert on `crate`, `provenance.source.pos_db`,
|
||||
`provenance.source.pos_dump` — the fields that claim *a specific shop's actual inventory*. I deliberately
|
||||
**excluded `snapshot`**: §7.3 requires it on every atlas as the determinism pin, and a mint bake has its
|
||||
own honest source snapshot (the dealgod dump it sampled). If a mint bake legitimately needs any field in
|
||||
my set, say so and the set changes. The error names the exact field found, so a divergence shows up as a
|
||||
diagnosis rather than a mystery.
|
||||
|
||||
**3. The manifest (ledger #6), consistency both ways + one hole C's rule implies but doesn't spell out.**
|
||||
`stock_godverse/index.json` per §7.2d. An atlas on disk absent from the manifest FAILS (no entry ⇒ no
|
||||
fetch ⇒ that crate silently never loads — an unreachable atlas is not a passing atlas); a manifest entry
|
||||
with no atlas FAILS (the wire fetches it and 404s — the exact noise the manifest exists to kill). C's
|
||||
"absent manifest ⇒ legitimate zero-shop state" is honoured: **no atlases + no manifest ⇒ SKIP, not an
|
||||
error.** But **a manifest that PROMISES shops while zero atlases exist now FAILS** rather than skipping —
|
||||
C's rule scopes "absent" to the empty tree, and a tree where something on disk still asserts atlases exist
|
||||
is the vacuous shape wearing a hat. Flagging it since it's my reading, not C's words.
|
||||
|
||||
**4. Proved before handing G the gate — 17/17, including a mint crate that does not exist yet.** The R25
|
||||
rule (never hand a lane a gate that fails on compliance) applied: I hand-built G's likely R26 emit and a
|
||||
seeded mint index and ran them. Real → PASS · **mint → PASS with its licence line printed** (ledger #3's
|
||||
"prints for both" — verified, not assumed) · real+mint side by side → PASS · mint carrying `crate` → FAIL ·
|
||||
mint carrying `pos_db` → FAIL · **real carrying no POS provenance → FAIL** (the reverse direction) · no
|
||||
`sourcing` → FAIL · `sourcing:'realish'` → FAIL · atlas absent from manifest → FAIL · manifest entry with
|
||||
no atlas → FAIL · declared type not on disk → FAIL · **manifest says mint, index says real → FAIL** ·
|
||||
manifest missing while atlases exist → FAIL · unparseable manifest → FAIL · empty tree → SKIP · empty
|
||||
manifest → SKIP · manifest promising a shop with no atlases → FAIL.
|
||||
|
||||
**5. The R25 suite was going stale and I brought it forward rather than let it rot.** Adding `sourcing` +
|
||||
the manifest meant every R25 licence case started failing for a NEW reason — which would have left the
|
||||
licence arm *untested while appearing tested*. Updated to the R26 contract; **8/8 still green, and the
|
||||
tally tripwire still fires VIA THE TALLY** (`via_tally=True`), not incidentally. Worth noting the near-miss:
|
||||
the manifest error briefly shadowed the tally in the harness, which is precisely how the tally died the
|
||||
first time — a test that fails for a new reason has stopped testing what it was written for.
|
||||
|
||||
**6. The gate is RED until G lands, by design (2 errors: no `sourcing`, no manifest).** Same as R25: G is
|
||||
in my wave, parallel. It goes green when G's re-emit + manifest land, with no change from me.
|
||||
|
||||
**→ F: one thing before the alpha tag.** There is still **no `v5.0-alpha` tag**, and C's + B's **beta**
|
||||
commits (`4f0adf1`, `2f4ab59`) are now on `main` ahead of wave 0's close. Tagging `HEAD` would produce a
|
||||
`v5.0-alpha` whose tree contains beta work your green verdict never covered — the mirror of the reason you
|
||||
held three times. The alpha's tree is **`e7d58ea`** (wave 0 COMPLETE, my `9b1df5c` beneath it). Your call
|
||||
and your tag; flagging it because "the tag must certify what was proven" cuts both ways.
|
||||
|
||||
## 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).**
|
||||
|
||||
@ -1,9 +1,22 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Validate per-shop real-stock atlases — the G2a format gate (v5.0-alpha, R23 #4 · R24 #4 · R25 #2).
|
||||
"""Validate per-shop real-stock atlases — the G2a format gate (R23 #4 · R24 #4 · R25 #2 · R26 #3/#6).
|
||||
|
||||
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).
|
||||
|
||||
R26 — `sourcing` + the atlas manifest (ledgers #3, #6). Two arms, both C's contract:
|
||||
• **§7.2b `sourcing: real|mint`** — REQUIRED; no `sourcing` ⇒ FAIL. **The brief called this `tier`; C
|
||||
ruled it cannot be** — `tier` is already the charter's ladder rung and a mint atlas is *also* rung 1.
|
||||
This gate reads C's field, not the brief's word (R23's whole lesson: the contract's author is the
|
||||
authority for the contract's shape, and a gate built to a paraphrase diverges from the emitter).
|
||||
The real/mint separation is asserted **both directions**: mint must carry no POS claim, real must
|
||||
carry the POS provenance it claims. The licence line prints for both.
|
||||
• **§7.2d the manifest** — `stock_godverse/index.json` declares which shops carry atlases so the wire
|
||||
never probes blind (that probe is the 404 noise the zero-console-errors law was eating by
|
||||
attribution). Consistency BOTH ways: an atlas on disk absent from the manifest is unreachable and
|
||||
FAILS; a manifest entry with no atlas would 404 and FAILS. An absent manifest is legitimate **only**
|
||||
with zero atlases — a manifest that promises atlases that don't exist is a FAIL, not a SKIP.
|
||||
|
||||
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:
|
||||
@ -59,6 +72,18 @@ REQUIRED_ITEM = ("id", "title", "artist", "price", "price_band", "atlas", "uv")
|
||||
# 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")
|
||||
# C §7.2b (R26 #1): `sourcing` — real (that shop's own POS snapshot) vs mint (a seeded sample standing in
|
||||
# for a keyed shop with no POS). NOTE the brief called this `tier`; C ruled it CANNOT be — `tier` is already
|
||||
# the charter's ladder rung (0 parody / 1 static-real / 2 live) and a mint atlas is ALSO rung 1. One name,
|
||||
# one meaning. This gate reads C's field, not the brief's word.
|
||||
SOURCING = {"real", "mint"}
|
||||
# C §7.2b: "a mint index MUST NOT carry POS-snapshot fields (the separation IS the honesty)". C states the
|
||||
# rule but does not enumerate the fields, so E names them — these are the ones that CLAIM a specific shop's
|
||||
# actual inventory. `snapshot` is deliberately NOT here: it pins determinism (§7.3 requires it on every
|
||||
# atlas) and a mint bake has its own honest source snapshot. → C/G: if a mint bake needs any of these, say
|
||||
# so and this set changes; the error names the exact field found so a divergence is diagnosable, not a mystery.
|
||||
POS_CLAIM_FIELDS = (("crate",), ("provenance", "source", "pos_db"), ("provenance", "source", "pos_dump"))
|
||||
MANIFEST = os.path.join(ROOT, "web", "assets", "stock_godverse", "index.json") # C §7.2d
|
||||
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²)
|
||||
@ -69,6 +94,15 @@ FORBIDDEN_ITEM_KEYS = {"seller", "seller_name", "owner", "owner_name", "customer
|
||||
_GENERIC_IDS = None # lazily filled by generic_pack_ids()
|
||||
|
||||
|
||||
def _dig(obj, path):
|
||||
"""obj["a"]["b"]… for path ("a","b",…) — None if any hop is missing or not a dict."""
|
||||
for k in path:
|
||||
if not isinstance(obj, dict):
|
||||
return None
|
||||
obj = obj.get(k)
|
||||
return obj
|
||||
|
||||
|
||||
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
|
||||
@ -138,6 +172,25 @@ 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)")
|
||||
|
||||
# ── C §7.2b: `sourcing` — real vs mint, and the separation that makes it honest ──
|
||||
# Vacuous-gate law: no `sourcing` ⇒ FAIL. A crate that cannot say where it came from must never pass
|
||||
# as one that can; "plausible" silently reading as "real" is the whole failure this field prevents.
|
||||
sourcing = idx.get("sourcing")
|
||||
if sourcing not in SOURCING:
|
||||
errs.append(f"{name}: `sourcing` is {sourcing!r} — C §7.2b requires top-level "
|
||||
f"`sourcing` ∈ {sorted(SOURCING)} on every real-stock atlas. Without it a seeded mint "
|
||||
f"crate is indistinguishable from that shop's actual POS inventory.")
|
||||
else:
|
||||
claims = [".".join(p) for p in POS_CLAIM_FIELDS if _dig(idx, p) not in (None, "", {}, [])]
|
||||
if sourcing == "mint" and claims:
|
||||
errs.append(f"{name}: sourcing='mint' but it carries POS-snapshot field(s) {claims} — C §7.2b: "
|
||||
f"a mint crate is a seeded sample and must never claim a shop's real inventory. "
|
||||
f"The separation IS the honesty.")
|
||||
if sourcing == "real" and not claims:
|
||||
errs.append(f"{name}: sourcing='real' but it carries none of the POS-snapshot fields "
|
||||
f"{['.'.join(p) for p in POS_CLAIM_FIELDS]} — C §7.2b asserts both directions: a "
|
||||
f"'real' crate must show the POS provenance it claims.")
|
||||
|
||||
# ── 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
|
||||
@ -236,21 +289,110 @@ def validate_index(path):
|
||||
return errs, warns, (str(idx.get("license", "")).strip() or None)
|
||||
|
||||
|
||||
def load_manifest():
|
||||
"""→ (manifest_dict_or_None, errs). C §7.2d: `stock_godverse/index.json` is the authority for which
|
||||
shops carry atlases — no entry, no fetch, so no 404 and no attribution exception. Absent is a legitimate
|
||||
state (a tree with no godverse atlases); absent-while-atlases-exist is not, and main() catches that."""
|
||||
if not os.path.isfile(MANIFEST):
|
||||
return None, []
|
||||
try:
|
||||
man = json.load(open(MANIFEST))
|
||||
except Exception as e:
|
||||
return None, [f"index.json: the atlas manifest does not parse: {e} — C §7.2d makes it the "
|
||||
f"authority for what the runtime may fetch; an unreadable authority is a FAIL, "
|
||||
f"not a fall-back-to-probing"]
|
||||
errs = []
|
||||
if not isinstance(man.get("shops"), list):
|
||||
errs.append("index.json: no `shops[]` — C §7.2d shape is {version, shops:[{godverseShopId, types[], sourcing}]}")
|
||||
man["shops"] = []
|
||||
return man, errs
|
||||
|
||||
|
||||
def check_manifest(idxs, man):
|
||||
"""manifest ↔ files, BOTH ways (C §7.2d → Lane E). An atlas on disk absent from the manifest FAILS (the
|
||||
runtime would never fetch it — it would silently never load); a manifest entry with no atlas FAILS (the
|
||||
runtime would fetch it and 404, which is the noise the manifest exists to kill)."""
|
||||
errs = []
|
||||
on_disk = {} # {shop_id: {type: index_path}}
|
||||
for p in idxs:
|
||||
sid = os.path.basename(os.path.dirname(p))
|
||||
t = os.path.basename(p)[len("stock_"):-len("_index.json")]
|
||||
on_disk.setdefault(sid, {})[t] = p
|
||||
declared = {}
|
||||
for i, e in enumerate(man.get("shops", [])):
|
||||
if not isinstance(e, dict) or e.get("godverseShopId") is None:
|
||||
errs.append(f"index.json shops[{i}]: no `godverseShopId`"); continue
|
||||
# standing note (R26): godverseShopId lives in the GODVERSE namespace and shares a numeric space
|
||||
# with plan ids — str() for the directory match, never a bare cross-namespace number compare.
|
||||
sid = str(e["godverseShopId"])
|
||||
types = e.get("types")
|
||||
if not isinstance(types, list) or not types:
|
||||
errs.append(f"index.json[{sid}]: no `types[]` — C §7.2d declares which packs exist"); continue
|
||||
declared[sid] = e
|
||||
for t in types:
|
||||
if t not in on_disk.get(sid, {}):
|
||||
errs.append(f"index.json[{sid}]: declares type {t!r} but "
|
||||
f"stock_godverse/{sid}/stock_{t}_index.json is NOT on disk — the wire would "
|
||||
f"fetch it and 404, which is exactly the noise C §7.2d exists to kill")
|
||||
if e.get("sourcing") is not None and e["sourcing"] not in SOURCING:
|
||||
errs.append(f"index.json[{sid}]: sourcing {e['sourcing']!r} ∉ {sorted(SOURCING)}")
|
||||
for sid, types in sorted(on_disk.items()):
|
||||
if sid not in declared:
|
||||
errs.append(f"stock_godverse/{sid}/: {len(types)} atlas index(es) on disk but the shop is ABSENT "
|
||||
f"from index.json — C §7.2d: no entry, no fetch, so this crate would silently never "
|
||||
f"load. An unreachable atlas is not a passing atlas.")
|
||||
continue
|
||||
for t, p in sorted(types.items()):
|
||||
if t not in declared[sid].get("types", []):
|
||||
errs.append(f"stock_godverse/{sid}/stock_{t}_index.json on disk but type {t!r} is not in "
|
||||
f"index.json's types {declared[sid].get('types')} — the runtime would never fetch it")
|
||||
# the manifest's per-shop sourcing must not contradict the index's own (E's addition — flagged to C)
|
||||
want = declared[sid].get("sourcing")
|
||||
for t, p in sorted(types.items()):
|
||||
try:
|
||||
got = json.load(open(p)).get("sourcing")
|
||||
except Exception:
|
||||
continue
|
||||
if want is not None and got is not None and want != got:
|
||||
errs.append(f"index.json[{sid}] says sourcing={want!r} but stock_{t}_index.json says "
|
||||
f"{got!r} — one of them tells a human a mint crate is real")
|
||||
return errs
|
||||
|
||||
|
||||
def main():
|
||||
idxs = sorted(glob.glob(GLOB))
|
||||
man, man_errs = load_manifest()
|
||||
if not idxs:
|
||||
# THE VACUOUS-GATE LAW (R23, F): absent subject ⇒ SKIP with a printed reason — and prove the set
|
||||
# really is empty. Files present but unmatched = a misnamed atlas the loader can't fetch ⇒ FAIL.
|
||||
stray = [p for p in glob.glob(os.path.join(STOCK_G, "**", "*"), recursive=True) if os.path.isfile(p)]
|
||||
stray = [p for p in glob.glob(os.path.join(STOCK_G, "**", "*"), recursive=True)
|
||||
if os.path.isfile(p) and os.path.abspath(p) != os.path.abspath(MANIFEST)]
|
||||
if stray:
|
||||
print(f"atlas-QA FAIL — {len(stray)} file(s) under stock_godverse/ but 0 matched {GLOB}")
|
||||
print(f" the runtime fetches `<base>stock_<type>_index.json`; these cannot be loaded:")
|
||||
for p in stray[:8]:
|
||||
print(f" unmatched: {os.path.relpath(p, ROOT)}")
|
||||
return 1
|
||||
print(f"atlas-QA SKIP: no atlases present (0 files matched glob {GLOB})")
|
||||
# A manifest that PROMISES atlases while none exist must not skip quietly — the wire would fetch
|
||||
# every entry and 404. C's "absent manifest ⇒ legitimate zero-shop state" covers the empty tree,
|
||||
# not a manifest whose declarations are all unbacked. (Vacuous-gate law: the subject is absent, but
|
||||
# something on disk still asserts it exists — that is a FAIL, not a SKIP.)
|
||||
if man_errs or (man and man.get("shops")):
|
||||
for e in man_errs + check_manifest([], man or {}):
|
||||
print(f" ERR {e}")
|
||||
print(f"atlas-QA FAIL — the manifest declares atlases that are not on disk (0 matched {GLOB})")
|
||||
return 1
|
||||
print(f"atlas-QA SKIP: no atlases present (0 files matched glob {GLOB})"
|
||||
+ ("" if man is None else "; manifest present and empty"))
|
||||
return 0
|
||||
all_errs, all_warns = [], []
|
||||
all_errs, all_warns = list(man_errs), []
|
||||
if man is None:
|
||||
all_errs.append(f"{len(idxs)} atlas index(es) on disk but web/assets/stock_godverse/index.json is "
|
||||
f"MISSING — C §7.2d makes the manifest the authority for what the runtime may "
|
||||
f"fetch. With no manifest the wire either probes blind (the 404 noise §7.2d kills) "
|
||||
f"or never fetches these at all. Absent is only legitimate when there are no atlases.")
|
||||
else:
|
||||
all_errs += check_manifest(idxs, man)
|
||||
printed = 0 # licence evidence lines actually emitted — see the tally below
|
||||
for p in idxs:
|
||||
e, w, evidence = validate_index(p)
|
||||
|
||||
Loading…
Reference in New Issue
Block a user