Files
XZBT/docs/evidence/phase4/2026-09-06-phase4a-contract.md
T
LabyricornandClaude Opus 5 3e27a668e2 docs(visual): specify the phase 4a scene, primitive, and appearance contract
Open the Visual subsystem contract at Format Specification revision 0.5 with
section 17, covering PRD 69-76: the renderer-neutral pipeline, canonical units
on a single degrees convention, the visuals container, layers, the scene model
with three coordinate spaces and three fit modes, 2.5D depth with a fixed sign,
stable sorting, parallax, perspective factor and per-object fog, the fourteen
primitives of Visual Primitive Set 0.1, common visual properties, a normative
transform composition order, appearance with the eight-mode safe blend set and
gradient paint, paths and splines with independently addressable points, text
restricted to the three generic font families, and the once-at-instantiation
resolution boundary for visual ValueSpec fields.

Visual objects are keyed rather than listed and carry no id field, matching the
audio node-identity rule that a Phase 3a blocking defect established. No visual
property becomes externally addressable in this slice; a binding, set, or
override naming one remains ERR_UNSUPPORTED_TARGET, and section 8.1 is
unchanged until section 19.1 adds its rows.

Add five diagnostic codes to the section 7 table, record the eight-slice Phase 4
delivery plan, mark the section 11 Visuals register row in progress, and refresh
the implementation status, which had not been updated since the 3c-1 contract.

Documentation only; no runtime, schema, fixture, or test file is touched.
npm test passes 102 tests with zero failures.

Co-Authored-By: Claude Opus 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01GwmTQU6zLwh3qbBvq5zf5B
2026-09-06 03:57:46 +00:00

7.6 KiB

Phase 4a evidence — Visual subsystem contract, part I (Format Specification section 17)

Date: September 6, 2026 Slice: 4a — Contract I (documentation only; no runtime change) Baseline: main at 6aab663 (Phase 3c slice 4) Specification revision: 0.4 → 0.5 PRD coverage: 69-76

What this slice fixes

Section 17 opens the Visual contract required by section 11. It covers the visual pipeline and its renderer-neutral scope, canonical units, the visuals container, layers, the scene model and the three coordinate spaces, 2.5D depth, the fourteen geometry primitives of Visual Primitive Set 0.1, common visual properties, the transform model, appearance and paint, paths and splines and text, and the resolution boundary for visual ValueSpec fields.

Sections 18 (Phase 4b) and 19 (Phase 4c) are named throughout as the owners of procedural systems and of automation, lifecycle, camera, post-effects, and the centralized ceilings. Those forward references are deliberate and mirror how section 14 referenced sections 15 and 16 before they were written; they are the only unresolved numeric references in section 17 and they close when 4b and 4c land.

Decisions taken, so 4d does not relitigate them

  1. Angles are degrees everywhere, 0 along +x, positive turning toward +y. No visual field is authored in radians or turns. This matches the audio contract's phase field (14.7).
  2. Increasing z is farther from the camera. Depth sorting draws greater z first and breaks ties by document key order, using the same document-order rule sections 9.3 and 14.4 already rely on. Perspective scaling is focalLength / (focalLength + z); orthographic leaves z affecting sorting, parallax, and fog but never scale.
  3. Visual objects are keyed, not listed. content and children are objects keyed by ID and a visual object carries no id field. This is the same node-identity rule section 14.3 adopted after the contradictory version was one of the four blocking defects the Phase 3a review closed; adopting it up front here avoids repeating that defect in a second subsystem.
  4. Transform composition order is normative: M_local = T(position + translate) x T(origin) x R(rotation) x K(skew) x S(scale) x T(-origin), with M_parent x M_local down a group hierarchy. Trace 3 pins it with a case where rotation and non-uniform scale do not commute, so a renderer cannot fold the order differently and pass.
  5. Visual ValueSpec fields resolve once, at their object's instantiation boundary, exactly as section 14.4 fixes for audio node fields. Rendering consumes no procedural stream, so procedural decisions stay identical across render rates and machines. Time variation comes from behaviors (18.6), visual automation (19.1), and the section 8.1 rows that 19.1 adds — from nothing else.
  6. No visual property is externally addressable in this slice. A binding, set, or override naming one is ERR_UNSUPPORTED_TARGET, and the section 8.1 table is unchanged. Section 1.3 reserves the visuals.systems.* namespace; reserving a namespace does not grant a capability.
  7. layer is a system property, not an object property. Letting siblings inside one transform hierarchy composite into different layers would make the hierarchical transform meaningless.
  8. Depth fog is per object, not per pixel, so it is exact on any renderer and raises no diagnostic. The conic gradient is the only appearance fallback in 0.1, and it raises WARN_VISUAL_APPROXIMATION once per paint instance rather than once per frame.
  9. font is restricted to the three generic CSS families. Section 13.3 requires the standalone artifact to make no external request, and 0.1 ships no font file.
  10. Degenerate geometry fails validation rather than being transformed. A zero-radius arc is ERR_OUT_OF_BOUNDS, not a silently substituted line, per PRD 89.

