The standalone build's source list is explicit, so the two modules the previous
commit added were called by validator.js inside XZBT.html without being defined
there. Both are now bundled ahead of validator.js and resolution.js, which are
their only consumers.
visual-validation.js used a local isPlainObject that would have collided with
validator.js's own once the bundler strips imports and concatenates into one
scope; it uses the shared isRecord of types.js instead.
The rebuilt artifact parses and carries validateVisualSubsystem and
matchVisualTarget. npm test remains at 131 passing.
Co-Authored-By: Claude Opus 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_0162Jb1J36judZNT8fHabGVt
Format Specification revision 0.8 closes the thirty repair packages
(V1-V30) and three additional defects (A1-A3) of reviews/01-triage.md
before slice 4d writes any renderer code. Every Tier-1/2/3 design
decision adopts the triage's own recommended fix; reviews/05-visual-fix-log.md
records each choice, its reason, and the sections it touched.
Contradictory surfaces first. `visuals.automation` is added to the 17.3
allowed-field table that previously rejected it. Trace 17.16.14 is
rewritten around the four target families that now exist rather than
asserting a table that changed. `fill` and `stroke` accept
ValueSpec<color>, which is what makes 18.1's own component example legal,
with three limits stated so a ValueSpec can never return a paint object.
The repeater automation registry loses its nonexistent `step` block. An
infinite loop is legal in every scope, bounded by whatever owns the
track.
Spawned-instance lifecycle moves into a `spawn` container. A top-level
`lifetime` is now unambiguously per item and `spawn.lifetime` per
instance, so a spawned emitter expresses both and a spawned repeater
takes an instance lifetime without contradicting 18.5. Component inputs
get one canonical location, the `component` object's own `inputs`, and
the system-level `inputs` on emitters and repeaters is removed.
The composition chain is written out in named spaces. The fit matrix
carries the contain and cover centering offsets it was missing, the
camera center is mapped into CSS coordinates before the translation is
formed, and the chain B x P x V x F x M applies the device-pixel
multiplier exactly once. Local extents and anchors are fixed for all
fourteen primitives, arc sweep is directed with its bound checked before
normalization, catmull-rom is a uniform cardinal spline with its equation
given, and a closed bezier spline closes with a line.
Compositing gets a normative eight-stage order. Layer opacity applies
once, at the layer, not a second time per object, and a separate release
factor initialized to 1 means release never rewrites an authored opacity.
The sixteen offscreen buffers are one pool shared by layers and objects,
with allocation order, reuse, and farthest-first shedding stated, and
buffer refusal named as a diagnosed exception to 17.1.
Sorting units are defined for emitters and repeaters, not only particles:
a procedural system is atomic, with a representative depth and internal
ordinal ordering. Depth fog fixes its blend space and fogs gradient stops
before the paint is built. Coherent noise becomes an algorithm - ordered
gradients, a 255-sample Fisher-Yates shuffle, the full lattice hash,
octave normalization, and curl as the explicit perpendicular of the
potential's gradient - with published tolerances. Distributions get their
equations and an explicit per-distribution draw list, replacing "field
order". All seventeen behaviors get complete field contracts, waveform
equations, an accumulating-versus-fresh rule, and channel write sets.
Live automation totals separate from authoring bounds: a spawn that would
cross the live budget is refused atomically, consuming no ordinal, rather
than being admitted with tracks dropped. One diagnostic cadence covers
every ceiling and every shed. The centralized table gains the ceilings it
was missing and two new authoring bounds - 64 declared systems and 16384
expanded static objects - that close the unbounded static draw load.
`focalLength` gains a real lower bound of 1 so the clamp has a value to
clamp to. The backing store cap wins over the multiplier floor on
displays wider than 4096. Parallax 0 is pinned against camera
translation, not exempt from zoom and rotation.
tools/verify-spec-contract.py commits the contract harness that was
previously run ad hoc. Its post-edit run reports 46 diagnostic codes
declared, 107 distinct cross-references all resolving, zero unresolved
references, 170 balanced fence markers, and 112 well-formed tables.
Documentation only: no runtime, schema, fixture, or test file was
touched, and npm test still passes 102 tests with zero failures. Every
19.5 value, including the two new static bounds, remains provisional
pending the slice 4h GC6 measurement.
Co-Authored-By: Claude Opus 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_0162Jb1J36judZNT8fHabGVt
Review Phase 3a before building on it, then implement Phase 3b.
The Phase 3a draft had four blocking defects: nodes were described as a
keyed map while every documented example carried an inline `id` field,
so under the strict unknown-field policy each minimal example would have
failed its own acceptance trace; no section said where a node lives; the
`audioMaxFrequency` ceiling was declared a semantic-stage error while
depending on a live AudioContext sample rate; and the sample-hold PRNG
child key that section 9.3 requires was undocumented. Close all four,
plus nine further gaps in noise seeding, spectral definitions, impulse
decay math, Nyquist handling, missing-field codes, LFO phase origin, the
units table, node-type staging, and a duplicated diagnostics table.
Add Format Specification section 15 for Phase 3b: nine processing and
routing node contracts, the component instance node, audio routing and
modulation with an explicit modulatable-property registry, twelve graph
legality rules, authoring limits, components with a component-scoped
`inputs.*` namespace, sound definitions and recipes, and buses.
Implement the subsystem in three modules. audio-contract.js holds the
declarative node, limit, and modulation tables every consumer reads.
audio-graph.js validates, expands components, and checks legality
without ever opening an AudioContext. audio-engine.js resolves node
fields once from the seeded stream, clamps frequencies to the live
device ceiling, realizes the graph through Web Audio, and owns the
runtime AudioSubsystem. Extend the schema, delegate the standalone
validator's audio checks to the shared module rather than carrying a
second implementation, and add a generic audio fixture.
Phase 3 is not accepted. Automation precedence, the lifecycle state
machine, unlock behavior, voice ceilings, and master protection are
Phase 3c. No sound has been heard from any build, so the audio
acceptance challenge, peak and finite-sample capture, and listening
observations remain open.
Co-Authored-By: Claude Opus 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_011FWPdCqKaaDnP9NC3JAwh6
- Record user evidence for directory fallback to complete GC1 (10/10 checks passed)
- Expand Format Specification 0.1 to Revision 0.2 with normative shared contracts
- Author JSON Schema Draft-07 at schema/xzbt-0.1.schema.json
- Implement zero-dependency semantic validator at tools/validate-exhibit.mjs
- Create 12-case conformance fixture suite and automated test runner (12/12 passing)
- Update implementation status, verification gates, and gap closure decisions
- Add devlog entry covering stall recovery and Phase 0 current state