open-standards/wai/extensions/score.md
Transaction Science 161d147767
Some checks failed
wai-quantum WebGPU member / member · discrete GPU, Vulkan (jetson-hub) (pull_request) Successful in 9m59s
spec citations resolve / Code cites no section its SPEC lacks (pull_request) Successful in 4s
standards workspaces build + test / arl-rs (pull_request) Successful in 1m12s
standards workspaces build + test / eoc-rs (pull_request) Successful in 2m15s
standards workspaces build + test / jcp-rs (pull_request) Successful in 1m48s
standards workspaces build + test / joule-ui-rs (pull_request) Successful in 1m10s
standards workspaces build + test / joulehook-rs (pull_request) Successful in 1m13s
standards workspaces build + test / proof-rs (pull_request) Successful in 1m35s
standards workspaces build + test / sense-rs (pull_request) Successful in 1m14s
standards workspaces build + test / sandbox-rs (pull_request) Successful in 2m35s
no-vanity-metrics / Scan committed Markdown for vanity metrics (pull_request) Has been cancelled
no-vanity-metrics / WAI public text names no comparison (pull_request) Has been cancelled
no-vanity-metrics / WAI public text names no company or product (pull_request) Has been cancelled
no-vanity-metrics / No new orphan source files (pull_request) Has been cancelled
standards workspaces build + test / jouleclaw-rs (pull_request) Has been cancelled
standards workspaces build + test / aac-rs (pull_request) Has been cancelled
standards workspaces build + test / joule-code-rs (pull_request) Has been cancelled
standards workspaces build + test / joulecontract-rs (pull_request) Has been cancelled
standards workspaces build + test / jouledesk-rs (pull_request) Has been cancelled
standards workspaces build + test / map-rs (pull_request) Has been cancelled
standards workspaces build + test / mesh-rs (pull_request) Has been cancelled
standards workspaces build + test / openpay (pull_request) Has been cancelled
standards workspaces build + test / macOS energy backends (pull_request) Has been cancelled
tests in CI / every test file is run by a job or listed with its reason (pull_request) Has been cancelled
WAI conformance / cargo-class corpora · linux-arm64 (pull_request) Has been cancelled
WAI conformance / cargo-class corpora · macos (pull_request) Has been cancelled
WAI conformance / quantum core and corpus under wasm32-wasip2 (wasmtime) (pull_request) Has been cancelled
WAI conformance / v2 vocabulary · manifests validate as stated (pull_request) Has been cancelled
WAI conformance / independent verifiers · claims, JWP, key discovery and integer payloads (Python) (pull_request) Has been cancelled
WAI conformance / delivery telemetry · CMCD and CMSD against an independent library (pull_request) Has been cancelled
WAI conformance / cross-arch byte-equality · linux (pull_request) Has been cancelled
WAI conformance / cross-arch byte-equality · linux-arm64 (pull_request) Has been cancelled
WAI conformance / cross-arch byte-equality · macos (pull_request) Has been cancelled
WAI conformance / codec wrappers · fuzz smoke, text decode limits, C entry points, provenance, the semantic path (pull_request) Has been cancelled
WAI conformance / C2PA manifest emission · signed, read back, validated (pull_request) Has been cancelled
WAI energy receipts / energy receipts · linux (pull_request) Has been cancelled
WAI energy receipts / energy receipts · linux-arm64 (pull_request) Has been cancelled
WAI energy receipts / energy receipts · macos (pull_request) Has been cancelled
WAI HTTP delivery / WAI HTTP · does this change touch it (pull_request) Has been cancelled
WAI HTTP delivery / HTTP corpus · falsify mutations 0/3 (pull_request) Has been cancelled
WAI HTTP delivery / HTTP corpus · falsify mutations 1/3 (pull_request) Has been cancelled
WAI HTTP delivery / HTTP corpus · falsify mutations 2/3 (pull_request) Has been cancelled
WAI HTTP delivery / HTTP corpus · falsify patches 0/3 (pull_request) Has been cancelled
WAI HTTP delivery / HTTP corpus · falsify patches 1/3 (pull_request) Has been cancelled
WAI HTTP delivery / HTTP corpus · falsify patches 2/3 (pull_request) Has been cancelled
WAI HTTP delivery / HTTP corpus · every patch and mutation in exactly one shard (pull_request) Has been cancelled
WAI HTTP delivery / HTTP corpus · verified both ways, and the differential (pull_request) Has been cancelled
WAI HTTP delivery / cache rules · controls and labelled caches (pull_request) Has been cancelled
WAI JPEG-AI whole decode (pinned inputs, required) / fetch pinned JPEG-AI inputs → whole decode + pixel hash, required (pull_request) Has been cancelled
WAI neural sink gates / model-free refusals of the neural sink (pull_request) Has been cancelled
wai-pack / wai-pack · does this change touch it (pull_request) Has been cancelled
wai-pack / wai-pack · linux (pull_request) Has been cancelled
wai-pack / wai-pack · linux-arm64 (pull_request) Has been cancelled
wai-pack / wai-pack · macos (pull_request) Has been cancelled
wai-pack / wai-pack · independent verifier (Python) (pull_request) Has been cancelled
wai-pack / wai-pack · the floor through a media prober (pull_request) Has been cancelled
wai-pack / wai-pack · dependency licences (pull_request) Has been cancelled
wai-quantum WebGPU member / shader checks · browser build · wasip2 inertness · MSRV (pull_request) Has been cancelled
wai-quantum WebGPU member / member · software Vulkan (linux) (pull_request) Has been cancelled
wai-quantum WebGPU member / member · Metal (macos) (pull_request) Has been cancelled
wai-quantum WebGPU member / member · browser WebGPU (macos) (pull_request) Has been cancelled
WAI section references / cited sections exist (pull_request) Has been cancelled
WAI mbt2018_mean integer decode (regenerated vectors) / regenerate mbt2018_mean integer vectors → Rust decode, required (pull_request) Has been cancelled
wai-web reach builds / wai-web reach · does this change touch it (pull_request) Has been cancelled
wai-web reach builds / wai-web reach builds · the package of record, every output as recorded (pull_request) Has been cancelled
wai-web reach builds / wai-web reach builds · this tree's wai-web, every rung on its engine line (pull_request) Has been cancelled
wai-web wasm32 / wai-web wasm32 build · corpus, menu and writers (pull_request) Has been cancelled
workflow hygiene / every workflow supersedes its own queue (pull_request) Has been cancelled
lockfiles / every Cargo.lock is current (pull_request) Has been cancelled
WAI conformance / cargo-class corpora · linux (pull_request) Has been cancelled
standards workspaces build + test / smart-byte-rs (pull_request) Has been cancelled
wai: reader limits for the extension formats' durations
A score, haptic signal, audio scene, splat4d clip or film declares its length in its
contract, and rendering allocates in proportion: a score's mixdown allocated `duration`
samples outright, a haptic channel `duration` × 2 bytes, a scene's stereo mix 20 bytes a
sample, and the splat4d and film receipts a hash a frame. Nothing bounded the
declaration, so a few bytes could ask a renderer for more memory than any machine has.
SECURITY.md recorded it as a gap when the fuzzing PR found the reader-side reservations.

