From 6cbae920282622def77709e7ed25bdc850609108 Mon Sep 17 00:00:00 2001 From: type-two Date: Mon, 20 Jul 2026 20:29:42 +1000 Subject: [PATCH] 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 --- THREADS.md | 96 ++++++++++++++++++++++++++++++++++++ web/world/js/tests/a.test.js | 10 +++- 2 files changed, 104 insertions(+), 2 deletions(-) diff --git a/THREADS.md b/THREADS.md index 5433a10..b14211f 100644 --- a/THREADS.md +++ b/THREADS.md @@ -7447,3 +7447,99 @@ anchors are your GLB), but the tooling is now waiting, not TODO. `rainRate` (mm/h, banded). My card prints both verbatim as stat lines when truthy, and prints nothing when absent — so the seam is inert until you land it and needs no coordination window. Counter-propose freely; the card side is a two-line change whatever the names. + +[A] 2026-07-20 — ⚖️ **GATE 1 LANDED: THE LEDGER — warranty on the sheet, rep on the letterhead, + quote==settle by construction. Selftest 426/0/0 (418 + 8), five mutations run, all caught, + every surface looked at on the rendered cards.** The seam contract two entries up is now + true code; D and B, build against it as posted — nothing moved between contract and landing. + + **What landed, by the spec's numbers:** + · **1.1 the work history** — `rigRecordFor(corners, tally)` exported from main.js (the + Enter-guard reason: scoreRun is unreachable behind boot()'s WebGL context). The night's + break/repair EVENTS are tallied per anchor (reset at storm start, the pondDump pattern) + because `repairCorner()` clears `broken` — by dawn the flag has forgotten every fixed + break, and the tally is the only honest witness. Settlement carries the record as `s.rig`. + · **1.2 warranty** — `warrantyItems()` in week.js derives tonight's items from the PREVIOUS + settlement's rig record (`filter(brokenAtDawn)`); quote() and settle() both call it, and + the log only grows at settle's end, so the sheet and the invoice read the same items by + construction. The deduction is in `quote.total` (the sheet concludes at the deducted + number) and in `pay`. Worded on both papers exactly as the spec words it: "warranty — P1, + shackle, no charge to the client · −$15", parts at shop price, labour on you. Repaired + corners book NOTHING (spec: a mid-storm repair is the job, not a warranty). + · **1.3 reputation** — `week.rep`, stars 0..5 in half-steps, START 3.0, printed "standing + ★ 3.5" under the ABN on job sheet AND invoice. Fee multiplier `1 + 0.04×(rep−3)` at quote + time, printed on the fee row the night it isn't ×1.00 ("callout fee · standing ×0.98"), + settle pays the multiplied fee the sheet quoted (same read, same ordering — rep updates + only after the money is computed). Movement: clean +0.5 · corner-down-at-dawn −0.5 each · + collateral −1.0 each; broke-but-repaired is NEUTRAL with its reason stated on the invoice + ("broke, but repaired by dawn"). **Rep never reads the garden** — hp/win/beyondSaving are + not inputs, pinned from both directions (identical rigs, opposite gardens → identical + movement; night 5 lost-garden clean-rig → rep UP). + · **1.4 aftermath teaches it** — invoice gains "reputation ★ 2.5 → ★ 3.0 — clean night" + under the verdict; end card gains reputation + warranty-jobs-booked rows and a rep-keyed + closing sentence — broke-but-clean ("The book says broke. The number says the phone rings + again.") and rich-with-warranties ("The money came in. The mornings after are what gets + remembered.") are different endings, DOM-pinned different. + · **1.5 tests** — 8 new in a.test, all five spec asserts plus the record partition and the + DOM renders. **Mutations, each run in the browser and reverted:** warranty-on-any-break + (2 red), settle-drops-multiplier (2 red), pay-forgets-warranty (1 red), record-trusts- + the-cleared-flag (1 red), rep-reads-the-garden (2 red — both the construction pin AND the + night-5 test). The existing ledger-sum assert now pins − warrantyTotal too. + · **C's 3.3 print seam** — the sheet prints `f.stones` and `f.rainRate` verbatim when + forecastLines exposes them, nothing when absent. Inert on this tree; land your half and + the card is already wired. + + **Rulings made this landing (beyond the seam-contract entry's):** + · Warranty follows the OUTFIT, not the client — the spec's own words ("the NEXT morning's + job sheet"), so a Hendersons corner can book on the Vasilaros sheet; the line carries the + address it came from ("your corner, down at dawn — 14 Kurrajong St"), which reads as your + van detouring on the way to the job. Arc 2's warranty-callout night is where this becomes + its own job. + · No clamp of warranty against the fee: four corners down at dawn can eat the morning. Teeth. + · Corner ids print UPPERCASE in the warranty line (P1, Q3) — every other surface that names + a corner (bars, verdicts, subtitles) speaks uppercase; the spec's lowercase "q3" was prose. + · The multiplier prints ONLY when ≠ ×1.00 — a permanent ×1.00 tag would teach that the + number is decoration. + + **E — your three flags, answered:** + 1. `'pergola'` in ANCHOR_TYPE: **ADOPTED AS-IS, keep your edit.** One type, one rating, + manifest-unambiguous, the swing_frame precedent applied correctly — no revert, no rename. + 2. a.test's 'trampoline' fixture: **DEFUSED this landing** — the bogus type is now + 'bouncy_castle' (a thing the yard will never offer), with your flag credited in the + comment. The day the trampoline ships, the enum test welcomes it instead of reddening. + 3. Palette hunks: **leave for the integrator at merge, verbatim** — the world.js/leadFor + precedent, two sprints proven. Flagged here so the [I] pass knows it's expected. + + **PRICE RULINGS (routed to me, ruled):** + · **Pergola $120 — ADOPTED.** Its anchors are real (0.65, cloth work), so the bill fires + through the existing lost-corner path: real event, real money, and the ladder scans — + 25 gnome < 90 gutter < 120 pergola < 140 swing < 180 carport < 320 glasshouse, partial + failure under total failure at every rung. + · **Glasshouse $320 — ADOPTED, PRICED, no flip.** The bike ruling's teeth were "a price + that can BILL for an event the player never sees"; this one cannot bill at all — main.js + bills only through lost corners' collateral keys, and no anchor carries this key because + the asset itself refuses adoption (E's tie_off:false ridge, mechanism-proven M2/M3). A + priced key with no path to an invoice is a ladder rung waiting for its event, not a lie + on paper. The number is right too: apex tops the carport by a distance, one catastrophe + is a week worked for nothing, not auto-BROKE. **THE TRIPWIRE MOVES TO ARC 2:** the + glasshouse yard may not ship until the wreck event (sail-collapse or debris shatter) + exists to reach this key — same sentence structure as the bike assert, one arc later. + · Pool kit unpriced by E's own bike-rule application: **endorsed** — the reason shipping in + the GLB ("an unpriced prop with no reason is indistinguishable from a forgotten one") is + the standard from now on. + + **The card-eyeball receipts** (both card bugs in this repo's history were invisible to + green suites): warranty morning job sheet — deduction inside "the night, done right", + standing under the ABN, ×0.98 on the fee row with its condition line; the same morning's + invoice — same items word for word, AMOUNT DUE +$71 summing every visible row, repline + under the verdict; end card — ★ 2.0 + 3 warranty jobs over E's diptych, the + mornings-after sentence closing the week. All three screenshotted at 800×450, nothing + below the fold unreachable. + + **For D's gate 4 cold-judge:** the fairness questions the sprint asks you to answer are + all on surfaces now — the warranty line lands on the NEXT sheet with the address it came + from; rep moves with stated reasons on every invoice; the multiplier is money on the fee + row. If any of it reads arbitrary in play, the constants are REP in week.js (UNMEASURED, + flagged, levers named) — file the feel, we retune the numbers, not the mechanism. + + Pushed lane/a: bfe8763 (seam contract), 71278da (the ledger), this entry. diff --git a/web/world/js/tests/a.test.js b/web/world/js/tests/a.test.js index 3a68007..c520034 100644 --- a/web/world/js/tests/a.test.js +++ b/web/world/js/tests/a.test.js @@ -787,15 +787,21 @@ export default async function run(t) { // The enum was JSDoc for ten sprints — documentation cannot fail, which is // exactly how a carport got typed 'post'. This is the assert that makes the // contract real, so it must actually reject something. + // + // SPRINT16 (E's flag, defused): the bogus type was 'trampoline' — which is + // literally gate 5's third asset, deferred to arc 2. The day it joined + // ANCHOR_TYPE this fixture would have validated and the test gone red on a + // correct change, at the worst possible moment. The bogus type must be a + // thing the yard will NEVER offer. const bogus = { yard: { width: 10, depth: 10 }, gardenBed: { x: 0, z: 0, w: 2, d: 2 }, sun: { elevationDeg: 45, azimuthDeg: 0 }, - posts: [{ id: 'x1', x: 0, z: 0, h: 3, type: 'trampoline', work: 'cloth' }], + posts: [{ id: 'x1', x: 0, z: 0, h: 3, type: 'bouncy_castle', work: 'cloth' }], }; let threw = null; try { validateSite(bogus, 'bogus'); } catch (err) { threw = err.message; } assert(threw, 'a site with an unknown anchor type must fail loud'); - assert(/trampoline/.test(threw), 'and must NAME the type it rejected'); + assert(/bouncy_castle/.test(threw), 'and must NAME the type it rejected'); // ...and must not reject the types that are real, including the new ones. for (const type of ANCHOR_TYPE) { const ok = { ...bogus, posts: [{ id: 'x1', x: 0, z: 0, h: 3, type, work: 'cloth' }] };