Files
XZBT/reviews/spec-review-2026-09-06-unknown-model-173816-c4f8a2d1.md
T
LabyricornandClaude Opus 5 c4332363a9 docs: raise the format specification to revision 0.9 and land the reconciliation
Revision 0.9 adds section 20, the cadence and event subsystems contract, and
carries two corrections the implementation forced. Section 6.1 now states that a
duration is the authored literal or a non-negative finite number already in
milliseconds, since a DurationSpec may be the resolved output of a ValueSpec or
a bounded TimeSpec, with the one documented exception of an automation track's
`at`, which 19.1 keeps literal-only so that point ordering stays decidable at
import. Section 20.11 documents the rejection of an undeclared input name in an
event action's `with` map as ERR_UNKNOWN_FIELD — the section's own convention
for that shape of error, replacing an invented code that appeared nowhere in the
registry.

The review record is committed with the code it describes: the two code triages
that found these defects, the reconciliation plan that sequenced the fixes, and
a follow-up debt record listing what was deliberately left open — the unchecked
JSON Schema artifact, degenerate path arcs, post-effect transient allocation,
the window-traffic fixture's per-copy wrap bounds, and the unstated
`ownership: "persistent"` value on a sound action. None of the five blocks phase
6; all five are written down rather than dropped.

Devlog entries are backfilled for the two milestones that had none: phase 3c
slice 2, the audio lifecycle and voice ceilings, and slice 4d, the renderer
core. The implementation status summary now reflects the reconciled state rather
than the in-flight one.

231 tests pass. tools/verify-spec-contract.py reports 46 declared diagnostic
codes with every used code resolving and its two long-standing unresolved
cross-references unchanged.

Co-Authored-By: Claude Opus 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01ShxxFqFmCUDQnQvFNm4TKy
2026-09-06 21:54:09 +00:00

8.8 KiB
Raw Blame History

Specification review — 2026-09-06 (America/Los_Angeles)

Scope

  • Local date: 2026-09-06 (America/Los_Angeles, PDT / UTC−7). Written 2026-09-06 17:38 UTC.
  • Branch: main
  • HEAD: 0af58da89dd6095fa9ca3ed546a2e48d7c7971b7 (feat(visual): implement the slice 4d renderer core)
  • Today’s commits (since 2026-09-06 07:00 UTC): 1bc4901 (spec §§17–19 rev 0.8), 6587d3e (schema/validator/resolution), 699492f (standalone bundle), 0af58da (4d renderer).
  • Uncommitted work: Phase 4e–4g runtime (src/runtime/visual-*.js, engine/actions/app/resolution/performance), tests, exhibits, evidence. Git cannot date uncommitted files; they are in scope as the current tree.
  • Authoritative sources: docs/XZBT_0-1_Format_Specification.md rev 0.8, especially §§6, 8.1, 9.1, 10.1–10.2, 17–19 (19.1–19.7). Supporting: docs/XZBT_0-1_Implementation_Plan.md Phase 4 slice table. PRD cited only where the spec restates it.
  • Not used: any file under /reviews.
  • Limitations: Action Model (spawn/remove shapes) is explicitly not fixed in §19.2; Phase 6 scenarios and 4h/GC6 (traces 20–21) are deferred and not treated as defects. Display judgment not run.

Traceability (today’s visual work → spec)

Item Spec Implementation Status
Scene / fit / primitives / compositing 17.4–17.13 visual-engine.js, visual-geometry.js, visual-canvas2d.js Satisfied (4d tests 17.16.*)
Camera matrix, parallax, perspective, focalLength clamp 19.3 cameraMatrix, planFrame Satisfied (static + execution tests)
Components, particles, emitters, repeaters, behaviors, fields, trails, links 18.1–18.8 visual-systems.js, visual-behaviors.js, visual-fields.js, visual-distributions.js Satisfied (18.10 traces in phase4-procedural.test.mjs)
Exhibit + system automation, shared curves/modes, live vs authoring budgets 19.1, 16.1 resolution.js, visual-automation.js, audio-automation.js Partial (curves/modes/budgets tested; local-track target walk unsafe; 19.7.3/4 coverage incomplete)
Lifecycle, spawn/remove, ownership, release factor 19.2 visual-lifecycle.js, VisualEngine.spawn/remove/cleanup Partial (DurationSpec after evaluation vs parseDuration; action lifetime not specified in §19)
Post-effects chain, grain isolation, pass ceiling 19.4 visual-effects.js, effectPlan Partial (pixel tests exist; radius/energy vs 19.4 table not fully asserted)
Aggregate ceilings + cadence 19.5–19.6 enforcePopulations, visual-diagnostics.js Satisfied for automated 19.7.18 cases; unverified vs measured 4h values (provisional by spec)
19.7 traces 1–19 19.7 test/phase4-execution.test.mjs Partial (many named tests; 19.7.3/4/8/13 not all matching the prose)
19.7 traces 20–21 19.7 — Deferred (4h / display); not a defect

Findings (confirmed gaps)

