Files
XZBT/docs/evidence/phase5/2026-09-06-phase5-events-cadence.md
T
LabyricornandClaude Opus 5 3db1df058f feat(cadence): implement the phase 5 event and cadence subsystems
Section 20 in full: the automatic scheduling algorithm with its eligible-pool
filtering, cooldown and overlap exclusion, weight evaluation, the anti-repetition
multiplier table applied by recency-queue position, pool relaxation when total
effective weight reaches zero, and reschedule by uniform sample divided by
intensity; the priority clocks and minimum-gap servicing of 20.6 with deferred
classes retained; intensity clamping and the pause threshold of 20.7, under
which ambient voices keep running; the 1024-unit dispatch budget and sixteen
levels of event nesting; and manual SAMPLE evaluation in an isolated stream that
does not perturb cadence scheduling.

Two defects found by the section 20 review triage are fixed here rather than
shipped. A sound action's usage check tested whether the target sound permitted
*some* action context instead of the caller's own, so a scenario-only sound was
playable from a manual action; it now checks the caller's context and rejects
with ERR_UNSUPPORTED_TARGET, the code 20.2.2 and 20.12 actually name, and the
two cases the previous test never exercised — manual-only from scenario, and
scenario-only from manual — are covered.

Traces 7 through 10 drove `triggerSound()` and `calculateEligiblePool()`, a
duplicate scheduler with no production call site, rather than the
`advance()`/`fireClass()` path a real exhibit runs. The two implementations
disagreed on recency-history semantics: 20.5.9 requires a plain queue of the
last four firings, and the duplicate moved an existing entry to the front
instead. Nothing caught it because nothing called both. Those traces now drive
`update()`/`advance()` with a seeded RNG, as traces 11 through 14 already did,
and the duplicate is deleted rather than reconciled.

Co-Authored-By: Claude Opus 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01ShxxFqFmCUDQnQvFNm4TKy
2026-09-06 21:53:51 +00:00

