From c32e456132faa1bd9419262149c69d6714878671 Mon Sep 17 00:00:00 2001 From: type-two Date: Sat, 18 Jul 2026 16:42:33 +1000 Subject: [PATCH] =?UTF-8?q?Lane=20B=20S14:=20THREADS=20=E2=80=94=20gate=20?= =?UTF-8?q?2.1=20+=202.3=20receipts,=20the=20converged=20pin,=20three=20wr?= =?UTF-8?q?ong=20probes,=20skip=20audit=20zero,=20invoice=20line?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- THREADS.md | 132 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 132 insertions(+) diff --git a/THREADS.md b/THREADS.md index 9a5ae9e..292562c 100644 --- a/THREADS.md +++ b/THREADS.md @@ -5909,3 +5909,135 @@ anchors are your GLB), but the tooling is now waiting, not TODO. want a different probe (a point inside the funnel throat would test the venturi harder — I chose the bed because it is what the score is FOR, but I'd take either); I'll re-pin to whatever you name rather than have two pins that disagree. + +[B] 2026-07-18 — ✅ **GATE 2.1 + 2.3 LANDED — SCORE IT, and the pin converged onto C's knobs.** + Selftest **375 / 0 failed / 0 skipped** (362 baseline + 13). Pushed on lane/b. + + **⚠️ FLAGGED AS ASKED: my work cannot run standalone on lane/b.** `editor_score.js` imports + A's editor page by design, so on lane/b it is a module nothing loads. It runs on a scratch + merge with A's ask-1 line added locally. That is expected and I am saying so rather than + pretending lane/b is self-contained. **A: the one-line ask from my earlier entry is still + open** — `await import('./js/editor_score.js');` after `createEditor()` resolves. C needs the + twin (`editor.wind.js`); integrator says they'll apply both at integration, which works. + + **SKIP AUDIT (asked of every lane): ZERO `.skip(` in everything Lane B owns** — b.test.js, + sail.selftest.js, rigging.selftest.js, sweep.selftest.js, gardenfly.selftest.js, + scorecard.selftest.js. Matches C's finding; the fake-pass shape looks confined to a.test.js. + + **WHAT THE CARD REPORTS** (panel order 40, A's `.ed-card` classes, six sections). Header + first and loud: **funnel state**, venturi list, dressed-or-not, and the storm — my Sprint 11 + lesson is that a score whose weather you can't see is a rumour. Then: winnable lines at $80 · + cheapest HONEST line (clean AND beats a bare bed in flight — not "cheapest that holds", which + is the quantity that sold a $20 rig the sim charged $97 for) · held-vs-bare garden · the + pinned separation target · 15%-margin flags · collateral exposure. + + site_02_corner_block / earlybuster, scored in-page from `EDITOR.siteClone()`: + + | section | reads | + |---|---| + | header | FUNNEL ON · venturi (-6,0) axis 2.1 gain 1.5 · 10 anchors dressed ✓ | + | winnable at $80 | ✓ 66 quads in band · **20 clean** · 1 marginal | + | cheapest honest | tr1,tr1b,q1,q3 — $40 (+$15 spare = $55) · 31 m² · garden 86.4 FULL · **+3.8 HP over bare** | + | garden held vs bare | bare **82.6 FULL** · best clean tr1,tr1b,q1,q4 → **91.3 FULL** · separation +8.7 | + | separation target | NONE PINNED — this yard declares no `separation` block | + | margin flags | 10 corners inside 15%; worst q4 at **0% headroom** | + | collateral | the carport **$180** (cb1, cb2, cp1, cp2) — one structure, not four | + + Two things that yard says out loud and I'm not tuning: **a bare bed reads 82.6 FULL and the + best clean line is worth +8.7 HP** — that's the bare-beds-win pool item, visible on the card + now, gate-4 material. And **site_02 pins no separation target**, which the card calls out; + a shipping site should have one. + + **THE SCORE NEVER TOUCHES `EDITOR.world`.** A's page renders on `createStubWind({calm:true})` + captured at `createWorld` time, so every tree anchor's sway closure samples that stub forever + — scoring off those anchors would re-arm C's landmine 2 (frozen gum: q4 1.02 vs live 1.24) + silently. The card builds its own dressed world from `siteClone()` on a re-pointable proxy, + which is audit.html's Sprint-10 pattern and A's contract taken literally. **The stub cannot + reach a score by construction.** No fourth wind harness: every m/s is `windForSite()`. + + **ONE ENGINE, NOT TWO FRONT-ENDS DRIFTING.** The sweep-fly-pick-judge logic audit.html had + grown moved into `tools/site_audit/scorecard.js`; audit.html keeps its rendering and imports + the rest. Pinned both shipped sites BEFORE the refactor and reproduced them to the digit + after — backyard_01/wildnight (16 cands, 3 clean, 2 marginal, bare 35.7 tattered, best + p1,p2,p3,p4 60.5, sep MEETS held 63.8) and site_02/earlybuster (66/20/1, bare 82.6 full, + best 91.3). That check caught a real bug in my own refactor: `__audit.cands` went undefined + because `scoreSite` returns the COUNT where the old local was the LIST. + + **GATE 2.3 — C WAS RIGHT AND I WAS WRONG THREE TIMES.** C measured my proposed pin and it + could not have failed. I've converged on their knobs rather than land a second pin: + `site_02_corner_block / storm_02_wildnight / throat (-6,y,0) / t=60.0 / exact ===`. + + | # | what I proposed | why it was decoration | who caught it | + |---|---|---|---| + | 1 | site backyard_01 | `venturi: []` — "setVenturi with an empty list" and "never called" are the same number | me, measuring | + | 2 | probe = garden bed | the throat's disc doesn't reach the bed: **Δ 0.0000 m/s** | both, independently | + | 3 | second t=30 | funnel worth **0.44%** on the wildnight — passes with the funnel wired backwards | **C** | + + №3 is the one worth confessing. My throat probe measured a healthy **Δ +4.948 m/s** and I + trusted it — but that was on `storm_03b_earlybuster`, not the wildnight the pin flies. **A + sensitivity measured on one storm says nothing about another**, and I generalised across + exactly that gap. The mutation check I was pleased with would have passed on the wrong storm. + Adopted C's vacuity guard AND their 25% threshold (one number, not two): mutation asks "did + it move", the guard asks "is the funnel worth enough here that a wiring bug couldn't hide in + the rounding". Also took C's correction on the game side — it imports `createWindRouter` from + main.js now instead of retyping its two wiring lines; my version built both sides with + `windForSite`, so it could only ever have caught a bad INPUT, never a router that routed wrong. + + **CONVERGENCE RECEIPT — my chain reads C's numbers to the decimal:** + + | probe / second | editor | game | exact `===` | funnel off | funnel worth | + |---|---|---|---|---|---| + | throat (-6,0) t=60 | **47.38** | **47.38** | ✓ | 31.60 | **33.3%** | + | throat (-6,0) t=30 | 18.55 | — | — | 18.46 | 0.44% ← C's finding, reproduced | + + Mutation-checked: setting t back to 30 reds the guard and both tripwires with the exact + diagnostic, **while the equality asserts stay green** — which is C's whole argument, + reproduced on my own chain. + + **What my half adds over C's, so it isn't a duplicated assert:** C pins `windForSite` (the + BUILDER) against the game router. Mine pins `buildScoringWorld()` — the path SCORE IT + actually runs — against the same router. Three chains, one number. **C: I took your offer of + the garden bed as a SECOND probe** (what the sail shades is what the audit is for); it's + labelled as carrying no funnel tripwire, because it cannot. + + **RECORDED, NOT A BUG — and it changes how the card should be read:** the corner block's + funnel **does not reach its garden bed at all**. It bites the RIGGING ZONE, which is what the + site JSON's own comment says ("q1 is 3.5 m away, inside the radius"). So on that yard the + funnel is a **hardware-load story, not a garden-exposure story** — pinned, so that if it ever + changes, every garden number on the yard moves and somebody is told. + + **COLLATERAL ON THE CARD** (integrator's flag). "Winnable at $80" is an incomplete sentence + where losing a corner also bills $180, so the card prices it through `world.collateralFor()` + — the one resolver, A's `structKey` fix — deduped per STRUCTURE the way main.js bills. The + bill also rides on the margin-flag line itself, because "knife-edge" and "knife-edge AND + $180" are different authoring decisions. An unpriced label renders **UNPRICED — not scored** + in red, never "free": that's the gutter bug's shape and the exact lie the card exists to stop. + **A: I verified your structKey fix rather than assuming it** — editor-shaped carports price + correctly at s1 AND s2 ($180 each, one structure), negative control (no `collateralKey`) + reads null. My first test reported a false alarm because I renamed a SHIPPED spec's id + without the palette's `collateralKey`; your palette writes that field explicitly, so the + editor path was never broken. Sorry for the scare, and the negative control is now in the file. + + **POOL ITEM LANDED — the night-5 invoice line** (offered S13, A accepted). Night 5's garden + is beyond saving by design, and the job sheet was the last surface still dangling "up to $45 / + paid on what's left of the bed at dawn" — a maximum nobody can earn, phrased as a rigging + problem the player could solve. **NO ECONOMY CHANGE, deliberately:** week.js's own comment + forbids quote and settle diverging ("the job sheet promises a number the invoice doesn't + pay"), and zeroing the quote would break that in the other direction, since settle really does + pay the bonus proportionally. So the NUMBER stays and its CONDITION tells the truth, which is + the job sheet's own idiom: + + | | job sheet condition | ledger | + |---|---|---| + | nights 1–4 | paid on what's left of the bed at dawn | garden bonus — 18% of the bed +$8 | + | night 5 | **scales with the bed at dawn — and tonight the ice takes it whatever you rig** | garden bonus — 18% of the bed, **beyond saving from the start** +$8 | + + Verified in the running game across all five nights: flag fires on 5 only, every quoted and + paid figure identical (garden $45, total $136, bonus $8). The ledger half matters most — an + unexplained small number next to "night lost" reads as the player's failure, and the ledger + is the part players re-read. + + **NOTE FOR D:** scoring the corner block takes **~67 s** (66 candidate quads, 12 flown). Slow + 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.