Format Specification section 18 (PRD 77-84) closes slice 4b: visual components and their inputs scope, particle systems with a normative integrator and life ramps, the nine placement distributions, emitters with exact fractional-accumulator emission timing, repeaters and the copy-scoped repeat.* namespace, the seventeen-behavior vocabulary and its channel set, the six procedural fields with a normative coherent noise function, and trails, ribbons, and links. Seven diagnostic codes are added to the section 7 table. Section 17 is amended in four places the new section requires: the visuals.fields container, the component visual object type beside the closed fourteen primitives, the now-declared behaviors field, and the widened visual limit row. Revision 0.5 -> 0.6. Documentation only; no runtime, schema, fixture, or test file changed. npm test remains 102 passing. Co-Authored-By: Claude Opus 5 <[email protected]> Claude-Session: https://claude.ai/code/session_019dTNHWyTdFobdevrKspoV6
11 KiB
Phase 4b evidence — Visual subsystem contract, part II (Format Specification section 18)
Date: September 6, 2026
Slice: 4b — Contract II (documentation only; no runtime change)
Baseline: main at 3e27a66 (Phase 4a, section 17)
Specification revision: 0.5 → 0.6
PRD coverage: 77-84
What this slice fixes
Section 18 continues the Visual contract section 17 opened. It covers reusable visual components and
their input scope, particle systems and the normative motion integrator, the nine placement
distributions, emitters and exact emission timing, repeaters and the copy-scoped repeat.* namespace,
the seventeen-behavior vocabulary and the channel set behaviors may write, the six procedural fields and
the normative coherent-noise function behind them, and trails, ribbons, and links.
Section 19 (Phase 4c) remains the owner of visual automation, lifecycle and ownership, camera, post-processing, and the centralized ceilings. The forward references to 19.1, 19.2, and 19.5 are the only unresolved numeric references in section 18, and they close when 4c lands.
Decisions taken, so 4e does not relitigate them
componentis a visual object type, not a fifteenth primitive. Visual Primitive Set 0.1 stays closed at the fourteen geometry primitives section 17.9 fixed. Section 18.1 addscomponentbeside that set, exactly as 15.11 added acomponentnode beside the audio node set 14.3 opened, so a component instance can be placed inline in anycontentorchildrencontainer instead of only being reachable through a repeater of count one.- Visual component parameters admit four types, audio's admit one.
number,boolean,string, andcolor— the shared scalar types of section 2. The audio contract (15.15) permits onlynumberbecause an audio node field is always numeric; a visual field may be a color, a label, or a visibility flag.min,max, andunitremain number-only. inputs.*andrepeat.*are construct-scoped, not document namespaces. Both follow the rule 15.15 fixed for audio components: legal only inside their construct,ERR_INVALID_REFERENCEanywhere else, absent from the section 1.3 namespace list, and granting no section 8.1 capability.- A component's expansion path, not its ID, is its stable instance key for section 9.3 stream derivation. Two instances of one component therefore sample independently, and reordering unrelated siblings does not perturb either — the same property 14.12 gives audio components.
- Particle motion has a normative integrator. Semi-implicit Euler, velocity before position, with
drag as
(1 - drag)^dtso it is tick-length independent. A renderer that integrates position first, or applies drag once per tick regardless ofdt, produces visibly different motion at a different tick rate and does not conform. Traces 5 and 6 pin both halves. - Life ramps interpolate resolved endpoints; they do not re-sample.
size,opacity, andcolormay ramp over normalized age using the same four curves PRD 85 fixes for automation.fromandtoresolve once at particle creation, so 17.14 and 9.3 hold unchanged: rendering still consumes no procedural stream. This is what gives PRD 78 itsageproperty without breaking reproducibility. - Emission timing is a fractional accumulator, not a per-tick rounding. Cumulative count after
tseconds at a constant rate isfloor(rate * t)exactly, under any tick length, with no drift and no reset when automation changes the rate later. - Unbounded emission fails validation. A system that declares emission but neither a per-item
lifetimenor a totallimitisERR_UNBOUNDED_EMISSION. An initialcountwith nolifetimestays legal — a fixed starfield that never expires is the common case, not the dangerous one. - Pool exhaustion evicts oldest-first, mirroring the voice eviction of 16.6, and is silent at the system level. The aggregate ceiling across systems and its diagnostic belong to 19.5.
- Index-driven placement needs a known count.
evenmodes and thegridtype place itemiofn, so they are legal in a repeater and in a fixedcountorburstpopulation and areERR_INVALID_DISTRIBUTIONon continuousrateemission. Distribution sample-consumption order is normative (x, theny, thenz; angle before radius) so fixtures place identically everywhere. - Coherent noise is specified, not left to the renderer. Three-dimensional gradient noise on the
integer lattice, twelve edge-midpoint gradients, a
256-entry permutation shuffled from the field's own stream at instantiation, and the quintic fade6u^5 - 15u^4 + 10u^3. Reproducibility (9.3) promises identical decisions rather than identical pixels, but a field that drove motion differently on two conforming renderers would make a fixture untestable, so the function itself is pinned.curlis the default mode because it is divergence-free and will not pile items into a point. - Ribbons are a trail render mode, not a separate system type. A ribbon is the same history buffer
drawn with area instead of a stroke, so
trail.modeisline,ribbon, orpoints. PRD 84 is satisfied without a fourth procedural system. linksis illegal on an emitter. Aparticlessystem and arepeaterhave bounded, known populations; an emitter's changes continuously and its pair search would have to be rebuilt every tick at exactly the cost the ceiling exists to prevent. All three PRD 84 rules —distance,nearest,index— are specified, withdistancethe required 0.1 minimum.- Behaviors write internal channels; they do not extend section 8.1. The
propertychannel set of 18.6 is a behavior's own permitted write set. External addressability of visual properties remains a section 19.1 decision, and a binding,set, oroverridenaming anything introduced here is stillERR_UNSUPPORTED_TARGET. - The morph rule section 17.13 deferred is now fixed: equal
type, equal point count, and equal splinemode, withERR_MORPH_INCOMPATIBLEon any mismatch. Resampling one shape onto another's point count would change the geometry the author wrote, so it fails validation instead.
Amendments to section 17
Four, all consequences of this slice rather than corrections:
- 17.3 gains a
fieldsrow for thevisuals.fieldscontainer. Without it the strict unknown-field policy would make every declared fieldERR_UNKNOWN_FIELD. - 17.9 records that Visual Primitive Set 0.1 is closed at fourteen and that 18.1 adds the
componentobject type beside it. - 17.10's
behaviorsrow no longer reads "Rejected asERR_UNKNOWN_FIELDuntil section 18 declares them"; it now carries the0to8bound. - 17.15's local
ERR_VISUAL_LIMIT_EXCEEDEDrow names the procedural-system ceilings this section adds.
No decision recorded in section 17 was reversed.
New diagnostic codes
Seven were added to the section 7 table, which remains the single authoritative list:
ERR_INVALID_DISTRIBUTION_TYPE, ERR_INVALID_DISTRIBUTION, ERR_INVALID_BEHAVIOR_TYPE,
ERR_INVALID_BEHAVIOR_TARGET, ERR_INVALID_FIELD_TYPE, ERR_MORPH_INCOMPATIBLE, and
ERR_UNBOUNDED_EMISSION. Section 18.9 repeats them for locality, exactly as 15.18, 16.10, and 17.15 do.
ERR_COMPONENT_RECURSION is reused for visual component recursion and over-nesting rather than
duplicated under a visual name, along with ERR_VISUAL_LIMIT_EXCEEDED, ERR_INVALID_REFERENCE,
ERR_INVALID_RANGE_ORDER, ERR_OUT_OF_BOUNDS, ERR_TYPE_MISMATCH, ERR_UNKNOWN_FIELD,
ERR_SCHEMA_VALIDATION, and WARN_AUTOMATION_FALLBACK.
Authoring limits fixed in this slice
| Limit | Bound | Diagnostic |
|---|---|---|
| Visual component nesting depth | 8 (matches audio, 15.14) | ERR_COMPONENT_RECURSION |
Particle capacity per system |
4096 | ERR_VISUAL_LIMIT_EXCEEDED |
Emitter capacity per system |
512 | ERR_VISUAL_LIMIT_EXCEEDED |
Repeater count |
1024 | ERR_VISUAL_LIMIT_EXCEEDED |
burst entries per system |
16 | ERR_SCHEMA_VALIDATION |
| Behaviors per object | 8 | ERR_VISUAL_LIMIT_EXCEEDED |
| Declared fields per exhibit | 8 | ERR_VISUAL_LIMIT_EXCEEDED |
| Fields referenced per system or behavior | 4 | ERR_VISUAL_LIMIT_EXCEEDED |
Noise octaves |
4 | ERR_OUT_OF_BOUNDS |
Grid columns / rows |
256 each | ERR_VISUAL_LIMIT_EXCEEDED |
Trail length |
128 samples | ERR_VISUAL_LIMIT_EXCEEDED |
Links per system per tick (maxLinks) |
1024 | ERR_VISUAL_LIMIT_EXCEEDED |
| Statically known population under a pairwise link rule | 256 | ERR_VISUAL_LIMIT_EXCEEDED |
Nearest-neighbour links per item (count) |
8 | ERR_SCHEMA_VALIDATION |
These are authoring bounds a document must satisfy at validation. The aggregate runtime ceilings — total active particles, total spawned systems, total links, total field evaluations, and the per-tick budget they share (PRD 89, 120) — remain slice 4c and are not set here. Slice 4h is what determines whether these bounds are the right ones.
Verification performed
This slice changes documentation only. No runtime source, schema, fixture, or test file was touched.
- Every diagnostic code used in section 18 (19 distinct codes) resolves to a row in the section 7 table; zero unresolved, checked programmatically.
- Every numeric cross-reference in section 18 resolves to an existing heading, except the intended forward references to 19.1, 19.2, and 19.5.
- All code fences in section 18 are balanced and every table row is well formed.
npm testpasses 102 tests with zero failures, confirming the existing suite is unaffected.- The section 11 contract register's Visuals row now reads In progress (Rev 0.6 / Phase 4a-4b) and names what remains for 4c.
Test boundary
Traces 1-19 of section 18.10 are automated and belong to slice 4e, where the procedural systems exist to
run them. Traces 20 and 21 — 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. Trace 20 is the same gate
as trace 15 of 17.16, restated for locality rather than added as a second gate.
State at this checkpoint
Sections 17 and 18 are contract only. No visual runtime code exists: src/runtime has no renderer
module, the JSON Schema has no visual definitions, exhibits/ has no visual fixture, and 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 sections 17-19 pass 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, and section 18 has now roughly doubled the surface that review would cover.