Skip to content

Commit 8d3584f

Browse files
committed
Separate machine inference from embodied hearing
1 parent 9ba457f commit 8d3584f

30 files changed

Lines changed: 172 additions & 80 deletions

File tree

.github/workflows/ci.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,21 +27,21 @@ jobs:
2727
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
2828
with:
2929
repository: sonicfieldlabs/earworm
30-
ref: v0.6.0
30+
ref: v0.6.1
3131
path: earworm
3232

3333
- name: Checkout AKOÚŌ contract
3434
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
3535
with:
3636
repository: sonicfieldlabs/akouo
37-
ref: v0.9.0
37+
ref: v0.9.1
3838
path: akouo
3939

4040
- name: Checkout Akousmata
4141
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
4242
with:
4343
repository: sonicfieldlabs/akousmata
44-
ref: v0.6.0
44+
ref: v0.6.1
4545
path: akousmata
4646

4747
- name: Install uv

.github/workflows/python-release.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,21 +22,21 @@ jobs:
2222
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
2323
with:
2424
repository: sonicfieldlabs/akouo
25-
ref: v0.9.0
25+
ref: v0.9.1
2626
path: akouo
2727

2828
- name: Checkout Earworm
2929
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
3030
with:
3131
repository: sonicfieldlabs/earworm
32-
ref: v0.6.0
32+
ref: v0.6.1
3333
path: earworm
3434

3535
- name: Checkout Akousmata
3636
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
3737
with:
3838
repository: sonicfieldlabs/akousmata
39-
ref: v0.6.0
39+
ref: v0.6.1
4040
path: akousmata
4141

4242
- name: Install uv

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
11
.DS_Store
2+
.env
3+
.env.*
4+
!.env.example
25
.codex/
36
.venv/
47
.uv-cache/

CHANGELOG.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,15 @@
11
# Changelog
22

3+
## 0.9.2 - 2026-08-03
4+
5+
- Reserved `heard` for separately attributable human reports. Local and host
6+
model transcripts, events, captions, and observations now remain inferred
7+
or interpreted, while DSP remains measured.
8+
- Demoted machine-supplied `heard` input at the gateway boundary and kept the
9+
original basis visible for audit.
10+
- Aligned with AKOÚŌ 0.9.1 and Earworm/Akousma 0.6.1 revision integrity,
11+
expanded environment-file ignore coverage, and added regression tests.
12+
313
## 0.9.1 - 2026-08-03
414

515
- Documented a dated exception for two PyTorch findings limited to local APIs

CITATION.cff

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ message: "If you use Oída in research, please cite this software release."
44
type: software
55
authors:
66
- name: "Sonic Field Labs"
7-
version: 0.9.1
7+
version: 0.9.2
88
date-released: 2026-08-03
99
license: Apache-2.0
1010
repository-code: "https://github.com/sonicfieldlabs/oida"

README.md

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,9 @@ still performs deterministic DSP; it does not invent a semantic caption.
3939
remember, or deep listening.
4040
- Inspect heard, measured, inferred, interpreted, speculative, and
4141
undetermined claims separately.
42+
- Treat `heard` as an attributable human listening-pass report; model
43+
transcripts, events, and captions remain inferred or interpreted, while DSP
44+
output remains measured.
4245
- Inspect the listening position, actual apertures, auditory scale, evidence
4346
sources, participants, temporal listening passes, provenance and cuts, route
4447
decisions, honest absences, and action authority that situate every result.
@@ -234,12 +237,12 @@ component for explicit cultivation handoffs.
234237

