feat(aterm): play the role's sound mark from pre-rendered samples (#1256) #1277
No reviewers
Labels
No labels
burndown-2026-06
burndown-2026-08
autonomy
async-consult
autonomy
epic
autonomy
headless
autonomy
live-collab
coherence-core
priority
P0
priority
P1
priority
P2
priority
P3
priority
P4
qa-fixture
role/devrel
role/eval
role/exec
role/frontend
role/gamedev
role/human
role/platform
role/qa
role/sysadmin
role/tpm
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
coilyco-flight-deck/agentic-os!1277
Loading…
Reference in a new issue
No description provided.
Delete branch "aos/claude/mu55-sound-mark"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Closes #1256. Tier 2 of the #1245 dispatch, built on #1251.
What ships
just aterm-soundsreads the live roster and renders one WAV per timbre intoaterm/sounds/, committed and embedded. Ten samples, 324 KB, one per personality:Spectral centroid spans 187 Hz to 1,489 Hz, so these are ten voices rather than ten pitches of one. All normalized to the same 0.62 peak, with RMS from 0.08 (snare-crack) to 0.21 (felt-mallet), which is the difference between a crack and a swell surviving the normalization.
Verified end to end in a pty:
aterm platformcached and playedfloor-tomthenwood-block, which is the pair the issue names.The renderer reads the vocabulary, it does not match it
Same property as #1255's figures.
timbrepicks a voice from a table, and a timbre outside it gets a soft mallet pitched from its own name rather than silence.contour's direction word bends the pitch, sotumbling-fallfalls.pulse's count word and manner word set the rhythm, sohurried-threestrikes three times. Tested against values the roster does not ship.Two synthesis defects the tests caught
Worth naming, because both had already produced shipped-looking files:
elapsed == 0and wrote nothing. The first ten WAVs were 34 KB of silence and looked fine on disk.internal/soundspecrenamedsoundPeaktopeak, which the local peak variable innormalizealready shadowed, soscale := peak / peak. The re-rendered files then clipped at 1.00.Neither is visible without measuring the samples, which is why the test asserts peak and determinism rather than that a file exists.
Silence
Off for
--silent, forATERM_SILENT, and whenever stdout is not a character device, which covers CI and every non-interactive launch. No player on PATH is silence, and a playback failure is swallowed rather than printed on top of the identity card. A silenced launch resolves no player and writes no cache, which the test asserts.afplayon macOS;paplay,aplay -q, thenplay -qon Linux, first on PATH. Playback runs in a goroutine under a 4-second budget so the harness is not held up.Layout
The spec moved to
aterm/internal/soundspecso both the launcher andaterm/soundgencan use it.soundgenis the generator behindjust aterm-sounds; the samples are committed because the issue asks for them to be auditionable, and because a release must not depend on a roster read.Verification
just aterm-fmt,just aterm-lint,just aterm-testclean;uv run pytest724 passed;pre-commit run --all-filescleaninternal/soundspectests: determinism byte for byte, the normalized peak, the length cap, contour and pulse grammar including syncopation moving rather than adding a hit, WAV header sizes, and filename sanitizingsound_test.go: every embedded sample is a WAV carrying audio, every timbre the fixtures ship has a sample (which is what catches a roster move with no regenerate), the card carries the mark, all three silence paths, and the session stage accepting--silentDocs
docs/aterm.mdis at 7,995 of 8,000 chars, so--silent,ATERM_SILENT, andjust aterm-soundsare documented in--helpand the recipe description only.docs/FEATURES.mdcarries the boundary change. Third instance on #1274.Every overlay ships sound_mark{timbre, contour, pulse} per personality and nothing in the estate had ever played one. A role carries two personalities, so a role sound mark is a two-note pair: platform is floor-tom then wood-block. Pre-rendered, as decided. `just aterm-sounds` reads the live roster and renders one WAV per timbre into aterm/sounds/, which is committed and embedded, so a launch needs no synth engine and every sample can be auditioned and rejected by ear before it ships. Adding a personality means regenerating; the generator prints the spec revision it rendered from. The renderer reads the vocabulary rather than matching it. timbre picks a voice from a table with a pitched soft-mallet fallback, contour's direction word bends the pitch, and pulse's count and manner words set the rhythm. An unshipped mark still speaks instead of going silent. Playback is afplay on macOS and paplay, aplay, or play on Linux, the first one on PATH, in the background so the harness is not held up. Silent for --silent, for ATERM_SILENT, and whenever stdout is not a character device, which covers CI and every non-interactive launch. No player on PATH is silence, never a diagnostic on top of the identity card. Two synthesis defects the tests caught: every hit broke on its first sample because the attack envelope starts at zero, and normalization scaled by one because a local shadowed the peak constant. Both had shipped silent-then-clipped samples before the assertions existed. Closes #1256 Co-authored-by: Kai Siren <coilysiren@gmail.com> Co-authored-by: Claude <noreply@anthropic.com> Agent-Role: platform