1. spawn.lifetime / action lifetime after evaluation is not a duration literal

  • Priority: P1
  • Spec: §6.1 — durations are unit strings converted internally to milliseconds. §19.2 — spawn.lifetime and spawn.release are DurationSpec; instance duration is that logical duration from instantiation.
  • Impl: visual-engine.js:466-468 always parseDuration(sampleTree(...)), which requires typeof value === 'string' (types.js:55-56). actions.js:48-50 may evaluateValue(action.lifetime) first.
  • Expected: Authored DurationSpec remains a duration literal through sampling, then converts to ms. If evaluation yields a number (ms), it must still be accepted or rejected with ERR_TYPE_MISMATCH, not ERR_INVALID_DURATION.
  • Actual: Any non-string (including a resolved number) throws ERR_INVALID_DURATION and aborts spawn.
  • Trigger: spawn action with evaluated lifetime, or a DurationSpec that the value resolver does not leave as a string.
  • Impact: Legal instance lifetimes fail at runtime; §19.2 “absent means until remove” path is the only reliably tested path.
  • Correction: Convert DurationSpec with parseDuration only when the value is still a string; if already a finite number, treat as milliseconds (or reject per strict coercion ban §2 — pick one and match §6.1).

2. Local automation target walk throws TypeError instead of ERR_INVALID_REFERENCE

  • Priority: P1
  • Spec: §19.1 — target naming an undeclared object is ERR_INVALID_REFERENCE; outside the registry is ERR_UNSUPPORTED_TARGET. Import should reject; runtime must not invent a third failure mode.
  • Impl: visual-automation.js:11-13: while (object?.children.some(...)) — if find returns undefined, .some is called on undefined.
  • Expected: Validator fault at import, or runtime RuntimeFault with those codes.
  • Actual: Uncaught TypeError during createSystem / instantiate (outside the per-tick try in advance).
  • Trigger: Dangling graphic-object key on a system automation track, or exhibit-scope fallback path visual-engine.js:403-406.
  • Impact: Tick/activation abort rather than a documented diagnostic.
  • Correction: Guard object?.children?.some; if missing, throw RuntimeFault('ERR_INVALID_REFERENCE', ...).

3. Required traces 19.7.3 and 19.7.4 are not implemented as specified

  • Priority: P2
  • Spec: §19.7 items 3–4 (lines ~3255–3258 of the format spec): (3) system-scope at from instantiation — two spawns 4s apart produce identical curves offset by 4s; (4) cross-scope / undeclared / out-of-registry targets raise ERR_INVALID_REFERENCE vs ERR_UNSUPPORTED_TARGET as specified.
  • Impl: test/phase4-execution.test.mjs “19.7.3” only checks one exhibit-scope stream; “19.7.4” only checks behavior/automation ERR_AUTOMATION_CONFLICT.
  • Expected: The behaviors named in 19.7.3–4 actually run (spec: “a parsed stub is never a passed runtime trace”).
  • Actual: Adjacent properties are tested; the named traces are not.
  • Trigger: Acceptance of slice 4f against 19.7.
  • Impact: Spawn-relative automation offset and target-error taxonomy can regress without a failing test.
  • Correction: Add the two-spawn 4s offset assertion and the four negative target cases from 19.7.4.

4. Blur/bloom radius vs 19.4 “32 scene units” is not enforced in the pixel filter

  • Priority: P3
  • Spec: §19.5 authoring table / 19.4 — blur and bloom radius 32 scene units; pipeline clamp of 8.1 on effect parameters.
  • Impl: visual-effects.js:4-5 caps box-blur radius at max(width,height) pixels (device radius from effectPlan). Contract numeric clamp is in effectPlan via POST_EFFECTS; the filter can still run at huge projected radii.
  • Expected: Authored/resolved radius in scene units stays in the 19.4 table; device radius is a projection of that, not an unbounded pixel kernel.
  • Actual: Device kernel can equal the long edge of the backing store.
  • Trigger: Large zoom × deviceRadius with radius still inside 32 scene units.
  • Impact: Frame hitch; not a silent spec violation of the authored 32 if effectPlan clamps scene units — partial. Confirm POST_EFFECTS max is 32 and that tests assert it (19.7.15 does not).
  • Correction: Assert 19.4 ranges in execution tests; cap device radius by a pixel budget derived from the scene-unit max.

Specification ambiguities (not defects)

  1. §19.2 vs Action Model: spawn/remove action shapes are explicitly not fixed in 19.2. Whether action.lifetime is DurationSpec, ValueSpec<number>, or either is undecided. Finding 1 is a defect only for spawn.lifetime after sampleTree; action-lifetime typing needs a decision in the Action Model (Phase 5/6), not a silent assumption.
  2. DurationSpec vs TimeSpec (§6.2): 19.2 names DurationSpec, not the random TimeSpec object. Whether spawn.lifetime: { "random": { "min": "1s", "max": "2s" } } is legal is unspecified. Implementation would currently fail parseDuration on an object.
  3. 19.5 values are provisional until 4h/trace 21; using 8192 particles / 2048 emitters in tests matches the current table, not a measured GC6 result.
  4. instances.* addressing is runtime-only (19.2 / 8.1). Tests use instances.s#N; the Action Model still owns the public remove target grammar.

Verification

  • Read spec §§6, 17–19.7 and traced spawn, advance, automation, lifecycle, effects, resolution visualValues.
  • node --test test/phase4-*.test.mjs test/phase1-runtime.test.mjs: 116 pass, 0 fail (prior turn). Tests are evidence of implemented behavior, not of 19.7.3/4 completeness.
  • Not verified: real-display 19.7.20, GC6 19.7.21, full Action Model document, audio 16.11 cross-check of every visual curve sample.

Actionable specification/implementation gaps exist (P1–P3 above). Traces 20–21 remain deferred by the spec itself.