235238
| Component | Version / contract | Role in OÍDA |
236239
| --- | --- | --- |
237-
| [AKOÚŌ](https://github.com/sonicfieldlabs/akouo) | `akouo-contract 0.9.0` / `akouo/v0.9` | Listening vocabulary, attributed text boundaries, provenance, temporal passes, route decisions, corpus listening, covenants, and sovereign mode. |
238-
| [Earworm / Akousma](https://github.com/sonicfieldlabs/earworm) | `akousma 0.6.0` / spec v1.5 | Addressable auditums, decision-only records, provenance, lineage, disagreement, attributed absence, forgetting receipts, and revision. |
239-
| [Akousmata](https://github.com/sonicfieldlabs/akousmata) | `akousmata 0.6.0` | Embedded library at `/library/`, accountable-memory audit, decision and forgetting views, and the shared durable store. |
240-
| OÍDA gateway | `sonicfield-oida 0.9.1` / `oida/gateway/v0.5` | Unified REST, MCP, agent, dashboard, local perception, host perception v0.4, listening events v0.3, and route outcomes. |
241-
| [GERM](https://github.com/sonicfieldlabs/germ) | 0.3.2 optional integration | Explicit sound, prompt, and lineage handoff when separately installed and enabled. |
242-
| [Algophony](https://github.com/sonicfieldlabs/algophony) | 0.5.1 integration | Batch evaluation can consume the same AKOÚŌ reports and Earworm context. |
240+
| [AKOÚŌ](https://github.com/sonicfieldlabs/akouo) | `akouo-contract 0.9.1` / `akouo/v0.9` | Listening vocabulary, embodied heard boundary, attributed text boundaries, provenance, temporal passes, route decisions, corpus listening, covenants, and sovereign mode. |
241+
| [Earworm / Akousma](https://github.com/sonicfieldlabs/earworm) | `akousma 0.6.1` / spec v1.5 | Addressable auditums, decision-only records, provenance, lineage, attributable disagreement resolution, attributed absence, forgetting receipts, and additive revision. |
242+
| [Akousmata](https://github.com/sonicfieldlabs/akousmata) | `akousmata 0.6.1` | Embedded library at `/library/`, accountable-memory audit, decision and forgetting views, and the shared durable store. |
243+
| OÍDA gateway | `sonicfield-oida 0.9.2` / `oida/gateway/v0.5` | Unified REST, MCP, agent, dashboard, local perception, host perception v0.4, listening events v0.3, and route outcomes. |
244+
| [GERM](https://github.com/sonicfieldlabs/germ) | 0.3.3 optional integration | Explicit sound, prompt, and lineage handoff when separately installed and enabled. |
245+
| [Algophony](https://github.com/sonicfieldlabs/algophony) | 0.5.2 integration | Batch evaluation can consume the same AKOÚŌ reports and Earworm context. |
243246
| [ORAM](https://github.com/sonicfieldlabs/oram) | 0.4.1 | ORAM recordings and exports can be listened and remembered through the normal file surface; no special adapter is required. |
244247

245248
## Quick Start

docs/gateway-contract.md

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ one decision-only outcome:
1313
perceptual passes. Oída returns the perception report, AKOÚŌ command output,
1414
normalized listening event, and an optional memory trace.
1515
2. **Host-supplied perception** — an audio-capable Hermes, Codex, Claude, or
16-
generic host describes what its active model heard using
16+
generic host submits what its active model inferred from audio using
1717
`oida/host-perception/v0.4`. Oída does not run MOSS again. It applies the
1818
same router, evidence permissions, claim taxonomy, Earworm provenance, and
1919
Akousmata memory flow.
@@ -26,9 +26,11 @@ one decision-only outcome:
2626
Host perception must declare its apparatus when known. Sample rate, channel
2727
count, bandwidth, calibration, preprocessing, and blind spots determine which
2828
claims can be supported. An undeclared apparatus is accepted but explicitly
29-
marked undetermined. Model output can never become a `measured` claim merely
30-
because the model used a number; measurements need DSP, metadata, a measuring
31-
tool, or a declared human measurement.
29+
marked undetermined. Model output can never become a `heard` or `measured`
30+
claim merely because the model processed audio or used a number. It remains
31+
inferred or interpreted; measurements need DSP, metadata, a measuring tool,
32+
or a declared human measurement. A `heard` claim requires `source: "human"`
33+
and a separately attributable `listening_pass_id`.
3234

3335
Prompts, transcripts, captions, and contextual notes are attributable inputs,
3436
not auditory evidence. They may ground inference or interpretation when their
@@ -160,8 +162,8 @@ deployment must provide its own authenticated HTTPS boundary.
160162
},
161163
"observations": [
162164
{
163-
"statement": "A repeating metallic impact is audible.",
164-
"category": "heard",
165+
"statement": "The model reports a repeating metallic impact.",
166+
"category": "inferred",
165167
"confidence": "medium",
166168
"source": "model",
167169
"time_range": {"start_s": 2.1, "end_s": 7.8}

harness/akouo/command.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ def build_apparatus(report: dict[str, Any] | None = None) -> dict[str, Any]:
4747
"known_blind_spots": [
4848
"MOSS-Audio receives 16 kHz mono audio: no stereo-image claims and no content claims above roughly 8 kHz.",
4949
"No absolute playback or capture level is known to the model.",
50-
"Model perception is machine-heard evidence, not measurement; measured claims come from DSP only.",
50+
"Model perception is attributable inference, not embodied hearing or measurement; measured claims come from DSP only.",
5151
],
5252
}
5353
model = engine.get("model")
@@ -121,7 +121,7 @@ def build_command_output(report: dict[str, Any], command: str = "/listen", quest
121121
"synthesis": synthesize_claims(claims, command),
122122
"claim_summary": claims,
123123
"risks": [
124-
"Model captions and paralinguistics are machine-heard evidence, not measurements.",
124+
"Model captions and paralinguistics are attributable inferences or interpretations, not embodied hearings or measurements.",
125125
"Contradictions between declared measurements and model perception remain undetermined.",
126126
],
127127
"recommended_next_mode": route.recommended_next_mode,

harness/akouo/routing.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -64,11 +64,11 @@ def claim_permissions_for(evidence_level: str, command: str = "/listen") -> dict
6464
"none": (False, False, False, False),
6565
"prompt_only": (False, False, True, True),
6666
"metadata_only": (False, True, True, True),
67-
"decoded_audio_metadata": (True, True, True, True),
68-
"measured_signal": (True, True, True, True),
67+
"decoded_audio_metadata": (False, True, True, True),
68+
"measured_signal": (False, True, True, True),
6969
"transcript_or_caption": (False, False, True, True),
7070
"contextual_note": (False, False, True, True),
71-
"mixed": (True, True, True, True),
71+
"mixed": (False, True, True, True),
7272
}
7373
heard, measured, inferred, interpreted = table.get(evidence_level, table["mixed"])
7474
if command == "/forensic":

harness/claim_mapper.py

Lines changed: 28 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@
6767

6868

6969
DEFAULT_CLAIM_PERMISSIONS = {
70-
"heard_allowed": True,
70+
"heard_allowed": False,
7171
"measured_allowed": True,
7272
"inferred_allowed": True,
7373
"interpreted_allowed": True,
@@ -83,6 +83,18 @@ def map_report_to_claims(
8383
question: str | None = None,
8484
) -> dict[str, list[dict[str, str]]]:
8585
permissions = {**DEFAULT_CLAIM_PERMISSIONS, **(claim_permissions or {})}
86+
observations = report.get("host_observations")
87+
if isinstance(observations, list) and any(
88+
isinstance(item, dict)
89+
and item.get("category") == "heard"
90+
and item.get("source") == "human"
91+
and isinstance(item.get("listening_pass_id"), str)
92+
and bool(item["listening_pass_id"].strip())
93+
for item in observations
94+
):
95+
# A host may carry a separately attributable embodied report. This
96+
# exception never applies to model, transcript, audio, or sensor output.
97+
permissions["heard_allowed"] = True
8698
claims = empty_claim_taxonomy()
8799
model_name = str(report.get("engine", {}).get("model") or "MOSS-Audio")
88100

@@ -122,12 +134,20 @@ def _map_host_observations(report: dict[str, Any], claims: dict[str, list[dict[s
122134
for item in observations:
123135
if not isinstance(item, dict) or not item.get("statement"):
124136
continue
125-
category = str(item.get("category") or "heard")
137+
category = str(item.get("category") or "inferred")
126138
source = str(item.get("source") or "model")
127139
basis = str(item.get("basis") or "host audio perception")
128140
confidence = str(item.get("confidence") or "medium")
129141
time_range = item.get("time_range") if isinstance(item.get("time_range"), dict) else None
142+
listening_pass_id = (
143+
item["listening_pass_id"].strip()
144+
if isinstance(item.get("listening_pass_id"), str) and item["listening_pass_id"].strip()
145+
else None
146+
)
130147
speech_content = bool(item.get("speech_content")) or source == "transcript"
148+
if category == "heard" and (source != "human" or not listening_pass_id):
149+
category = "inferred"
150+
basis = f"{basis}; demoted because heard requires an attributable embodied listening pass"
131151
if category == "measured" and source not in {"dsp", "metadata", "human"}:
132152
_add(
133153
claims,
@@ -160,6 +180,7 @@ def _map_host_observations(report: dict[str, Any], claims: dict[str, list[dict[s
160180
basis,
161181
source=source,
162182
time_range=time_range,
183+
listening_pass_id=listening_pass_id,
163184
speech_content=speech_content,
164185
)
165186

@@ -245,7 +266,7 @@ def _map_transcript(report: dict[str, Any], claims: dict[str, list[dict[str, str
245266
time_range = _range(segment.get("t0"), segment.get("t1"))
246267
statement = f"Transcript{time_range}: {segment['text']}"
247268
confidence = str(segment.get("confidence") or "medium")
248-
add(claims, "heard", statement, confidence, f"{model_name} ASR, temp 0, timestamp anchored when available")
269+
add(claims, "inferred", statement, confidence, f"{model_name} ASR, temp 0, timestamp anchored when available")
249270

250271

251272
def _map_events(report: dict[str, Any], claims: dict[str, list[dict[str, str]]], model_name: str) -> None:
@@ -278,7 +299,7 @@ def _map_events(report: dict[str, Any], claims: dict[str, list[dict[str, str]]],
278299
time_range=time_range,
279300
)
280301
continue
281-
add(claims, "heard", statement, confidence, basis, time_range=time_range)
302+
add(claims, "inferred", statement, confidence, basis, time_range=time_range)
282303

283304

284305
def _map_caption(report: dict[str, Any], claims: dict[str, list[dict[str, str]]], model_name: str) -> None:
@@ -490,6 +511,7 @@ def _add(
490511
*,
491512
source: str | None = None,
492513
time_range: dict[str, float] | None = None,
514+
listening_pass_id: str | None = None,
493515
speech_content: bool = False,
494516
) -> None:
495517
if category not in CLAIM_CATEGORIES:
@@ -502,6 +524,8 @@ def _add(
502524
claim["source"] = source
503525
if time_range:
504526
claim["time_range"] = time_range
527+
if listening_pass_id:
528+
claim["listening_pass_id"] = listening_pass_id
505529
if speech_content:
506530
claim["speech_content"] = True
507531
claims[category].append(claim)

0 commit comments

Comments
 (0)