HardYards/web/world/js
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
..
tests Lane A S17 gates 0+1+2: THE JOB BOARD — two offers a morning, the chosen job IS the night 2026-07-21 02:11:16 +10:00
anchor_ratings.gen.js Lane E S16 gate 5: the next temptations — glasshouse (collateral apex, $320, wreck empties not falls), pool kit (14 fence posts, 14 explicit tie_off denials, unpriced by the bike ruling), pergola (the 0.65 middle rung D endorsed, $120, partial-failure wreck). Shared-helper wrecks, deterministic (2 runs, 44 files shasum-identical, zero churn on the 31 existing GLBs); manifest gains exactly the pergola entry 2026-07-20 20:21:38 +10:00
board.js Lane A S17 gates 0+1+2: THE JOB BOARD — two offers a morning, the chosen job IS the night 2026-07-21 02:11:16 +10:00
broom.js Lane D: calibrate the douse to B's real ponds; fix the sagging-belly refusal 2026-07-17 09:23:17 +10:00
camera.js Sprint 13 gate 2.5: two camera fixes — spawn framing, aftermath cloth-swallow 2026-07-18 01:18:29 +10:00
contracts.js Lane E S16: 'pergola' enters ANCHOR_TYPE — A's file, my edit, the swing_frame precedent, flagged in THREADS. A deck is not concrete; the type string is the player's pre-rig read 2026-07-20 20:21:57 +10:00
debris.js debris: delete the dead sail.nodes seam — sail._applyDebris is the one contact model 2026-07-18 19:03:36 +10:00
editor_score.js Lane B S16: gate 2.3 — separation pins ATTEMPTED and honestly REFUSED, with receipts 2026-07-20 20:32:37 +10:00
editor_storm.js Lane C S16: gate 3 lands — the fabric bet pinned, forecast argues it, storm in the lists; selftest 438/0/0 2026-07-20 20:33:10 +10:00
editor.js 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
editor.wind.js Lane C S15: converge gate 2.2 onto B's THREADS proposal — B's filename/global/source/default taken, storm+time API kept; THREADS: seam receipt + gate-1.3 storm-side zero-delta confirmation 2026-07-20 18:23:31 +10:00
garden.js Sprint 13: garden model exported as garden.js (B's gate-1.2 blocker) + applyMute(sky,on) as a value 2026-07-18 12:44:37 +10:00
hud.js Lane A S17 gates 0+1+2: THE JOB BOARD — two offers a morning, the chosen job IS the night 2026-07-21 02:11:16 +10:00
interact.js Lane D: calibrate the douse to B's real ponds; fix the sagging-belly refusal 2026-07-17 09:23:17 +10:00
ladder.js Lane D: ladder survives a mid-carry knockdown, and the prompt names the right bracket 2026-07-18 01:00:01 +10:00
main.js Lane A S17 gates 0+1+2: THE JOB BOARD — two offers a morning, the chosen job IS the night 2026-07-21 02:11:16 +10:00
player.js Lane D: the player leans into the wind (gate 2.4 — as a root pose, not a clip) 2026-07-18 01:33:47 +10:00
player.sim.js Lane D: the player leans into the wind (gate 2.4 — as a root pose, not a clip) 2026-07-18 01:33:47 +10:00
ratings.js Lane E S15 gate 1.2: ratings.js — factoryExtras(type), the runtime end of the manifest; refuses to guess for ambiguous types, warns once 2026-07-20 17:49:38 +10:00
rigging.js Lane B S16: ponding fabric-blindness RULED a known simplification — the comments stop lying 2026-07-20 20:48:34 +10:00
rigging.selftest.js Lane B S16: gate 2.2 THE RECORD — the fabric bet is on the paperwork 2026-07-20 20:25:22 +10:00
sail.js Lane B S16: ponding fabric-blindness RULED a known simplification — the comments stop lying 2026-07-20 20:48:34 +10:00
sail.selftest.js Lane B S16 pool: the frame-determinism bound is pinned — and it is 66.7 ms, not 83 2026-07-20 20:25:42 +10:00
skyfx.js Lane C S13 gate 2.3 + D's sliver: ambient leaves from 30 km/h; hail pool hides at zero 2026-07-18 11:51:26 +10:00
stormgen.js Lane C S16: makeStorm(seed) — seeded storms inside authored envelopes (gate 3.2) 2026-07-20 20:11:34 +10:00
testkit.js Gate 0: name the harness dispute's cause; make skips real (testkit) 2026-07-17 10:21:01 +10:00
weather.core.js Lane C S16: gate 3 lands — the fabric bet pinned, forecast argues it, storm in the lists; selftest 438/0/0 2026-07-20 20:33:10 +10:00
weather.js Lane C S16: gate 3 lands — the fabric bet pinned, forecast argues it, storm in the lists; selftest 438/0/0 2026-07-20 20:33:10 +10:00
week.js Lane A S17 gates 0+1+2: THE JOB BOARD — two offers a morning, the chosen job IS the night 2026-07-21 02:11:16 +10:00
world.js Sprint 15 integration: merge all lanes (418/0/0), apply E's world.js manifest patch, [I] entry 2026-07-20 19:38:11 +10:00