# 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..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.