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
7.7 KiB
7.7 KiB
XZBT 0.1 triage — fix log (what was applied, what remains)
Record of edits to docs/XZBT_0-1_Format_Specification.md (1499-line version, working
tree = commit e5ed468; spec file itself unmodified in git status at time of writing).
Consolidates the 13 defects of 00-triage.md. Scope constraint honored: nothing that
overlaps the in-flight Phase 3c slice-2 implementation (16.3 lifecycle, 16.4 release,
16.5 endings, 16.6 eviction, disposal, traces 16.11.7/9/10/11, or the runtime/schema/test
files that slice has open) was touched. Doc-text edits only; no code, schema, or test
changes.
Applied — 7 of 13 defects
| T | Location(s) | Change | Verification |
|---|---|---|---|
| T4 | §7 row ERR_INVALID_RANGE_ORDER; 14.12 |
Refiled Semantic / Runtime with a cause covering both uses: literal paired bounds at import, resolved paired bounds at node instantiation, automation at ordering at import. 14.12 now states the literal/resolved split explicitly. 14.12's invalid-case example (min: 1, max: -1) remains an import case, consistent. |
Code grounding: audio-graph.js:186 emits the code only when both bounds are literal numbers, i.e. import stage. |
| T5 | 16.1 "Points." | Added: "A track's point values are resolved once at the owning sound instance's instantiation boundary, sampled from that instance's stream in depth-first, property-document order, with automation taken after nodes and routes." Wording matches 14.4's and 9.3's own vocabulary; automation follows nodes/routes per the 14.3 graph-object field table. |
None needed (forward-looking; automation is slice 3c-3). |
| T6 | 15.14 (limits paragraph); §7 row ERR_NODE_LIMIT_EXCEEDED |
Automation tracks/points removed from the runtime-ceiling enumeration (voice ceilings remain, with a 16.6 cross-reference) and pointed to 16.1's semantic enforcement instead. §7 cause extended: "...or automation tracks or points per expanded sound". | 16.10 and 15.18 tables do not restate either amended row; no drift. |
| T10 | 16.2 | Clause added to the node-property paragraph: override actions on node fields are barred exactly like BindingSpec (14.4), so the winning override stage of the pipeline is always absent for node properties — "absent, not an identity hook (8.1)". |
— |
| T11 | 14.9 impulse envelope table | Column relabelled "Value at p = 1" → "Value as p → 1⁻" with corrected cells a, 0, a x 0.001 (exponential no longer self-contradicts its -60 dB annotation). |
Rows checked against the piecewise definition (0 <= p < 1, exactly 0 for p >= 1). |
| T12 | 15.16 sounds metadata | Sentence added: name > 128 chars, > 16 tags, or a tag > 32 chars is ERR_SCHEMA_VALIDATION. |
Grounded: schema/xzbt-0.1.schema.json enforces name maxLength 128, tags maxItems 16, item maxLength 32 (Sound definition). |
| T13 | 16.2 | Mis-citation fixed: "parameter-masking rule of section 8.1" → masked-override rules of 8.3 (underlying stages keep evaluating while masked) and 8.4 (release resolves against the current lower value recomputed without the releasing override). | 8.3 line 370 and 8.4 currentLowerValue text verified as the actual referents. |
Net diff: 12 insertions / 10 deletions in 9 regions. Nothing else in the file changed.
Not applied — 6 of 13 defects, with reasons
| T | Reason |
|---|---|
| T1 (bus-gain automation/modulation surface; 8.1/15.17/16.1/16.2/16.11.8) | (design) — the triage's own edit list marks it decision-required before an edit can be written. Recommended option (b): give audio.buses.<id>.gain an authoring surface and name it in 16.1's target rule. Not in Gemini's slice (automation is 3c-3), so it can be picked up independently, but needs a decision first. |
T2 (delete component modulation-target row; 15.13/15.11/15.19.4) |
Blocked on coordination, not on Gemini's slice per se: the registry row is mirrored in audio-contract.js, asserted by a green Phase 3b test (test/phase3-audio.test.mjs:313, trace 15.19.4), and 15.19.4 is an accepted contract trace. Deleting spec text alone would leave doc contradicting code+test. The runtime and test files are currently open by the slice-2 work; the delete (plus trace amendment and test/registry update) must land as one coordinated change, or be consciously deferred as a contract decision. |
| T3 (16.6 eviction step 3 frees no slot) | Gemini's slice — 16.6 and trace 16.11.10 are being implemented and tested right now. A spec change here would invalidate the in-flight suite and evidence record. After slice 2 lands, reconcile: Gemini's audio-engine.js has already made some choice for step 3; check it against the triage's two options (recommended: evicted ACTIVE one-shot leaves the ceiling count at the moment of eviction, release running outside the budget, with the matching exception added to the 16.6 counting rule). |
| T7 (16.5 resonator bound over empty retained-mode set) | Gemini's slice — 16.5 ending computation and trace 16.11.9. One-sentence fix ("...or zero when no mode is retained") ready to apply after slice 2 lands; check against Gemini's implementation choice for single-mode resonators on a 44.1 kHz device. |
| T8 (16.5 delay bound under modulation) | Gemini's slice + (design) + blocked on T9. Alternative fix (exclude modulated bound-contributors from determinable-ending status via ERR_INDETERMINATE_ONESHOT) touches 16.5 semantics the slice is implementing. |
| T9 (oscillator modulation output magnitude undefined; 15.13) | (design) — stating a range in the spec would be a behavioral contract change for accepted Phase 3b modulation code (custom-partial normalization) that no implementation performs; the registry and summation code live in files the slice has open. Needs a decision, then coordinated spec + contract-registry change. |
T14 (exposed parameter without min/max has no clamp range) |
Conditional on T2 — moot unless T2's option two (live parameter tracking) is chosen. Remains closed while T2 is open. |
Follow-ups recorded, not actioned
- T4 implementation gap (pre-existing): no instantiation-time range-order check exists.
audio-graph.js:186is the only enforcement site and it guards on both bounds being literal numbers (typeof low === 'number' && typeof high === 'number'). A document with resolved (e.g. random)sample-holdbounds that invert at resolution is import-legal and currently unchecked at instantiation. The spec now says the check happens there; the runtime follow-up belongs to the phase-3a code owner (files open by Gemini's slice). - §8 out-of-scope finding from the triage: §8.5 trace 6 and §8.3's masked-automation sentence are already unimplementable for want of a target exposing both automation and override (T1's root cause, independent of §§14–16). Still to be logged against §8; T1 must not be closed without addressing it.
- 14.3 canonical example (
oscillator → gain → output) is not a legaloneshotrecipe as-is (ERR_INDETERMINATE_ONESHOT); noted as editorial, not a defect. Unchanged. - 14.7 all-partials-omitted oscillator deserves one clarifying sentence (Kimi #5 / DeepSeek F7 downgrade in the triage); not a Tier-2 defect. Not actioned.
Housekeeping
- Edits are uncommitted in the working tree (12+/10−, 9 regions, spec only). Recommended:
land as a dedicated
docs(audio): ...commit before Gemini's slice-2 commit, per the project's contract-before-implementation convention, so the two changes never mix. - Verified: no stale "Value at
p = 1" header remains; §7 rows appear once each; 15.18 and 16.10 tables unaffected; all new cross-references (15.14 → 16.6/16.1; 16.2 → 8.1/8.3/8.4; 14.12 → 14.4) resolve. No test suite was run — none is affected by doc-text edits, and the slice-2 suite was in flight.