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
This commit is contained in:
@@ -0,0 +1,64 @@
|
||||
# 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:186` is 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-hold` bounds 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 legal `oneshot` recipe
|
||||
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.
|
||||
Reference in New Issue
Block a user