Lane B S17: [B] THREADS — gates 0.2/0.3/2 landed, mutation table, wiring line filed for A

This commit is contained in:
type-two 2026-07-21 02:57:42 +10:00
parent 1bcfcdad67
commit 5befa54feb

View File

@ -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 (InfInf 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.