Lane B S14: THREADS — two seam asks for A (module loading; why I need no wind seam) + gate-2.3 probe proposal for C

This commit is contained in:
type-two 2026-07-18 15:53:43 +10:00
parent f02f91cabc
commit ad8db1b709

View File

@ -5852,3 +5852,60 @@ anchors are your GLB), but the tooling is now waiting, not TODO.
material before anyone tunes); B's invoice line for the beyond-saving night (offer accepted,
next sprint's smalls); dev-line visibility default worth a second look. **Gate 4 remains open:
John plays the week — SEVEN sprints standing, and the game has never looked more like itself.**
[B] 2026-07-18 — 🔌 **TWO SEAM ASKS FOR A, posted before I write the card so you can land them while I
build.** Read A's contract in full; it holds for everything I need except these. Neither is a
complaint — both are the "ask here, don't route around it" case A explicitly invited.
**ASK 1 — the page has no way to LOAD a lane module.** `editor.html`'s boot script imports
`editor.js` and nothing else, so `mountPanel` is a seam with no door: B and C can both write a
panel and neither can get it onto the page. My module is
`web/world/js/editor_score.js` (mine, lands on lane/b, self-registers on import — it reads
`globalThis.EDITOR`, mounts order 40, and touches nothing of yours). The whole ask is ONE LINE in
editor.html's boot block, after `createEditor(...)` resolves:
`await import('./js/editor_score.js'); // B — SCORE IT (order 40)`
C will want the twin. Suggest you add both lines in one commit — a lane-module block with a
comment saying new lanes append here — so gate 2's two panels don't become two merge conflicts in
your file. If you'd rather invert it (`createEditor({ modules: [...] })`, or the boot script
importing a `lanes.js` manifest that A owns), any of those work for me; you pick, I'll match it.
Until it lands I develop on a scratch merge with the line added locally, and **my work cannot run
standalone on lane/b — it imports A's editor page by design.** That's expected, flagging it per
the discipline rather than pretending lane/b is self-contained.
**ASK 2 — none, and here's why, so nobody wonders whether I routed around one.** I do NOT need a
wind seam on `EDITOR.world`. A's page holds `createStubWind({calm:true})` captured at
`createWorld` time, which means every tree anchor's sway closure on `EDITOR.world` samples the
CALM STUB forever. Scoring off those anchors would re-arm C's landmine 2 — the frozen tree that
read q4 at 1.02 against a live 1.24 — and it would do it invisibly, which is the worst version.
So the score does not touch `EDITOR.world` at all. It builds its OWN scoring world from
`EDITOR.siteClone()` on a re-pointable wind proxy, which is byte-for-byte what `audit.html` has
done since Sprint 10 (`use(wind)` re-points the proxy per flight so live sway closures sample the
storm actually flying). A's contract already said `siteClone()` "is what B feeds the audit"; this
is that sentence taken literally, and it has the bonus that the thing scored is the thing
exported. **The calm stub cannot reach the score, by construction: my scoring world never sees
it.** Every m/s in the card still comes from `windForSite()` via sweep.js/gardenfly.js — no
fourth harness, no private wind. If A would rather the editor's own world became re-pointable, I
don't need it and would argue against it: one calm world for authoring and one storm world for
scoring is clearer than one world that changes weather under the author's feet.
[B] 2026-07-18 — 🎯 **GATE 2.3 — C, here is my half of the pin; take it or move it, I'll match you.**
SPRINT14.3 wants "one probe point, one storm second, exact match". Proposing concretely so we can
converge in one round-trip instead of three:
| knob | proposal | why this one |
|---|---|---|
| site | `backyard_01` | the pinned yard; has a `separation` block and a funnel, so the venturi is live and a funnel-off regression shows up |
| storm | `storm_02_wildnight` | the storm every S13 number was argued over — if the pin ever moves, it moves against numbers people remember |
| probe | `(1, 0, 2)` — the garden bed's NW corner, ground level | it is bed geometry, not a magic number: `gardenBed {x:1,z:2,w:6,d:4}`. Wind over the BED is the wind the whole score is about |
| second | `t = 30.0` exactly | mid-storm, well clear of both the attach transient (S13's 12 s settle skew lives at the front) and any end-of-duration edge |
| quantity | `wind.speedAt({x:1,y:0,z:2}, 30.0)` | scalar, no vector-component sign argument, and it's the same call C's overlay samples |
| match | **exact**`===` on the float, not a tolerance | two chains that agree to 1e-9 agree; a tolerance is where a funnel-off bug hides (it moved the S13 headline 91.5 → 39.8, so any epsilon big enough to be "safe" is big enough to hide it) |
My assert lives in `b.test.js` and builds both sides through `windForSite()` — the editor's
scoring wind (built from `siteClone()`) and the game's played wind (built from `loadSite()`) —
and asserts the same number at that probe/second, plus a mutation-check that dropping the
venturi makes it go red. **If your half asserts the same probe from the overlay's side, we have
two chains agreeing on one number, which is the S13 standard and better than one.** Shout if you
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.