Commit Graph

376 Commits

Author SHA1 Message Date
type-two
a1873da381 Lane E S18: [E] THREADS — correction, I invalidated the check my own entry told you to run
The gate-4 entry says to check asset_report.json's `blender` field before
building. My own run then regenerated that file, so it reads 5.0.1 while 37 of
the 39 GLBs beside it are still the 5.1.2 exports I reverted — the field now
says "you are on the right Blender" precisely when you are not.

Same defect shape as everything else this sprint hunted: a source of truth that
quietly starts answering a different question. Recorded rather than papered over,
with what is actually true of the committed tree (my two files are 5.0.1, the
other 37 plus all textures are untouched 5.1.2), why reverting was still safe
(the report's per-asset facts are identical either way, measured), and the check
that does not lie: build, then git status — if files you did not author come back
modified, you are on the wrong Blender.

The generated file is left alone deliberately. It says do-not-hand-edit, and a
doctored report is worse than a mislabelled one.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-25 19:50:56 +10:00
type-two
162b78c3e1 Lane E S18: [E] THREADS — the tier, the palette hunk, and the gate-5 seam for A
Two entries at the tail. Gate 4: the premise correction (S16 already shipped the
glasshouse; the gap was that its $320 could not be reached), the asset, the tell
measured twice, the 0.80 rung with the reasoning beside it, the five controls,
the determinism result, the Blender 5.1.2-vs-5.0.1 finding, placement facts and
the wreck apron, plus the editor palette hunk verbatim for A and the flag that
the tier is placeable — with the one-variable law restated as A's to enforce.

Gate 5: my half (two author-time pins) and the exact wiring A needs — why
renaming the structures' keys alone makes it WORSE (the anchors take their key
off the baked GLB node, so both stop matching and both corners become free),
the two world.js hunks and the validateSite refusal, and what it buys: D's
$115-vs-$45 split closes to $115 vs $90, leaving exactly the gnome's $25 as
A's ruling rather than two unknowns.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-25 19:46:06 +10:00
type-two
0a279b36f3 Lane E S18 gates 4+5: e.test — the tier's pins, and the shared-collateral-key landmine disarmed
Seven new pins, ten new rows (the two assets also add dims/nodes rows).

