site_audit: refuse dress-source site JSON instead of false-unwinnable
A's committed site schema (SPRINT10 world.js loadSite/createWorld) is
dress-source, and my loadSite assumed resolved positions. Run head-on against
A's real data/sites/backyard_01.json the tool reported:
✗ FAIL — no quad in the band shades the bed at all. The site cannot be rigged.
That is a lie, and the dangerous kind: the site is fine; the TOOL couldn't read
it. It is the SPRINT6 unwinnable-site trap in reverse — a false negative that,
in a "every site runs the audit before it ships" workflow, condemns a good site.
Two things make the schema unreadable headless, both real:
· posts are pre-rake. JSON carries {id,x,z,h}; world.js:361 leans each post 8°
off centre. p4's spec (-3.2,-1.2) dresses to (-3.72,-1.40) — the exact 0.56 m
error this tool's own snapshot shipped in SPRINT9. Reading x/z raw re-makes it.
· house/tree anchors have no coordinates — only `node`, a GLB empty's name.
Their position exists only after dress() reads matrixWorld, and dress() needs
GLTFLoader + fetch, neither of which runs in node. Branch anchors are exactly
where the dangerous quads live (t2b at 10 kN), so dropping them silently is
the worst possible failure.
The correct source of dressed positions is createWorld(site).anchors, which is
browser-only. That path lands once A's data-driven createWorld is in main; until
then loadSite REFUSES dress-source JSON with the reason and the plan, and exits 2
(distinct from the winnability FAIL's exit 1). The built-in DRESSED snapshot and
a resolved { anchors:[{id,type,pos}] } export both still audit. Raised to A in
THREADS: audit in-browser off createWorld(site).anchors, or export resolved anchors.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
parent
2996b092ae
commit
d222a1e0dd
@ -119,7 +119,44 @@ async function verifyPosts(site) {
|
||||
async function loadSite(path) {
|
||||
if (!path) return BACKYARD_01;
|
||||
const j = JSON.parse(await readFile(path, 'utf8'));
|
||||
// site-as-data shape (Lane A, gate 2). Tolerant: only anchors + bed are needed.
|
||||
|
||||
// A's committed site schema (SPRINT10, world.js loadSite/createWorld) is
|
||||
// DRESS-SOURCE, not resolved positions, and headless node cannot turn one into
|
||||
// the other. Two reasons, both load-bearing for an audit that must not lie:
|
||||
//
|
||||
// · POSTS are pre-rake. The JSON carries {id,x,z,h}; world.js:361 leans every
|
||||
// post 8° away from the yard centre before it becomes an anchor. p4's JSON
|
||||
// spec (-3.2,-1.2) dresses to (-3.72,-1.40) — 0.56 m, the exact error this
|
||||
// tool's own snapshot shipped with in SPRINT9. Reading x/z raw re-makes it.
|
||||
// · HOUSE and TREE anchors have NO coordinates at all — just `node`, a name
|
||||
// baked into E's GLB (fascia_anchor_01, branch_anchor_02…). Their world
|
||||
// position exists only after dress() reads the empty's matrixWorld, and
|
||||
// dress() needs GLTFLoader + fetch, neither of which runs in node.
|
||||
//
|
||||
// So a headless read of this file gets posts wrong and tree/house anchors not
|
||||
// at all — and the branch anchors are exactly where the dangerous quads live
|
||||
// (t2b pulled 10 kN in SPRINT9). Reporting on that silently is the SPRINT6
|
||||
// trap in reverse: a site called unriggable because the TOOL couldn't read it.
|
||||
//
|
||||
// The correct source of dressed positions is createWorld(site).anchors — which
|
||||
// is browser-only. Until that path lands (this is raised to A in THREADS), the
|
||||
// honest move is to refuse this schema loudly, not to guess at it.
|
||||
const dressSource = Array.isArray(j.posts) || j.house || Array.isArray(j.trees) || Array.isArray(j.structures);
|
||||
const resolved = Array.isArray(j.anchors) && j.anchors.length
|
||||
&& j.anchors.every((a) => Number.isFinite(a.pos?.x ?? a.x));
|
||||
if (dressSource && !resolved) {
|
||||
throw new Error(
|
||||
`"${j.name || j.id || path}" is a DRESS-SOURCE site (posts/house/trees), and its anchor\n` +
|
||||
` positions cannot be resolved headless: posts are pre-rake (world.js leans them 8°) and\n` +
|
||||
` house/tree anchors are GLB node refs that only exist after dress(), which node cannot run.\n` +
|
||||
` Audit it in the browser off createWorld(site).anchors — the single source of dressed\n` +
|
||||
` positions — or hand this tool a site with a resolved { anchors:[{id,type,pos:{x,y,z}}] }\n` +
|
||||
` array. Run with no argument to audit the built-in DRESSED backyard_01 snapshot.\n` +
|
||||
` (This limitation and the browser-audit plan are in THREADS for Lane A.)`);
|
||||
}
|
||||
|
||||
// Resolved-positions shape: a flat anchors[] each carrying real coordinates.
|
||||
// This is what a dressed export (or a future createWorld dump) would hand us.
|
||||
const anchors = (j.anchors || []).map((a) => ({
|
||||
id: a.id, type: a.type || 'post',
|
||||
pos: { x: a.pos?.x ?? a.x, y: a.pos?.y ?? a.y, z: a.pos?.z ?? a.z },
|
||||
|
||||
Loading…
Reference in New Issue
Block a user