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
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
- Angles are degrees everywhere,
0along+x, positive turning toward+y. No visual field is authored in radians or turns. This matches the audio contract'sphasefield (14.7). - Increasing
zis farther from the camera. Depth sorting draws greaterzfirst and breaks ties by document key order, using the same document-order rule sections 9.3 and 14.4 already rely on. Perspective scaling isfocalLength / (focalLength + z);orthographicleaveszaffecting sorting, parallax, and fog but never scale. - Visual objects are keyed, not listed.
contentandchildrenare objects keyed by ID and a visual object carries noidfield. 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. - 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), withM_parent x M_localdown 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. - 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.
- No visual property is externally addressable in this slice. A binding,
set, oroverridenaming one isERR_UNSUPPORTED_TARGET, and the section 8.1 table is unchanged. Section 1.3 reserves thevisuals.systems.*namespace; reserving a namespace does not grant a capability. layeris a system property, not an object property. Letting siblings inside one transform hierarchy composite into different layers would make the hierarchical transform meaningless.- 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_APPROXIMATIONonce per paint instance rather than once per frame. fontis 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.- Degenerate geometry fails validation rather than being transformed. A zero-radius
arcisERR_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 testwas 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.