Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
f21f70a
plan: harmonics voice increment 1 — spec + buildable plan (devague /t…
OriNachum Jul 8, 2026
8f92f15
feat: shared expressive-axis vocabulary (harmonics/axes.py)
OriNachum Jul 8, 2026
4ab4ba6
feat: note-event core (harmonics/notes.py) [t1]
OriNachum Jul 8, 2026
f62e242
merge(t1): note-event core (harmonics/notes.py)
OriNachum Jul 8, 2026
e305ea6
feat: sentence->axes inference (harmonics/inference.py) [t5]
OriNachum Jul 8, 2026
96f4d26
merge(t5): sentence->axes inference (harmonics/inference.py)
OriNachum Jul 8, 2026
6b2c9a6
docs: replace template self-descriptions with the harmonics voice mis…
OriNachum Jul 8, 2026
cbc533e
merge(t10): replace template self-descriptions with the harmonics voi…
OriNachum Jul 8, 2026
107bd0f
style: black-format harmonics/axes.py
OriNachum Jul 8, 2026
5df1727
feat: identity voice-print (harmonics/identity.py) [t3]
OriNachum Jul 8, 2026
09332b3
merge(t3): identity voice-print (harmonics/identity.py)
OriNachum Jul 8, 2026
1ec684c
feat: deterministic micro-variation (harmonics/variation.py) [t4]
OriNachum Jul 8, 2026
87edb70
merge(t4): deterministic micro-variation (harmonics/variation.py)
OriNachum Jul 8, 2026
088e7de
test: ear-test protocol + offline note-sequence harness [t11]
OriNachum Jul 8, 2026
3d6b22d
merge(t11): ear-test protocol + offline note-sequence harness
OriNachum Jul 8, 2026
f014093
feat: axes->sonic-params mapping spine (harmonics/mapping.py) [t2]
OriNachum Jul 8, 2026
88fe6e5
merge(t2): axes->sonic-params mapping spine (harmonics/mapping.py)
OriNachum Jul 8, 2026
49339a8
feat: play verb — explicit axes -> notes, dry-run default [t8]
OriNachum Jul 8, 2026
07c3df3
feat: text->melodic contour (harmonics/contour.py) [t6]
OriNachum Jul 8, 2026
c1af8f2
merge(t8): play verb — explicit axes -> notes, dry-run default
OriNachum Jul 8, 2026
cf2c803
merge(t6): text->melodic contour (harmonics/contour.py)
OriNachum Jul 8, 2026
d56f93e
feat: expressive stress — pitch+volume emphasis within the ceiling [t7]
OriNachum Jul 8, 2026
975e0d1
merge(t7): expressive stress — pitch+volume emphasis within the ceiling
OriNachum Jul 8, 2026
52efabf
feat: say verb — sentence -> axes+contour+stress -> notes [t9]
OriNachum Jul 8, 2026
7b4679e
merge(t9): say verb — sentence -> axes+contour+stress -> notes
OriNachum Jul 8, 2026
169bc08
feat: offline audio backend + end-to-end sound (harmonics/audio/) [t12]
OriNachum Jul 8, 2026
51ca827
merge(t12): offline audio backend + end-to-end sound (harmonics/audio/)
OriNachum Jul 8, 2026
712fdf0
docs: markdownlint-clean the exported spec/plan; ignore .devague work…
OriNachum Jul 8, 2026
5cd70cd
chore: bump version 0.4.1 -> 0.5.0 (harmonics voice domain)
OriNachum Jul 8, 2026
fd7166c
chore: sync uv.lock to 0.5.0
OriNachum Jul 8, 2026
e16ba3d
fix: avoid float-eq in mapping, Signature return type, string concat,…
OriNachum Jul 8, 2026
e508cf4
merge(fixB): core-module review fixes (float-eq, Signature return, st…
OriNachum Jul 8, 2026
3d74319
fix: big-endian playback byteswap; correct explain catalog --play/--w…
OriNachum Jul 8, 2026
e022ee7
merge(fixC): big-endian playback byteswap; correct explain catalog --…
OriNachum Jul 8, 2026
6e5ba47
fix: play/say — avoid float-eq, return int|None, reduce complexity, C…
OriNachum Jul 8, 2026
dfce0ec
merge(fixA): play/say review fixes (float-eq, int|None, complexity, C…
OriNachum Jul 8, 2026
83067a4
feat: --articulation voice styles (discrete/speechy/smooth/alien); gl…
OriNachum Jul 8, 2026
21a10fd
merge(glide): --articulation voice styles (discrete/speechy/smooth/al…
OriNachum Jul 8, 2026
cdd62e9
docs(changelog): note --articulation voice styles
OriNachum Jul 8, 2026
97b10ed
fix(synth): clamp _smoothstep (S2583); extract glide pitch/amp helper…
OriNachum Jul 8, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .devague/current
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
harmonics-gives-an-agent-or-robot-its-own-non-spee
1 change: 1 addition & 0 deletions .devague/current_plan
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
harmonics-gives-an-agent-or-robot-its-own-non-spee
Original file line number Diff line number Diff line change
@@ -0,0 +1,293 @@
{
"slug": "harmonics-gives-an-agent-or-robot-its-own-non-spee",
"title": "harmonics gives an agent or robot its own non-speech VOICE: it turns the agent's live intent, confidence, urgency, state, and identity into short, pleasant sonic gestures a listener recognizes by who is speaking and what they mean \u2014 the first-person inverse of a spectator soundtrack, rendered as a note sequence first and sound second.",
"schema_version": 1,
"status": "exported",
"created": "2026-07-08T05:35:46Z",
"updated": "2026-07-08T05:52:57Z",
"claims": [
{
"id": "c1",
"kind": "announcement",
"text": "harmonics gives an agent or robot its own non-speech VOICE: it turns the agent's live intent, confidence, urgency, state, and identity into short, pleasant sonic gestures a listener recognizes by who is speaking and what they mean \u2014 the first-person inverse of a spectator soundtrack, rendered as a note sequence first and sound second.",
"origin": "user",
"status": "confirmed",
"honesty_conditions": [
{
"id": "h1",
"text": "In a blind ear test the output reads as one agent's discrete first-person utterance \u2014 not an ambient bed narrating events \u2014 and two identities rendering the same axes are recognizably different voices.",
"status": "confirmed"
}
],
"hard_questions": [],
"links": []
},
{
"id": "c2",
"kind": "audience",
"text": "AI agents and physical robots that must express themselves without a screen or speech, plus the humans and peer agents nearby who listen and need to know \u2014 by ear \u2014 who is present, what they intend, and how it's going.",
"origin": "llm",
"status": "confirmed",
"honesty_conditions": [
{
"id": "h10",
"text": "The audience is real and reachable: a concrete consumer exists on each side \u2014 a headless/robot agent that emits, and a human or peer agent that listens and acts on what it hears.",
"status": "confirmed"
}
],
"hard_questions": [],
"links": []
},
{
"id": "c3",
"kind": "after_state",
"text": "An agent can render its current meaning (intent/confidence/urgency/state/identity) into a short, pleasant note sequence \u2014 and thence audio \u2014 that a listener recognizes as *that agent* saying *that thing*, produced offline, deterministically, with a dependency-free core.",
"origin": "llm",
"status": "confirmed",
"honesty_conditions": [
{
"id": "h11",
"text": "The after-state is demonstrable end to end: one command takes axes (or a sentence) and yields a note sequence, and an audio backend can render that sequence \u2014 with the core path needing no audio device.",
"status": "confirmed"
}
],
"hard_questions": [],
"links": []
},
{
"id": "c4",
"kind": "before_state",
"text": "Today a headless agent is silent, or borrows a third-person spectator soundtrack (like league-of-agents' replay score) that narrates a match from the outside off an event log; there is no first-person non-speech channel an agent emits as itself, live, in the moment.",
"origin": "llm",
"status": "confirmed",
"honesty_conditions": [
{
"id": "h12",
"text": "The gap is real: no existing surface gives an agent a first-person non-speech voice; league's soundtrack is third-person and event-log-driven, per its own module docs.",
"status": "confirmed"
}
],
"hard_questions": [],
"links": []
},
{
"id": "c5",
"kind": "why_it_matters",
"text": "A recognizable non-speech voice makes a headless agent or robot present and legible by ear \u2014 you can tell who is working, who just succeeded, who is stuck \u2014 with no screen to read and no speech to synthesize or parse.",
"origin": "llm",
"status": "confirmed",
"honesty_conditions": [
{
"id": "h13",
"text": "The benefit is observable: from sound alone, with no screen, a listener identifies who is acting and the broad state (working/succeeded/blocked) above chance.",
"status": "confirmed"
}
],
"hard_questions": [],
"links": []
},
{
"id": "c6",
"kind": "boundary",
"text": "Not TTS (no words or phonemes); not a spectator soundtrack, match score, or event-log narration; not an ambient bed you tune out. It is a first-person utterance you attend to, driven by the agent's own axes rather than an external timeline.",
"origin": "llm",
"status": "confirmed",
"honesty_conditions": [
{
"id": "h14",
"text": "The boundary is enforceable: the surface reproduces no phonemes or words, and its output is driven by the agent's own axes/sentence \u2014 never by an external match or event log.",
"status": "confirmed"
}
],
"hard_questions": [],
"links": []
},
{
"id": "c7",
"kind": "success_signal",
"text": "Given axes plus an agent identity, harmonics emits a deterministic note sequence (dry-run, no audio device) that unit tests assert on directly; and by ear a listener can tell two different agents apart, and tell a confident success from an uncertain question.",
"origin": "llm",
"status": "confirmed",
"honesty_conditions": [
{
"id": "h15",
"text": "The signal is measured, not asserted: tests assert on emitted note sequences with no device, and a documented ear-test protocol backs the two human-discrimination claims (agent-vs-agent, success-vs-question).",
"status": "confirmed"
}
],
"hard_questions": [],
"links": []
},
{
"id": "c8",
"kind": "requirement",
"text": "A pure text->notes core: 'harmonics play --intent <i> [--confidence <c>] [--urgency <u>] [--state <s>] [--as <agent>]' maps the axes to a documented note-event sequence. Dry-run by default (emits the notes); making sound or a file needs an explicit --play/--out. The core imports no audio stack and runs with no device.",
"origin": "llm",
"status": "confirmed",
"honesty_conditions": [
{
"id": "h2",
"text": "Same axes + same identity produce an identical note sequence (no wall-clock, no unseeded randomness); the entire text->notes path runs in the test suite with no third-party import and no audio device present.",
"status": "rejected"
},
{
"id": "h5",
"text": "Same axes + same identity + same nonce (--seq) produce an identical note sequence, and the micro-variation across nonces is itself a pure function of the nonce \u2014 no wall-clock, no unseeded randomness; the whole text->notes path runs in tests with no third-party import and no audio device present.",
"status": "confirmed"
}
],
"hard_questions": [
{
"id": "q1",
"text": "Does the first increment ship only 'play' (explicit axes -> notes), with 'say' (sentence -> inferred axes) as a follow-up? Or must sentence inference land in the same increment? [RESOLVED: both 'play' (explicit axes) and 'say' (sentence inference) ship in increment 1 \u2014 see the 'say' requirement.]",
"resolved": true,
"blocking": false
}
],
"links": []
},
{
"id": "c9",
"kind": "requirement",
"text": "Each agent carries a recognizable signature (its 'voice print' \u2014 key / instrument-timbre / motif seed) derived deterministically from its identity string, generalizing league's per-team register into per-agent identity, with an optional hand-authored override in the palette.",
"origin": "llm",
"status": "confirmed",
"honesty_conditions": [
{
"id": "h3",
"text": "The same identity always renders the same signature; two distinct identities render audibly distinct, stable signatures; a hand-authored palette override deterministically replaces the derived one.",
"status": "confirmed"
}
],
"hard_questions": [],
"links": []
},
{
"id": "c10",
"kind": "decision",
"text": "A rendered gesture is a sequence of note events, each a small record (start, duration, pitch, velocity, voice/timbre) \u2014 the machine-readable 'notes' of text-to-notes. This sequence is the unit-test surface and the MIDI/robot-consumable representation; audio backends render FROM it, never instead of it.",
"origin": "llm",
"status": "confirmed",
"honesty_conditions": [],
"hard_questions": [],
"links": []
},
{
"id": "c11",
"kind": "requirement",
"text": "The palette stays pleasant and non-fatiguing even at the urgent end: urgency is carried by tempo, attack sharpness, and repetition \u2014 never by dissonance or raw loudness \u2014 so an urgent voice is attention-grabbing but never an alarm-clock, and repeated play next to a human does not fatigue.",
"origin": "llm",
"status": "confirmed",
"honesty_conditions": [
{
"id": "h4",
"text": "'Non-fatiguing' and 'non-alarm' are checkable on the note sequence: every gesture stays within a documented consonant palette and bounded velocity/attack, and the urgent-vs-calm difference shows up only as bounded inter-onset/tempo/repetition \u2014 never as added dissonance or a raised level ceiling.",
"status": "confirmed"
}
],
"hard_questions": [
{
"id": "q2",
"text": "risk: Even with bounded palette/velocity/tempo proxies, final 'pleasantness' needs a human ear; the checkable proxies reduce but do not eliminate subjectivity.",
"resolved": false,
"blocking": false
}
],
"links": []
},
{
"id": "c12",
"kind": "requirement",
"text": "'harmonics say \"<sentence>\"' parses a sentence into the five axes and then renders it \u2014 the text->notes surface. It ships in the same increment as 'play', reusing 'play's mapping once axes are inferred. Dry-run by default like every producing verb.",
"origin": "llm",
"status": "confirmed",
"honesty_conditions": [
{
"id": "h6",
"text": "Sentence->axes inference is deterministic and offline: a documented cue/keyword->axis rule table (not a network or model call) maps a sentence to the axes; the same sentence always yields the same axes; the test path makes no network call and imports no model.",
"status": "confirmed"
}
],
"hard_questions": [],
"links": []
},
{
"id": "c13",
"kind": "requirement",
"text": "A caller-supplied nonce ('--seq', with a stable default) selects among deterministic micro-variations of the same gesture, so repeated utterances feel alive rather than robotic while staying fully reproducible (generalizing league's field-hashed variety).",
"origin": "llm",
"status": "confirmed",
"honesty_conditions": [
{
"id": "h7",
"text": "Two different nonces yield audibly-but-subtly different utterances of the same intent; the same nonce always yields the same one; the default (no --seq) is itself a fixed, documented value \u2014 variation is never a function of wall-clock or entropy.",
"status": "confirmed"
}
],
"hard_questions": [],
"links": []
},
{
"id": "c14",
"kind": "requirement",
"text": "The 'say' tune is derived from the sentence's own units (letters / syllables / words -> pitch, timbre, rhythm steps), not only from inferred axes, so a human can APPROXIMATELY connect the sound back to the text \u2014 following 'what is being said' by how it is voiced, the way you follow a hummed phrase. Still non-speech: no phonemes are reproduced.",
"origin": "llm",
"status": "confirmed",
"honesty_conditions": [
{
"id": "h8",
"text": "The text->contour mapping is documented and deterministic (same text -> same contour); in a small blind ear-test, listeners match a rendered tune back to its source phrase (from a short candidate set) better than chance.",
"status": "confirmed"
}
],
"hard_questions": [],
"links": []
},
{
"id": "c15",
"kind": "requirement",
"text": "The agent/robot can STRESS parts of the tune via pitch and volume to emote \u2014 raising pitch and/or loudness on marked segments, emphasis carried explicitly (emphasis markers in the text or a stress argument), layered over the intent/confidence/urgency axes. Stress modulation stays WITHIN c11's documented level ceiling, so emphasis never becomes an alarm.",
"origin": "llm",
"status": "confirmed",
"honesty_conditions": [
{
"id": "h9",
"text": "Stressing a segment measurably raises that segment's note pitch and/or velocity in the emitted sequence relative to the neutral baseline, deterministically and within the level ceiling; with no stress markers the render is the documented neutral baseline.",
"status": "confirmed"
}
],
"hard_questions": [],
"links": []
},
{
"id": "c16",
"kind": "success_signal",
"text": "By ear a listener can approximately connect a rendered 'say' tune to its source sentence, and can tell which parts were stressed \u2014 the voice reads as 'this text, emoted', not an arbitrary motif.",
"origin": "llm",
"status": "confirmed",
"honesty_conditions": [
{
"id": "h16",
"text": "The legibility/stress signal is measured: a documented ear-test protocol exists \u2014 tune->phrase matching from a candidate set and stressed-part identification \u2014 with a stated better-than-chance bar.",
"status": "confirmed"
}
],
"hard_questions": [],
"links": []
}
],
"open_vagueness": [
{
"id": "v2",
"text": "Audio backend for actual sound (pure-Python sine/FM offline default vs sounddevice/simpleaudio/soundfont). The core stays dependency-free and offline-testable, so this does not block the spec.",
"kind": "unknown_nonblocking",
"claim_id": null
},
{
"id": "v3",
"text": "Granularity of the text->contour unit (per-letter vs per-syllable vs per-word, and how letters color pitch/timbre) \u2014 the legibility requirement is fixed; the exact unit is an implementation choice to settle in the plan.",
"kind": "unknown_nonblocking",
"claim_id": null
}
]
}
Loading
Loading