218 lines
15 KiB
Markdown
218 lines
15 KiB
Markdown
# 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.
|