From ed62c7d4be39f3f91ee2e515e9c661b248c904ab Mon Sep 17 00:00:00 2001 From: type-two Date: Mon, 20 Jul 2026 19:38:11 +1000 Subject: [PATCH] Sprint 15 integration: merge all lanes (418/0/0), apply E's world.js manifest patch, [I] entry --- THREADS.md | 33 +++++++++++++++++++++++++++++++++ web/world/js/world.js | 10 ++++++++++ 2 files changed, 43 insertions(+) diff --git a/THREADS.md b/THREADS.md index a8b65d9..43691ce 100644 --- a/THREADS.md +++ b/THREADS.md @@ -7349,3 +7349,36 @@ anchors are your GLB), but the tooling is now waiting, not TODO. bolted-to-deck option would turn "fascia or nothing" into a real spend-vs-risk decision — the number argues its own case and I'll build against it gladly when SPRINT16 wires the swing lawn. + +[I] 2026-07-19 — **SPRINT 15 INTEGRATION (main).** All four lanes merged; E's world.js patch applied + verbatim at merge exactly as filed (four hunks, the leadFor precedent — comment in world.js says + so); selftest **418/0/0** on the merged tree, the exact sum D predicted on their scratch (410 + + B 3 + C 3 + E 2), verified in the browser. Game boots clean; posts adopt at ratingHint 1.00 + through E's manifest, live in the real chain (D measured p1 committing at eff 3,200 in play — + a 0.90 world would have read 2,880). + + **The sprint closed every gate it opened:** + · Gate 1 — ruled 1.00 (shipped value canon), re-baked, mechanism landed (factory manifest → + runtime, ambiguous types refuse to guess, unrated-undenied nodes fail the BUILD), pinned + against the manifest never a literal, and verified zero-delta from THREE directions (B cloth, + C storm, D played). The expensive-sounding gate became cheap because the ruling came first — + sequencing is a tool. + · Gate 2 — the score is iterative and moved nothing (every card byte-identical; MessageChannel + not setTimeout, or Chrome's throttling clamps an occluded run to one flight per minute); ONE + storm picker via a shared store B proposed and C landed converged; D's acceptance verdict is + the receipt: a three-position bed study with predictions before each card, one prediction + wrong IN A RUN instead of in a shipped yard. C's worst-second button predicted the second h3 + actually broke in play. "Batch, not iterative" is dead. + · Gate 3 — landed last integration (honest edges), stands. + · Gate 4 — branch RULED by John (all three, sequenced: teeth → sites/clients → heatwaves; + ROADMAP.md is the growth canon). The play half stands open as ever. + + Carried forward: B declined the coarse-rank cull as a design change needing a ruling (correct — + it changes card numbers by construction); E's pergola_01 proposal has D's playtester endorsement + ("the ladder jumps 0.45-on-grass straight to 1.00-in-concrete; a 0.65 bolted-to-deck mid-rung + turns fascia-or-nothing into a real decision") — TEETH's palette call. D filed their own + harness's fake-Enter artifact so nobody blames A's gate-3.1 work. + + **SPRINT16 — TEETH — FIRES NOW: its own header's condition ("fires when 15 integrates") is met, + its pins stand on post-ruling numbers as designed, and the swing lawn is waiting to become a + real night.** diff --git a/web/world/js/world.js b/web/world/js/world.js index 0d813fe..dbad5f1 100644 --- a/web/world/js/world.js +++ b/web/world/js/world.js @@ -13,6 +13,13 @@ import * as THREE from '../vendor/three.module.js'; import { ANCHOR_TYPE, createStubWind } from './contracts.js'; +// SPRINT15 gate 1.2 — E's patch, applied verbatim by the integrator at merge +// (the leadFor precedent): a node-less anchor takes the factory's word at +// construction, because dress() will never reach it. Object.assign ignores +// null, so each hunk is inert exactly where adoptAnchor already owns the job. +// At the ruled 1.00 this changes ZERO shipped numbers; it exists for the NEXT +// asset. E's e.test pins runtime === manifest so divergence can't be silent. +import { factoryExtras } from './ratings.js'; import { validateSiteWind } from './weather.core.js'; /** @@ -350,6 +357,7 @@ export function createWorld(scene, opts = {}) { anchors.push(Object.assign( makeStaticAnchor(a.id, a.type ?? 'house', new THREE.Vector3(-5 + i * 5, 2.6, -9.9)), { work: a.work }, + a.node ? null : factoryExtras(a.type ?? 'house'), )); } @@ -464,6 +472,7 @@ export function createWorld(scene, opts = {}) { anchors.push(Object.assign( makeStaticAnchor(spec.id, spec.type ?? 'post', top), { work: spec.work }, + spec.node ? null : factoryExtras(spec.type ?? 'post'), )); } @@ -532,6 +541,7 @@ export function createWorld(scene, opts = {}) { anchors.push(Object.assign( makeStaticAnchor(a.id, a.type ?? 'post', new THREE.Vector3(st.x, heightAt(st.x, st.z) + 2.4, st.z)), { work: a.work }, + a.node ? null : factoryExtras(a.type ?? 'post'), )); } }