Compare commits

...

3 Commits

Author SHA1 Message Date
type-two
008b78a0d4 Sprint 14 integration: merge all lanes (406/0/0), fix palette _v1 suffix bug, [I] entry 2026-07-18 17:58:44 +10:00
type-two
0414d34b9e Lane D S14: THREADS — gate 3.2 cold authoring pass, and the palette ships both new props inert
Headline for A: editor.js palette entries 239/243/257/260 omit the _v1 suffix every
other entry carries, so swing_set_01 and tree_jacaranda_01 404, never draw, and
adopt at ratingHint 1.00 instead of E's designed 0.45 and 0.95/0.52/0.40.
adoptAnchor's `rating_hint ?? 1` turns a missing model into the best steel in the
game, and the palette writes the bad name into the exported site JSON. Negative-
controlled both directions on a local patch; editor.js untouched on lane/d.

Also: site_03 candidate authored, scored (82.5 s, winnable at $80, 11 clean of 81)
and played (trap bites: t1c breaks, 83.9 vs a bare 83.7). Phantom sail verified
dead across a live site transition. Friction filed by owner; three candidate
findings checked and withdrawn.

Selftest 406/0/0.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-18 17:45:13 +10:00
type-two
0b858abc9d Lane D S14: site_03_swing_lawn — the site_03 candidate, authored cold in the editor
Gate 3.2. Data only; inert until a week.js NIGHTS entry names it.

SCORE IT (storm_03_southerly, funnel ON, 11 anchors, 82.5 s):
WINNABLE at $80 — 81 quads in band, 11 clean, 16 marginal. Cheapest honest
line h3,t2,t2b,p1 at $65. Bare bed 83.7 FULL, best clean 90.0, separation
+6.3 HP. The best-READING line is MARGINAL at 91.8 — the prettiest number in
the yard is the one that breaks. Collateral exposure $230 on an $80 job.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-18 17:32:27 +10:00
3 changed files with 517 additions and 4 deletions

View File

