Files
XZBT/reviews/.completed-artifacts/visual-contract-review-abacus-ai-agent-20260906-kimi-k3.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

30 KiB
Raw Blame History

Visual Contract Review — §17–§19 (rev 0.7)

Reviewer: Abacus AI Agent (independent adversarial pass, pre–slice 4d) Scope: §17 (scene/primitives/transforms/appearance), §18 (components/procedural systems/behaviors/fields), §19 (automation/lifecycle/camera/effects/ceilings), plus the cross-referenced shared/audio sections (§1.3, §2, §4, §6, §7, §8, §9, §10, §14.4–14.7, §15.11/15.14/15.15, §16.1–16.7) used as consistency anchors. Method: from-scratch read; no other file in reviews/ was opened before or during this pass. Line numbers refer to docs/XZBT_0-1_Format_Specification.md rev 0.7.

Result: 33 defects (4 high, 13 medium, 16 low). All locked decisions were checked against the text; every one is present as claimed except "coherent noise is fully specified," which does not hold (H3).


High severity

H1. Perspective factor: §17.6 and §19.3 give two different, incompatible compositions

  • Location: §17.6 "Perspective scaling" (line 1630) vs §19.3 (line 2507).
  • What: §17.6 says "an object's transform is post-multiplied by the uniform factor focalLength / (focalLength + z) about the camera's projection center." §19.3 says each object "additionally receives the uniform factor … about the projection center, exactly as 17.6 states, applied after V." Post-multiplying the object's local matrix by a scale applies the scale in local space (about the object's origin, also scaling its own translation); scaling after V about the projection center is a display-space operation. These produce different pixels whenever the object is off-center, and the projection center is not even expressible in local space, so the 17.6 phrasing is not realizable as written. "Exactly as 17.6 states" is false. A knock-on gap: §19.3 (line 2511) pins stroke/blur/glow/shadow scaling for camera zoom only; whether the perspective factor also scales stroke width is undecidable while the composition point is ambiguous.
  • Why it matters for 4d: the camera/depth path is core renderer work, and acceptance traces 17.16 #6 and 19.7 #14 both assert "the documented factor" — but the document specifies two. Whichever an implementer picks, a second conforming renderer can pick the other and both cite the spec.
  • Location: §19.1 "Loop modes" (line 2398).
  • What: "…it is legal only on a persistent scope, and an infinite loop on a spawned system with a finite lifetime (19.2) is legal and simply ends with the system." The second clause flatly contradicts the first. Remaining holes: an infinite loop on a spawned system without lifetime (which may run indefinitely until removed) is unaddressed, and no diagnostic is named for the illegal case (ERR_SCHEMA_VALIDATION? ERR_VISUAL_LIMIT_EXCEEDED?).
  • Why it matters for 4d: automation-track validation ships with the document model the renderer core builds; this rule cannot be implemented, and 19.7 trace 2 cannot be extended to spawned scopes, until the sentence is rewritten with a single rule and a named error.

H3. Coherent noise is not fully specified, despite the locked decision and §18.7's own claim

  • Location: §18.7 "Coherent noise is normative" (lines 2246–2254); §18.6 wander/twinkle/point-wander (lines 2185, 2189, 2187); 18.10 trace 15–16 (line 2332–2333).
  • What: The text fixes "3D gradient noise, twelve edge-midpoint gradients, 256-entry permutation shuffled from the field's own stream, quintic fade" — but omits everything that makes two implementations agree: (a) how the permutation table is indexed from a lattice coordinate (the hash composition, e.g. perm[x+perm[y+perm[z]]], and any wrapping/doubling); (b) how the hash selects one of 12 gradients (256 is not divisible by 12 — mod 12 biases four gradients); (c) the exact Fisher-Yates loop — "consuming one sample per entry" is 256 draws, which matches neither the standard backward (n−1 draws) nor forward variants, so the table itself differs across implementations; (d) the octave normalization — "normalized so the result stays within [-1, 1]" states a bound, not a formula (divide by Σp^k? by the analytic max?); (e) the derivative method for curl/gradient modes (analytic gradient of the faded noise vs finite differences, and at what epsilon) — trace 16 requires curl to be divergence-free "to within the documented tolerance," a tolerance documented nowhere. Separately, §18.6's wander and twinkle are driven by "a value-noise sample (18.7)" — but §18.7 defines gradient noise, a different function, and the sampling coordinates for behavior noise (a function of what? t*rate alone?) are never fixed.
  • Why it matters for 4d: reproducibility of identical decisions from identical seeds is the format's core promise (§9.3), and every field-, wander-, twinkle-, point-wander-, and noise-displace-driven fixture depends on this function being byte-exact. Renderer core decides where noise evaluation lives and how the visual stream is plumbed; if the function is not pinned before fixtures are written, 18.10 traces 15–16 are unwriteable.