Each extension's contract section (score, haptics, spatial-audio, volumetric,
linear-film and its reel) now has a reader limit shared with SPEC §2, through a new
always-on module `wai::limits`:
- score and haptics: `duration × channels` at most 2^27 samples;
- audio scene: `duration` at most 2^26, so the stereo floor is at most 2^27 samples;
- splat4d `n_frames`, film `frames`, a reel's shots together: at most 2^20 frames.
A reader may refuse past them (`duration_too_long`) when it reads the contract, before
anything is rendered; a conforming encoder writes none.

The film schedule's tick, `start_tick + f × ticks_per_frame`, wrapped in release builds
and panicked in debug ones. A reader must now refuse a schedule whose last tick passes
2^64 - 1 (a film's, and each shot's of a reel); `Film::frame_tick` saturates and
`Reel::frame_tick` uses checked arithmetic.

tests/extension_duration_limits.rs rewrites a committed vector of each format to declare
exactly its limit (it reads) and one past it (refused by name), and checks the film
schedule ending at 2^64 - 1 (reads) and past it (refused). Falsified: with the readers
as they were, all three tests fail. The world, audio, haptic, splat4d, score and film
corpora verify unchanged; the 275 lib tests with the container features pass. CI runs
the test beside container_reservations on every leg.

SECURITY.md drops the gap and keeps the one this exposes: replaying a world to a far
tick costs time in proportion (memory is bounded, time is not).

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-14 11:07:16 -04:00

143 lines
6.3 KiB
Markdown
Raw Permalink 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.