100 lines
8.0 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Phase 5: Events and Cadence Acceptance Evidence
**Date:** September 6, 2026
**Status:** Complete and fully verified
**Specification References:** PRD 61–68 (Cadence Model), 90–91 (Event Model 0.1), 139 (Milestone criteria); Format Specification Revision 0.9, Section 20 ("Cadence and Event Subsystems Contract")
---
## 1. Executive Summary
Phase 5 completes the Cadence and Event subsystems of XZBT 0.1, delivering:
1. **Contract & Schema:** Complete Section 20 normative contract in the Format Specification and JSON Schema definitions for `CadenceConfig`, `CadenceClockRange`, `SoundCadence`, `ActionSpec`, and `EventDefinition`.
2. **Static & Semantic Validation:** Implemented in `src/runtime/cadence-validation.js`, integrated with `src/runtime/validator.js` and `tools/validate-exhibit.mjs`. Static cycle detection for events (`ERR_CYCLIC_DEPENDENCY`), clock range ordering (`ERR_INVALID_RANGE_ORDER`), and sound cadence metadata validation.
3. **Action Model 0.1:** Implemented in `src/runtime/actions.js` with `type: 'event'` and `type: 'sound'`, per-tick action dispatch budget (1024 units/tick), 16-level event recursion limit, strict input parameter scoping, default value substitution, type validation (`ERR_TYPE_MISMATCH`), undeclared parameter rejection (`ERR_UNKNOWN_FIELD`), and sound usage gating (`ERR_UNSUPPORTED_TARGET`).
4. **Procedural Cadence Engine:** Implemented in `src/runtime/cadence.js` with clock interval management for `routine`, `intermittent`, `occasional`, and `rare` classes, minimum gap scheduling (`minGap`, default 1.5s), priority queue ordering (`rare` > `occasional` > `intermittent` > `routine`), weighted random selection, cooldown checking, overlap refusal, anti-repetition recency multipliers (`0.0`, `0.25`, `0.50`, `0.75`) with automatic pool relaxation, continuous ambient sound voice auto-start and maintenance, and strict PRNG domain isolation (`cadence` domain).
5. **Content Integration:** All four reference exhibits (`exhibits/exhibit-{a,b,c,d}.xzbt`) populated with valid audio synthesis graphs, sounds, cadence clocks, and lifecycle events.
6. **Verification:** All 14 acceptance traces of Section 20.15 verified in `test/phase5-cadence.test.mjs`. The full suite of 229 automated tests passes with zero failures. Deterministic builds of `XZBT.html` produce byte-identical SHA-256 digests.
---
## 2. Test Execution and Acceptance Traces
The 14 acceptance traces defined in Section 20.15 of the Format Specification are verified by `test/phase5-cadence.test.mjs`:
| Trace | Title | Verification Target | Status |
|---|---|---|---|
| **Trace 1** | Schema & Static Validation | Top-level cadence and sound cadence validation; clock range with `min > max` rejected with `ERR_INVALID_RANGE_ORDER`. | PASS |
| **Trace 2** | Static Cycle Detection | Static dependency graph analysis detects direct, mutual, and transitive event cycles, rejecting them with `ERR_CYCLIC_DEPENDENCY`. | PASS |
| **Trace 3** | Event Scoping & Typing | Declared default inputs are applied; caller overrides are strictly type-checked; undeclared parameters are rejected with `ERR_UNKNOWN_FIELD`. | PASS |
| **Trace 4** | Event Recursion Limit | Dynamic event nesting exceeding 16 levels halts dispatch cleanly with `ERR_DISPATCH_BUDGET`. | PASS |
| **Trace 5** | Dispatch Budget | Per-tick action execution budget of 1024 units is strictly enforced; excess actions refused with `ERR_DISPATCH_BUDGET`. | PASS |
| **Trace 6** | Sound Action Usage | Actions attempting to trigger sounds from unauthorized contexts are refused with `ERR_UNSUPPORTED_TARGET`. | PASS |
| **Trace 7** | Cooldown Refusal | Sounds are refused if re-triggered before their declared `cooldown` duration has elapsed. | PASS |
| **Trace 8** | Overlap Refusal | Sounds configured with `overlap: false` refuse dispatch when another voice instance of that sound is active. | PASS |
| **Trace 9** | Anti-Repetition Multipliers | Recent sound playbacks receive monotonically graded multipliers: rank 0 = `0.0`, rank 1 = `0.25`, rank 2 = `0.50`, rank 3 = `0.75`. | PASS |
| **Trace 10** | Pool Relaxation | When all candidate sounds in a pool are penalized to effective weight zero, weights relax to base values so scheduling never deadlocks. | PASS |
| **Trace 11** | Intensity Scaling | Higher intensity compresses clock intervals; lower intensity expands intervals; clamped to safe bounds (>= 100ms). | PASS |
| **Trace 12** | Minimum Gap & Priority | Automatic sound scheduling respects the minimum gap (`minGap`, default 1.5s) and prioritizes `rare` > `occasional` > `intermittent` > `routine`. | PASS |
| **Trace 13** | Ambient Voice Maintenance | Continuous ambient sounds auto-start when audio is unlocked and maintain exactly one voice, restarting if stopped. | PASS |
| **Trace 14** | Manual SAMPLE PRNG Isolation | Interspersing manual SAMPLE draws from the `manual-sample` / `sample` PRNG domain has zero effect on cadence scheduling. | PASS |
### Test Suite Execution Output
```
> node test/phase5-cadence.test.mjs
✔ Trace 1: Schema & Static Validation of cadence and sound metadata (3.4712ms)
✔ Trace 2: Static cycle detection rejects circular event action chains (0.5927ms)
✔ Trace 3: Event input scoping, defaults application, and strict type checking (1.2611ms)
✔ Trace 4: Dynamic event nesting exceeding 16 levels is halted (0.4059ms)
✔ Trace 5: Per-tick 1024-unit action dispatch budget is strictly enforced (0.9943ms)
✔ Trace 6: Sound actions targeting unauthorized sounds are refused with ERR_UNSUPPORTED_TARGET (0.5403ms)
✔ Trace 7: Sound cooldown refrains from re-dispatching before interval expires (0.7546ms)
✔ Trace 8: Overlap false prevents new instance while existing voice is active (0.6852ms)
✔ Trace 9: Anti-repetition penalties apply 0.0, 0.25, 0.50, 0.75 recency multipliers (0.2897ms)
✔ Trace 10: Anti-repetition relaxation to base weights when all candidates are penalized to zero (0.2865ms)
✔ Trace 11: Intensity scaling inversely compresses or expands clock intervals (0.1554ms)
✔ Trace 12: Minimum gap (1.5s) and priority ordering (rare > occasional > intermittent > routine) (0.1433ms)
✔ Trace 13: Continuous ambient sounds auto-start and maintain exactly one active voice (0.1067ms)
✔ Trace 14: Manual SAMPLE evaluations run in isolated stream without perturbing cadence scheduling (0.9915ms)
ℹ tests 14
ℹ suites 0
ℹ pass 14
ℹ fail 0
ℹ cancelled 0
ℹ skipped 0
ℹ todo 0
ℹ duration_ms 15.0156
```
Full repository regression (`npm test`): **229 tests pass, 0 fail**.
---
## 3. Exhibits A–D Content Validation
All reference exhibits were augmented with audio graphs, sounds, cadence configurations, and events:
- **Exhibit A (Procedural Machine):** `machine-hum` (ambient drone), `relay-click` (routine percussive), `steam-purge` (intermittent burst), `emergency-siren` (rare alarm), and `minor-disturbance` event.
- **Exhibit B (Deep Abstract Field):** `pad-drone` (ambient sine drone), `harmonic-resonance` (intermittent chord), `sub-swell` (occasional low swell), and `field-shift` event.
- **Exhibit C (Natural Environment):** `wind-atmosphere` (ambient pink noise), `organic-chimes` (occasional resonant bell), `wind-gust` (rare swept gust), and `breeze-surge` event.
- **Exhibit D (Instrument Display):** `radar-pulse` (routine telemetry ping), `button-click` (manual UI click), `telemetry-alert` (occasional alert chime), and `sweep-alert` event.
All exhibits validated cleanly via `tools/validate-exhibit.mjs`:
```
[PASS] exhibits/exhibit-a.xzbt (0 errors)
[PASS] exhibits/exhibit-b.xzbt (0 errors)
[PASS] exhibits/exhibit-c.xzbt (0 errors)
[PASS] exhibits/exhibit-d.xzbt (0 errors)
```
---
## 4. Deterministic Build Digest
Rebuilding `XZBT.html` via `node tools/build-xzbt.mjs` incorporates all new runtime modules (`src/runtime/cadence-validation.js`, `src/runtime/cadence.js`, and updated `actions.js`, `audio-engine.js`, `performance.js`, `app.js`):
- **Artifact:** `XZBT.html`
- **File size:** 502,989 bytes
- **SHA-256 Digest:** `f3f634d7d33b2f8a57cae541fc31b4dcedce88b2ee2648093f92a2cfc168d718`
- **Determinism:** Successive independent builds generate the identical byte sequence and hash.