H4. §18.2's "every ValueSpec resolves once per particle" contradicts itself and §19.1's automation registry

  • Location: §18.2 "Per-particle resolution boundary" (line 2027) vs the field table it covers (lines 2002–2025) and §19.1 registry (line 2408); parallel text §18.4 (line 2124).
  • What: "Every ValueSpec above resolves once per particle, at that particle's creation." The table above includes count and rate — which drive particle creation and cannot resolve per particle (circular), and position, acceleration, drag — which §19.1 then lists as system-scope automatable channels (rate, position.x/y, acceleration.x/y/z, drag). Automation is time-varying by definition; per-particle creation-time resolution is fixed by definition. The spec never says which wins: does automating drag rewrite live particles' drag each tick, or only re-base future creations? §18.4 carves rate and burst[].at out as emitter-level ("properties of the emitter, not of an item") but leaves position/acceleration/drag per item, so emitters inherit the same ambiguity. (The registry's omission of velocity while including acceleration suggests an intent — live channels vs creation channels — that is never stated.)
  • Why it matters for 4d: who owns these values — the system or the item — determines the runtime data layout and the per-tick evaluation order the renderer core is built around. Guessing wrong here is a structural rework in 4e/4f, not a patch.

Medium severity

M1. The 128-track/2048-point automation limit is runtime-dependent but classified as an import-time authoring bound

  • Location: §19.1 "Limits" (line 2431); §19.5 two-kinds table (line 2563) and aggregate row (line 2582).
  • What: The limit counts "across both scopes and across every live spawned instance" — a quantity that only exists at runtime — yet §19.5 lists it as "Authoring bound (19.1), not a shed," and authoring bounds are defined as "checked at import; the exhibit is rejected." Nothing says what happens when a spawn action at runtime pushes the live count past the bound: spawn refused (with WARN_VISUAL_CEILING? as 19.2's instance ceiling does)? Action failure with ERR_VISUAL_LIMIT_EXCEEDED? Exhibit failure? It is also unspecified whether a spawned template's tracks count once at import.
  • Why for 4d: the import/runtime staging split is exactly what the validator half of renderer core encodes; 19.7 trace 6 asserts the numeric boundary but cannot be implemented without the runtime rule.

M2. §17.12 types fill/stroke as literal-only, but §18.1's normative example uses a ref ValueSpec as fill

  • Location: §17.12 table (lines 1766–1767) vs §18.1 example (line 1945: "fill": { "ref": "inputs.tint" }).
  • What: fill is "color, paint object, or null" — a {"ref": …} is none of those. §17.14 licenses ValueSpec "exactly where each field table says so," and 17.12's table does not say so. The same question is unanswered for gradient stop colors (can a stop be {"ref": "inputs.tint"}?). As written, the spec's first visual-component example is invalid, and with it the whole color-typed component-parameter mechanism (18.1, line 1964) has no legal consumer.
  • Why for 4d: paint parsing and style resolution are 4d core; the ValueSpec-vs-literal decision determines the shape of the entire style pipeline.

M3. §19.1's registry automates a repeater step block that does not exist

  • Location: §19.1 registry (line 2408) vs §18.5 field table (lines 2146–2155).
  • What: "for repeater, the numeric fields of its step block." §18.5 defines repeat, count, distribution, position, inputs, behaviors, fields, links — no step. The row is dead text (or a remnant of a dropped design), and with it the only repeater automation surface.
  • Why for 4d: target validation must assign ERR_UNSUPPORTED_TARGET vs ERR_INVALID_REFERENCE per the registry; a registry entry whose referent doesn't exist can't be classified, and 19.7 trace 4's expectations wobble with it.

M4. §19.5's "centralized" ceiling table omits enforced ceilings and mis-cites one

  • Location: §19.5 restated table (lines 2587–2614) vs §17.13 (line 1829: path commands 512), §18.2/§18.4 (lines 2008, 2107: burst entries 16), §18.3 (line 2076: grid columns/rows 256), §15.14 (line 1148: oscillator partials 64), §15.10 (line 1042: resonator modes 16).
  • What: The table claims "every ceiling the engine enforces appears here," but path commands (512), burst entries (16), and grid dimensions (256) are absent, as are custom oscillator partials (64) from the audio side. The "Resonator modes" row gives the value as "Per section 14" with "Fixed in: 15.10" — the value 16 lives in 15.10; "section 14" is a stale citation.
  • Why for 4d: 4d implements path rendering; an implementer coding limits from the central table — the table's stated purpose — will ship without the 512-command bound.

M5. The offscreen-buffer ceiling's shed rule doesn't cover layer buffers, and its warning has no rate limit

  • Location: §17.5 (line 1620) vs §19.5 aggregate table (line 2578).
  • What: Layers with non-default opacity/blend "require an offscreen compositing buffer" counted against the 19.5 budget of 16 — but the shed rule speaks only of "the excess objects" drawn "without their non-default blend, mask, blur, glow, or filters, farthest-z first." There is no rule for a layer whose buffer is shed (draw at opacity 1? drop the blend? in what order relative to object sheds?). The WARN_VISUAL_APPROXIMATION this shed raises also has no stated rate (per object? per frame? once ever?) — unlike every other diagnostic in the table, and unlike the conic-fallback and post-effect uses of the same code, which are explicitly "once per instance."
  • Why for 4d: the compositor's buffer allocator and degradation path are renderer core.

M6. Emitted items and repeater copies have no draw-order rule in their layer

  • Location: §18.2 "Drawing" (line 2059) — particles only; §18.4 and §18.5 have no drawing paragraph; §18.8 (line 2294) references "the system's own depth position (18.2)."
  • What: Particles get an explicit rule: drawn as one unit, system's sort key is its lowest-z particle, internal order z descending then creation ordinal. Nothing says whether an emitter's items or a repeater's copies draw as one unit (and at what z) or interleave per-item with graphic objects in the layer's depth sort. §18.8's link drawing rule cross-references a per-system depth position that only §18.2 defines, and only for particles — so links on a repeater (explicitly legal) have an undefined depth position.
  • Why for 4d: the layer sort and scene-graph structure are built in 4d; the unit-vs-interleave decision is architectural, not a detail.

M7. §18.3 distribution math has holes that break its own "byte-identical" guarantee

  • Location: §18.3 (lines 2067–2083); relatedly §18.6 follow-path (line 2186).
  • What: (a) depth's linear and exponential curves have no formulas — "biasing items toward near" admits many functions (u², 1−√(1−u), any exponential rate). (b) ring/path even modes have no placement formula at all ("distributes angle evenly by index" — i/n or i/(n−1)? measured from startAngle?); line even uses i/(count−1), which divides by zero at n = 1 — NaN, which §2 forbids outright (the count = 1 guard exists for repeat.fraction in §18.5 but was not carried here). (c) The normative sample-consumption order covers x,y,z and polar forms but not select-then-place distributions: rectangle perimeter needs an edge-selection sample and an along-edge sample, in an unstated order. (d) path random is "uniform by arc length," and follow-path moves at scene units/second — both require an arc-length parameterization (flattening tolerance? adaptive quadrature?) that is never fixed, contradicting §18.3's stated goal that placements be "byte-identical across renderers."
  • Why for 4d: placement resolves at instantiation — a renderer-core code path — and 18.10 trace 10 demands documented positions from a fixed seed; without formulas there is nothing to document.

M8. fit's default collides with the viewport validation rule

  • Location: §17.4 (lines 1591, 1600).
  • What: fit defaults to contain; for viewport, "fit is ignored and a fit other than stretch is ERR_SCHEMA_VALIDATION." Read literally, an absent fit resolves to contain — "a fit other than stretch" — so every viewport-space exhibit that doesn't explicitly write fit: "stretch" is invalid. If "ignored" is meant to cover absence, the default never engages and the sentence contradicts itself. Either way it needs an "explicitly authored" qualifier.
  • Why for 4d: scene/fit resolution is the subject of 17.16 trace 1 — the first acceptance trace of the slice.

M9. Post-effect blur/bloom radii are in undefined units

  • Location: §19.4 table (lines 2534, 2537).
  • What: blur.radius is "Scene units, scaled by camera zoom"; bloom.radius is "Scene units" without even the zoom note. But post-effects run on the composited frame (line 2515) — display space, after fit resolution, and after per-object perspective factors that make scene scale non-uniform across the frame. The scene→display conversion for the post chain (fit scale? coordinate space? which layer's parallax?) is never defined. scanlines and grain in the same table use device pixels, so the scene-unit choice is conspicuous.
  • Why for 4d: pass sizing and backing-store math for blur/bloom are set up by the renderer core; two renderers will pick different conversions and both will be "conforming."

M10. §17.16 trace 14 contradicts §8.1/§19.1 (and §19.7 trace 7) as of rev 0.7

  • Location: §17.16 trace 14 (line 1910) vs §8.1 rows (lines 329–332), §19.1 (lines 2416–2427), §19.7 trace 7 (line 2645).
  • What: Trace 14: "A binding, set, or override addressing any visual property is ERR_UNSUPPORTED_TARGET." That was true when 4a landed; it is false now — visuals.camera.zoom et al. are legal binding targets, and 19.7 trace 7 requires them to work. §19.1 (line 2425) carefully preserves §17.14 and 18.10 trace 19 ("survive this slice unchanged") but overlooks trace 14's blanket wording, which was not scoped to per-object properties.
  • Why for 4d: 17.16 is the 4d acceptance suite; as written it fails the document model 4d is required to build.

M11. §18.6 behavior field contracts are incomplete against §12's template, and oscillate's waveforms are undefined

  • Location: §18.6 table (lines 2179–2197); §12 (line 542).
  • What: §12 requires every construct to record required/optional fields, ranges, and defaults. The behavior table lists field names only: oscillate has no stated default for center (0? the authored base?), no requiredness for amplitude/frequency, no phase default; pulse never defines how duty splits between rise and fall, nor its curve default; wander, twinkle, noise-displace give no ranges or defaults (noise-displace's scale/speed/octaves/persistence presumably borrow 18.7's — unstated); rotate.speed, orbit.radius/speed/phase, follow-path.offset, attract/repel.strength, morph.curve, drift.damping likewise. And the waveform functions themselves — triangle, square, sawtooth polarity, duty, and phase origin in w(frequency·t + phase/360) — are never defined, so even with defaults the behavior is not reproducible across renderers.
  • Why for 4d: the document parser and object model ship behavior schemas with renderer core; every missing default is a guess two implementers will make differently.

M12. vortex (and orbit) direction is ambiguous in the y-down scene space

  • Location: §18.7 (line 2239), §18.6 orbit (line 2184) vs §17.2 (line 1543) and §17.4 (lines 1599–1601).
  • What: All three coordinate spaces put +y downward; §17.2's positive angles turn toward +y, i.e. clockwise on screen. vortex is "perpendicular to the outward ray, counter-clockwise for positive strength" without saying whether that is display-visual counter-clockwise or the 17.2 convention — in a y-down space those are opposite vectors. orbit never states the direction of positive speed at all.
  • Why for 4d: sign conventions get baked into the field evaluator and behavior math; a flipped sign passes every automated trace that isn't written and fails the visual acceptance that is.
  • Location: §18.8 links table (lines 2281–2296).
  • What: (a) style defaults to "the system's style" — no system type has a style field (§17.7, §18.2, §18.4, §18.5 define none); the default has no referent. (b) fadeWithDistance fades "from full at distance 0 to zero at maxDistance," but for rule nearest maxDistance is optional — fading with it absent is undefined. (c) The 256-population validation uses particles.capacity as the static proxy, which rejects systems whose live count can never approach it (e.g. capacity: 400, count: 10, no rate/burst → rejected at import); the false positive is unacknowledged. And when repeater.count is a non-literal ValueSpec, the "statically known" precondition silently fails and the instantiation-time diagnostic is unstated.
  • Why for 4d: links validation and default-style resolution land in the renderer core's system model.

Low severity

  • L1 — §19.2 vs §10.1 (lines 2444, 2476, 483): cancelWithScenario semantics are hollow. With ownership: "persistent" the instance transfers to the performance root, so scenario cleanup would not touch it regardless; meaning is given only to false. Either the default true lets a scenario cancel a root-owned instance (making the transfer hollow) or the flag is redundant. 19.7 trace 11 tests a distinction the text never defines. (4d relevance: lifecycle flags ship in the system object model.)
  • L2 — §19.5 (lines 2564, 2583) and §19.2 (line 2480): WARN_VISUAL_CEILING has two unreconciled triggers — "once per ceiling per second" on any shed, and a separate "120 consecutive ticks" degradation report using the same code; and 19.2's spawn refusal "raises once" without saying whether the 1/sec rate limit applies. (Renderer core emits these.)
  • L3 — §17.16 trace 9 (line 1905): "9 layer nesting levels" — layers don't nest; presumably group nesting (already trace 4) or the 16-layer count was meant. (Corrupts the 4d acceptance suite.)
  • L4 — §19.7 trace 9 (line 2647) vs §19.2: the trace requires "a second remove on a DISPOSED instance is a no-op"; §19.2 never states this (§16.3 states it for audio). A trace without normative basis.
  • L5 — §18.2/§18.4/§18.5 count fields (lines 2006, 2107, 2149): integer-typed ValueSpecs with no rounding rule when they resolve non-integer (contrast §8.1's integer-target rounding and §13.2's half-away-from-zero); burst[].count's resolution timing (emitter instantiation vs burst tick) is also unstated — §18.4 (line 2124) carves out burst[].at only.
  • L6 — §17.9 (line 1704) vs §17.6/§19.3: per-point z "offsets the object's z for depth purposes" but the object "is sorted and drawn as one unit" — with points at differing z, which z drives the single perspective factor and fog fraction? z_parent + z_local (17.11) covers groups, not point offsets. A spline spanning z=0..100 needs one number; the spec doesn't say which.
  • L7 — §18.3 path distribution (line 2075): the sibling-key form ("the key of a sibling path/spline/polyline/polygon object in the same container") has no possible referent — distributions live on systems, and systems have no sibling object containers (render/emit/repeat are singular). Dead syntax, or a missing referent such as a graphic system's content.
  • L8 — §18.6 morph (lines 2197, 2214): the operand set is undefined for point-less primitives — compatibility keys on point count, which is meaningless for rectangle/ellipse/arc/ring/text and for path (commands, not points); whether morph there is ERR_INVALID_BEHAVIOR_TARGET or interpolates size/radius is unstated. "Reads the target's resolved points" is also ambiguous when the target's points are moving under point-wander.
  • L9 — §18.1 (lines 1966, 1976) vs §15.11 (line 1059): visual component diagnostics diverge from the audio contract they claim to mirror: undeclared inputs key → ERR_INVALID_REFERENCE (visual) vs ERR_UNKNOWN_FIELD (audio); missing required parameter → ERR_INVALID_REFERENCE at instantiation (visual) vs import-time ERR_SCHEMA_VALIDATION (audio); supplied-value-out-of-range is specified for audio (ERR_OUT_OF_BOUNDS) and unstated for visual. The instantiation staging also means a persistent system passes import and fails at activation — a new failure mode the strict-validation posture elsewhere avoids.
  • L10 — §18.4/§18.5 (lines 2117, 2152) vs §18.1 (line 1974): dual inputs paths — the component object carries its own inputs, and the emitter/repeater carries a separate system-level inputs "only when emit/repeat is a component object," both sampled per item/copy, with no merge or conflict rule when both are present.
  • L11 — §19.2 (line 2450) vs §1.3 (line 58): "the instances.* runtime namespace section 1.3 reserves" — §1.3's prefix list omits instances.*; only §8.1/§8.3 mention it. Dangling cross-reference; the reservation 19.2 relies on doesn't exist where it says it does.
  • L12 — §19.2 (line 2472): release "ramps the instance's composited opacity linearly from 1 to 0" — systems have no opacity property (§17.7), so where the release factor multiplies the compositing stack is undefined, and "from 1" reads as absolute where audio's 16.4 says "from its current value"; the literal reading pops a 0.5-opacity instance to full before fading.
  • L13 — §19.4 (line 2532) vs §17.12 (line 1799): color-adjust claims "the 17.12 filter semantics" but renames the parameters (saturation vs saturate, hueRotate vs hue-rotate) — an unforced inconsistency for implementers mapping one onto the other. §19.4 also never states the resolution boundary for effect parameters (presumably activation; §17.14 covers object fields).
  • L14 — §8.1 (line 329) vs §19.3 (line 2493): the camera row's safety clamp is "the per-field range of 19.3," but focalLength's range is the open interval "above 0" — automation or binding driving it ≤ 0 has no finite bound to clamp to.
  • L15 — §19.2 (line 2439) vs §17.7 (line 1654): the lifecycle row claims it is "Added to the 17.7 system field table by this section," but 17.7 already contains it in rev 0.7. Stale double-definition; harmless, but it signals the two tables can drift.
  • L16 — §19.5 (lines 2557, 2620) and §17.7–17.9: no ceiling bounds declared systems per exhibit or authored objects per system, while governance "never sheds an authored persistent object or a declared system." A document can author unbounded per-frame draw load with no runtime recourse (audio bounds nodes per sound and voices; visuals bounds neither objects per system nor systems per exhibit). Deliberate or not, the gap is unacknowledged in a table that claims completeness.

Checked and found sound

Verified directly against the text (presence, internal consistency, and cross-references), no defect found:

  • All locked §17 decisions present and consistent: degrees/0-+x/positive-toward-+y (17.2, applied to arc/ring/skew/conic); z sign, greater-z-first sort with document-key-order ties and stability (17.6); perspective factor formula and z <= -focalLength culling with no diagnostic (17.6, 19.3, traces 17.16#6 / 19.7#14 mutually consistent); orthographic z behavior; keyed objects with no id field (17.8); transform order T(position+translate) × T(origin) × R × K × S × T(−origin) and M_parent × M_local, z_parent + z_local (17.11); once-at-instantiation ValueSpec resolution and no procedural stream in rendering (17.14, 9.3); layer system-only with ERR_UNKNOWN_FIELD on objects (17.10); fog formula exact, per object, no diagnostic (17.6); conic fallback the sole appearance fallback, warn once per paint instance (17.12); three-font font enum (17.13); live readouts deliberately deferred (17.13).
  • All locked §18 decisions present: fourteen primitives + component as fifteenth object type (17.9, 18.1); component parameter types number/boolean/string/color vs audio's number-only (18.1, 15.15); inputs.*/repeat.* construct scope with ERR_INVALID_REFERENCE and no §8.1 capability (18.1, 18.5); expansion path as the §9.3 stable key (18.1); the normative integrator v ← (v + a·dt)·(1−drag)^dt; p ← p + v·dt (18.2); life ramps interpolating once-resolved endpoints (18.2); fractional accumulator, cumulative floor(rate·t), no reset on automated rate change (18.4); ERR_UNBOUNDED_EMISSION with count-alone legal (18.2/18.4); oldest-first eviction (18.2/18.4); ERR_INVALID_DISTRIBUTION for index-driven placement on continuous emission (18.3); normative sample order x,y,z / angle-before-radius (18.3, as far as it goes — see M7); noise parameters (3D, 12 gradients, 256-entry permutation, quintic fade) present in text (completeness defect H3 notwithstanding); curl default (18.7); ribbon as trail.mode (18.8); links as ERR_UNKNOWN_FIELD on emitters (18.8); morph compatibility rule (18.6).
  • All locked §19 decisions present: exactly four system-level §8.1 rows, verified in the §8.1 table itself (lines 329–332) with visuals.layers.<id>.visible deliberately absent (19.1); two automation scopes with spawn-relative time origin and cross-scope ERR_INVALID_REFERENCE (19.1); 16.1 track shape plus loop, ping-pong count = full round trip (19.1); automatable registry broader than the §8.1 rows (19.1); behavior/track ERR_AUTOMATION_CONFLICT with pipeline-then-behaviors array-order composition (19.1); explicit lifecycle enum and ERR_UNKNOWN_FIELD on persistent systems (19.2, 17.7); spawn stream key <system-id>#<spawn-ordinal> (19.2); five states plus FAILED, no SCHEDULED, with a stated reason (19.2); release default 0ms with one RELEASING tick (19.2); spawn-at-ceiling refusal, never eviction (19.2); normative camera matrix with parallax on translation only (19.3 — algebra spot-checked: reduces to T(c)·S·R·T(−x,−y) at p=1 and to one-fifth camera translation at p=0.2, matching trace 13); projection authored once (19.3); seven effects in normative array order, blur/bloom two passes and the rest one, 4-entry/8-pass arithmetic checks out (19.4); reduced-resolution and unavailable-effect warnings once per effect instance, never substituted (19.4); grain the sole reproducibility exemption, consuming no stream, with a correct justification against §9.3/§14.6 precedent (19.4); §19.5 centralization with provisional values and the Phase-6 gap for scenario/timeline ceilings explicitly named.
  • Diagnostic-code parity: every code introduced by 17.15 (5), 18.9 (7), and 19.6 (2) is present in §7 with matching stage and cause; §7's ERR_AUTOMATION_CONFLICT text is already widened to the visual scope exactly as 19.6 claims; §19.6's "two, and no more" holds.
  • §19.5 restated values match their subsystem sources for every row checked (16 layers, 8 group nesting, 512 vertices, 256 spline points, 16 stops, 4 filters, 8 component nesting, 4096/512 capacities, 1024 repeater count, 8 behaviors, 8/4 fields, 128 trail, 1024 maxLinks, 4 effects, 32 radius, 64 spawned, 64/16 voices, 64/256 audio automation, 1024 dispatch units, 16 event depth, 256 hook actions).
  • §16.1 → §19.1 track-shape reuse: field-for-field match (target/mode/interpolation/points, duration-literal at, strictly-increasing rule, hold-first/hold-last), with loop the only addition, as claimed.
  • State machine: the visual machine is the audio machine minus SCHEDULED, transitions otherwise parallel, and the reasoning (no second clock) is stated; cleanup deadline interplay with §10.2 (shorter of authored release and 5s, WARN_CLEANUP_FORCED) is consistent.
  • 17.16 / 18.10 / 19.7 trace lists are internally consistent with their sections everywhere except the flagged items (M10, L3, L4).