# Independent review — 2026-09-06 (America/Los_Angeles) ## Review scope - **Local date:** 2026-09-06 (America/Los_Angeles, PDT / UTC−7). Review written 2026-09-06 17:31 UTC. - **Branch:** `main` - **HEAD:** `0af58da89dd6095fa9ca3ed546a2e48d7c7971b7` — `feat(visual): implement the slice 4d renderer core` (2026-09-06 16:38:44 +0000) - **Today’s commits (LA calendar day, since 2026-09-06 07:00 UTC):** - `1bc49018` docs(visual): apply the sections 17-19 review triage in full at revision 0.8 - `6587d3e4` feat(visual): align the schema, validator, and resolution engine with the 0.8 visual contract - `699492f8` build(visual): bundle the visual contract and validation modules into the standalone artifact - `0af58da8` feat(visual): implement the slice 4d renderer core - **Uncommitted work (staged: none):** modified runtime/docs/build files plus untracked Phase 4e–4g modules, tests, exhibits, evidence, and tools. **When those uncommitted edits were made cannot be established from Git;** they are included because they are the current tree. - **Out of scope:** existing files under `/reviews`, `.abacusai/`, `.labyricorn/devlog/second-test-entry/`, `Claude outputs/`. No implementation files were modified for this review. - **Limitation:** review is of the working tree vs HEAD plus today’s commits; Phase 4a–4c *docs* commits from late 2026-09-05 PDT are not treated as “today.” ## Findings (by severity) ### 1. Spawn `lifetime` is passed through `parseDuration`, which only accepts duration strings - **Priority:** P1 - **Where:** `src/runtime/visual-engine.js:466-468`, `src/runtime/actions.js:48-50`, `src/runtime/types.js:55-56` - **Trigger:** `ActionExecutor` evaluates `action.lifetime` (or spawn-input substitution yields a number) and `VisualEngine.spawn` always does `parseDuration(sampleTree(value, …))`. `parseDuration` throws `ERR_INVALID_DURATION` unless `typeof value === 'string'`. - **Impact:** A legal numeric or already-resolved lifetime cannot spawn; the action fails as a runtime fault instead of applying the duration. Graphic-object `lifetime` in `visual-motion.js:70` has the same string-only assumption after sampling. - **Evidence:** `spawn` helper `duration = (value, fallback) => value === undefined ? fallback : parseDuration(...)`. Tests in `test/phase4-execution.test.mjs` never pass `action.lifetime` or a numeric lifetime. - **Correction:** Accept already-numeric milliseconds (and duration strings) in one helper; evaluate action lifetime to that type consistently with the spec. ### 2. Local visual automation crashes if the target object is missing - **Priority:** P1 - **Where:** `src/runtime/visual-automation.js:11-13` - **Trigger:** `visualLocalTracks` walks `root.find(...)` then `while (object?.children.some(...))`. If `find` returns `undefined`, `object?.children` is `undefined` and `.some` is still invoked. - **Impact:** Instantiating or advancing a system with a dangling automation target throws `TypeError` instead of a `RuntimeFault` / import error, taking down the visual tick (`failSystem` only catches errors *inside* the per-system try after tracks are built at `createSystem`). - **Evidence:** Optional chaining stops at `children`, not at `.some`. Validator is supposed to reject bad targets, but runtime still concatenates tracks for exhibit-scope fallbacks (`visual-engine.js:403-406`) and spawned substitutes. - **Correction:** Use `object?.children?.some(...)` and no-op or fault when `object` is missing. ### 3. Bloom / color-adjust write unclamped channel math into `Uint8ClampedArray` without documenting wrap vs clamp; blur radius is clamped to `max(width,height)` - **Priority:** P2 - **Where:** `src/runtime/visual-effects.js:4-5`, `38`, `74` - **Trigger:** `bloom` adds `pixels + glow * intensity`; `color-adjust` can emit values outside `[0,1]` before `* 255`. `visualBoxBlur` sets `r = min(max(width,height), round(radius))`. - **Impact:** Clamped arrays hide overflow (no crash), but a full-frame-radius blur is O(pixels × max(edge)) and can hitch on large backing stores when `deviceRadius` is large. Tests only assert “pixels changed,” not energy conservation or radius semantics (`test/phase4-execution.test.mjs` 19.7.15). - **Evidence:** No `Math.min(255, …)` before assignment; radius cap is the long edge, not a contract ceiling. - **Correction:** Clamp processed channels explicitly; cap blur radius to the post-effect numeric range / a small pixel budget. ### 4. `remove` actions always report `executed` even when the instance id is unknown - **Priority:** P3 - **Where:** `src/runtime/actions.js:53-55`, `src/runtime/visual-engine.js:475` - **Trigger:** `this.visual.remove(action.target)` → `this.instances.get(id)?.remove(this.time)`. - **Impact:** Callers cannot distinguish a successful release from a no-op (typo’d id). Low severity because spawn returns the id and tests use that id. - **Correction:** Return `refused` / `failed` when the map has no entry. ## Verification - `node --test test/phase4-*.test.mjs test/phase1-runtime.test.mjs`: **116 pass, 0 fail** (≈2.5s). - Inspected Git status, today’s LA-window commits, unstaged diffs, and untracked `src/runtime/visual-*.js` plus tests. - Traced spawn/remove, tick (`performance.js` `onTick` → `VisualSubsystem.advance` → `VisualEngine.advance`), automation loop, effects, lifecycle, and resolution effect sampling. - **Not verified:** browser/Canvas `getImageData` on the real `XZBT.html` artifact; audio regression for `automationValueAt` loop (shared with visual); exact wall-clock of uncommitted files; full `test/*.test.mjs` outside phase1/phase4. No P0 defects were confirmed. Remaining risk is concentrated in uncommitted Phase 4e–4g runtime (lifetime typing, automation target walk) rather than the four committed 4d/contract commits.