Deliberate scope deferral

Live numeric readouts are not in 0.1. Because text resolves once at instantiation, it renders authored strings and static labels only. The instrument and radar displays of PRD 130 item 7 and Exhibit D are to be built from generic geometry driven by state. The reason is recorded in 17.13: a live readout needs a number-to-string formatting contract (precision, rounding, locale, unit suffixes) that PRD 72 does not specify and that would introduce the first subject-shaped construct into the visual set. Slice 4g revisits this if the Exhibit D visuals cannot be built without it. This is the one place in section 17 where a later slice may have to reopen the contract.

New diagnostic codes

Five codes were added to the section 7 table, which remains the single authoritative list: ERR_INVALID_SYSTEM_TYPE, ERR_INVALID_PRIMITIVE_TYPE, ERR_INVALID_PATH, ERR_VISUAL_LIMIT_EXCEEDED, and WARN_VISUAL_APPROXIMATION. Section 17.15 repeats them for locality, exactly as 15.18 and 16.10 do.

ERR_INVALID_RANGE_ORDER, ERR_OUT_OF_BOUNDS, ERR_UNKNOWN_FIELD, ERR_SCHEMA_VALIDATION, ERR_INVALID_REFERENCE, ERR_INVALID_ID, and ERR_UNSUPPORTED_TARGET are reused rather than duplicated under visual-specific names.

Authoring limits fixed in this slice

Limit Bound Diagnostic
Layers per exhibit 16 ERR_VISUAL_LIMIT_EXCEEDED
Group nesting depth 8 (matches audio component nesting, 15.15) ERR_VISUAL_LIMIT_EXCEEDED
polyline / polygon vertices 512 ERR_VISUAL_LIMIT_EXCEEDED
path commands 512 ERR_VISUAL_LIMIT_EXCEEDED
spline points 256 ERR_VISUAL_LIMIT_EXCEEDED
Gradient stops 16 ERR_VISUAL_LIMIT_EXCEEDED
filters entries 4 ERR_VISUAL_LIMIT_EXCEEDED
strokeDash entries 8 ERR_SCHEMA_VALIDATION
text length 256 characters ERR_SCHEMA_VALIDATION

Runtime ceilings — active particles, emission rate, active spawned systems, link count, trail history, blur radius, post-processing passes, and rendering resolution (PRD 89, 120) — belong to slice 4c and are not set here.

Verification performed

This slice changes documentation only. No runtime source, schema, fixture, or test file was touched.

  • Every diagnostic code used in section 17 resolves to a row in the section 7 table (checked programmatically; zero unresolved).
  • Every numeric cross-reference in section 17 resolves to an existing heading, except the intended forward references to 18.1, 18.2, 18.4, 18.5, 18.6, 18.8, 19.1, 19.2, 19.3, 19.4, and 19.5.
  • npm test was run to confirm the existing suite is unaffected; the result is recorded in the commit.
  • The section 11 contract register's Visuals row now reads In progress (Rev 0.5 / Phase 4a) and names what remains for 4b and 4c.

Test boundary

Traces 1-14 of section 17.16 are automated and belong to slice 4d, where the renderer exists to run them. Traces 15 and 16 — the PRD 130 visual challenge judged on a real display, and the early combined GC6 benchmark at 1920 x 1080 — are user-observed and close slice 4h. Phase 4 is not accepted until both do.

State at this checkpoint

Section 17 is contract only. No visual runtime code exists; src/runtime has no renderer module and the JSON Schema has no visual definitions. Nothing has been drawn from any build. Phase 3 also remains unaccepted while its own user-observed gates (traces 15-17 of section 16.11) and the Phase 1 direct-file restart observation are open; no Phase 4 slice depends on them, and no Phase 4 slice can close them.

Whether section 17-19 passes a multi-model review before slice 4d begins — the pass that found thirteen defects in sections 14-16, nine of which any single reviewer would have missed — remains an open decision.