PROCITY/docs/LANES/ROUND27_INSTRUCTIONS.md

218 lines
15 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# PROCITY — Round 27 lane instructions (from Fable, integrator)
Date: 2026-07-17 · **R26 wave-4 verdict: C and E landed the mint-id fence, and both wrote the
same honest headline — "the rule was the stale thing, not E's check."** C owned its stale §7.2a
squarely (second time a C contract line met a case written after it and another lane took the
red); E proved the fix is *stronger* than the rule it replaces (the easy green was dropping the
prefix check; instead the prefix is now a sourcing-scoped namespace fence). The epoch's four
holds now all trace to the same species — a rule meeting a case written before the case
existed — and all four were caught before they could lie. The system is working exactly as
designed.
**Open: F's wave-4 step 3.** The beta tag is one re-run away. Round 27 opens there, then closes
the epoch: **v5.0 — THE LIVE CRATE.**
## WAVE 0 — F tags the beta
`qa.sh --strict --matrix` (the 6/1/0 should flip to 7/0/0 — E's fence is in, C's line is law),
tag **`v5.0-beta`**, push. Nothing below starts until this lands.
## Then: v5.0 — THE LIVE CRATE (tier 2, per the ratified G3)
The charter's last rung, under John's binding A-then-B ruling: **read-live, sell-sandboxed**
`/reserve` and `/buy` stay ABSENT (not stubbed; a sandbox a config typo can flip isn't a
sandbox). The server enriches, never gates: every boot path, gate, and tag works with the
server dead. Scope honesty up front: if tier 2 proves bigger than one round, F holds and we
split — four holds have proven the pattern; nobody forces an epoch close.
## The ledger
1. **The read endpoints (G, on ultra — server-side).** G3 §4 as ratified: `GET
/godverse/v1/shop/<godverse_id>/stock` (items + `gone:[sku]` + etag) and `/crates` (the
rotation menu), read-only over the live POS, serving **metadata only** (covers stay static
tier-1 files — the API never serves the atlas). Monster Robot is the only real shop; that's
the point — one shop, live, true. Deterministic-where-possible discipline: same POS state →
same response (etag'd).
2. **The tier-2 reader (F, with C's seam).** Async enrichment at room build: on entering a
keyed real-sourced shop, the shell fires the stock read (timeout-guarded, etag-cached) and
the crate applies the `gone` list + live prices when the response lands — the dig NEVER
blocks on the network (charter risk #1). C: if the crate needs a post-build content-adjust
hook, that's your seam to publish (half-day rule); if the existing adapter re-read covers
it, say so and F wires direct. Server dead / unreachable / slow → tier 1 exactly, silently.
3. **The kill-the-server gate (F — the epoch's defining gate).** Three arms, all falsifiable:
boot server-up → live fields present (assert etag/`gone` consumed); **kill the server
mid-session** → next read degrades to tier 1 with ZERO console errors and no stutter
(frame-time measured across the failure); boot server-down → pure tier 1, byte-identical to
the beta behaviour. This is charter law #1 made a gate. It runs as its own smoke class —
server lifecycle is controlled by the gate itself, so the assertion is deterministic even
though live stock isn't.
4. **Sold-means-gone, sandboxed (F + G).** The server's `gone` list removes items from the
live crate read (a record sold IN THE REAL SHOP disappears from the game crate — that's the
GODVERSE magic, direction: real→game). In-game buys stay session-local per Option A. Assert
both directions of the sandbox: a real `gone` item never renders; a game buy never appears
in any server state (there's no verb to carry it — prove the absence).
5. **The v5 tour + money shot (F).** `docs/shots/release_v5/`: the crate walk — Musgrave Road
→ Monster Robot Party's frontage (B's mark visible) → the riffle with real covers → the
price sticker → the buy. Plus one mint-shop frame (the honest caption: plausible, not real)
and the `?classic=1` control. The R21 cluster-pose primitive poses the street frames.
6. **Docs freeze (all lanes, light).** A: CITY_SPEC v5 section (the tier ladder, sourcing,
the id-space fences, the manifest) + charter risk-list retired-or-carried, v4-style. E:
provenance v5-final (mint atlases + the licence line's story). C: LANE_C_PUB v5-frozen
marker. G: the G3 doc updated design→as-built. B/D: notes current; nothing else owed.
7. **The tag + the retro.** F: `qa.sh --strict --matrix` + the kill-the-server gate green →
tag **`v5.0`** → push. Then **Fable writes the epoch retro** (not a lane deliverable), and
the v6 conversation opens with John (the editor and multiplayer are still chartered; the
GODVERSE has more rungs — Option B's reservation upgrade is already chartered as v5.x).
## Laws
Charter v5 laws, all now with case law behind them · the vacuous-gate law · the id-namespace
fences (`sku_`/`mint_`, plan-id/godverse-id) · no golden moves expected this round (tier 2
touches no plan, no cache, no atlas bytes) · the offline law is THE gate this round, not a
footnote.
## WAVE-2 STATUS + F'S THREE LOAD-BEARING INPUTS (Fable, post-wave review)
*A/B/C/E/G are ALL IN. The beta tagged. What remains is F's close (#2 reader → #3 gate → #4
sandbox → #5 tour → #7 tag). The waves handed F three inputs that change the brief's letter —
build to THESE, not to my original wording:*
1. **C's seam ruling (§8): direct wire, no hook — but PICK-THEN-OMIT is law.** The naive wiring
(filter `pack.items`) RESHUFFLES the crate — C measured one sale changing 21 other records.
The reader draws from the stable full list and omits `gone` after: a crate with 3 sold shows
13, not a different 16. **Assert zero collateral in the gate** (sell one fixture record, the
other 119 identities unchanged). "Selling one record must remove one record, not re-stock
the shop."
2. **G's finding: `gone[]` has no subject in production.** The real POS has recorded no sale
since 2026-07-01 — 0 of crate 550's 120 records have ever sold, so a sold-means-gone assert
on live data passes vacuously forever. G built the remedy: **`make-fixture`** gives the gate
a subject. The gate MUST use it (vacuous-gate law — G flagged it before the gate could be
born blind).
3. **G's lifecycle is the kill switch:** `godverse_server.py start|stop|status` — the
kill-the-server gate drives it directly. The three fences are machine-enforced (read-only
credential measured permission-denied; `/reserve`+`/buy` → 501; metadata only, mint shops
404) — assert on them as fences, not re-derive them.
*Also for the record: E's freeze caught redhill_godverse missing from the towns roster for
three rounds (on disk, pinned, bootable by key — invisible only in B's selector; the one
consumer nobody gated). E owned it, fixed it, and wrote the gate-shape lesson. B verified the
R26 handshake against G's real manifest. A judged the risk list line-by-line and correctly
CARRIED risk #1 — "nothing retires this line except that gate going green."*
## WAVE-3 STATUS + TWO RATIFICATIONS (Fable, post-reader review)
*F's reader is IN (`39cfc3d`): pick-then-omit with `gone`/`price` applied IN PLACE (identity
and order preserved), fire-and-forget with a 1200 ms abort + circuit breaker, real-sourced
shops only. Browser-proven: 3 fixture sales → 0 collateral; server killed mid-session → 13.1 ms
enter, 14 ms worst frame gap, zero errors. Two F rulings are hereby RATIFIED as law:*
1. **Tier 2 is opt-in: `?live=1` / `?live=<url>`; absent → byte-identical to the beta.** F's
reasoning is the R26 lesson applied to a server — a default boot must never ask a question
that has no answer on machines that aren't John's. "Tier 2 is a place you go, not a thing
that happens to you." Auto-discovery is a v5.x question with a reachability contract.
2. **The collateral assertion is the canonical sold-means-gone gate.** "The gone item never
renders" cannot discriminate pick-then-omit from filter-the-array — both hide the record;
only COLLATERAL (the other 119 identities and order unchanged) tells them apart. Gates
assert collateral. (The vacuous-gate law's most precise application yet.)
**F's remaining close, in order:** formalize the browser proofs as the permanent smoke class
(#3's three arms + #4's both-directions sandbox, collateral-asserted, fixture-subject via
`make-fixture`) → the v5 tour (#5 — the crate walk, the mint-shop honest caption, the classic
control) → docs (#6 F-side: README v5 + the flags table gains `?live`) → `qa.sh --strict
--matrix` + the new smoke class → tag **`v5.0`** → push. Then Fable writes the epoch retro.
## WAVE-4 (Fable): two ratifications, one micro-task, and the tag path
**RATIFIED — F's §27 console-error ruling, and it is strictly stronger than the brief it
replaces.** The brief's "ZERO console errors on server death" (my wording, echoed in A's risk
line #1) is physically unachievable: a dead-host fetch logs `ERR_CONNECTION_REFUSED` at the
browser level where no `.catch()` reaches — to log zero, the reader would have to know the
server is dead without asking. One refusal is the irreducible cost of discovering death. The
ratified assertion: **zero errors from game code + EXACTLY ONE refused connection** — which
proves the circuit breaker, where "zero" could never distinguish a working breaker from a
broken one (both fail it). F filed this loudly as the beneficiary instead of relaxing it
quietly; that is the standard. (A: your risk-line wording is superseded by this record — a
one-line amendment at your leisure, not a blocker.)
**RATIFIED — the control-based frame assertion.** F's original `<250 ms` threshold passed
while measuring Lane C's room build and calling it network behaviour; the control (same walk,
breaker tripped, no network: 202 ms) exposed it, and the death's true cost is **Δ+2 ms**.
Assertions on frame cost are DELTAS AGAINST A CONTROL from here on, not absolute numbers —
the R21 lesson, now law for performance gates.
**THE MICRO-TASK — B: the frontage pose (F's filed ask).** F produced three frames of empty
road trying to re-derive your frontage anchor, then stopped — correctly (the cluster primitive
answers "where is the town's heart", and Red Hill's heart doesn't contain Monster Robot; a
frontage frame asks a different question). You own the frontage geometry, the R26 shopfront
mark, and the `poseForVenue` machinery: publish a pose helper or bookmark that frames a shop's
frontage BY LOT (keyed off `shop.lot` / godverseShopId — `poseForShopFront(shopOrId, dist)`),
verified on Monster Robot (mark visible, door centred, sleeves-through-glass a bonus). One
commit, B-pathspec. This also closes the gap for every future godverse tour frame.
**Then F closes:** the 4th frame through B's helper → full `qa.sh --strict --matrix` +
the (now-permanent, corrected) kill-the-server smoke class → tag **`v5.0`** → push. Fable's
retro follows.
## WAVE-5 (Fable): THE SPEC RULING — the facade is +Z, and the fifth hold stands
*B's micro-task found why F photographed empty road three times: it was never the pose.
`plan_osm.js:443` aims the lot's Z at the road (implementing CITY_SPEC:71); `buildings.js:404`
draws the facade on +Z (CITY_SPEC:335, B's canon). The spec contradicts itself; each generator
implemented one half; synthetic follows B's canon so every golden has been green over a wrong
product since R18 — v4.0 shipped on it. The epoch's signature species at its worst: not a gate
failing on correct behaviour, but a green suite over a wrong world.*
**THE RULING: the visible facade is LOCAL +Z. B's canon is canonical.** It has been the de
facto truth since v1 (buildings.js drew it there from the start; venue.js seats door-glow/
queue/posters there; A's own R15 write-up said "the visible venue face is +Z"). CITY_SPEC:71's
Z line described the SIM convention (rig-forward at ry=0) and got written into the lots
contract by ambiguity — the same Z/+Z species as R13's RY_FLIP and R15's posters, now at the
root. The spec amends so the lots contract states: **facade/door/frontage = local +Z**; the
sim/rig-forward convention is documented separately as the different thing it is.
**A — the fix, the sweep, the pins (ONE commit):**
1. Land B's proven one-liner in the real-roads seating (`ry = atan2(-nx,-nz)` — B measured
katoomba 0/72 → 72/72 facing and F's money shot works 4 m from Musgrave Road; B reverted it
because it's your file).
2. **Measure the marched-osm path for the same flaw** — don't assume it's clean because nobody
noticed; that's how this one survived nine rounds. State the verdict either way.
3. Amend CITY_SPEC:71 per the ruling, re-pin every moved golden (the 36 real-town pins move;
marched/synthetic only if your measurement says so), all in the same commit per the
amendment law.
4. **The cross-convention gate (the lesson made law):** the selfcheck gains an assert measured
in B's canon — every lot's +Z facade faces its frontEdge street side — so the two
conventions are compared AGAINST EACH OTHER forever, not each against its own spec line.
A self-consistent check over a self-contradicting spec passes under either convention;
only the cross-check sees it. (F proved this the hard way and recorded it.)
**F — then the close:** re-gate (the matrix against A's re-pins), re-shoot the tour (the
frontage frame through B's `poseForShopFront` — and `street_noon` on real towns, which has
been "46 draws of bare road" since R18, becomes a real street), `qa.sh --strict --matrix`,
tag **`v5.0`**, push.
**B — done, with honours:** the helper (door-centred by projection, `doorCentreNdcX = 0.0000`),
the selector extracted to ONE home (`'g:31'` — the id-namespace fence now has a single
resolver), the self-correction of your own R27 intel, and the discipline of proving A's fix
then reverting it. Nothing further owed.
## THE EXACT RUN ORDER
0. **WAVE 0: F re-runs and tags `v5.0-beta`.** Hard stop until it lands.
1. **Start together: G (#1 endpoints, on ultra) + C (#2 seam ruling: publish the hook or bless
the direct wire) + A/E (#6 docs prep — can run the whole round).**
2. **When G's endpoints are live on the tailnet and C's seam is ruled: F (#2 reader).**
3. **F (#3 kill-the-server gate + #4 sandbox proofs + #5 tour), then #7: tag `v5.0`, push.**
4. **Fable: the epoch retro.**
Waves: **[F-beta-tag] → [G, C, A+E] → [F reader] → [F gate/tour/tag] → [retro]**. B/D on-call.
## Standing
- **John — one infra FYI, nothing to decide:** the kill-the-server gate needs the thriftgod
server reachable from m3 over the tailnet AND stop/start control from the gate (G owns the
mechanism — a lifecycle endpoint or an ssh'd systemd unit, G's call; it's in-house infra
under existing access). Your A-then-B ruling continues to hold the write verbs absent.
- **v5.x / v6 preview (the retro decides, do not start):** Option B's reservation upgrade
(behind your hold budget) · more POS shops if monsterrobot ever gets siblings · the editor ·
multiplayer presence · the v4.x/v5.x polish tails.