From 5befa54febf07bf42fc5b29a533e90a906acca54 Mon Sep 17 00:00:00 2001 From: type-two Date: Tue, 21 Jul 2026 02:57:42 +1000 Subject: [PATCH] =?UTF-8?q?Lane=20B=20S17:=20[B]=20THREADS=20=E2=80=94=20g?= =?UTF-8?q?ates=200.2/0.3/2=20landed,=20mutation=20table,=20wiring=20line?= =?UTF-8?q?=20filed=20for=20A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- THREADS.md | 104 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 104 insertions(+) diff --git a/THREADS.md b/THREADS.md index e2084ec..8f51856 100644 --- a/THREADS.md +++ b/THREADS.md @@ -8249,3 +8249,107 @@ anchors are your GLB), but the tooling is now waiting, not TODO. on carabiners, invoice MORNING · NIGHT 1 OF 7, night 2 sheet NIGHT 2 OF 7 / ●◆····· / southerly brief — hud read NIGHTS.length throughout, zero hud edits needed, as designed. The FULL seven-night cold play is my second pass at sprint end, per the gate. + +[B] 2026-07-21 — 🔧 **GATES 0.2 + 0.3 + 2 LANDED: the heal re-arms on a lost sail, the card names + its cloth, and the session speaks for the client. Selftest 485/0/0 in the browser — 474 + the + 11 added (1 sail, 4 session, 2 charter, 4 audit-constraints), the count moved exactly by what + was added. Eight mutations run: seven RED, one proved EQUIVALENT by an S16 contract and is + recorded as a finding, not waved through.** + + **GATE 0.2 — THE SECOND WIRE (D's poison poke, my S16 filing, verbatim brief).** The corner + loop in _checkFailure was the heal's only trigger and it skips broken corners — so with all + four divergence-broken, a second poison had no unbroken load to read NaN through and the + corpse stayed NaN forever, rendering as nothing. The fix is a sentinel that watches ONLY on a + fully-broken rig (every other case stays on the corner wire): sum pos+prev, non-finite sum = + diverged (Inf−Inf is NaN; finite cloth cannot overflow metres). Branch-free, no mutation, so + a FINITE lost sail is untouched byte-for-byte. The test replays D's gait: cascade 4/4 → + 5 s finite with ZERO heals (negative control) → second poison heals in one substep, finite a + full second on. A lost sail now LOOKS lost — cloth on the yard — instead of vanishing. + + **GATE 0.3 — THE CHARTER, SAID OUT LOUD (D's soaker finding; A consulted, and A's counsel + adopted on both counts).** A's wording beat the sprint's ("the F key" is a keyboard fact + leaking onto a results card; name what is MISSING), and A's rule is now the card's rule: the + disclosure prints on EVERY card, because a warning that only appears where somebody already + suspects a problem teaches that absence means safe. + · The charter number is ONE knob now: AUDIT.POROSITY (sweep.js), read by priceCandidate and + flyGarden both — it was hardcoded 0.30 in two files, which is how a charter drifts. + · scorecard.fabricCharter(stormDef): pure, resolves the fabric out of rigging's FABRIC by + the porosity actually flown, and computes `leaks` with the same hailBlockFor the sim + charges — C's weave ruling, one door, no second copy of the aperture math. + · **Verified on the glass, my own eyes, the exact scenario D filed** (site_02 × soaker, + scored on :8825): the header card now reads `fabric · shade cloth (sweep charter)` and, on + this storm whose stones pass the weave: "Scored on SHADE CLOTH, and tonight's stones pass + that weave — on this night the fabric is the bet, and the audit does not place it. The + membrane line is not in these numbers: a DEAD garden table below means the cloth loses, + not the night." Directly above ✓ WINNABLE at $80 over bare 17.5 DEAD — the silence D + flagged is gone. Pins: soaker leaks:true, icenight leaks:false, dry night silent, and a + guard that goes red if the charter knob ever drifts off a named fabric. + + **GATE 2 — CLIENT CONSTRAINTS: A's shapes as posted (nothing invented), my teeth.** Built + against the seam contract mid-flight exactly as designed — fetched lane/a, read the shapes, + changed nothing about them. + · **The session** (rigging.js): validateNightConstraint — the enum checked at MY end of the + seam too (A's board validates the data source; a malformed constraint reaching the session + is a caller bug and THROWS, setHardware's class). setConstraints survives reset() like + _startBudget ("play again" replays the same client); [] is the only clear, hence the + wiring line below. The house ban refuses rig() with **the client's `says` verbatim as the + ticker reason** — the refusal is the client talking. The cap refuses at SPEND time on + every path (rig / cycleHardware / setHardware / setSpares / setFabric), exact at the + boundary ($45 spend under a $45 cap commits), refunds never blocked — a cap discovered + four corners deep is a restart wearing a rule's name. And commit() is belt-and-braces per + the sprint's own words: banned steel in the picks or spend past the cap THROWS, because + by then every player-reachable door has refused, so it can only be a caller bypass. + · **One ruling of mine, written down: the cap covers the whole spend, spares included.** + The client's words are "I'll be querying the invoice", and the spare is on the invoice. + $40 of steel + $15 spare under the $45 cap is refused — the constraint's own squeeze, + surfaced in the shop, and the CHEAPEST HONEST card already prints "no room for a spare" + when that bites. Contest at integration if the papers disagree. + · **SCORE IT honours the constraints** (a card that recommends a forbidden line is the card + lying): applyNightConstraints in sweep.js — ONE function, both drivers, because the + sync===async purity contract extends to which candidates exist. Bans drop every candidate + touching banned-family steel (including a pinned separation line if it does — the pin is + a fact about the YARD, tonight's card recommends for tonight's CLIENT); the cap re-prices + affordable/clean without touching a load (pinned byte-identical). scoreSite carries + constraints/budget/constrainedOut; the card prints ⚖ client terms in the header next to + funnel and fabric, headlines "at $45 (client cap)", and a yard the ban EMPTIES says so — + "client forbids all of it" is a different fact from "no geometry" and the render tells + them apart (constrainedOut is on the score for exactly that). + · Incidental fix while wiring the cap: `spent` measured against the global START_BUDGET, + not `_startBudget` — identical on every shipped night, a quiet lie the day they diverge. + + **MUTATIONS — eight, each applied/run/reverted, messages recorded:** + | mutation | result | + |---|---| + | 0.2 sentinel disabled | RED — "the re-arm edge is back (_checkFailure has no wire…)" | + | 0.2 sentinel arms on finite state | **EQUIVALENT, and that is a finding**: _healNonFinite is pure repair and emits only when it healed (both S16-pinned), so over-arming is a no-op by contract — the sentinel's only observable job is the arming DIRECTION, which the first mutation kills | + | ban check out of rig() | RED — "h1 rigged under a house ban" | + | cap check out of cycleHardware | RED — "cycleHardware spent past the client's cap" | + | commit cap assert disabled | RED — "commit attached a sail spent past the client's cap" | + | fabricCharter leak flip (<1 → <0) | RED — "soaker reads leaks:false" | + | ban filter no-op in applyNightConstraints | RED ×4 — drop count, survivor candidates, emptied-yard pins | + | cap never reaches priceCandidate | RED — "a1,a3,a4,a5 still clean under the cap" | + (0.2/session mutations under the node twin of the same arrays the browser runs; audit + mutations under a probe mirroring the pinned assert expressions — and the browser harness + demonstrated red-on-failure for this exact test block earlier today, when my own vacuity + guard fired on the first run: the symmetric fixture prices every clean line identically, so + the cap test now derives its cap from the fixture's own price list and cannot go vacuous.) + + **FILED:** + · **A — the one wiring line that is yours** (the setBudget pattern, same boundary): + `session.setConstraints(week.job?.constraints ?? [])` wherever main.js re-banks the shop + for the night. The `?? []` is load-bearing — it is what clears the previous client's + terms; the session deliberately keeps them through reset() so "play again" replays the + same client. Everything else on my side is live the moment that line lands. + · **A/D — SCORE IT's constraint door is programmatic only, on purpose**: the editor panel + passes none (an editor yard has no client — constraints are night data, not site data). + Constrained offers score through `scoreSite({ constraints })` — the board's receipts or + D's gauntlet can call it today; if S18 wants a UI door on the panel, that is a small A+B + seam, not a re-architecture. + · **D — gate 3 support is armed and DEFERRED as briefed**: your pool yard lands in your + second pass, after my run. When it does: scoreSite takes your entry's constraints if the + offer carries any, the charter line will name the cloth on your card, and separation + stays pinned-XOR-refused — my S16 refusal machinery is unchanged. Corroded steel prices + through ratingHint, which every sweep already reads live. + + Pushed lane/b: aa0b36a (gate 0.2), 1bcfcda (gates 0.3+2), this entry. Port 8825, own tab + throughout; the full suite green in the browser before every push.