# WAI Extension: Score (Music as Instructions)
> Status: Draft. Phase 6 — the deepest audio lever. Ship the
> composition, not the recording: a score of note events the sink
> synthesizes. Conformance is **mixdown-equivalence**, the music
> counterpart of spatial audio. Reference impl: the `score` feature of
> `wai-rs`; corpus: `score-conformance/`; live sink:
> wai.transaction.science/score.
Keywords **MUST**, **MUST NOT**, **SHOULD**, **MAY** are RFC 2119/8174.
## 1. Scope and model
A `wai.audio.score` object carries **no recorded audio** — only note
events. Where `wai.audio.scene` mixes recorded sound *objects*, a score
is reconstructed from instructions: a deterministic reference synth
turns the notes into a canonical PCM mixdown, and a sink with a richer
instrument (soundfont, neural) renders the same score for presentation.
It is lever 3 (instructions-at-the-sink) for music — a minute of music
is kilobytes of notes, not megabytes of samples.
In scope: the container, the note model, the deterministic reference
synthesis, the **mixdown-equivalence** conformance criterion, the
receipt profile. Out of scope: a transport; the sink's instrument
(soundfonts, neural synths — presentation, not conformance); MIDI-file
import (an authoring concern).
Relationship to the core spec: mirrors spatial audio. The reconstruct
runs in the `wai.det.fixed64` floor; `media` takes the value `"audio"`;
`wai.audio.score` is authoritative.
## 2. Container (`WSCR`)
```
"WSCR" | u16 n_sections | section table (u8 kind, u32 off, u32 len) | sections
```
| kind | section | required |
|---|---|---|
| `0x01` | contract (canonical JSON) | REQUIRED |
| `0x02` | note events | REQUIRED |
### 2.1 Contract
```json
{ "channels": 1, "duration": 34000, "numeric": "wai.det.fixed64",
"sample_rate": 22050 }
```
`duration` is the rendered mixdown length in samples.
**Reader limit.** A reader MUST NOT refuse a score for its length while `duration ×
channels` is at most 134 217 728 (2²⁷, the audio limit of SPEC §2), and MAY refuse one
past it (`duration_too_long`), when it reads the contract, before it renders anything.
A conforming encoder writes no score past it.
### 2.2 Notes
`n_notes u32`, then per note (65 bytes):
`start u64 | dur u64 | phase_inc i64 Fx | gain i64 Fx | waveform u8 |
attack u64 | decay u64 | sustain i64 Fx | release u64`.
`phase_inc` is the per-sample phase advance `freq / sample_rate`,
authored off-line from the pitch — so the floor never evaluates an
exponential to turn a note into a frequency (the same authoring
discipline as the avatar quaternion). `waveform` selects a reference
timbre: `0` saw, `1` square, `2` triangle, `3` 25%-pulse.
### 2.3 Authoring form (informative)
`wai score build` writes a `WSCR` from a JSON document that holds every
field as an integer, so the committed document is the definition and no
platform's floating-point `pow` can change a pitch:
```json
{ "sample_rate": 22050, "channels": 1, "duration": 34000,
"numeric": "wai.det.fixed64",
"notes": [ { "start": 0, "dur": 3500, "phase_inc": 50960238,
"gain": 1717986918, "waveform": 0, "attack": 220,
"decay": 600, "sustain": 2791728742, "release": 1500 } ] }
```
`phase_inc`, `gain` and `sustain` are the raw Q32.32 bits. `numeric` may
be left out. The tool refuses a number with a fraction or an exponent, a
member it does not name, a member given twice (readers differ on which of
the two values they keep), more than one channel, a `phase_inc` of a whole
cycle or more, a `gain` or `sustain` above 1.0, a waveform above 3, and a
note whose release would end after `duration`, so the mixdown always
holds every note whole. `score-conformance/notes/` holds each vector in
this form, and `wai score build` turns it back into the committed `WSCR`
byte for byte.
## 3. Reference synthesis (trig-free)
For each note, a phase accumulator advances by `phase_inc` each sample
(wrapping at `1.0`); a **piecewise-linear** oscillator maps the phase to
`[-1, 1]` (no trig); a **linear ADSR** envelope (attack ramp → decay to
`sustain` → held until `dur` → release to zero over `release`) scales
it; the result times `gain` accumulates into the mixdown buffer. Each
output sample is quantized to `i16` (`round(v · 32767)`, half away from
zero, clamped) in integer space. The whole path is `+ − × ÷` in the
`Fx` floor — bit-identical on every machine.
## 4. Conformance — mixdown-equivalence
> Given the same `wai.audio.score`, a conforming sink MUST reconstruct
> the identical canonical `i16` PCM via the reference synth, hence the
> identical BLAKE3 — on every machine, no tolerance parameter.
```
mixdown_hash = BLAKE3("wai:score-mixdown\x01" || i16le PCM)
score_hash = BLAKE3("wai:score\x01" || contract || notes) // identity
```
A conformance vector also states `pcm_sha256`, the SHA-256 of the same
`i16le` PCM (the audio buffer of SPEC §7 *Digests*), so a verifier that
holds only SHA-256 checks the samples. `wai score render` prints both
and, with `--pcm`, writes the samples.
A sink MAY play a soundfont/neural instrument instead; that is
presentation and does not affect conformance, exactly as the audio-scene
HRTF render or the worlds renderer does not.
## 5. Receipt (JWP profile)
`score_hash` is the identity; the group's objects are the mix PCM blocks
(per a fixed sample span), Merkle-bound; one Ed25519 signature (verified as
SPEC §7 *Signatures* requires) over score_hash + root + exact work (= duration × notes) + carried
`joules_micro`; `parent_receipt_hash` chains — the worlds/audio receipt
shape reused. The figure's acquisition class rides beside it as an optional signed label
([energy-measurement](energy-measurement.md) §2.8): absent, the receipt keeps
its legacy bytes and the figure is unlabelled; present, it is inside the
signature. The reference meter labels every figure it measures
`OnChipCounter`, with its declared uncertainty.
## Appendix
Mixdown-equivalence is spatial audio's criterion with the recorded
objects replaced by note events: both render a deterministic `i16` mix
in the `Fx` floor and hash it. The score is the most extreme
instructions-at-the-sink case in audio — there is no recording anywhere
in the payload, only the composition. Sight, hearing, touch, motion,
state, captured-content provenance — and now the composition itself —
are one floor, one verification.