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
5.9 KiB
Spec Review — Grok 4.6
Source: Grok 4.6 Scope: sections 14–16 only Received: 2026-09-06 Status: raw, untriaged — verbatim as delivered
Review of sections 14–16 only. Deliberate omissions from your list are not reported.
1. ERR_INVALID_RANGE_ORDER on sample-hold min/max — semantic stage cannot enforce it
Severity: high (unimplementable staging; same class as the prior two)
§14.12 says min / max are ValueSpecs resolved once at instantiation (14.4), and "min resolving to a value greater than or equal to max is ERR_INVALID_RANGE_ORDER."
§7 files ERR_INVALID_RANGE_ORDER as Semantic only. Semantic validation runs at import with no instantiation and no resolved ValueSpecs.
Literals such as the documented invalid case { "min": 1, "max": -1 } are checkable at import. A legal { "min": { "random": { "min": -1, "max": 1 } }, "max": { "random": { "min": -1, "max": 1 } } } is not. The stage that can see the resolved pair is instantiation, which is not Semantic.
Smallest fix: In §7, stage ERR_INVALID_RANGE_ORDER as Semantic / Runtime (literals at import; resolved ValueSpecs at instantiation). Do not call the resolved-order failure a semantic-stage error.
2. One-shot bound: empty retained resonator modes
Severity: high (undefined for a legal graph)
§16.5 resonator contribution is "the longest decay among its retained modes." §15.10 / §14.7: a mode whose resolved frequency exceeds audioMaxFrequency is omitted at instantiation. audioMaxFrequency needs the live sample rate (14.5).
Legal input: one mode with frequency: 20000 (semantic-legal vs 24000). On 44.1 kHz, audioMaxFrequency = min(24000, 19845) = 19845, the mode is omitted, retained set is empty, longest decay is undefined. Longest-path then has no defined resonator term.
Smallest fix: Define empty retained modes as contribution 0 (signal dropped; duration not extended).
3. Automation point value draws a seeded stream with no sampling rule / key
Severity: high (reproducibility unimplementable)
§16.1: each point is { "at": <duration literal>, "value": ValueSpec<number> }, and "values remain full ValueSpecs and may be random."
§14.4 samples nested ValueSpecs from the sound instance stream only for node-object fields. §15.12 explicitly folds route depth into that rule. Track value is neither a node field nor given that fold. §14.12 is the only extra child-key document, and it is sample-hold only.
An implementor cannot know when value is drawn, in what order relative to node fields / depth, or from which stream.
Smallest fix: One sentence in 16.1: point value ValueSpecs are resolved once at instantiation with the other graph ValueSpecs, depth-first in document order on the sound instance stream (14.4 / 9.3). No new child key.
4. Override-vs-automation for node properties vs 14.4
Severity: high (internally unimplementable)
§14.4: a set / override addressing a node field is ERR_UNSUPPORTED_TARGET. Node fields are not in the 8.1 table.
§16.2 still puts winning override on the node property pipeline and requires: override masks automation; on release the property follows the track's current value.
§16.11.8 requires a trace of that behavior.
Those traces cannot pass if 14.4 rejects the override.
Smallest fix: In 16.2, state that the override stage is absent for node properties (14.4). Keep override-vs-automation only for audio.buses.<id>.gain. Drop or retarget 16.11.8 to bus gain.
5. Bus gain "takes automation" with no place to declare a track
Severity: medium–high
§16.2 (and 8.1): audio.buses.<id>.gain takes automation.
§16.1 / §14.3: tracks exist only on graph automation arrays (<node-key>.<property>).
§15.17 bus object allowed fields: gain only.
No legal target can name a bus, and a bus cannot hold tracks. Bus automation is required and impossible to author.
Smallest fix: Either add an automation array on the bus object (targets gain only) or strike automation from the bus capability in 16.2 and leave 8.1 to a later erratum. Do not leave both claims standing.
6. Automation track/point limits: runtime in 15.14, semantic in 16.1
Severity: medium (wrong stage in one of the two)
§15.14: automation tracks (64) and points (256) "are runtime ceilings rather than document properties."
§16.1 / §16.11.6: exceeding them is ERR_NODE_LIMIT_EXCEEDED (Semantic in §7), and the trace is import-time.
Counts after expansion are document properties; Semantic can enforce them. 15.14's "runtime ceiling" classification is then false (and would be unenforceable as a runtime-only rule without a second code).
Smallest fix: In 15.14, move tracks/points into the authoring-limit table with expanded nodes/routes, or say Phase 3c enforces them as semantic ERR_NODE_LIMIT_EXCEEDED. Do not call them runtime ceilings.
Classes with no finding
- Prose vs JSON in the same section: none.
- Field on a container missing from that container's allowed-field table: none beyond (5), where the field never appears on the bus table at all.
- Diagnostic code used in 14–16 but absent from §7: none. Staging errors are (1) and (6).
- Cross-references to sections that do not exist: none.
- Non-termination: 16.5 longest-path is stated to terminate on the acyclic expanded graph; no extra finding. Delay
log(feedback)is defined on the legal range(0, 0.95]. - Breach with no behavior: component
releaseis excluded by 14.3/15.15 unknown-field policy; not reported.
Deliberate items (node id, bindable surface, noise/impulse vs sample-hold reproducibility, one track vs summing modulation, provisional master protection, absent audio.master, literal automation at, GC4 stall bound, bus processing / compressor-reverb-waveshaper modulation) were not treated as defects.