From 50385c0f08273e79850b7e5aaf1a95a7fa46cab1 Mon Sep 17 00:00:00 2001 From: m3ultra Date: Sat, 18 Jul 2026 16:37:02 +1000 Subject: [PATCH] =?UTF-8?q?Lane=20F=20R31=20wave=201=20(v7.0-alpha=20close?= =?UTF-8?q?):=20THE=20DIG=20FLIP=20=E2=80=94=20the=20alpha-blocker=20Fable?= =?UTF-8?q?'s=20playtest=20found.=20DIG=5FON=20=3D=20flagOn('dig')=20(defa?= =?UTF-8?q?ult-ON,=20=3Fdig=3D0=20opt-out,=20=3Fclassic=3D1=20off=20?= =?UTF-8?q?=E2=80=94=20the=20v3.1=20pattern;=20the=20v2-era=20opt-in=20sur?= =?UTF-8?q?vived=206=20epochs=20past=20the=20README's=20'dig=20on'=20claim?= =?UTF-8?q?=20because=20every=20R30=20gate=20booted=20dig=3D1=20explicitly?= =?UTF-8?q?:=20the=20explicit-flag=20blindfold).=20Fenced=20forever:=20def?= =?UTF-8?q?ault=5Fboot=5Fgate=20asserts=20dig=20REACHABILITY=20on=20a=20NA?= =?UTF-8?q?KED=20boot=20(E=20at=20a=20bin=20=E2=86=92=20digActive=20true),?= =?UTF-8?q?=20classic=5Fregression=20asserts=20dig=20INERT=20at=20the=20bi?= =?UTF-8?q?n=20(zero=20pcdg=20DOM,=20measured=20not=20assumed).=20PROCITY.?= =?UTF-8?q?flags=20gains=20dig.=20Splash=20de-staled=20('Every=20door=20op?= =?UTF-8?q?ens.'=20=E2=80=94=20no=20more=20'(soon)';=20controls=20line=20c?= =?UTF-8?q?arries=20E=20riffle/sell=20=C2=B7=20C=20crate=20=C2=B7=20SLEEP?= =?UTF-8?q?=20to=20save)=20+=20README=20manual=20row=20(sell=20at=20counte?= =?UTF-8?q?r=20=C2=B7=20C=20crate=20=C2=B7=20SLEEP=20=3D=20save/advance/ro?= =?UTF-8?q?tate).=20PROCITY=5FQA=5FPORT=20env=20override=20(flags=5Fcheck,?= =?UTF-8?q?=20interior=5Fscale=5Fcheck,=20town=5Fmatrix)=20so=20the=20suit?= =?UTF-8?q?e=20runs=20port-isolated=20instead=20of=20silently=20reusing=20?= =?UTF-8?q?whatever=20holds=20:8130.=20Verified=20both=20ways=20on=20:8951?= =?UTF-8?q?=20(naked=20boot=20digs=20+=20closes=20clean;=20dig=3D0=20and?= =?UTF-8?q?=20classic=20zero=20dig=20DOM,=20classic=20ZERO=20storage=20cal?= =?UTF-8?q?ls;=20noassets=20digs=20parody,=200=20errors).=20qa.sh=20--stri?= =?UTF-8?q?ct=20--matrix=20on=20:8931:=207/0/0/0,=20flags=5Fcheck=200=20fa?= =?UTF-8?q?ils=200=20warns,=20MATRIX=2010=20towns=20green.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Fable 5 --- README.md | 1 + tools/flags_check.py | 60 +++++++++++++++++++++++++++++++- tools/qa/interior_scale_check.py | 4 +-- tools/qa/town_matrix.py | 4 +-- web/index.html | 17 ++++++--- 5 files changed, 76 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index 707aca5..2cbaa4c 100644 --- a/README.md +++ b/README.md @@ -23,6 +23,7 @@ Click **START** to lock the mouse. Then: | **W A S D** + mouse | walk / look (first person) | | walk into a shop door | enter the interior (open shops only — check the hours tooltip) | | **E** (inside a shop) | open the crate at a record bin — then it's cursor-driven: click sleeves to riffle, click BUY | +| **E** (at the counter) · **C** (street) · **SLEEP** (top bar) | sell a find to the keeper (always under what you paid) · open THE CRATE — your collection · sleep = save, the day advances, stock rotates | | click a book spine / toy box | pull-and-buy card (real price stickers in godverse shops) | | walk out the door / **Esc** | leave the shop (Esc also frees the mouse anywhere) | | **M** | 2D town map (street only) | diff --git a/tools/flags_check.py b/tools/flags_check.py index 99794c8..5f5bea3 100644 --- a/tools/flags_check.py +++ b/tools/flags_check.py @@ -24,7 +24,10 @@ except ImportError: "tools/.venv/bin/pip install playwright && tools/.venv/bin/python -m playwright install chromium") ROOT = pathlib.Path(__file__).resolve().parent.parent -PORT = 8130 +# [R31] PROCITY_QA_PORT: run the suite on an isolated port. The default (:8130) is also the house preview +# port — ensure_server() would silently REUSE a dev server already parked there, and a shared server is +# somebody else's cache semantics + somebody else's lifecycle. Gates want their own server or a named one. +PORT = int(os.environ.get('PROCITY_QA_PORT', '8130')) HOST = f'http://127.0.0.1:{PORT}' SEED = 20261990 GOLDEN_HASH = 0x5f76e76 # [R27w5] AMENDED. Was 0x3fa36874 "forever" since R16 — and that town @@ -173,6 +176,30 @@ def classic_regression(p): if state['winmap'] or state['digActive']: FAIL(f"a flipped/opt-in flag leaked into ?classic (winmap/dig): {state}") else: OK('flipped + opt-in flags off under ?classic (winmap/dig)') + # [R31 — THE DIG FLIP, classic side] dig is default-ON now, so classic's dig-lessness must be + # MEASURED at a bin, not inferred from an idle digActive (which is vacuously false on the street): + # enter a record shop, E aimed at a bin — the riffle must NOT open and ZERO dig DOM may exist + # (createDig is never constructed off-flag; the E falls through trySell(null game) + shelf no-op). + dug = pg.evaluate("""() => { + const P = window.PROCITY, D = window.DBG; D.setSegment(2); + const s = (P.plan.shops || []).find(x => x.type === 'record' && P.isOpen(x)); + if (!s) return { err: 'no open record shop' }; + D.enterShop(s.id); + const bins = []; P.interiorMode.current.group.traverse(o => { if (o.userData && o.userData.kind === 'bin') bins.push(o); }); + if (!bins.length) { D.exitShop(); return { err: 'no bins' }; } + const bp = new P.THREE.Vector3(); bins[0].getWorldPosition(bp); + P.camera.position.set(bp.x, 1.6, bp.z + 1.4); P.camera.lookAt(bp.x, bp.y + 0.4, bp.z); P.camera.updateMatrixWorld(); + window.dispatchEvent(new KeyboardEvent('keydown', { code: 'KeyE' })); + const opened = !!P.interiorMode.digActive; + const dom = document.querySelectorAll('[class^="pcdg"]').length; + D.exitShop(); + return { opened, dom }; + }""") + if dug.get('err'): WARN(f"?classic dig-inert leg unmeasured — {dug['err']}") + elif not dug['opened'] and dug['dom'] == 0: + OK('?classic dig INERT at the bin — E opened nothing, zero dig DOM (measured, not assumed)') + else: + FAIL(f"?classic dig LEAKED: E at a bin → opened={dug['opened']}, dig DOM nodes={dug['dom']}") if state['streamMode']: OK('R7 roster flip in effect — streamed roster ACTIVE under ?classic (the v2 baseline)') else: FAIL('roster flip REGRESSED — ?classic is not streaming (expected streamMode:true)') @@ -255,6 +282,37 @@ def default_boot_gate(p): OK(f"default-boot street budget @ venue block: {state['draws']} draws ≤ {STREET_DRAWS_MAX}, {state['tris']:,} tris ≤ {STREET_TRIS_MAX:,}") else: FAIL(f"default-boot street OVER budget @ venue block: {state['draws']} draws / {state['tris']:,} tris (Fable scope call — not silent-trim)") + # [R31 — THE DIG FLIP GATE] Fable's wave-0 playtest found the alpha-blocker this whole suite + # missed: every R30 game-loop gate booted `dig=1` EXPLICITLY (belt-and-braces that became a + # blindfold), so the suite was green while the NAKED boot's E did nothing at a bin — index.html + # still carried the v2-era opt-in. The gates tested the game; nobody tested that the default boot + # IS the game. So this gate now proves dig REACHABILITY with zero dig params: enter a record shop, + # E at an aimed bin, the riffle must open. Un-flip the default again and this line goes red. + f2 = state['flags'] or {} + if not f2.get('dig'): + FAIL(f"dig intent OFF on the naked boot (PROCITY.flags.dig falsy) — the R31 flip regressed: {f2}") + dug = pg.evaluate("""() => { + const P = window.PROCITY, D = window.DBG; D.setSegment(2); + const s = (P.plan.shops || []).find(x => x.type === 'record' && P.isOpen(x)); + if (!s) return { why: 'no open record shop' }; + D.enterShop(s.id); + const bins = []; P.interiorMode.current.group.traverse(o => { if (o.userData && o.userData.kind === 'bin') bins.push(o); }); + if (!bins.length) { D.exitShop(); return { why: 'no bins' }; } + const bp = new P.THREE.Vector3(); bins[0].getWorldPosition(bp); + P.camera.position.set(bp.x, 1.6, bp.z + 1.4); P.camera.lookAt(bp.x, bp.y + 0.4, bp.z); P.camera.updateMatrixWorld(); + window.dispatchEvent(new KeyboardEvent('keydown', { code: 'KeyE' })); + const opened = !!P.interiorMode.digActive; + const out = document.querySelector('.pcdg-out'); if (out) out.click(); + const closed = !P.interiorMode.digActive; + D.exitShop(); + return { opened, closed }; + }""") + if dug.get('opened') and dug.get('closed'): + OK('dig REACHABLE on the naked boot — E at a bin opened the riffle (and closed clean); the default boot IS the game') + elif dug.get('opened'): + WARN(f"naked-boot dig opened but close unconfirmed — {dug}") + else: + FAIL(f"THE DIG IS OFF ON A PLAIN BOOT — the R31 alpha-blocker is back: {dug}") if errs: FAIL(f"{len(errs)} console error(s) on the default boot; first: {errs[0][:140]}") else: OK('0 console errors on the default boot') finally: diff --git a/tools/qa/interior_scale_check.py b/tools/qa/interior_scale_check.py index 4d45a6c..ee3f754 100644 --- a/tools/qa/interior_scale_check.py +++ b/tools/qa/interior_scale_check.py @@ -24,10 +24,10 @@ Run: tools/.venv/bin/python tools/qa/interior_scale_check.py [--seed N] Setup: the same Playwright venv as tools/soak.py / tools/flags_check.py. Needs Lane B's window.DBG hook (?dbg=1) + window.PROCITY.interiorMode (Lane C/F). """ -import sys, time, socket, subprocess, pathlib +import sys, os, time, socket, subprocess, pathlib ROOT = pathlib.Path(__file__).resolve().parent.parent.parent -PORT = 8130 +PORT = int(os.environ.get('PROCITY_QA_PORT', '8130')) # [R31] port-isolated suite runs (see flags_check.py) HOST = f'http://127.0.0.1:{PORT}' SEED = 20261990 if '--seed' in sys.argv: diff --git a/tools/qa/town_matrix.py b/tools/qa/town_matrix.py index 6d3805b..f228240 100644 --- a/tools/qa/town_matrix.py +++ b/tools/qa/town_matrix.py @@ -16,10 +16,10 @@ Gates per town (all on the DEFAULT boot — gigs/weather/winmap/tram on, post-R1 Run: tools/.venv/bin/python tools/qa/town_matrix.py Needs the Playwright venv + Lane B's ?dbg=1 hook + Lane F's real-cache shell wiring (R17). """ -import sys, time, socket, subprocess, pathlib +import sys, os, time, socket, subprocess, pathlib ROOT = pathlib.Path(__file__).resolve().parent.parent.parent -PORT = 8130 +PORT = int(os.environ.get('PROCITY_QA_PORT', '8130')) # [R31] port-isolated suite runs (see flags_check.py) HOST = f'http://127.0.0.1:{PORT}' STREET_DRAWS_MAX, STREET_TRIS_MAX = 300, 200_000 # [R21 ledger #6c] B's R20 tram ruling: on a REAL-ROADS town the tram only runs if its best main chain diff --git a/web/index.html b/web/index.html index 8e8f6cc..c19bbb5 100644 --- a/web/index.html +++ b/web/index.html @@ -31,10 +31,10 @@

PROCITY

A procedurally generated, walkable 90s-Australian shopping town. - Every door opens (soon). Walk the strip, watch the day turn.
+ Every door opens. Dig the crates, sell the flips, sleep — the town remembers.
-
WASD move · shift run · mouse look · click a door · [ ] time of day · M map · P screenshot
+
WASD move · shift run · mouse look · click a door · E riffle a bin / sell at the counter · C your crate · SLEEP to save · [ ] time · M map