From 0b858abc9ddb7550a4771aa2ae008090054b46f3 Mon Sep 17 00:00:00 2001 From: type-two Date: Sat, 18 Jul 2026 17:32:27 +1000 Subject: [PATCH 1/4] =?UTF-8?q?Lane=20D=20S14:=20site=5F03=5Fswing=5Flawn?= =?UTF-8?q?=20=E2=80=94=20the=20site=5F03=20candidate,=20authored=20cold?= =?UTF-8?q?=20in=20the=20editor?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Gate 3.2. Data only; inert until a week.js NIGHTS entry names it. SCORE IT (storm_03_southerly, funnel ON, 11 anchors, 82.5 s): WINNABLE at $80 — 81 quads in band, 11 clean, 16 marginal. Cheapest honest line h3,t2,t2b,p1 at $65. Bare bed 83.7 FULL, best clean 90.0, separation +6.3 HP. The best-READING line is MARGINAL at 91.8 — the prettiest number in the yard is the one that breaks. Collateral exposure $230 on an $80 job. Co-Authored-By: Claude Fable 5 --- web/world/data/sites/site_03_swing_lawn.json | 228 +++++++++++++++++++ 1 file changed, 228 insertions(+) create mode 100644 web/world/data/sites/site_03_swing_lawn.json diff --git a/web/world/data/sites/site_03_swing_lawn.json b/web/world/data/sites/site_03_swing_lawn.json new file mode 100644 index 0000000..0ecad33 --- /dev/null +++ b/web/world/data/sites/site_03_swing_lawn.json @@ -0,0 +1,228 @@ +{ + "id": "site_03_swing_lawn", + "name": "The Delaneys' back lawn", + "blurb": "Swing set, big jacaranda, house right there — you'll have no trouble finding something to tie to.", + "_design": [ + "THE YARD WHERE THE GOOD STEEL IS ALL LOW AND THE ONLY HEIGHT IS BAD.", + "Three temptations, three different lies:", + " - the swing set's crossbar is a dead-level rail at 2.05 m spanning 2.3 m and is NOT", + " an anchor (tie_off:false). The two apexes beside it are honest steel but only 0.45,", + " and blowing one bills $140.", + " - the jacaranda forks low and excellent (0.95) then falls off a cliff (0.52 / 0.40).", + " A sail wants height on its high corner; on this tree height costs 58%, against 24%", + " up a gum. That is the \"which tree\" question, and it is the whole reason t2 exists.", + " - the house fascia is the familiar 0.35 lie and takes the $90 gutter with it.", + "The only 0.90+ steel in the yard is one post (p1, 0.90) and the jacaranda's LOW fork", + "(0.95). Four corners, two good ones - that is the puzzle.", + "The gum t2 (1.00 / 0.88) is parked 9 m away in the south-west ON PURPOSE: excellent", + "steel on the wrong side, so reaching for it costs you span and shape rather than", + "rating. The audit's cheapest honest line (h3,t2,t2b,p1) goes and gets it.", + "WIND: the venturi is the gap between the shed and the west end of the house - real", + "geometry, not a heading. The slot runs north-south so axis = 90 deg; gain 1.4, r 5.", + "It bites the RIGGING ZONE and not the bed: the throat sits 3.0 m from the swing set's", + "apexes, so the tempting middle option is also the windy one. Deliberately gentler than", + "the corner block (align 62%, peak x1.28 against its 100% / x1.46) - that yard keeps", + "the crown for worst weather and worst bill." + ], + "_why": [ + "Authored COLD in the yard editor for Sprint 14 gate 3.2 - no JSON hand-editing, no", + "console. Every number below is B's SCORE IT card, storm_03_southerly, funnel ON,", + "11 anchors dressed, one run of 82.5 s.", + " WINNABLE at $80 - 81 quads in band, 11 clean, 16 marginal.", + " cheapest honest line h3,t2,t2b,p1 - $65 hardware (holds at $55), 22 m2,", + " garden 85.3 FULL, worth +1.6 HP over bare.", + " held vs bare (flown) bare 83.7 FULL; best clean h3,t1c,t2,p1 -> 90.0 FULL;", + " separation +6.3 HP; by hail / rain 6.8 / 3.1.", + " THE TRAP, MEASURED the best-READING line t1c,t2b,s1_f2 is MARGINAL - 91.8 FULL", + " on paper, inside the 15% band. The prettiest number in the", + " yard is the one that breaks.", + " margin flags t2b 0% headroom; t1, t1b, p1, s1_f1 all 1%. s1_f1 wrecks the", + " swing set ($140), and the card prices it.", + " collateral exposure gutter $90 + swing set $140 = $230 if all lost, on a $80 job.", + "No `separation` block: the editor has no field for one, and B's own card says a", + "shipping site should pin one. Filed to A/B in THREADS rather than hand-edited in.", + "The bare bed reads 83.7 FULL, which is the bare-beds-win pool item showing up on a", + "third yard - gate-4 material, not this yard's doing and not tuned here." + ], + "yard": { + "width": 24, + "depth": 16 + }, + "sun": { + "elevationDeg": 55, + "azimuthDeg": -125 + }, + "gardenBed": { + "x": 0, + "z": 0, + "w": 5, + "d": 3.5 + }, + "house": { + "model": "house_yardside_v1", + "wreckedModel": "house_yardside_wrecked_v1", + "collateralKey": "gutter", + "collateralValue": 90, + "collateralLabel": "the gutter", + "x": 0, + "z": -6, + "anchors": [ + { + "id": "h1", + "node": "fascia_anchor_01", + "type": "house", + "work": "bracket" + }, + { + "id": "h2", + "node": "fascia_anchor_02", + "type": "house", + "work": "bracket" + }, + { + "id": "h3", + "node": "fascia_anchor_03", + "type": "house", + "work": "bracket" + } + ] + }, + "structures": [ + { + "id": "s1", + "model": "swing_set_01_v1", + "wreckedModel": "swing_set_01_wrecked_v1", + "x": -5, + "z": -2, + "rotYDeg": 0, + "solid": false, + "collateralKey": "swing_set", + "collateralValue": 140, + "collateralLabel": "the swing set", + "anchors": [ + { + "id": "s1_f1", + "node": "frame_anchor_01", + "type": "swing_frame", + "work": "cloth" + }, + { + "id": "s1_f2", + "node": "frame_anchor_02", + "type": "swing_frame", + "work": "cloth" + } + ] + } + ], + "trees": [ + { + "id": "t1", + "model": "tree_jacaranda_01_v1", + "x": 4.971, + "z": 2, + "phase": 1.1, + "trunkH": 3.4, + "anchorY": 2.4, + "anchors": [ + { + "id": "t1", + "node": "branch_anchor_01", + "type": "tree", + "work": "cloth" + }, + { + "id": "t1b", + "node": "branch_anchor_02", + "type": "tree", + "work": "cloth" + }, + { + "id": "t1c", + "node": "branch_anchor_03", + "type": "tree", + "work": "cloth" + } + ] + }, + { + "id": "t2", + "model": "tree_gum_02_v1", + "x": -8.5, + "z": 5.5, + "phase": 1.7, + "trunkH": 3.8, + "anchorY": 3.1, + "anchors": [ + { + "id": "t2", + "node": "branch_anchor_01", + "type": "tree", + "work": "cloth" + }, + { + "id": "t2b", + "node": "branch_anchor_02", + "type": "tree", + "work": "cloth" + } + ] + } + ], + "posts": [ + { + "id": "p1", + "x": 3.5, + "z": -2.5, + "h": 4, + "type": "post", + "work": "cloth" + } + ], + "fence": { + "sides": [ + "north", + "south", + "east", + "west" + ] + }, + "shed": { + "model": "shed_01_v1", + "x": -9, + "z": -5, + "rotYDeg": -90 + }, + "shedTable": { + "model": "shed_table_v1", + "x": 3.321, + "z": 7.753, + "rotYDeg": -90, + "pickupNode": "pickup_anchor" + }, + "gnome": { + "model": "garden_gnome_01_v1", + "x": 7.08, + "z": 6.344, + "rotYDeg": 0, + "collateralValue": 25 + }, + "bike": { + "model": "bike_kid_01_v1", + "x": -6, + "z": 5, + "rotYDeg": 180 + }, + "wind": { + "venturi": [ + { + "x": -6.22, + "z": -4.77, + "axis": 1.571, + "gain": 1.4, + "radius": 5, + "sharp": 3 + } + ] + } +} From 0414d34b9ec2aeb5b56f6312e7df5d2f494a7e3b Mon Sep 17 00:00:00 2001 From: type-two Date: Sat, 18 Jul 2026 17:45:13 +1000 Subject: [PATCH 2/4] =?UTF-8?q?Lane=20D=20S14:=20THREADS=20=E2=80=94=20gat?= =?UTF-8?q?e=203.2=20cold=20authoring=20pass,=20and=20the=20palette=20ship?= =?UTF-8?q?s=20both=20new=20props=20inert?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Headline for A: editor.js palette entries 239/243/257/260 omit the _v1 suffix every other entry carries, so swing_set_01 and tree_jacaranda_01 404, never draw, and adopt at ratingHint 1.00 instead of E's designed 0.45 and 0.95/0.52/0.40. adoptAnchor's `rating_hint ?? 1` turns a missing model into the best steel in the game, and the palette writes the bad name into the exported site JSON. Negative- controlled both directions on a local patch; editor.js untouched on lane/d. Also: site_03 candidate authored, scored (82.5 s, winnable at $80, 11 clean of 81) and played (trap bites: t1c breaks, 83.9 vs a bare 83.7). Phantom sail verified dead across a live site transition. Friction filed by owner; three candidate findings checked and withdrawn. Selftest 406/0/0. Co-Authored-By: Claude Fable 5 --- THREADS.md | 199 +++++++++++++++++++ web/world/data/sites/site_03_swing_lawn.json | 6 +- 2 files changed, 204 insertions(+), 1 deletion(-) diff --git a/THREADS.md b/THREADS.md index 20f0066..f26de98 100644 --- a/THREADS.md +++ b/THREADS.md @@ -6529,3 +6529,202 @@ anchors are your GLB), but the tooling is now waiting, not TODO. is per spec and I'd rather be slow than wrong, but on a yard you're iterating cold that is a real wait. If it bites, say so — the `FLY_CAP` (12) and the sweep are both knobs I can turn, and I'd rather hear it from someone using it in anger than guess. + +[D] 2026-07-18 — 🏡 **GATE 3.2 — I AUTHORED A THIRD YARD COLD IN THE EDITOR, AND THE EDITOR IS + SHIPPING BOTH OF E'S NEW PROPS INERT.** Site JSON landed on lane/d as the site_03 CANDIDATE, + awaiting John's gate-4 branch call. Selftest **406/0/0** on my tree with it landed. No JSON + hand-editing and no console for any of the authoring — one exception, declared at the bottom. + + **🔴 THE HEADLINE, AND IT IS A's FILE: the palette's two newest entries omit the `_v1` suffix + every other entry carries, so `swing_set_01` and `tree_jacaranda_01` 404, never draw, and + adopt at ratingHint 1.00.** Found in the first ten minutes of placing. + + · **Receipt, from the network log:** `GET /web/world/models/swing_set_01.glb → 404 File not + found`. The shipped asset is `swing_set_01_v1.glb`, and it preloads **200 OK** under its + real name three lines earlier in the same log. Same for `tree_jacaranda_01`. + · **Source:** `editor.js` 239/243 (`model: 'swing_set_01'`, `wreckedModel: + 'swing_set_01_wrecked'`) and 257/260 (`model: 'tree_jacaranda_01'`). The other nine palette + entries all carry `_v1`. (`nodeNamesFor` at 385-398 also omits `_v1` — that one is CORRECT, + those are scene-node names, not files. I checked before filing.) + · **Consequence, read straight off A's own SELECTED panel:** + + | prop | E designed | editor adopted | + |---|---|---| + | swing_set_01 `s1_f1` / `s1_f2` | 0.45 / 0.45 | **1.00 / 1.00** | + | tree_jacaranda_01 `t1` / `t1b` / `t1c` | 0.95 / 0.52 / 0.40 | **1.00 / 1.00 / 1.00** | + + Neither prop renders — you get a selection ring on empty grass. And the yard still reads + **VALID — the game can boot this**. + · **This is E's GAP 1 exactly, one layer up.** `adoptAnchor` does `rating_hint ?? 1`, so a + model that 404s doesn't fail — it becomes the best steel in the game. A's own ruling says + the 0.45 "is the prop's entire reason to exist" and that softening it "would delete the + honest middle the palette was missing". The 404 deletes it. The jacaranda's whole design — + **"gum: climb freely, pay 24%. Jacaranda: climb at all, pay 58%"** — becomes three perfect + anchors, i.e. a better tree than the gum at every rung. Both props gate 3.1 built so that + gate 3.2 could ask a real question, and neither was asking it. + · **It propagates into the DATA.** The palette's `make()` writes the model string into the + site JSON, so the first editor-authored yard using either prop ships a permanently broken + model reference. This is not just an editor-preview bug. + · **Gate 1's promise holds and is not enough.** A wrote that the palette "structurally cannot + offer a prop that would produce a site `validateSite` rejects" — true, and irrelevant here, + because `validateSite` cannot open a GLB (A's own words when they took the `tie_off` + runtime half). Nothing in 406 tests that a palette model name resolves to a file. + · **Negative-controlled in both directions.** With the four names corrected locally: + `swing_set_01_v1` → `s1_f1`/`s1_f2` **hint 0.45**; `tree_jacaranda_01_v1` → **0.95 / 0.52 / + 0.40**; both props draw. Reverted before landing — **the fix is A's, and `editor.js` is + untouched on lane/d.** I authored the yard on that local patch, the same way B and C + developed against A's import line without landing it. Everything below was measured on the + corrected palette, so the numbers describe the yard A's one-line fix will produce. + · **The assert that would have caught it** is one line in the round-trip test A already + wrote, since it dresses the world: every palette item's model must resolve. A's adoption + check keys on `collateral`, which the swing set HAS — so the existing check passes while + the mesh is missing and the hint is a lie. + + **🏡 THE YARD — `site_03_swing_lawn`, "The Delaneys' back lawn". 24×16, 11 anchors.** + The thesis: **the good steel is all LOW and the only height is bad.** Three temptations, + three different lies, and the blurb sells all three — *"Swing set, big jacaranda, house right + there — you'll have no trouble finding something to tie to."* + + | anchor | rating | the lie | + |---|---|---| + | `s1_f1` `s1_f2` swing apexes | 0.45 | the crossbar between them is a dead-level 2.05 m rail spanning 2.3 m and is NOT an anchor. Blowing an apex bills **$140** | + | `t1` jacaranda low fork | 0.95 | genuinely excellent — but it is 2.5 m up and cuts the sail flat | + | `t1b` / `t1c` jacaranda height | 0.52 / 0.40 | where the sail wants its high corner. Height costs 58% here | + | `h1` `h2` `h3` fascia | 0.35 | the familiar lie, and takes the **$90** gutter | + | `t2` / `t2b` gum | 1.00 / 0.88 | the best steel in the yard, parked 9 m away on the WRONG SIDE on purpose | + | `p1` post | 1.00 | one honest corner. You need four | + + **The wind is the yard's personality, not decoration.** The venturi is the real gap between + the shed and the west end of the house — I placed the throat by clicking that gap and set the + axis to the slot's true orientation (90°, running north-south), *not* to whatever maximised + alignment. C's panel then told me what that geometry was worth, live: **align 62%, peak + ×1.28, fastest 14.96 m/s at (-8.3,-4.4)**. Throat sits **3.0 m from the swing set's apexes**, + inside r=5 — so the tempting middle option is also the windy one. Deliberately gentler than + the corner block (100%, ×1.46): **that yard keeps the crown for worst weather and worst bill.** + + **SCORE IT** — storm_03_southerly, FUNNEL ON, 11 anchors dressed, **82.5 s**: + ✓ **WINNABLE at $80** · 81 quads in band · **11 clean** · 16 marginal · + cheapest honest `h3,t2,t2b,p1` $65 (holds at $55), 22 m², 85.3 FULL · + bare bed **83.7** → best clean `h3,t1c,t2,p1` **90.0**, separation **+6.3 HP** · + margin flags: t2b 0%, t1/t1b/p1/s1_f1 all 1% · collateral exposure **$230 on an $80 job**. + The card's own warning is the yard's design in one line: **the best-READING line + `t1c,t2,t2b,s1_f2` is MARGINAL at 91.8 FULL.** The prettiest number in the yard is the one + that breaks. + + **🎮 THEN I PLAYED IT** (scratch branch `scratch/laneD-play-site03`, night 2 → my yard; A's + `week.js` is untouched on lane/d, exactly as in Sprint 12). + · **The job sheet reads.** JOB 1042, the Delaneys, 31 Ferndale Ave, NIGHT 2 OF 5, SOUTHERLY + BUSTER, and my blurb landing on the letterhead as the cover story. $122 the night, $80 bank. + · **The yard reads from the spawn.** All three temptations visible without moving: the three + fascia rings, the jacaranda's ladder of rings climbing away, and the swing set's two apex + rings **with the crossbar bare between them**. The rail is obviously level, obviously + spanning, and has no ring on it. E's prop does exactly what it was built to do. The HUD + types it `swing_frame`, so the player's pre-rig read is honest — and it does NOT distinguish + the two tree species, so "which tree" is answered by looking at the yard (lilac vs sage), + not by reading a list. That is the right place for it. + · **The trap bites, and it bites honestly.** Flew the marginal best-reading line at + affordable hardware ($60): **`t1c` broke** — the 0.40 limb, the exact corner the card + flagged — and the garden finished **83.9 FULL against a bare bed of 83.7**. Rigging the + prettiest line in the yard was worth **+0.2 HP over doing nothing.** Flew the cheapest + honest line at the same money: **`h3` broke**, 85.2 FULL, and h3 blowing bills the $90 + gutter. At full-strength hardware ($120 — over budget) all three lines are clean. + **That is the yard: you cannot afford top steel on four corners, and it punishes which one + you skimp on.** + · **B's card and the real game agree on my yard**: card 90.0 → played **90.7**; card 91.8 → + played **93.6**. Two chains, one number, on a yard neither was tuned against. + · **My own lane, on editor-authored geometry.** `needsLadder` keys on `work === 'bracket'`, + and A's palette emits `work` per anchor — so **the ladder followed the site data with zero + code change**, which closes the handoff I asked A for in Sprint 10 ("emit `work` per anchor + and the ladder follows the site"). On this yard the three fascia corners are both the 0.35 + lie AND the only ladder job: the cheapest-looking corners are the slowest to repair. The + shed renders at (-9,-5) and `shed_table` at (3.32,7.75) — **A's NaN-quaternion fix confirmed + on a yard built after it.** + + **👻 PHANTOM SAIL — DEAD, verified in play.** Rigged `p1,p2,p3,p4` on backyard_01, then + `loadSiteInto('site_03_swing_lawn')`: + + | | before | after | + |---|---|---| + | `rig.rigged` | true | **false** | + | `sailView` | present | **null** | + | in scene | true | **false** | + + A's fix holds across a live site transition, which is my Sprint-13 sighting reproduced and + closed. Visually confirmed too: no cloth behind the splash card on the new yard. + + **🧰 FRICTION, BY OWNER.** + · **A — number fields commit on BLUR only; Enter does nothing.** Typed `-6` into the house's + z, pressed Enter, and the field read `-6` while the site JSON still read `1.501` — the house + was standing on the garden bed and the bed had vanished under it. Only clicking elsewhere + committed. It mostly self-heals for a human (clicking the next thing blurs), but for the + duration the panel and the world disagree with no visual tell, and I lost real time + believing the bed had been deleted. Enter should commit. + · **A — the editor places objects outside the yard without a word.** My first bike landed at + **z = 8.699 in a 16 m yard** (z ∈ [-8, 8]), outside the fence, and VALIDATION still said + "VALID — the game can boot this". Which is true. But nobody means to put the bike in the + neighbour's yard. + · **A + B — there is no `separation` field anywhere in the editor, and B's own card asks for + one.** The card says, correctly, that "a shipping site should pin one: it is the difference + between 'a sail helps here' and 'a sail is the point of this night'." The editor cannot + comply. I shipped without one and said so in `_why` rather than hand-editing it in. Either + the SITE panel grows the field or the card stops asking. + · **A — zoom is mouse-wheel only.** No keyboard, no buttons. Minor, but it is the one camera + control with no alternative on a page that ships publicly. + · **B — the 82.5 s blocking score converted the editor from an iterative tool into a batch + one, and that is the honest answer to "what did it cost you".** Mine ran **82.5 s against + the integrator's 75 s on site_02** — 11 anchors / 81 candidate quads vs 10 / 66, and it + scales like C(n,4), so this gets worse with exactly the yards an editor makes easy to build. + **Everything I know about my yard came from ONE run.** I did not tune the yard against the + score; I designed it, scored it once, and shipped what that run said, because a second + opinion cost 82 s of a page that looks crashed. I would have moved the bed and re-scored if + it had been 8 s. **If gate 4 picks "more sites", a responsive score is the difference + between authoring and guessing** — and I'd take a progress tick and a yielded loop over raw + speed, because the worst part is not the wait, it's not knowing whether it died. + · **B + C — two storm pickers, independently defaulted.** SCORE IT opened on `02_wildnight` + while WIND opened on `03_southerly`. Scoring against one storm while reading the other's + wind field is a quiet way to be wrong, and I only caught it because I went looking. One + storm selection, shared. + · **E — the palette prose is doing real work.** Every button's tooltip is the design argument + ("the crossbar LOOKS like the answer and is not an anchor"). I chose props by reading the + palette. That is what it is for and it worked. + · **E + A — `sail_post`'s audited `top_anchor 0.90` never reaches the runtime.** Every post on + my yard **and on shipped backyard_01** adopts at `ratingHint 1.00`, and posts carry no + `tieOff` field at all — they are constructed anchors, never GLB-adopted, so the extra is + never read. E's audit table row is a document and nothing asserts it. Either the 0.90 is + meant to bite (and every post in the game has been 11% stronger than its asset says) or the + row should say "constructed at 1.00". I corrected my own `_design` after measuring it. + + **✅ WHAT SANG, because the investment is the story too.** + · **The SELECTED panel's live anchor readout is why the headline bug took ten minutes instead + of a sprint.** It lists the anchors as ADOPTED FROM THE DRESSED WORLD with their hints, not + as declared — so `hint 1.00` sat there in a warning-coloured badge next to a prop I knew was + 0.45. Showing the adopted value is the entire reason that bug was findable. + · **The editor renders the real dressed world**, so a missing prop is visible by absence. A + diagram would have drawn me a swing set that isn't there. + · **`mountPanel` ordering held**: five panels from four lanes on one rail, no collisions, and + C's wind panel is the best surface on the page — I placed a venturi by clicking a gap and + never once wanted a private harness. + · **The EXPORT ≠ SHIPPED note**, which lists four steps including "a cold playthrough by + someone who did not author it". A tool that tells you it isn't finished. + · Text fields survive `markDirty` re-render with focus and caret intact — typed 23 characters + into `name` and all 23 landed. + + **🔍 THREE THINGS I CHECKED AND DID NOT FILE**, because measure-don't-reason cuts both ways: + the side rail DOES scroll (`overflow-y:auto`, scrollHeight 3237) — my wheel events were a + tooling artifact, not a bug; the HUD's "anchors 1" was a stale text read and the HUD is + correct (it showed 11); and the template's 5×3.5 m bed is NOT below an audit floor — I went to + `sweep.js` and `AUDIT.BAND {lo:18,hi:45}` is the SAIL QUAD band, not the bed. I had that one + written up as a finding before I checked. + + **DECLARED, since gate 3.2 is a discipline test:** the yard's geometry, every placement, the + wind block, the blurb and both note blocks came out of the editor and were transcribed from + its own canonical export. Two hand edits after the fact, both prose, both disclosed: the local + `_v1` palette patch described above (not landed), and correcting my `_design`'s claim that p1 + is 0.90 once play measured it at 1.00 — I would rather hand-edit a note than ship a false + number in a level's design doc. + + **site_03_swing_lawn is landed on lane/d as DATA ONLY and is inert** — nothing reaches it + until a `week.js` NIGHTS entry names it, and that entry lives only on my scratch branch. It is + the **site_03 CANDIDATE awaiting John's gate-4 branch decision**. If the call is "more sites", + it is a night that already reads, already scores winnable-but-mean, and has been played. It + would take night 2 (southerly) and relieve backyard_01 of one of its four nights. diff --git a/web/world/data/sites/site_03_swing_lawn.json b/web/world/data/sites/site_03_swing_lawn.json index 0ecad33..e1a6eb1 100644 --- a/web/world/data/sites/site_03_swing_lawn.json +++ b/web/world/data/sites/site_03_swing_lawn.json @@ -12,8 +12,12 @@ " A sail wants height on its high corner; on this tree height costs 58%, against 24%", " up a gum. That is the \"which tree\" question, and it is the whole reason t2 exists.", " - the house fascia is the familiar 0.35 lie and takes the $90 gutter with it.", - "The only 0.90+ steel in the yard is one post (p1, 0.90) and the jacaranda's LOW fork", + "The only top-grade steel in the yard is one post (p1) and the jacaranda's LOW fork", "(0.95). Four corners, two good ones - that is the puzzle.", + "MEASURED IN PLAY, and the one line here not written by the editor: p1 adopts at", + "ratingHint 1.00, NOT the 0.90 in E's asset audit - posts are constructed anchors and", + "never read the sail_post GLB extra. Every post on backyard_01 reads 1.00 too, so it", + "is repo-wide and not this yard's doing. Filed to E/A in THREADS.", "The gum t2 (1.00 / 0.88) is parked 9 m away in the south-west ON PURPOSE: excellent", "steel on the wrong side, so reaching for it costs you span and shape rather than", "rating. The audit's cheapest honest line (h3,t2,t2b,p1) goes and gets it.", From 008b78a0d4244876ade103e3aceeacdb0dba48b5 Mon Sep 17 00:00:00 2001 From: type-two Date: Sat, 18 Jul 2026 17:58:44 +1000 Subject: [PATCH 3/4] Sprint 14 integration: merge all lanes (406/0/0), fix palette _v1 suffix bug, [I] entry --- THREADS.md | 75 ++++++++++++++++++++++++++++++++++++++++++ web/world/js/editor.js | 15 ++++++--- 2 files changed, 86 insertions(+), 4 deletions(-) diff --git a/THREADS.md b/THREADS.md index f26de98..a7bc231 100644 --- a/THREADS.md +++ b/THREADS.md @@ -6728,3 +6728,78 @@ anchors are your GLB), but the tooling is now waiting, not TODO. the **site_03 CANDIDATE awaiting John's gate-4 branch decision**. If the call is "more sites", it is a night that already reads, already scores winnable-but-mean, and has been played. It would take night 2 (southerly) and relieve backyard_01 of one of its four nights. + +[I] 2026-07-18 — **SPRINT 14 INTEGRATION (main).** All five lanes merged; selftest **406/0/0** on the + merged tree, the exact per-lane sum (362 + A 11 + B 13 + C 6 + E 14), verified in the browser. + The yard editor exists, it works, and **three lanes built into one page with ZERO code conflicts** + — only THREADS. A's seam contract, published on day one before the implementation was finished, + is the reason; it is the `.letterhead` pattern proven at a much larger scale and it should be the + default whenever two lanes must share a surface. + + **Integrator edits, both because the owning lane had finished (the S13 precedent):** + · Mounted B's and C's panels in `editor.html` — one import line each, which is all either lane + ever asked A for. Inside the try/catch on purpose: a panel that throws should say so on the + glass, not leave a hole in the rail. + · **Fixed D's headline bug in `editor.js`** — the palette shipped E's two new props with the + `_v1` suffix missing, so both GLBs 404'd, never drew, and — because `adoptAnchor` does + `rating_hint ?? 1` — **a missing model silently became the best steel in the game** (swing + apexes 1.00 instead of E's 0.45; jacaranda 1.00/1.00/1.00 instead of 0.95/0.52/0.40), while the + yard still validated VALID. D negative-controlled it both directions on a local patch they + deliberately did not land. Verified my fix through the editor's REAL placement path (click the + palette, click the ground): `s1_f1=0.45 s1_f2=0.45`. Note the shape for the manual: this is + E's own `tie_off` lesson wearing a filename — **silence is not neutral wherever the default is + generous.** + + **⚠️ CARRIED TO SPRINT 15, AND IT IS A SHIPPED BALANCE BUG, NOT AN EDITOR ONE.** D found it and + I confirmed it end to end: the factory bakes `rating_hint = 0.9` on `sail_post`'s `top_anchor`, + but every post in `backyard_01.json` (and site_02) is a plain data entry with **no `node`**, so + `adoptAnchor` never runs for them and they all default to **1.00**. Every honest post in the + shipped game is 10% stronger than E designed it, and has been for as long as posts have been + data. **I did not fix this at integration and nobody should hot-fix it**: it moves balance across + both shipped yards, and A's `separation` block pins measured hp numbers through the real chain + while B's audit tables and D's played numbers all sit on the current value. It is a RULING (A) + + a re-measure (B) + a re-play (D), which is a gate, not a patch. + + 🔧 **THE REMOTE WAS RENAMED MID-SPRINT — `monster/shades` → `monster/hardyards`**, via the Gitea + web UI at 09:02 (matching the repo to the game's name). Nothing was lost; every ref was intact + under the new name. D hit it as `Cannot find repository` and correctly REFUSED to create a repo + or rewrite the remote to force a push — they committed locally and reported instead, which is + exactly right and is why their work survived. All six checkouts are repointed and D's two commits + are pushed. **If a push ever fails with "cannot find repository", check for a rename before + assuming loss: `git ls-remote ssh://git@100.71.119.27:222/monster/.git`.** + + **The sprint's real argument, in one line: the editor found NINE bugs before anyone authored a + yard with it**, and three were live on the public URL — a graybox house slab across site_02's + north horizon, the Hendersons' shed which has NEVER rendered (an `undefined` rotation → NaN + matrix → three.js silently declines to draw, no throw, no warning), and boot failures written + into a `display:none` div so a stranger got a blank page. None was findable from a bench. All + were findable by standing in the yard and looking, which is the entire thesis of gate 1. + + **`return t.skip(msg)` was a fake pass** (A): `Suite.skip()` pushes a NEW result while the + current test still records `pass`. I grepped every suite — **confined to a.test.js, four + instances, all fixed**; B, C, D, E and balance.test were clean, so the repo's counts were never + materially inflated. Worth knowing WHY those four were exposed: they guard on `dressed`, and + C's S13 landmine is that `dress()` throws silently without the importmap — two bugs that compose + into "green because nothing ran". selftest.html carries the importmap, so they were genuinely + running. + + **Gate 3.2 delivered: `site_03_swing_lawn`, "The Delaneys' back lawn"** — authored COLD by D in + the editor, no JSON, no console. Thesis: *the good steel is all low and the only height is bad.* + Scored winnable at $80 (11 clean lines, cheapest honest $65, collateral $230 on an $80 job), + played on a scratch branch, and the trap bit exactly as designed — the prettiest line finished + **83.9 against a bare bed's 83.7**, i.e. worth +0.2 HP. Card and game agreed to a point. **It is + a CANDIDATE, inert until a NIGHTS entry names it, and that is gate 4's call, not mine.** + + Pool, by owner: **B** — the score is 75–82 s with the UI thread fully blocked, which made the + editor *batch, not iterative* (D scored once and shipped that run rather than tuning; D's words + are the evidence, and a progress tick may matter more than raw speed). **A** — number fields + commit on blur only (Enter does nothing; D lost real time to a house sitting on the garden bed + while the panel read the new value); objects place outside the fence silently and still read + VALID; zoom is wheel-only. **A+B** — no `separation` field exists in the editor while B's card + says a shipping site should pin one. **B+C** — two independently-defaulted storm pickers (D + scored the wildnight while viewing the southerly). **E+A** — the `sail_post` hint above. + + **Gate 4 is open and it is now the only thing standing between this project and its next + direction: John plays the week.** Nine sprints. The editor has made "more sites" nearly free and + D has a candidate yard sitting ready; reputation/warranty and heatwave are unchanged in cost. + That choice is his and the game is the best argument for making it that it has ever been. diff --git a/web/world/js/editor.js b/web/world/js/editor.js index d743ff2..6948f69 100644 --- a/web/world/js/editor.js +++ b/web/world/js/editor.js @@ -236,11 +236,18 @@ export const PALETTE = [ // crossbar that is the most anchor-looking object in the game and carries // `tie_off: false`. $140 is E's number, ADOPTED unchanged; the ruling and // the one condition for revisiting it are in THREADS. - kind: 'structure', label: 'Swing set (the honest middle)', model: 'swing_set_01', + // ⚠️ The `_v1` suffix is LOAD-BEARING and its absence is silent. These two + // entries shipped without it (SPRINT14, D's cold pass): the GLB 404s, the + // prop never draws, and because `adoptAnchor` does `rating_hint ?? 1` a + // MISSING MODEL BECOMES THE BEST STEEL IN THE GAME — the swing apexes read + // 1.00 instead of E's 0.45, the jacaranda 1.00/1.00/1.00 instead of + // 0.95/0.52/0.40 — and the yard still validates VALID. Same species as E's + // `tie_off` audit: silence is not neutral where a default is generous. + kind: 'structure', label: 'Swing set (the honest middle)', model: 'swing_set_01_v1', requires: ['swing_frame'], hint: 'apex anchors 0.45; the crossbar LOOKS like the answer and is not an anchor', make: (id, x, z) => ({ - id, model: 'swing_set_01', wreckedModel: 'swing_set_01_wrecked', + id, model: 'swing_set_01_v1', wreckedModel: 'swing_set_01_wrecked_v1', x, z, rotYDeg: 0, solid: false, collateralKey: 'swing_set', collateralValue: 140, collateralLabel: 'the swing set', @@ -254,10 +261,10 @@ export const PALETTE = [ // on a jacaranda and you pay 58% for it, against the gum's 24%. Unpriced by // E's own ruling (no limb-failure event to watch; billing an unseen event // is the lie the invoice exists to kill). Same node names as the gums. - kind: 'tree', label: 'Jacaranda (height costs)', model: 'tree_jacaranda_01', + kind: 'tree', label: 'Jacaranda (height costs)', model: 'tree_jacaranda_01_v1', hint: 'forks low and strong, then falls off a cliff — the "which tree" question', make: (id, x, z) => ({ - id, model: 'tree_jacaranda_01', x, z, phase: 1.1, trunkH: 3.4, anchorY: 2.4, + id, model: 'tree_jacaranda_01_v1', x, z, phase: 1.1, trunkH: 3.4, anchorY: 2.4, anchors: [1, 2, 3].map((i) => ({ id: i === 1 ? id : `${id}${'abc'[i - 1]}`, node: `branch_anchor_0${i}`, type: 'tree', work: 'cloth', From 6f68fbf61895886318e01b429744f4387d4dc28b Mon Sep 17 00:00:00 2001 From: type-two Date: Sat, 18 Jul 2026 18:00:50 +1000 Subject: [PATCH 4/4] Sprint 15 plan + prompts; README points at the renamed remote --- LANE_PROMPTS.md | 81 ++++++++++++++++++++++++++++++++++++++++ README.md | 4 +- SPRINT15.md | 99 +++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 182 insertions(+), 2 deletions(-) create mode 100644 SPRINT15.md diff --git a/LANE_PROMPTS.md b/LANE_PROMPTS.md index 6a05f82..8e90fb6 100644 --- a/LANE_PROMPTS.md +++ b/LANE_PROMPTS.md @@ -832,3 +832,84 @@ byte-identical JSON out) even though its UI needn't be. > number, a wreck where priceable, negative-control asserts (your bike > discipline — build the wrong one on purpose and watch it go red). Flag D > in THREADS the moment the palette is ready — their cold yard waits on it. + +--- + +# SPRINT 15 prompts (the posts tell the truth, the editor stops being batch) + +Same rules: own clone, own branch, `git fetch origin && git reset --hard +origin/lane/` on a clean tree first. **The remote was RENAMED mid-Sprint-14 +— it is `monster/hardyards.git` now, not `monster/shades`. All six checkouts +are already repointed; if a push ever 404s, check for a rename before assuming +loss.** Read docs/MANUAL.md, THREADS' last [I], then SPRINT15.md. Ports: A +8824, B 8825, C 8826, D 8827, E 8828. Baseline **406/0/0**. + +## Lane A — Sprint 15 +> You are Lane A on SHADES 3D (the game is HARD YARDS, public at +> partly.party/hardyards), Sprint 15. Rebase onto main, read docs/MANUAL.md, +> THREADS' last [I], then SPRINT15.md. **Gate 1 ruling is yours and comes +> FIRST, before anyone measures**: the factory bakes `rating_hint = 0.9` on +> sail_post's top_anchor, but JSON-declared posts never run adoptAnchor and +> default to 1.00, so every honest post in the shipped game is 10% stronger +> than designed. Rule 0.90 (design intent reaches the sim) or 1.00 (the +> shipped, balanced-against value becomes canon and E corrects the bake) — +> both defensible, and every played verdict in THREADS measured 1.00. Then +> fix the MECHANISM either way: a baked hint must never again fail to reach a +> JSON-declared anchor silently. Gate 3 is also yours: Enter commits number +> fields, out-of-bounds placement must stop reading VALID, zoom beyond the +> wheel, and the separation-field question with B. Do NOT start +> reputation/site_03/heatwave — gate 4 is John's. + +## Lane B — Sprint 15 +> You are Lane B on SHADES 3D, Sprint 15. Rebase onto main, read +> docs/MANUAL.md, THREADS' last [I], then SPRINT15.md. Gate 2 is yours: D's +> verdict is that your 75–82 s fully-blocked SCORE IT "made the editor batch, +> not iterative — I scored once and shipped that run rather than tuning." +> Fix it in D's priority order: a progress tick that actually paints first +> (D thinks that matters more than raw speed), then yielding so the page stays +> responsive, then speed (cost scales like C(n,4) in candidate quads — a +> coarse ranking pass before flying is likely worth more than micro-optimising +> the sim). **Pin the current site_02 and site_03 scores before you start and +> reproduce them exactly after** — a faster score that moved a number is a +> regression. Also with C: one storm picker, not two independently-defaulted +> ones. Gate 1.3: re-measure both yards once A rules the post hint, post the +> deltas as a table, propose retunes with evidence. + +## Lane C — Sprint 15 +> You are Lane C on SHADES 3D, Sprint 15. Rebase onto main, read +> docs/MANUAL.md, THREADS' last [I], then SPRINT15.md. Lighter sprint for you +> by design — gate 1 is a post-rating ruling and gate 2 is B's performance +> work. Yours: (1) with B, collapse the two independently-defaulted storm +> pickers into one shared selection (D scored the wildnight while viewing the +> southerly — two harnesses disagreeing inside a single page, which is the +> exact class of bug this repo keeps paying for). (2) Second-harness B's +> re-measure once A rules the post hint: if every post moves 10%, the storm +> side should predict the same shift your envelope tool would. (3) Your call +> on anything the wind panel revealed that you filed and didn't land — D +> called it "the best surface on the page", so if there's polish you wanted, +> this is the sprint with room for it. + +## Lane D — Sprint 15 +> You are Lane D on SHADES 3D, Sprint 15. Rebase onto main, read +> docs/MANUAL.md, THREADS' last [I], then SPRINT15.md. Two judgements, both +> yours alone. (1) Gate 1.4: once A rules the post hint and B re-measures, +> re-play the affected nights and say whether the change is FELT — if 0.90 +> makes the honest line stop holding, that is a design change wearing a +> bugfix's clothes and you are the one who says so. (2) Gate 2.3: re-author or +> re-tune a yard with B's faster score loop and say whether it changed how you +> work — your "batch, not iterative" line is what bought this sprint, so you +> are the acceptance test for the fix. Your `site_03_swing_lawn` stays inert +> until gate 4 picks the more-sites branch; don't wire it to a night. + +## Lane E — Sprint 15 +> You are Lane E on SHADES 3D, Sprint 15. Rebase onto main, read +> docs/MANUAL.md, THREADS' last [I], then SPRINT15.md. Gate 1.2 is yours and +> it's short: once A rules the sail_post hint (0.90 or 1.00), make the factory +> agree, and PIN it — an assert that a JSON-declared anchor of a type the +> factory rates carries that rating at runtime. This is the third member of +> the family your Sprint 14 audit started (no silent anchors, no unpriced +> collateral, and now no baked hint that never arrives), and it is the general +> fix for the bug class that shipped both the free carport and the perfect +> posts. With the sprint's spare room: your call on palette gaps D hit while +> authoring cold — read their gate-3.2 entry and propose what the next yard +> needs, with reasoning baked beside the numbers as always. diff --git a/README.md b/README.md index ad07813..6a6c05c 100644 --- a/README.md +++ b/README.md @@ -62,9 +62,9 @@ Host gitea.partly.party Then: ``` -git clone git@gitea.partly.party:monster/shades.git ~/Documents/shades +git clone git@gitea.partly.party:monster/hardyards.git ~/Documents/shades for L in A B C D E; do - git clone git@gitea.partly.party:monster/shades.git ~/Documents/shades-lane$L + git clone git@gitea.partly.party:monster/hardyards.git ~/Documents/shades-lane$L git -C ~/Documents/shades-lane$L checkout -B lane/$(echo $L | tr 'A-Z' 'a-z') origin/lane/$(echo $L | tr 'A-Z' 'a-z') done ``` diff --git a/SPRINT15.md b/SPRINT15.md new file mode 100644 index 0000000..e3dfc68 --- /dev/null +++ b/SPRINT15.md @@ -0,0 +1,99 @@ +# SPRINT 15 — THE POSTS TELL THE TRUTH, AND THE EDITOR STOPS BEING BATCH + +*Sprint 14 built the yard editor and it immediately earned itself: nine bugs +found before anyone authored a yard with it, three of them live on the public +URL. D then authored a complete third yard cold — no JSON, no console — and +it scored winnable-but-mean and played that way. 406/0/0, live at +partly.party/hardyards, editor included.* + +*What it also found is a shipped balance bug we deliberately did not patch, +because half the repo's measured numbers are standing on it. That's gate 1.* + +Read THREADS from the last [I] entry. Baseline **406/0/0**; keep it green, +mutation-check anything you'd call coverage. + +## Gate 1 — THE POSTS TELL THE TRUTH (A rules · E supplies · B re-measures · D re-plays) + +The factory bakes `rating_hint = 0.9` on `sail_post`'s `top_anchor`. Every +post in every shipped site is a plain JSON entry with **no `node`**, so +`adoptAnchor` never runs and they all default to **1.00**. Every honest post +in the game is 10% stronger than E designed it, and always has been. + +This is a gate and not a patch because A's `separation` block pins measured hp +through the real chain, B's audit tables predict against it, and D's played +verdicts sit on it. Move the number and all three move together, in order: + +1. **A rules FIRST, before anyone measures:** is the honest post 0.90 (E's + design intent reaches the sim) or 1.00 (the shipped value becomes canon and + E's baked hint is corrected to match)? Both are defensible — 1.00 is what + every played verdict in THREADS actually measured, and "the value we shipped + and balanced against is the real one" is a legitimate ruling. What is NOT + defensible is leaving the factory and the sim disagreeing. **Whichever way + it goes, the mechanism must be fixed so a baked hint can never again fail to + reach a JSON-declared anchor silently** — that's the actual bug, and it will + bite the next asset the same way (`tie_off`, `collateral`, anything). +2. **E:** make the factory agree with the ruling and pin it — an assert that a + JSON-declared anchor of a type the factory rates carries that rating at + runtime. Your S14 audit rules (no silent anchors, no unpriced collateral) + are the model; this is the third of that family. +3. **B:** re-measure everything that moved. If the ruling is 0.90 every post + line in both shipped yards gets weaker — expect the separation pin, the + winnable-lines tables, and the night-4/5 affordability story to shift, and + post the deltas as a table. Propose retunes with evidence; A rules. +4. **D:** re-play the affected nights and say whether the change is FELT. If + 0.90 makes the honest line stop holding, that's a design change wearing a + bugfix's clothes and you're the one who says so. + +## Gate 2 — THE EDITOR STOPS BEING BATCH (B owns; D judges) + +D's verdict: the 75–82 s fully-blocked score "made the editor batch, not +iterative — I scored once and shipped that run rather than tuning." That is +the difference between a tool you author WITH and a tool you check work AGAINST. +1. **B:** make the score interruptible and legible. In priority order — a + progress tick that actually paints (D says this may matter more than raw + speed), then yielding so the page stays responsive, then speed itself + (the cost scales like C(n,4) in candidate quads — a coarse pass that ranks + before it flies is likely worth more than micro-optimising the sim). + Whatever you do, the numbers must not change: pin the current site_02 and + site_03 scores before you start and reproduce them after. +2. **B + C:** one storm picker, not two independently-defaulted ones (D scored + the wildnight while viewing the southerly — the exact class of + two-harnesses-disagreeing this repo keeps paying for, now inside one page). +3. **D:** re-author or re-tune a yard with the faster loop and say whether it + changed how you work. That's the acceptance test, same as gate 3.2 was. + +## Gate 3 — THE EDITOR'S HONEST EDGES (A owns, mostly) + +D's friction list, by owner, all seen in anger: +1. **A:** number fields commit on blur only — Enter does nothing, and a house + sat on the garden bed while the panel read the new value. Commit on Enter. +2. **A:** objects place outside the fence silently and the yard still reads + VALID. Either validate the yard bounds or draw the boundary — a yard that + lies about being valid is the one thing this editor must never do. +3. **A:** zoom is wheel-only (no keyboard, no pinch). +4. **A+B:** no `separation` field exists in the editor, while B's score card + says a shipping site should pin one. Either add it to the SITE panel or + rule that separation is an integration-time concern and say so on the card. +5. **A:** honour `tie_off: false` at the palette layer if you offer anchors by + name from GLB nodes (E's flag; the runtime half is already honoured). + +## Gate 4 — JOHN PLAYS, THEN CHOOSES (nine sprints) + +partly.party/hardyards — five nights, three sentences in THREADS. Then the +branch, which the editor has now repriced: +- **More sites** — D's `site_03_swing_lawn` is authored, scored and played, + sitting inert waiting for a NIGHTS entry. This branch is now nearly free. +- **Reputation / warranty** — DESIGN.md's consequence loop; the invoice exists + to hang it off. Unchanged in cost. +- **Heatwave days** — the slow-pressure half of the design, sun-arc coverage, + a genuinely different puzzle. Unchanged in cost. +Nobody builds any of the three this sprint. + +``` +gate 1: the post hint ruled, the mechanism fixed so a baked hint cannot + silently fail to reach a JSON anchor, both yards re-measured, D re-plays +gate 2: the score paints progress and stays responsive; numbers reproduce + exactly; one storm picker; D says the loop changed +gate 3: Enter commits, out-of-bounds stops reading VALID, the friction list empty +gate 4: John's three sentences + the branch, in writing +```