Gate 4 — the tier:
  · the frame BRACKETS the glass: footprint strictly contains the glasshouse's
    on both axes, head clears the ridge by 0.47 m, all four eyes above it. The
    tell is a measurement because the tell is a position.
  · the 20 m read is METALNESS not lightness: powder-coat <= 0.15, galvanised
    >= 0.6 as the control, and the paint the brighter base colour. An assert
    whose stated reason is the mechanism, so the docstring cannot be "fixed"
    the wrong way (S17's inverted-sign lesson).
  · a NEW RUNG at 0.80, pinned against the MANIFEST not a literal: above the
    pergola, below the post, collateral 'glasshouse', four agreeing sources.
  · the APEX IS REACHABLE — this one was RED by construction before this
    sprint, and its message says why. Plus the corollary: nothing but the
    glasshouse may CLAIM its key.
  · the wreck folds at one end, keeps its height, carries no glass, offers no
    anchor, and is unpriced by ruling.

Gate 5 — D's second-rust-post landmine, disarmed at author time:
  · no shipped yard gives two structures the same resolved collateral key
    (mirrors structKey() exactly), and structure ids are unique — a duplicate
    id makes structures.set() silently replace the first, which then never
    renders, never bills and never wrecks with nothing said anywhere.
  · every collateral an authored anchor names is OWNED by exactly one thing in
    that yard. RULE 2's runtime twin: RULE 2 proves a key is priced somewhere
    in the palette, this proves it is owned in the yard that names it. Zero
    owners is the gutter bug reborn; two is the landmine.

Five negative controls witnessed red in the real harness, then green: the frame
un-bracketed, the paint turned galvanised, the frame claiming the glass's key,
the anchors no longer naming the glass (the pre-sprint state), and a second
corroded post in the pool yard. Counts held at 533 throughout, so nothing
vanished while other things were red.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-25 19:46:06 +10:00
type-two
00e6b288c8 Lane E S18 gate 4: THE GLASSHOUSE TIER — the hail-net frame, and the apex made reachable
S16 shipped the glasshouse and priced it at $320. e.test said the rest in its
own words: "nothing in the sim wrecks a glasshouse yet — the value is inert
data". main.js bills collateral off a broken rig corner's baked key, and a
glasshouse rightly offers no anchors, so the most expensive object in the game
could not cost anybody a cent — RULE 2's mirror image, a price with no key that
can reach it.

DESIGN.md line 179 named the missing asset: hail nets rigged OVER glass. You
tie to the frame that straddles it. hail_net_frame_01 / _wrecked: a powder-coat
portal frame clear of the glasshouse on all four sides, head at 2.75 m to clear
the 2.28 ridge, four welded eyes at 2.690 baking collateral 'glasshouse'.

The tell is a POSITION, not a defect — the frame's numbers are good and the
hazard is where it stands. Pinned as geometry off two GLBs (footprint strictly
contains the glass; head clears the ridge) rather than as paint on one. The 20 m
read is metalness: powder-coat at 0.05 renders bright where every trusted
galvanised steel at 0.90 goes near-black with no environment map (S17's measured
lesson, applied on purpose this time).

Rung 0.80, proposal, A rules: it earns the highest rung below the honest post
(engineered frame, four footings, the only structure built to be tied to) and is
de-rated 20% for section, not condition. It usually holds — that is the tier:
the corner failure that costs a shackle on a sail post costs $320 here.

The root deliberately carries NO collateral_key. structFor() takes the first
match, so a frame claiming the glass's key would bill the panes and wreck the
frame, both papers agreeing and both wrong. That omission is gate 5 in one line.

Wreck racks at one end (0.45 in at the head, 0.45 out at the feet) after the
first cut still read as a clean level rectangle in the render. Carries no glass:
the glasshouse swaps independently. Unpriced by ruling.

ANCHOR_TYPE widened with 'hail_net_frame' (contracts.js is A's — revert and tell
me; corroded_post precedent). Manifest unambiguous: 0.80, glasshouse, 4 sources.

Determinism held: runs 2 and 3 are 56/56 byte-identical. NOTE the shipped GLBs
were exported by Blender 5.1.2 and this box has 5.0.1 — the 45-binary churn that
causes is semantically nil (60 nm accessor drift, PNGs losing sRGB/gAMA/cHRM
with identical pixels) and was reverted, not shipped. Documented in the header.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-25 19:45:42 +10:00
type-two
e6d4c36daa [I] John's ruling (declining costs standing), S18 speced, two-integrator convergence recorded — 522/0/0 2026-07-25 18:51:08 +10:00
type-two
d726f88994 Merge remote-tracking branch 'origin/main' 2026-07-25 18:45:29 +10:00
type-two
fcbeea9b40 SPRINT18 speced: John's ruling (declining costs you), the emergency callout, the glasshouse tier — lane prompts at the tail 2026-07-25 18:45:06 +10:00
type-two
a7a417c02a Merge remote-tracking branch 'origin/main'
# Conflicts:
#	THREADS.md
2026-07-21 06:35:05 +10:00
type-two
a012225259 Sprint 17 integration [I] entry: the board live, seven nights, convergence recorded 2026-07-21 06:32:13 +10:00
type-two
9498dfc1b9 S17 integration: apply C's offerBand hunk — the board stops lying about night 7 (hail on every offer card) 2026-07-21 06:25:14 +10:00
type-two
8edf461286 Merge remote-tracking branch 'origin/lane/c'
# Conflicts:
#	THREADS.md
2026-07-21 06:21:56 +10:00
type-two
3717ef0d54 Merge remote-tracking branch 'origin/lane/b'
# Conflicts:
#	THREADS.md
2026-07-21 06:21:16 +10:00
type-two
5ae696040d Lane D S17: [D] THREADS — convergence declared, the other D session's pool yard + cold-play adopted
Two Lane D sessions ran gates 3.2 + 4 in parallel; found via push rejection.
Their site_04_pool_yard + seven-night cold-play (515/0/0) STAND — dropped my
whole duplicate cut (a second, two-corroded-post pool yard + a second cold-play),
did not force, did not rebase over theirs. Verified their tree green (515/0/0)
before adding a line.

Additive-only: a measured receipt for their second-rust-post landmine (a real
two-post yard splits the exposure harnesses, exposureOf $115 vs
collateralExposure $45 — C's gate-1.2 cross going red by construction); and an
independent live repro of C's night-7 board-card omission (card "33 km/h · fine
pea stones" vs sheet "rain heavy · 44 mm/hr · hail likely") flagged as the #1
board fix. Scratch merge judged the wider tree (main + newest b/c) at 517/0/0,
per-lane sum verified, nothing lost.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-21 06:14:11 +10:00
type-two
69a24a3f70 Sprint 17 integration: the board, the terms, the pool yard — 515/0/0, [I] entry 2026-07-21 04:38:03 +10:00
type-two
d8466355e8 Lane D S17: [D] THREADS — the seven-night cold play through the board, verdicts per night
Two alternatives taken (the pool yard N1, the $45 cap N4), the marquee, the
designed loss and the fabric bet on the spine. THE WEEK HELD 7/7 · 6/7 · $401
· star 0.0 · 5 warranty jobs. Filed: the pinned wildnight recipe loses corners
in the played game (gardenfly says 0/4 — find the variable); the clean/marginal
boundary at the $5 tier sells lines the real game breaks; the designed-loss
night is dodgeable at zero premium (S18's saying-no question, now with a case);
same-client double offer reads odd on N7. Final tree 515/0/0.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-21 04:30:20 +10:00
type-two
4cdb2fead8 Lane B S17 gate 3: the corroded tier prices honestly in the card
The piece the 0.2/0.3/2 pass explicitly deferred. Pins E's corroded tier
through the card's own pricing surfaces, off E's real resolver (not a
hand-typed 0.55):

- STEEL half (rigging.selftest): factoryExtras('corroded_post') -> hint 0.55
  + collateral key; _effRating on a corroded corner is rating x 0.55, so the
  same load a carabiner holds on a sound post is over a carabiner on a
  corroded one. The rust costs a tier.
- COLLATERAL half (gardenfly.selftest, real dressed world): a node-less
  corroded placement -> collateralFor =  'the corroded post', summed by
  collateralExposure -- through the resolver, not the baked GLB value direct
  (the carport-to-null shortcut).

Cross-lane seam: the tier lives on lane/e, so both pins skip-with-disclosure
on bare lane/b (SKIPPED, visible in the report) and go live at integration.
Measured GREEN on a scratch merge of lane/a + lane/e (hint 0.55, collateral
). Browser 485/3/0, node sail 47/47 rigging 29/29.

Test-only + THREADS; adopted the landed 0.2/0.3/2 unchanged rather than
overwrite pushed work.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-21 03:59:53 +10:00
type-two
64fb25529f Lane D S17: [D] THREADS — gate 3.2 landing (the pool yard, receipts, the second-rust-post filing)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-21 03:53:46 +10:00
type-two
39701884e3 Lane D S17 gate 3.2: THE POOL YARD — authored cold, in the game only by being chosen
site_04_pool_yard: E's ring (fourteen honest noes) east, the bed poolside, ONE
corroded post in the venturi channel where the NE corner wants steel. Authored
in the editor (palette shapes, iterative SCORE IT x3, canonical export).
Gauntlet: WINNABLE at $80 — 13 quads, 6 clean, 1 marginal; cheapest hold $40
(h1,t1b,p2,p3, 92.7 FULL, no rust); every 92%-cover line routes through c1 —
clean $65 rated on t1,p1,p2,c1, UNHOLDABLE on the two shapes that pull the eye
harder. audit.html over the shipped file reproduces the card to the digit.
Separation REFUSED with receipts (bare 83.7 FULL — mild-night canon, A's 0.4).

board.js (A's granted edit): pool_yard_southerly POOL entry with the audit
receipt. d.test: +5 pins (chosen-never-scripted, ring/rust facts, judged-XOR,
wreck apron, exposure $160). gardenfly.selftest (B's file, flagged): judged
walk 3 -> 4 in the same commit that ships the yard.

Selftest 515/0/0 (510 + 5, the count moved by exactly what was added).
Mutations: 1 full-suite (finding stripped -> DOUBLE red: B's walk 'UNJUDGED'
+ my XOR pin, 513/2), 10 probed (entry deleted/re-paired/receipt stripped/
scripted-slot, gnome unpriced/rust zeroed/fence priced, apron x3) — every one
red with its own words, controls green.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-21 03:53:20 +10:00
type-two
bb8451d12e Sprint 17 pt 1 integration: the board live (510/0/0), constraint seam verified at merge, [I] entry 2026-07-21 03:14:44 +10:00
type-two
3548b6edc1 Lane C S17 gate 1 (cont.): the OFFER BAND and the PAIRING law — night 7 stops lying
Landed ON TOP of f029274 with not one line of it changed. Two Lane C sessions
ran gate 1 in parallel; I found out by having my push rejected. forecastHonest
answers "can the forecast describe this STORM" and is better than the storm-side
half I had written, so mine is deleted. These are the two things it structurally
cannot reach — it takes a def, not a pairing, and it never touches the card.

weather.js is +180/-0. The only line of theirs I touch anywhere is widening one
c.test import from { NIGHTS } to { NIGHTS, nightAt }.

1. THE OFFER BAND, and the finding that motivates it. A's card prints f.wind
   and f.stones, and under that pair NIGHT 7 LIES:
     soaker (scripted)   gusts to ~55 km/h · fine pea stones
     early buster (alt)  gusts to ~76 km/h · pea stones
   On both printed lines the soaker is the softer job. It is not: 14.9s of hail
   against 2.4s, 44 mm/hr against 16.5. The soaker's whole design is that its
   wind reads gentle and its hail is the trap, so the board recommended the trap
   in the storm's own voice. offerBand(def, lead) returns an ORDERED LIST, so
   the forecast decides which facts a night carries and a card cannot drop the
   next one added — same construction as A's stormsToPreload(nights, pool).
   Verified in the real card on :8826.

   Second finding: storm_03 and storm_03b are identical in every number the band
   prints except the change time (30s vs 18s), and the board offers exactly that
   pair on nights 5 and 7. Without the change line it offers two indistinguish-
   able jobs and calls it a choice. Pinned.

2. PAIRING_LAW. A band can be perfectly honest about a storm and still be an
   invitation to a night nobody can work. A's three POOL exclusions were prose;
   promoted to checked data with the measurement in each message, credited by
   owner (the soaker's is mine with the S16 ~31% receipt; wildnight and icenight
   are recorded as A's reasons, not re-measured by me). Absent key = unrestricted
   deliberately — inventing a refusal for a pairing nobody flew is the same
   offence inverted, and that direction is pinned too. pairingRefusals is NOT a
   filter: silently dropping an entry is a runtime surprise wearing a fix's
   clothes. Walks NIGHTS u POOL carrying the SITE: 12 pairings, 0 refusals, with
   a vacuity guard in the same case.

Mutation-checked on THIS tree after the code changed address: hail line dropped
(RED, names the storm and the seconds), soaker restriction deleted (RED x2,
including the vacuity guard), change line dropped (RED, names the two busters).
All restored, 494/0/0.

Filed in THREADS, not landed: the hud/main hunk for A (leadFor precedent), and
a floor for stoneWord — hail.size 0 words itself "fine pea stones" because
stoneWord has no floor. Their STONE_WORD_CEILING fixes the top of that range;
nothing fixes the bottom. It belongs inside forecastHonest, which is theirs.

Selftest 494/0/0 (their 490 + 4).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-21 03:07:02 +10:00
type-two
44f019f31d Merge remote-tracking branch 'origin/lane/e'
# Conflicts:
#	THREADS.md
2026-07-21 03:06:26 +10:00
type-two
4cfb227935 Merge remote-tracking branch 'origin/lane/b'
# Conflicts:
#	THREADS.md
2026-07-21 03:06:16 +10:00
type-two
895539da7c Merge remote-tracking branch 'origin/lane/c'
# Conflicts:
#	THREADS.md
2026-07-21 03:05:43 +10:00
type-two
99345f40b1 Lane A S17: B's wiring line landed — setConstraints fed at the setBudget boundary, guarded until lane/b merges, seam closed 2026-07-21 03:04:18 +10:00
type-two
5befa54feb Lane B S17: [B] THREADS — gates 0.2/0.3/2 landed, mutation table, wiring line filed for A 2026-07-21 02:57:42 +10:00
type-two
1bcfcdad67 Lane B S17 gates 0.3 + 2: the card names its cloth, the session speaks for the client
GATE 0.3 — THE CHARTER, SAID OUT LOUD (D's soaker finding, A consulted on
wording and their every-card rule adopted). The audit always flew shade cloth
and never said so; on the soaker that silence read 'WINNABLE over an all-DEAD
garden — the night is broken'. Now: AUDIT.POROSITY is the one charter knob
(sweep.js + gardenfly.js both read it), scorecard.fabricCharter() names the
fabric and whether tonight's stones pass its weave (same hailBlockFor the sim
charges), and the SCORE IT header prints 'fabric · shade cloth (sweep
charter)' on EVERY card — plus, on leaky-storm nights, A's wording: the
fabric is the bet, and the audit does not place it.

GATE 2 — CLIENT CONSTRAINTS: A's shapes (seam contract, built against as
posted), this lane's teeth.
· rigging.js: validateNightConstraint (checked enum, both ends of the seam),
  setConstraints (survives reset like _startBudget; [] is the only clear).
  The house ban refuses the pick with the CLIENT'S WORDS as the ticker
  reason; the cap refuses at SPEND time on every path (rig / cycle / set /
  spares / fabric), exact at the boundary, refunds always free — and commit
  is belt-and-braces: a caller who walked around the doors gets a THROW.
  The cap covers the whole invoice, spares included — the client queries the
  invoice, not the hardware line.
· sweep.js: applyNightConstraints, ONE function both drivers share — bans
  shrink the candidate list (a card that recommends a forbidden line is the
  card lying), the cap re-prices affordable/clean without touching a load.
· scoreSite carries constraints/budget/constrainedOut; the card prints the
  client's terms next to funnel and fabric, and tells 'no geometry' from
  'client forbids all of it'.
· spent getter now measures against _startBudget (the re-banked session was
  measuring spend against the default bank).

Selftest 485/0/0 in the browser (474 + exactly the 11 added: 1 sail, 4
session, 2 charter, 4 audit-constraints). Wiring line for A filed in THREADS:
session.setConstraints(week.job?.constraints ?? []) at the night boundary.
2026-07-21 02:45:49 +10:00
type-two
aa0b36a54c Lane B S17 gate 0.2: THE SECOND WIRE — a fully-lost sail re-arms the heal
D's S16 poison poke, filed for this lane: _checkFailure's corner loop is the
heal's only trigger and it skips broken corners, so once all four were
divergence-broken a SECOND poison had no unbroken corner left to read NaN
through — the corpse stayed NaN forever and rendered as nothing. A lost sail
is still cloth in the yard; it must LOOK lost, not vanish.

The sentinel runs ONLY on a fully-broken rig (the corner wire covers every
other case): sum pos+prev — any NaN/±Inf makes the sum non-finite (Inf−Inf is
NaN), finite cloth cannot overflow it. Branch-free O(n) adds, no mutation, so
a finite lost sail is untouched byte-for-byte.

Test replays D's gait: cascade 4/4 → 5 s finite with ZERO heals (the negative
control — the sentinel must never mistake 'lost' for 'sick') → second poison
heals in one substep, finite a full second on. Node suite 47/47.
2026-07-21 02:45:28 +10:00
type-two
f029274940 Lane C S17 gate 1 + 1.2: the honesty gate on the board, and the exposure cross
- forecastHonest(def): "a storm the forecast can't describe honestly doesn't
  get offered" as a predicate, not a sentence — validator + measurable stats +
  the stone vocabulary ceiling (STONE_WORD_CEILING 2.0: past it, "golf ball"
  undersells the ice and the word ambushes where the band can't). The band-
  containment recomputes are disclosed as structural regression armour, not
  counted as coverage.
- c.test walks NIGHTS ∪ POOL from the shipped data (the union, per A's
  stormsToPreload finding — a pool-only storm is covered the day it exists).
  Negative controls: a lying windchange, a cricket-ball stone, both refused
  by name. Lead-0 card pins: the offer card's gust/sustained figures parsed
  back out and matched against stormStats; a lead-0 offer must not hedge.
- The exposure cross (the S14 pin pattern, third outing): my failure-route
  envelope (built world, anchor collateral keys through world.collateralFor,
  the gnome per scoreRun) vs A's exposureOf — item-level equality on ALL
  THREE yards: backyard 115, corner block 205, swing lawn 255. Zero unpriced
  keys. Teeth proven in-suite: strip the carport key and the cross reds.

Selftest 490/0/0 (A's 485 + 5), browser-verified; board verified live on
:8826 — both cards print the honest lead-0 lines and the crossed dollars.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-21 02:39:07 +10:00
type-two
bfc43c6da3 Lane A S17 second shift: separation-block fabric field RULED (B's S16 ask), E's corroded-post palette hunk applied verbatim, enum widening endorsed 2026-07-21 02:22:27 +10:00
type-two
dd69a2cf6c Lane A S17 gates 0+1+2: THE JOB BOARD — two offers a morning, the chosen job IS the night
Gate 0 rulings (written, with reasoning, in THREADS):
- 0.4 hail-light balance: CANON. B's finding reproduces exactly ($4/$2 garden
  spread), but the mild-night rig market buys the STEEL and the collateral, not
  the bed — a cheap rig that fails on site_02 swings $184 and two stars against
  the same rig holding, and the cheapest HOLDING line is $40, not the $20 floor.
  Ruled for B's option (b): the separation block asks the wrong question on
  those nights; the new shape is B's and is NOT this sprint. Rain drain-weight
  lever declined at its proper price (full gauntlet re-measure, own gate).
- 0.4b gradeFor scraped/solvent >=3 STANDS on the seven-night shape, ruled on
  the arithmetic (savable 6 → solvent is 4-6 dead, which is what the copy says).
- 0.3 score-header wording consulted for B (no code from me).

Gate 1 — the board: board.js (pure data, node-testable), week.offers()/take(),
seeded from week+night via contracts' mulberry32 — no Date.now, no Math.random.
An offer carries a whole NIGHT ENTRY and take() installs it, so sheet, quote,
invoice, ledger, warranty, rep and end card all read a chosen job through the
path they already had — seven surfaces, zero changed lines. Scripted spine runs
byte-identically when nothing is taken.

Gate 2 (data half) — constraints as night data, checked enum, premium ruled
(+25% anchor ban / +20% budget cap, both UNMEASURED and flagged cut-first),
stated on the offer, the job sheet and the invoice it was paid under. ONE
calloutFee() now serves quote() and settle(). Enforcement is B's.

Two bugs found off the suite: take() stored raw pool entries (crashed quote()
on a missing pay block) → normaliseNight() split so both doors share it; and
NIGHT 1 HAD NO BOARD — the splash bypassed it — found by looking, not testing.
Pool pairings audited in the browser before shipping; both constraints checked
for soft-lock against real holding lines.

Mutation-checked ×6. One did NOT go red: "every pool storm is preloaded" passed
with the POOL source deleted, because every pool storm is also in NIGHTS — the
same coincidence that hid the calm-day bug. stormsToPreload(nights, pool) split
so it can fail. Selftest 485/0/0 (474 + 11).
2026-07-21 02:11:16 +10:00
type-two
6e0608a6fb Lane E S17 gate 3.1: THE CORRODED TIER — mutations restored, tell verified at 20 m, droop pinned to geometry
Recovers an interrupted session and finishes its verification honestly.

RESTORED (the predecessor was killed mid-mutation-check):
- build_sail_post_corroded still had negative control M1 APPLIED — clean
  galvanised steel, DROOP=0 — so both shipped GLBs were the untelled post.
  Restored: steel_weathered/rust/rust_deep, DROOP_DEG = 38.
- asset_report.json held 1 of 37 assets and contact_sheet.png was a 196 KB
  truncated write. Both were interrupted artifacts, not decisions; a clean
  rebuild restores 37 assets and a 5.07 MB 1680x4200 sheet.

DETERMINISM: 37/37 GLBs byte-identical across two consecutive full runs;
report and contact sheet byte-identical too. Zero churn on the 35 pre-existing
GLBs.

ASSERT THAT COULD NOT FAIL, KILLED: the sag pin (honestY - corrodedY > 0.05)
reads 0.060 at ZERO droop, because the eye hangs off a weld line 160 mm down
the post — measured on the M-B build, anchor at (0, 3.920, 0). It measured the
weld offset and called it a sag. Replaced with the droop ANGLE derived from
the exported anchor and pinned to baked extras (padeye_droop_deg / arm_m /
weld_y_threejs / dir_threejs), all stated in three.js coords — the axis trap
closed the swing_set way, so note and mesh can only lie together.

ASSERT WHOSE REASON WAS BACKWARDS, FIXED: the 20 m pin claimed the corroded
shaft read darker. Measured off look.html's canvas at 20 m: honest lum 50,
corroded lum 94 — it renders twice as BRIGHT. Base colour is darker but
metalness drives the pixels (gal 0.90/0.35 goes near-black with no env map;
weathered 0.55/0.60 is diffuse). Test now pins both halves and names the
mechanism the player actually sees.

Three tells split into three tests so one failure cannot mask the others —
pre-split, the M-A mutation went red on rust area and never reached the
lightness or droop asserts at all.

Mutation-checked in the browser, all three witnessed red: M-A clean steel
(1/3 + 2/3 red, 3/3 green, factory GREEN throughout — the trap it cannot see,
confirmed); M-B flat eye (3/3 red, others green); M-C baked note lies while
mesh is honest (3/3 red, proving the pin reads the extra, not a literal).

Selftest 483/0/0 (474 baseline + 9 exactly). Tell verified by looking at
20 m at the game's own camera height, screenshots taken.

editor.js untouched — palette hunk filed verbatim in THREADS for A.
contracts.js ANCHOR_TYPE widening flagged for A.
Lane D flagged: the tier is placeable, gate 3.2 unblocked.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-21 01:51:57 +10:00
type-two
a180fce8c3 WIP Lane E S17 gate 3.1: corroded tier (PREDECESSOR STATE — negative control M1 still applied)
Preserved verbatim from the interrupted session. NOTE: build_sail_post_corroded
still carries the M1 mutation (clean galvanised steel, DROOP=0), so the two GLBs
in this commit are the UNTELLED post, not the shipped asset. Restored in the
next commit after the red-check is witnessed.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-21 01:18:44 +10:00
type-two
75d5f9a4bf Lane D S17 gate 0.1: SEVEN NIGHTS — the wildnight restored at night 5 (John's ruling)
Ladder: gentle, southerly, earlybuster×site_02, southerly×swing_lawn,
WILDNIGHT×backyard, icenight×backyard (beyondSaving rides the night),
soaker×site_02. Icenight brief reverts to 'less wind than last night'
(true again); new Hendersons brief sells the pyrrhic stake. Law pins
retitled + one new ruling pin (wildnight in, known yard, before the
icenight); a.test re-pinned to the seven-shape; gradeFor clean bar
derived (held >= savable) per the S16 same-commit demand. Selftest
474/0/0; verified live on :8827.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-21 00:36:03 +10:00
type-two
a1b7d468a4 Sprint 17 plan + prompts: the book of clients pt 1 — the board; John's seven-night ruling recorded 2026-07-21 00:09:22 +10:00
type-two
f27539d716 Sprint 16 (TEETH) integration: merge lane/d (473/0/0), [I] entry — six nights live 2026-07-20 22:32:48 +10:00
type-two
f53a0d5ee9 Lane D S16: [D] THREADS — gate 4.1/4.2 wiring + eviction filing, gate 4.3 cold-play verdicts
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-20 22:23:11 +10:00
type-two
d8e7087c2c Lane D S16 gate 4.1+4.2: swing lawn re-scored (zero deltas), THE SIX-NIGHT WEEK wired
- site_03 re-scored on the post-ruling tree, S15 loop, FUNNEL ON: every number
  reproduces the S14 card to the digit (81 quads, 11 clean/16 marginal, cheapest
  honest $65 h3,t2,t2b,p1 85.3 FULL, bare 83.7, best clean 90.0, sep +6.3,
  best-reading 91.8 MARGINAL). Nothing moved; nothing to fix; B's PIN REFUSED
  (measured) card renders the finding on this yard.
- NIGHTS is six: gentle, southerly, earlybuster(s02), SOUTHERLY over the SWING
  LAWN (new site, survived storm), icenight (flag intact, no longer final),
  SOAKER over the CORNER BLOCK (C's measured pairing). Two new briefs: Ruby's
  swing set sells the crossbar trap; the Vasilaros return sells the cloth
  default the forecast argues against.
- THE STRUCTURAL CONSEQUENCE, filed loudly: six slots cannot hold five old
  storms + a survived-storm debut + the soaker. The WILD NIGHT leaves the
  rotation (every other candidate is load-bearing); storm file, tests and the
  pinned backyard separation all stand. If the eviction is wrong the fix is a
  seven-night week — one entry, a ruling.
- week asserts updated (a.test): six nights, final-night=6 both directions on
  the broke rule, three clients with night 6 a RETURN booking.
- four six-night-law pins in d.test: one new site / one new storm / never same
  night; survived-storm debut; soaker pairing (C's receipt in the message);
  beyond-saving night neither new nor final.
- hud surfaces read NIGHTS.length (splash, morning header, end card) — flagged
  for A; hardcoded 'five' would lie on every paper.
- selftest 473/0/0 (469 + 4); mutations M1 soaker→backyard, M2 debut→wildnight,
  M3 flag→final each RED with the law's own words, restored, green.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-20 21:49:58 +10:00
type-two
1073ac97e8 Sprint 16 builders integration: merge a/e/c/b (469/0/0), hud keep-both, E's palette hunks applied 2026-07-20 21:06:27 +10:00
type-two
6508d53c89 Merge remote-tracking branch 'origin/lane/b'
# Conflicts:
#	THREADS.md
#	web/world/js/hud.js
2026-07-20 20:59:28 +10:00
type-two
a7cb661b62 Merge remote-tracking branch 'origin/lane/c'
# Conflicts:
#	THREADS.md
2026-07-20 20:57:35 +10:00
type-two
186e75839d Merge remote-tracking branch 'origin/lane/e'
# Conflicts:
#	THREADS.md
2026-07-20 20:57:35 +10:00
type-two
f84e00f46b Lane B S16: THREADS — gate-2 entries (heal, record, refusals, membrane table, crossing closed); fabricnote as verdict-sibling for A's ledger merge
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-20 20:55:03 +10:00
type-two
f7a22eabb8 Lane B S16: ponding fabric-blindness RULED a known simplification — the comments stop lying
C's gate-3 finding, answered in the file it names: _applyPonding never reads
porosity, so cloth and membrane pond identically while setFabric's comment and
the cloth blurb promised shedding. Ruled, not silently fixed: every pinned
cloth number (backyard separation, the section-7 gates, C's storm_06 pins, the
S15 zero-delta lattice) was measured under fabric-blind ponding, and a pond-
physics change mid-TEETH moves them all against the one-variable law. The fix
(porosity-scaled intake + through-weave leak) wants its own gate with a full
gauntlet re-measure; C's soaker is its test case. setFabric's comment carries
the ruling, _applyPonding carries the warning, the cloth blurb drops 'sheds
water' (a player-facing claim the sim doesn't cash).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-20 20:48:34 +10:00
type-two
7a2024c2f9 Lane B S16: adopt C's gardenfly porosity hunk byte-identical — convergent, uncontested
Both lanes added the identical param (same name, same 0.30 default, one-line
rig change) the same day. C's copy taken verbatim so integration merges clean;
my default-unmoved + membrane-heavier asserts in gardenfly.selftest.js stand
and cover both copies.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-20 20:42:51 +10:00
type-two
a7e71df125 Lane C S16: gate 3.1 coda — full audit sweep receipt on the soaker (best cloth 32 DEAD across the space, bare 17.5 cross-harness identical) 2026-07-20 20:38:37 +10:00
type-two
d03712ae47 Lane C S16: gate 3 lands — the fabric bet pinned, forecast argues it, storm in the lists; selftest 438/0/0
Gate 3.1 pins (c.test): the soaker over site_02 through gardenfly, porosity
the only variable — bare <30 (17.5), best cloth line <50 (42.3, still >bare:
the leak is partial), same $75 ring on membrane >90 FULL (96.5) with lost<2
and cost<=80, $60 membrane ring wins too (68.8), separation >40 (54.2). The
inverse guard: membrane on carabiners reads WORSE than cloth (19.1/3 lost vs
24.5/2) — the F key is a bet, not an upgrade. Gate 3.3: forecastLines grows
stones + rainRate (worded, banded); stormStats.hailSize + forecastFor
hail.size band, spread 0.30, nesting/truth-holding pinned in the resolving
loop; existing card fields byte-identical (new band draws last). storm_06 in
STORM_KEYS + suite STORMS (sync assert is the tripwire). Envelope tool flown:
throat 21.55 @ 59.2, q1 17.78 (rated slot), q2 wind-coldest yet cloth-side
second-hottest — the pond's signature isolated between harnesses. Mutations,
separate runs, red-then-green: gardenfly seam hardcoded -> both 3.1 pins red;
STORM_KEYS drop -> list-sync red with diff; stormgen rng -> byte-equal red.
Browser selftest 438/0/0 (418 + 4 storm honesty + 12 stormgen + 4 gate-3).
THREADS: gate entries + D pairing receipt + B seam/finding notes.
2026-07-20 20:33:10 +10:00
type-two
458e9a5412 Lane B S16: gate 2.3 — separation pins ATTEMPTED and honestly REFUSED, with receipts
Measured post-ruling (garden_probe, funnel ON, 2026-07-20):
  site_02 x earlybuster: bare 82.6 FULL (hail 10.7 + rain 6.8) · best flown 90.2 · gain +7.6
  site_03 x southerly:   bare 83.7 FULL (hail 10.7 + rain 5.6) · best flown 89.8 · gain +6.1
Bare WINS both nights by >30 points; 'bareMustLoseBelow' cannot be written
honestly at any threshold, so per the gate's own rule this is a FINDING, not
a fudged pin. Each yard carries _separation_finding (measured refusal with
numbers + the delete-on-pin instruction); scorecard exposes it and SCORE IT's
NONE PINNED branch becomes PIN REFUSED (measured). New assert: every shipped
yard is separation-JUDGED — pinned XOR refused-with-finding; silence and
stale-finding both red. Balance fight filed in THREADS.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-20 20:32:37 +10:00
type-two
6cbae92028 Lane A S16: gate-1 THREADS entry (landing + rulings + E's flags answered); defuse the 'trampoline' bogus-type fixture (E's flag)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-20 20:29:42 +10:00
type-two
e5df63128a Lane B S16 pool: the frame-determinism bound is pinned — and it is 66.7 ms, not 83
ROADMAP carried '>83 ms determinism bound (documented, un-tested)'. Measured:
the spiral guard fires whenever a step() consumes MAX_SUBSTEPS, dropping even
a legal sub-SIM_DT residual — so the unconditionally-lossless bound is
(MAX_SUBSTEPS-1)*SIM_DT = 66.7 ms; 67-83 ms may drop up to one SIM_DT by
accumulator phase; >=83 ms always drops. Pinned AS MEASURED (no retune):
frames <=66 ms converge on the fixed trace at equal sim clocks with zero wall
time lost; one 120 ms hitch drops exactly its overflow (36.7 ms). Mutations
red-then-green: MAX_SUBSTEPS shrunk (6 s went missing); guard deleted
(deficit 3 ms vs expected 37). Test header is the documented waiver.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-20 20:25:42 +10:00
type-two
edce5c2758 Lane B S16: flyGarden grows a porosity param — the audit engine can fly membrane
Default stays the pinned 0.30 shade cloth (asserted: omitting porosity ===
explicit 0.30 to the digit, hp and every corner peak), so no pinned number
moves. porosity 0 flies genuinely heavier (per-corner strictly greater,
measured 1.23x average on the synthetic funnel yard). C's storm_06 gate-3.1
membrane-vs-cloth pin and B's membrane-balance tables ride this seam.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-20 20:25:42 +10:00