@ -6529,3 +6529,277 @@ anchors are your GLB), but the tooling is now waiting, not TODO.
is per spec and I'd rather be slow than wrong, but on a yard you're iterating cold that is a
real wait. If it bites, say so — the `FLY_CAP` (12) and the sweep are both knobs I can turn,
and I'd rather hear it from someone using it in anger than guess.
[D] 2026-07-18 — 🏡 **GATE 3.2 — I AUTHORED A THIRD YARD COLD IN THE EDITOR, AND THE EDITOR IS
SHIPPING BOTH OF E'S NEW PROPS INERT.** Site JSON landed on lane/d as the site_03 CANDIDATE,
awaiting John's gate-4 branch call. Selftest **406/0/0** on my tree with it landed. No JSON
hand-editing and no console for any of the authoring — one exception, declared at the bottom.
**🔴 THE HEADLINE, AND IT IS A's FILE: the palette's two newest entries omit the `_v1` suffix
every other entry carries, so `swing_set_01` and `tree_jacaranda_01` 404, never draw, and
adopt at ratingHint 1.00.** Found in the first ten minutes of placing.
· **Receipt, from the network log:** `GET /web/world/models/swing_set_01.glb → 404 File not
found`. The shipped asset is `swing_set_01_v1.glb`, and it preloads **200 OK** under its
real name three lines earlier in the same log. Same for `tree_jacaranda_01`.
· **Source:** `editor.js` 239/243 (`model: 'swing_set_01'`, `wreckedModel:
'swing_set_01_wrecked'`) and 257/260 (`model: 'tree_jacaranda_01'`). The other nine palette
entries all carry `_v1`. (`nodeNamesFor` at 385-398 also omits `_v1` — that one is CORRECT,
those are scene-node names, not files. I checked before filing.)
· **Consequence, read straight off A's own SELECTED panel:**
| prop | E designed | editor adopted |
|---|---|---|
| swing_set_01 `s1_f1` / `s1_f2` | 0.45 / 0.45 | **1.00 / 1.00** |
| tree_jacaranda_01 `t1` / `t1b` / `t1c` | 0.95 / 0.52 / 0.40 | **1.00 / 1.00 / 1.00** |
Neither prop renders — you get a selection ring on empty grass. And the yard still reads
**VALID — the game can boot this**.
· **This is E's GAP 1 exactly, one layer up.** `adoptAnchor` does `rating_hint ?? 1`, so a
model that 404s doesn't fail — it becomes the best steel in the game. A's own ruling says
the 0.45 "is the prop's entire reason to exist" and that softening it "would delete the
honest middle the palette was missing". The 404 deletes it. The jacaranda's whole design —
**"gum: climb freely, pay 24%. Jacaranda: climb at all, pay 58%"** — becomes three perfect
anchors, i.e. a better tree than the gum at every rung. Both props gate 3.1 built so that
gate 3.2 could ask a real question, and neither was asking it.
· **It propagates into the DATA.** The palette's `make()` writes the model string into the
site JSON, so the first editor-authored yard using either prop ships a permanently broken
model reference. This is not just an editor-preview bug.
· **Gate 1's promise holds and is not enough.** A wrote that the palette "structurally cannot
offer a prop that would produce a site `validateSite` rejects" — true, and irrelevant here,
because `validateSite` cannot open a GLB (A's own words when they took the `tie_off`
runtime half). Nothing in 406 tests that a palette model name resolves to a file.
· **Negative-controlled in both directions.** With the four names corrected locally:
`swing_set_01_v1``s1_f1`/`s1_f2` **hint 0.45**; `tree_jacaranda_01_v1` → **0.95 / 0.52 /
0.40**; both props draw. Reverted before landing — **the fix is A's, and `editor.js` is
untouched on lane/d.** I authored the yard on that local patch, the same way B and C
developed against A's import line without landing it. Everything below was measured on the
corrected palette, so the numbers describe the yard A's one-line fix will produce.
· **The assert that would have caught it** is one line in the round-trip test A already
wrote, since it dresses the world: every palette item's model must resolve. A's adoption
check keys on `collateral`, which the swing set HAS — so the existing check passes while
the mesh is missing and the hint is a lie.
**🏡 THE YARD — `site_03_swing_lawn`, "The Delaneys' back lawn". 24×16, 11 anchors.**
The thesis: **the good steel is all LOW and the only height is bad.** Three temptations,
three different lies, and the blurb sells all three — *"Swing set, big jacaranda, house right
there — you'll have no trouble finding something to tie to."*
| anchor | rating | the lie |
|---|---|---|
| `s1_f1` `s1_f2` swing apexes | 0.45 | the crossbar between them is a dead-level 2.05 m rail spanning 2.3 m and is NOT an anchor. Blowing an apex bills **$140** |
| `t1` jacaranda low fork | 0.95 | genuinely excellent — but it is 2.5 m up and cuts the sail flat |
| `t1b` / `t1c` jacaranda height | 0.52 / 0.40 | where the sail wants its high corner. Height costs 58% here |
| `h1` `h2` `h3` fascia | 0.35 | the familiar lie, and takes the **$90** gutter |
| `t2` / `t2b` gum | 1.00 / 0.88 | the best steel in the yard, parked 9 m away on the WRONG SIDE on purpose |
| `p1` post | 1.00 | one honest corner. You need four |
**The wind is the yard's personality, not decoration.** The venturi is the real gap between
the shed and the west end of the house — I placed the throat by clicking that gap and set the
axis to the slot's true orientation (90°, running north-south), *not* to whatever maximised
alignment. C's panel then told me what that geometry was worth, live: **align 62%, peak
×1.28, fastest 14.96 m/s at (-8.3,-4.4)**. Throat sits **3.0 m from the swing set's apexes**,
inside r=5 — so the tempting middle option is also the windy one. Deliberately gentler than
the corner block (100%, ×1.46): **that yard keeps the crown for worst weather and worst bill.**
**SCORE IT** — storm_03_southerly, FUNNEL ON, 11 anchors dressed, **82.5 s**:
**WINNABLE at $80** · 81 quads in band · **11 clean** · 16 marginal ·
cheapest honest `h3,t2,t2b,p1` $65 (holds at $55), 22 m², 85.3 FULL ·
bare bed **83.7** → best clean `h3,t1c,t2,p1` **90.0**, separation **+6.3 HP** ·
margin flags: t2b 0%, t1/t1b/p1/s1_f1 all 1% · collateral exposure **$230 on an $80 job**.
The card's own warning is the yard's design in one line: **the best-READING line
`t1c,t2,t2b,s1_f2` is MARGINAL at 91.8 FULL.** The prettiest number in the yard is the one
that breaks.
**🎮 THEN I PLAYED IT** (scratch branch `scratch/laneD-play-site03`, night 2 → my yard; A's
`week.js` is untouched on lane/d, exactly as in Sprint 12).
· **The job sheet reads.** JOB 1042, the Delaneys, 31 Ferndale Ave, NIGHT 2 OF 5, SOUTHERLY
BUSTER, and my blurb landing on the letterhead as the cover story. $122 the night, $80 bank.
· **The yard reads from the spawn.** All three temptations visible without moving: the three
fascia rings, the jacaranda's ladder of rings climbing away, and the swing set's two apex
rings **with the crossbar bare between them**. The rail is obviously level, obviously
spanning, and has no ring on it. E's prop does exactly what it was built to do. The HUD
types it `swing_frame`, so the player's pre-rig read is honest — and it does NOT distinguish
the two tree species, so "which tree" is answered by looking at the yard (lilac vs sage),
not by reading a list. That is the right place for it.
· **The trap bites, and it bites honestly.** Flew the marginal best-reading line at
affordable hardware ($60): **`t1c` broke** — the 0.40 limb, the exact corner the card
flagged — and the garden finished **83.9 FULL against a bare bed of 83.7**. Rigging the
prettiest line in the yard was worth **+0.2 HP over doing nothing.** Flew the cheapest
honest line at the same money: **`h3` broke**, 85.2 FULL, and h3 blowing bills the $90
gutter. At full-strength hardware ($120 — over budget) all three lines are clean.
**That is the yard: you cannot afford top steel on four corners, and it punishes which one
you skimp on.**
· **B's card and the real game agree on my yard**: card 90.0 → played **90.7**; card 91.8 →
played **93.6**. Two chains, one number, on a yard neither was tuned against.
· **My own lane, on editor-authored geometry.** `needsLadder` keys on `work === 'bracket'`,
and A's palette emits `work` per anchor — so **the ladder followed the site data with zero
code change**, which closes the handoff I asked A for in Sprint 10 ("emit `work` per anchor
and the ladder follows the site"). On this yard the three fascia corners are both the 0.35
lie AND the only ladder job: the cheapest-looking corners are the slowest to repair. The
shed renders at (-9,-5) and `shed_table` at (3.32,7.75) — **A's NaN-quaternion fix confirmed
on a yard built after it.**
**👻 PHANTOM SAIL — DEAD, verified in play.** Rigged `p1,p2,p3,p4` on backyard_01, then
`loadSiteInto('site_03_swing_lawn')`:
| | before | after |
|---|---|---|
| `rig.rigged` | true | **false** |
| `sailView` | present | **null** |
| in scene | true | **false** |
A's fix holds across a live site transition, which is my Sprint-13 sighting reproduced and
closed. Visually confirmed too: no cloth behind the splash card on the new yard.
**🧰 FRICTION, BY OWNER.**
· **A — number fields commit on BLUR only; Enter does nothing.** Typed `-6` into the house's
z, pressed Enter, and the field read `-6` while the site JSON still read `1.501` — the house
was standing on the garden bed and the bed had vanished under it. Only clicking elsewhere
committed. It mostly self-heals for a human (clicking the next thing blurs), but for the
duration the panel and the world disagree with no visual tell, and I lost real time
believing the bed had been deleted. Enter should commit.
· **A — the editor places objects outside the yard without a word.** My first bike landed at
**z = 8.699 in a 16 m yard** (z ∈ [-8, 8]), outside the fence, and VALIDATION still said
"VALID — the game can boot this". Which is true. But nobody means to put the bike in the
neighbour's yard.
· **A + B — there is no `separation` field anywhere in the editor, and B's own card asks for
one.** The card says, correctly, that "a shipping site should pin one: it is the difference
between 'a sail helps here' and 'a sail is the point of this night'." The editor cannot
comply. I shipped without one and said so in `_why` rather than hand-editing it in. Either
the SITE panel grows the field or the card stops asking.
· **A — zoom is mouse-wheel only.** No keyboard, no buttons. Minor, but it is the one camera
control with no alternative on a page that ships publicly.
· **B — the 82.5 s blocking score converted the editor from an iterative tool into a batch
one, and that is the honest answer to "what did it cost you".** Mine ran **82.5 s against
the integrator's 75 s on site_02** — 11 anchors / 81 candidate quads vs 10 / 66, and it
scales like C(n,4), so this gets worse with exactly the yards an editor makes easy to build.
**Everything I know about my yard came from ONE run.** I did not tune the yard against the
score; I designed it, scored it once, and shipped what that run said, because a second
opinion cost 82 s of a page that looks crashed. I would have moved the bed and re-scored if
it had been 8 s. **If gate 4 picks "more sites", a responsive score is the difference
between authoring and guessing** — and I'd take a progress tick and a yielded loop over raw
speed, because the worst part is not the wait, it's not knowing whether it died.
· **B + C — two storm pickers, independently defaulted.** SCORE IT opened on `02_wildnight`
while WIND opened on `03_southerly`. Scoring against one storm while reading the other's
wind field is a quiet way to be wrong, and I only caught it because I went looking. One
storm selection, shared.
· **E — the palette prose is doing real work.** Every button's tooltip is the design argument
("the crossbar LOOKS like the answer and is not an anchor"). I chose props by reading the
palette. That is what it is for and it worked.
· **E + A — `sail_post`'s audited `top_anchor 0.90` never reaches the runtime.** Every post on
my yard **and on shipped backyard_01** adopts at `ratingHint 1.00`, and posts carry no
`tieOff` field at all — they are constructed anchors, never GLB-adopted, so the extra is
never read. E's audit table row is a document and nothing asserts it. Either the 0.90 is
meant to bite (and every post in the game has been 11% stronger than its asset says) or the
row should say "constructed at 1.00". I corrected my own `_design` after measuring it.
**✅ WHAT SANG, because the investment is the story too.**
· **The SELECTED panel's live anchor readout is why the headline bug took ten minutes instead
of a sprint.** It lists the anchors as ADOPTED FROM THE DRESSED WORLD with their hints, not
as declared — so `hint 1.00` sat there in a warning-coloured badge next to a prop I knew was
0.45. Showing the adopted value is the entire reason that bug was findable.
· **The editor renders the real dressed world**, so a missing prop is visible by absence. A
diagram would have drawn me a swing set that isn't there.
· **`mountPanel` ordering held**: five panels from four lanes on one rail, no collisions, and
C's wind panel is the best surface on the page — I placed a venturi by clicking a gap and
never once wanted a private harness.
· **The EXPORT ≠ SHIPPED note**, which lists four steps including "a cold playthrough by
someone who did not author it". A tool that tells you it isn't finished.
· Text fields survive `markDirty` re-render with focus and caret intact — typed 23 characters
into `name` and all 23 landed.
**🔍 THREE THINGS I CHECKED AND DID NOT FILE**, because measure-don't-reason cuts both ways:
the side rail DOES scroll (`overflow-y:auto`, scrollHeight 3237) — my wheel events were a
tooling artifact, not a bug; the HUD's "anchors 1" was a stale text read and the HUD is
correct (it showed 11); and the template's 5×3.5 m bed is NOT below an audit floor — I went to
`sweep.js` and `AUDIT.BAND {lo:18,hi:45}` is the SAIL QUAD band, not the bed. I had that one
written up as a finding before I checked.
**DECLARED, since gate 3.2 is a discipline test:** the yard's geometry, every placement, the
wind block, the blurb and both note blocks came out of the editor and were transcribed from
its own canonical export. Two hand edits after the fact, both prose, both disclosed: the local
`_v1` palette patch described above (not landed), and correcting my `_design`'s claim that p1
is 0.90 once play measured it at 1.00 — I would rather hand-edit a note than ship a false
number in a level's design doc.
**site_03_swing_lawn is landed on lane/d as DATA ONLY and is inert** — nothing reaches it
until a `week.js` NIGHTS entry names it, and that entry lives only on my scratch branch. It is
the **site_03 CANDIDATE awaiting John's gate-4 branch decision**. If the call is "more sites",
it is a night that already reads, already scores winnable-but-mean, and has been played. It
would take night 2 (southerly) and relieve backyard_01 of one of its four nights.
[I] 2026-07-18 — **SPRINT 14 INTEGRATION (main).** All five lanes merged; selftest **406/0/0** on the
merged tree, the exact per-lane sum (362 + A 11 + B 13 + C 6 + E 14), verified in the browser.
The yard editor exists, it works, and **three lanes built into one page with ZERO code conflicts**
— only THREADS. A's seam contract, published on day one before the implementation was finished,
is the reason; it is the `.letterhead` pattern proven at a much larger scale and it should be the
default whenever two lanes must share a surface.
**Integrator edits, both because the owning lane had finished (the S13 precedent):**
· Mounted B's and C's panels in `editor.html` — one import line each, which is all either lane
ever asked A for. Inside the try/catch on purpose: a panel that throws should say so on the
glass, not leave a hole in the rail.
· **Fixed D's headline bug in `editor.js`** — the palette shipped E's two new props with the
`_v1` suffix missing, so both GLBs 404'd, never drew, and — because `adoptAnchor` does
`rating_hint ?? 1`**a missing model silently became the best steel in the game** (swing
apexes 1.00 instead of E's 0.45; jacaranda 1.00/1.00/1.00 instead of 0.95/0.52/0.40), while the
yard still validated VALID. D negative-controlled it both directions on a local patch they
deliberately did not land. Verified my fix through the editor's REAL placement path (click the
palette, click the ground): `s1_f1=0.45 s1_f2=0.45`. Note the shape for the manual: this is
E's own `tie_off` lesson wearing a filename — **silence is not neutral wherever the default is
generous.**
**⚠️ CARRIED TO SPRINT 15, AND IT IS A SHIPPED BALANCE BUG, NOT AN EDITOR ONE.** D found it and
I confirmed it end to end: the factory bakes `rating_hint = 0.9` on `sail_post`'s `top_anchor`,
but every post in `backyard_01.json` (and site_02) is a plain data entry with **no `node`**, so
`adoptAnchor` never runs for them and they all default to **1.00**. Every honest post in the
shipped game is 10% stronger than E designed it, and has been for as long as posts have been
data. **I did not fix this at integration and nobody should hot-fix it**: it moves balance across
both shipped yards, and A's `separation` block pins measured hp numbers through the real chain
while B's audit tables and D's played numbers all sit on the current value. It is a RULING (A) +
a re-measure (B) + a re-play (D), which is a gate, not a patch.
🔧 **THE REMOTE WAS RENAMED MID-SPRINT — `monster/shades` → `monster/hardyards`**, via the Gitea
web UI at 09:02 (matching the repo to the game's name). Nothing was lost; every ref was intact
under the new name. D hit it as `Cannot find repository` and correctly REFUSED to create a repo
or rewrite the remote to force a push — they committed locally and reported instead, which is
exactly right and is why their work survived. All six checkouts are repointed and D's two commits
are pushed. **If a push ever fails with "cannot find repository", check for a rename before
assuming loss: `git ls-remote ssh://git@100.71.119.27:222/monster/<newname>.git`.**
**The sprint's real argument, in one line: the editor found NINE bugs before anyone authored a
yard with it**, and three were live on the public URL — a graybox house slab across site_02's
north horizon, the Hendersons' shed which has NEVER rendered (an `undefined` rotation → NaN
matrix → three.js silently declines to draw, no throw, no warning), and boot failures written
into a `display:none` div so a stranger got a blank page. None was findable from a bench. All
were findable by standing in the yard and looking, which is the entire thesis of gate 1.
**`return t.skip(msg)` was a fake pass** (A): `Suite.skip()` pushes a NEW result while the
current test still records `pass`. I grepped every suite — **confined to a.test.js, four
instances, all fixed**; B, C, D, E and balance.test were clean, so the repo's counts were never
materially inflated. Worth knowing WHY those four were exposed: they guard on `dressed`, and
C's S13 landmine is that `dress()` throws silently without the importmap — two bugs that compose
into "green because nothing ran". selftest.html carries the importmap, so they were genuinely
running.
**Gate 3.2 delivered: `site_03_swing_lawn`, "The Delaneys' back lawn"** — authored COLD by D in
the editor, no JSON, no console. Thesis: *the good steel is all low and the only height is bad.*
Scored winnable at $80 (11 clean lines, cheapest honest $65, collateral $230 on an $80 job),
played on a scratch branch, and the trap bit exactly as designed — the prettiest line finished
**83.9 against a bare bed's 83.7**, i.e. worth +0.2 HP. Card and game agreed to a point. **It is
a CANDIDATE, inert until a NIGHTS entry names it, and that is gate 4's call, not mine.**
Pool, by owner: **B** — the score is 7582 s with the UI thread fully blocked, which made the
editor *batch, not iterative* (D scored once and shipped that run rather than tuning; D's words
are the evidence, and a progress tick may matter more than raw speed). **A** — number fields
commit on blur only (Enter does nothing; D lost real time to a house sitting on the garden bed
while the panel read the new value); objects place outside the fence silently and still read
VALID; zoom is wheel-only. **A+B** — no `separation` field exists in the editor while B's card
says a shipping site should pin one. **B+C** — two independently-defaulted storm pickers (D
scored the wildnight while viewing the southerly). **E+A** — the `sail_post` hint above.
**Gate 4 is open and it is now the only thing standing between this project and its next
direction: John plays the week.** Nine sprints. The editor has made "more sites" nearly free and
D has a candidate yard sitting ready; reputation/warranty and heatwave are unchanged in cost.
That choice is his and the game is the best argument for making it that it has ever been.

View File

@ -0,0 +1,232 @@
{
"id": "site_03_swing_lawn",
"name": "The Delaneys' back lawn",
"blurb": "Swing set, big jacaranda, house right there — you'll have no trouble finding something to tie to.",
"_design": [
"THE YARD WHERE THE GOOD STEEL IS ALL LOW AND THE ONLY HEIGHT IS BAD.",
"Three temptations, three different lies:",
" - the swing set's crossbar is a dead-level rail at 2.05 m spanning 2.3 m and is NOT",
" an anchor (tie_off:false). The two apexes beside it are honest steel but only 0.45,",
" and blowing one bills $140.",
" - the jacaranda forks low and excellent (0.95) then falls off a cliff (0.52 / 0.40).",
" A sail wants height on its high corner; on this tree height costs 58%, against 24%",
" up a gum. That is the \"which tree\" question, and it is the whole reason t2 exists.",
" - the house fascia is the familiar 0.35 lie and takes the $90 gutter with it.",
"The only top-grade steel in the yard is one post (p1) and the jacaranda's LOW fork",
"(0.95). Four corners, two good ones - that is the puzzle.",
"MEASURED IN PLAY, and the one line here not written by the editor: p1 adopts at",
"ratingHint 1.00, NOT the 0.90 in E's asset audit - posts are constructed anchors and",
"never read the sail_post GLB extra. Every post on backyard_01 reads 1.00 too, so it",
"is repo-wide and not this yard's doing. Filed to E/A in THREADS.",
"The gum t2 (1.00 / 0.88) is parked 9 m away in the south-west ON PURPOSE: excellent",
"steel on the wrong side, so reaching for it costs you span and shape rather than",
"rating. The audit's cheapest honest line (h3,t2,t2b,p1) goes and gets it.",
"WIND: the venturi is the gap between the shed and the west end of the house - real",
"geometry, not a heading. The slot runs north-south so axis = 90 deg; gain 1.4, r 5.",
"It bites the RIGGING ZONE and not the bed: the throat sits 3.0 m from the swing set's",
"apexes, so the tempting middle option is also the windy one. Deliberately gentler than",
"the corner block (align 62%, peak x1.28 against its 100% / x1.46) - that yard keeps",
"the crown for worst weather and worst bill."
],
"_why": [
"Authored COLD in the yard editor for Sprint 14 gate 3.2 - no JSON hand-editing, no",
"console. Every number below is B's SCORE IT card, storm_03_southerly, funnel ON,",
"11 anchors dressed, one run of 82.5 s.",
" WINNABLE at $80 - 81 quads in band, 11 clean, 16 marginal.",
" cheapest honest line h3,t2,t2b,p1 - $65 hardware (holds at $55), 22 m2,",
" garden 85.3 FULL, worth +1.6 HP over bare.",
" held vs bare (flown) bare 83.7 FULL; best clean h3,t1c,t2,p1 -> 90.0 FULL;",
" separation +6.3 HP; by hail / rain 6.8 / 3.1.",
" THE TRAP, MEASURED the best-READING line t1c,t2b,s1_f2 is MARGINAL - 91.8 FULL",
" on paper, inside the 15% band. The prettiest number in the",
" yard is the one that breaks.",
" margin flags t2b 0% headroom; t1, t1b, p1, s1_f1 all 1%. s1_f1 wrecks the",
" swing set ($140), and the card prices it.",
" collateral exposure gutter $90 + swing set $140 = $230 if all lost, on a $80 job.",
"No `separation` block: the editor has no field for one, and B's own card says a",
"shipping site should pin one. Filed to A/B in THREADS rather than hand-edited in.",
"The bare bed reads 83.7 FULL, which is the bare-beds-win pool item showing up on a",
"third yard - gate-4 material, not this yard's doing and not tuned here."
],
"yard": {
"width": 24,
"depth": 16
},
"sun": {
"elevationDeg": 55,
"azimuthDeg": -125
},
"gardenBed": {
"x": 0,
"z": 0,
"w": 5,
"d": 3.5
},
"house": {
"model": "house_yardside_v1",
"wreckedModel": "house_yardside_wrecked_v1",
"collateralKey": "gutter",
"collateralValue": 90,
"collateralLabel": "the gutter",
"x": 0,
"z": -6,
"anchors": [
{
"id": "h1",
"node": "fascia_anchor_01",
"type": "house",
"work": "bracket"
},
{
"id": "h2",
"node": "fascia_anchor_02",
"type": "house",
"work": "bracket"
},
{
"id": "h3",
"node": "fascia_anchor_03",
"type": "house",
"work": "bracket"
}
]
},
"structures": [
{
"id": "s1",
"model": "swing_set_01_v1",
"wreckedModel": "swing_set_01_wrecked_v1",
"x": -5,
"z": -2,
"rotYDeg": 0,
"solid": false,
"collateralKey": "swing_set",
"collateralValue": 140,
"collateralLabel": "the swing set",
"anchors": [
{
"id": "s1_f1",
"node": "frame_anchor_01",
"type": "swing_frame",
"work": "cloth"
},
{
"id": "s1_f2",
"node": "frame_anchor_02",
"type": "swing_frame",
"work": "cloth"
}
]
}
],
"trees": [
{
"id": "t1",
"model": "tree_jacaranda_01_v1",
"x": 4.971,
"z": 2,
"phase": 1.1,
"trunkH": 3.4,
"anchorY": 2.4,
"anchors": [
{
"id": "t1",
"node": "branch_anchor_01",
"type": "tree",
"work": "cloth"
},
{
"id": "t1b",
"node": "branch_anchor_02",
"type": "tree",
"work": "cloth"
},
{
"id": "t1c",
"node": "branch_anchor_03",
"type": "tree",
"work": "cloth"
}
]
},
{
"id": "t2",
"model": "tree_gum_02_v1",
"x": -8.5,
"z": 5.5,
"phase": 1.7,
"trunkH": 3.8,
"anchorY": 3.1,
"anchors": [
{
"id": "t2",
"node": "branch_anchor_01",
"type": "tree",
"work": "cloth"
},
{
"id": "t2b",
"node": "branch_anchor_02",
"type": "tree",
"work": "cloth"
}
]
}
],
"posts": [
{
"id": "p1",
"x": 3.5,
"z": -2.5,
"h": 4,
"type": "post",
"work": "cloth"
}
],
"fence": {
"sides": [
"north",
"south",
"east",
"west"
]
},
"shed": {
"model": "shed_01_v1",
"x": -9,
"z": -5,
"rotYDeg": -90
},
"shedTable": {
"model": "shed_table_v1",
"x": 3.321,
"z": 7.753,
"rotYDeg": -90,
"pickupNode": "pickup_anchor"
},
"gnome": {
"model": "garden_gnome_01_v1",
"x": 7.08,
"z": 6.344,
"rotYDeg": 0,
"collateralValue": 25
},
"bike": {
"model": "bike_kid_01_v1",
"x": -6,
"z": 5,
"rotYDeg": 180
},
"wind": {
"venturi": [
{
"x": -6.22,
"z": -4.77,
"axis": 1.571,
"gain": 1.4,
"radius": 5,
"sharp": 3
}
]
}
}

View File

@ -236,11 +236,18 @@ export const PALETTE = [
// crossbar that is the most anchor-looking object in the game and carries
// `tie_off: false`. $140 is E's number, ADOPTED unchanged; the ruling and
// the one condition for revisiting it are in THREADS.
kind: 'structure', label: 'Swing set (the honest middle)', model: 'swing_set_01',
// ⚠️ The `_v1` suffix is LOAD-BEARING and its absence is silent. These two
// entries shipped without it (SPRINT14, D's cold pass): the GLB 404s, the
// prop never draws, and because `adoptAnchor` does `rating_hint ?? 1` a
// MISSING MODEL BECOMES THE BEST STEEL IN THE GAME — the swing apexes read
// 1.00 instead of E's 0.45, the jacaranda 1.00/1.00/1.00 instead of
// 0.95/0.52/0.40 — and the yard still validates VALID. Same species as E's
// `tie_off` audit: silence is not neutral where a default is generous.
kind: 'structure', label: 'Swing set (the honest middle)', model: 'swing_set_01_v1',
requires: ['swing_frame'],
hint: 'apex anchors 0.45; the crossbar LOOKS like the answer and is not an anchor',
make: (id, x, z) => ({
id, model: 'swing_set_01', wreckedModel: 'swing_set_01_wrecked',
id, model: 'swing_set_01_v1', wreckedModel: 'swing_set_01_wrecked_v1',
x, z, rotYDeg: 0, solid: false,
collateralKey: 'swing_set',
collateralValue: 140, collateralLabel: 'the swing set',
@ -254,10 +261,10 @@ export const PALETTE = [
// on a jacaranda and you pay 58% for it, against the gum's 24%. Unpriced by
// E's own ruling (no limb-failure event to watch; billing an unseen event
// is the lie the invoice exists to kill). Same node names as the gums.
kind: 'tree', label: 'Jacaranda (height costs)', model: 'tree_jacaranda_01',
kind: 'tree', label: 'Jacaranda (height costs)', model: 'tree_jacaranda_01_v1',
hint: 'forks low and strong, then falls off a cliff — the "which tree" question',
make: (id, x, z) => ({
id, model: 'tree_jacaranda_01', x, z, phase: 1.1, trunkH: 3.4, anchorY: 2.4,
id, model: 'tree_jacaranda_01_v1', x, z, phase: 1.1, trunkH: 3.4, anchorY: 2.4,
anchors: [1, 2, 3].map((i) => ({
id: i === 1 ? id : `${id}${'abc'[i - 1]}`,
node: `branch_anchor_0${i}`, type: 'tree', work: 'cloth',