Skip to content

Release Oida 0.13.2 - #15

Merged
emeisazam merged 42 commits into
mainfrom
release/ship-2026-10-14
Oct 14, 2026
Merged

emeisazam merged 42 commits into
mainfrom
release/ship-2026-10-14

Conversation

@emeisazam

Copy link
Copy Markdown
Contributor

LISTENING.md representation and inscription support with the 0.13.2 cohort vendored; advisory reviews renewed to 12 November. Tag: v0.13.2.

Fast-forward of the reviewed local main (2043c76); merged with a merge commit so the tagged commit keeps its identity. Ship E13, 14 October 2026.

🤖 Generated with Claude Code

emeisazam and others added 30 commits September 6, 2026 21:48
Phase 0 baseline: 501 tests passed, 17 skipped, and 46 failed. Failures cluster around stale installed AKOÚŌ schema assets and an unavailable MASA validator module.
Preserve the selected route on immutable audio while adding native DSP, source-bound previews and per-band evidence. Publish selected views and ordinary listening in one governed record with explicit expiry. Expose actual ring boundaries and require distinct 0.8.1 storage artifacts. Phase 0–3 audit: 601 core tests plus corrected release metadata follow-up, targeted owner tests, and 26 exact installed-wheel tests including optional workers passed. Local only.
Three faults sat between a configured mac-mps profile and a model that
listens. None was in the model.

The Keychain write stored nothing. `security add-generic-password -w`
with a bare trailing flag prompts on a terminal; with no terminal it does
not read the answer from stdin, stores an empty password and exits 0. So
the credential endpoint reported credential_saved and stored_securely
true, the item existed, and every read came back empty, which every
provider then reported as "API key is not configured". It now sends the
command through `security -i`, which keeps the secret out of argv exactly
as before and actually stores it, and it reads the value back before
returning: a store that cannot return what it just accepted raises
instead of reporting success.

A cold engine and a broken one looked identical. On mac-mps without
require_model the engine is wrapped in a FallbackEngine that substitutes
the stub when the primary raises EngineUnavailable. The substitution is
honest in the pass receipt, which said stub/no-audio-model, but the
engine status said "cold" with no detail, so an engine that could never
start read as one that simply had not started yet. runtime_status now
carries primary_unavailable_reason and falls_back_to_stub, and a new
cheap ensure_ready answers "would you work?" by importing the MOSS
modules without paying for a ten-gigabyte load. The unavailability
message names the repository it looked in and the underlying error.

Capture failures blamed the wrong thing. Any ValueError, RuntimeError,
OSError or TimeoutError became "source configuration and native format
must match", which sent operators to the source manifest for faults that
had nothing to do with it. The real one here was libtorchcodec failing to
load because the only FFmpeg present was version 9 and torchcodec links
against 4 to 8. The exception is now logged and its type and message are
carried into the reason; a capture failure holds no audio and no
credential, so there is nothing to leak.

With the moss extras installed, a ten-second SomaFM capture now runs
through MOSS-Audio-4B-Instruct: provider local-moss, weights known with a
sha256 manifest, effective input known at 16 kHz mono, 160000 samples.
The caption describes a wide stereo field from that mono input, which is
the overreach the paper documents in the Amsterdam case, reproduced live.

The secrets test asserted the broken mechanism, argv[-1] == "-w" with the
value on stdin. It now asserts the intent, that no secret reaches argv,
and two tests were added: a write that cannot be read back is an error,
and the quoting survives quotes and backslashes.

627 passed, 25 skipped, ruff clean.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
A model handed LISTENING.md as orientation can echo it back as an event
label, and _event_title() promoted the first label to the account title.
The account read "Centaur Listening Central's Listening Identity".

Of the three places the boundary could go, this takes the middle one.
Rejecting labels at parse time would delete model output from the record,
and what the model returned is a true fact about the model worth keeping
attributed — the Amsterdam case exists to keep overreach visible rather
than corrected. Preferring the caption for every title would change every
title in the system. So the label stays in the record and is refused only
the title, and the aggregate gains a warning naming the refusal, which
follows the precedent already there for a revision mismatch.

The detector is deliberately tight: a candidate must be at least 18
characters and four distinct words, and at least ninety per cent of its
words must appear in the orientation, before it is refused. Substring
matching was tried first and is too strict, because a model paraphrases
as it echoes. Eight cases are tested, including four real labels of
varying length that must not be refused.

The identity text is threaded to the aggregate and never stored: records
keep the digest in listening_identity, never the document.

NOT CLOSED. In the live field/library path the title still echoed the
orientation, this time as "Name The Aperture", and the event's
listening_identity block came back with application and sha256 both null,
so the guard had no text to compare and was blind. The prompt injection
reads its snapshot from RoutedAudioEngine._request_listening_identity(),
which is not the same object the event block is built from. Either that
path does not serialize the block or its policy snapshot is empty; both
mean the record under-declares an orientation that was in fact applied,
which is a larger problem than the title. Step 14 must still not export
titles.

628 passed, ruff clean.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The first guard caught the paraphrase and missed the next echo. Run live,
the title came back "Name The Aperture", a verbatim line from
LISTENING.md at three words and seventeen characters, under a length bar
that had been set for a five-word paraphrase.

Both rules are needed and neither subsumes the other. A phrase of three
or more words repeated verbatim is quoting the document whatever its
length; a longer phrase built almost entirely from the document's own
words is quoting it even when reworded. Substring alone misses the first
echo, containment alone misses the second.

Twelve cases tested: both real echoes refused, and ten real labels kept,
including three- and four-word ones and two-word verbatim fragments,
which stay because that is where real labels live.

Verified live on the same excerpt: the title is no longer the
orientation, and the account carries the refusal in its own words, naming
the label and saying it is kept in the record because it describes what
the model returned rather than a sound that was heard.

Residual, and deliberate: a single-word echo still passes. The title came
back "Invention", a section heading in the document. Refusing single
words would refuse "Silence" and "Listening", which are real labels, so
the guard does not adjudicate one word. A one-word title is weak; a guard
that eats real labels is worse.

628 passed, ruff clean.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
On mac-mps without require_model, an engine that could not serve fell
back to the stub and produced an account labelled stub/no-audio-model.
The provenance was honest and the status now carried the reason, but
the operator learned of it after the fact, and a stub standing behind a
real profile is the kind of quiet substitution the record exists to
refuse.

Decided 15 September: a backup model is optional. OIDA_MOSS_BACKUP_MODEL
names one; when set, build_engine wraps the primary in a FallbackEngine
bound to that model, and a substituted pass carries
substituted_for_unavailable_primary in its provenance with the reason
and the backup's name. When unset, build_engine returns the primary
alone and an unavailable engine refuses. The stub is a profile, not a
fallback.

FallbackEngine keeps its shape, because tests construct it directly with
a stub to exercise the explicit-selection and input-binding refusals;
those still hold and are now the only way a stub stands behind mac-mps.

Five tests cover what the audit found untested: ensure_ready names the
repository it looked in and what to install; runtime_status
distinguishes a cold engine from a broken one and carries no reason for
a ready one; no backup means refusal; a backup means a recorded
substitution; and a capture failure carries its real exception rather
than blaming the source configuration.

633 passed, ruff clean.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
… from

Finding P1-02. A generated sound reviewed as a new subject was retained as an
ordinary capture with an empty parent_akousma_ids, so the join between a sound
and the listening it was made from lived only in the Central's run receipt, where
no exporter could reach it.

Checked the schema before extending anything, as R-C asks. Nothing needed
extending: akousma has carried lineage.parent_akousma_ids and typed
lineage.relations all along, with an enum that already includes response_to. What
was missing was anyone telling the owner.

build_akousma_from_listen now accepts a `lineage` declaration, applied by
apply_declared_lineage. This is kinship oída cannot observe: _maybe_link_same_source
already links records sharing a content hash, which is kinship oída sees for
itself, but only the caller knows that this listening reviews a sound generated
from that earlier account.

Deliberately strict, because a lineage claim is evidential:

- An unrecognised relation type is refused, never mapped to `other`. Coercion
  would make every unknown kinship look like one deliberate choice, which is the
  same defect as an unknown edge becoming `reuse`.
- parent_akousma_ids are merged, never replaced, so kinship oída observed is not
  overwritten by kinship a caller asserts.
- A relation without a target, a parent that is not a usable string, and a record
  naming itself as its own parent are each refused.
- Nothing is inferred from proximity. The caller states it and `note` says on
  what basis, so the claim can be contested.

Records written before this keep their empty lineage and are joined by
attestation on the Central's side instead - never by rewriting them (rule 7).

20 new tests. 653 passed, 25 skipped, 13 subtests.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…the record

The unit tests for apply_declared_lineage all passed and the live path did not
work. Running it found what reading it had not: GatewayListenRequest had no
declared_lineage field, so the Central's declaration was dropped at the door, and
remember_event had no parameter to carry it even if it had arrived.

Both added, and the first qualification run proves the difference. Before:

  akm_01M2KCS4QSTK1XPZBZR456WE52
  lineage: {"parent_akousma_ids": [], "operation": "listen"}

After, through the live stack, MOSS-Audio-4B-Instruct on mac-mps, 51s:

  akm_01M2KCX8ESY8N3AWTSEACKGWM3
  lineage: {
    "parent_akousma_ids": ["akm_01M2K0DRKNYB1RBGB2QNC3R4JR"],
    "operation": "lineage_qualification",
    "relations": [{"type": "response_to",
                   "target_akousma_id": "akm_01M2K0DRKNYB1RBGB2QNC3R4JR",
                   "note": "Qualification run for finding P1-02."}]
  }

This is the implemented / unit-tested / runtime-qualified distinction the paper
argues for, applied to itself: two green suites, one broken path, and only a run
against a real owner could tell them apart.

653 passed, 25 skipped, 13 subtests.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Found by qualifying MOSS-Audio-4B-Thinking for the first time. It is installed
and available and had never been run, so nothing had ever exercised the path
where a request selects a model by id rather than by kind.

When it does, `settings.model_kind` keeps its default of "instruct" while the
engine loads the thinking weights. The receipt then recorded the right weights
beside the wrong kind: a pass_provenance asserting that a listening used the
instruct model when it used the thinking one. 653 tests passed throughout,
because none of them ran Thinking.

The weights are the ground truth, so the kind is now derived from the model
actually loaded. A disagreement is recorded rather than silently corrected -
`model_kind_basis` reads "loaded_model; the request asked for 'instruct'" -
because a caller getting a different model than it asked for usually means
something upstream is wrong, and quietly fixing the label would hide it. An
override or unconfigured path falls back to the request and says that is what it
is. The basis defaults to "requested", never to the strongest answer.

Verified live after restart: MOSS-Audio-4B-Thinking on mac-mps, 124s, receipt
reading `model_kind: thinking, basis: loaded_model; the request asked for
'instruct'`.

6 new tests. 659 passed, 25 skipped, 13 subtests.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Found while enabling the Gemini trial. PUT /reasoning/budget returned 500 - a
ResponseValidationError, because update_config returns a BudgetConfig model and
the route is typed as returning a dict. The config had already been applied by
the time FastAPI rejected the response: the caller was told the request failed
while the ledger had in fact been changed, which is the worse of the two ways a
write can go wrong.

The route now returns the ledger's own state view, the same object GET returns,
so the two agree by construction. Verified after restart: PUT 200, enabled
persisted, and the two Gemini probes recorded before the restart survived it.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Fallback status names configured backup/profile instead of an
unconditional stub flag. Router resolves configured aliases from the
request-scoped target and records requested vs actual model. Server
matches explicitly configured local checkpoints by canonical identity and
advertises exact local availability to Central. Warm-input binding is
verified by invocation role. Targeted re-listener verifies source identity
before and during inference and retains pass receipts; bounded
relisten-provenance-projection/v1. Optional claim categories accept only
lists. Local planner worker derives a request-bound schema; local_ecology
accepts a loopback-only base_url. Regression coverage for each repair.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
A public_radio station may carry retention "research_sample" with an operator
attestation and a TTL (60 s to 30 days). A capture listening that asks with
retain_research_sample keeps exactly the file it listened to, only if its SHA-256
equals the event's segment.data_ref.sha256, in <data dir>/research-samples/ (0600,
outside every scanned audio folder), local only and never exported. Refused before
capture for a station not opted in or under a covenant forbidding raw-audio or memory
retention. A sweep every 30 s deletes expired samples with a journaled receipt;
DELETE /sources/research-samples/{id} deletes one early. The acquisition receipt names
the sample and says raw_audio_deleted: false.

Only these changes are committed; the in-flight specialist and routing work in
source_api.py and server.py stays uncommitted in the working tree.

Runtime record: telar/docs/acceptance-2026-09-24-phase-r.md.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…, sample resolution

Work from 20–24 September 2026 that the running Testing stack already
used from the working tree. Committed as one checkpoint because the
bodies of work share files (source_api.py, routing/service.py); each is
described separately.

Model routing T0–T10 (20–23 September). New oida/routing package:
the routing service and its oida/routing-decision/v1 contract,
provider registry, cost/budget accounting, a queued job runner with
cooperative cancellation, the TypeSafe adapter and the archive view
that inquiry reads. reasoning_workspace wires it in; registry and
specialist context changes follow. This is the owner side of Telar's
routing checkpoint 20d9ab9. The 23 September audit closeout's Oída
regressions (tests/test_audit_closeout.py) are included.

Specialists. A speech-quality worker (specialists/quality_worker.py)
with its contract test; per-task specialist deployments on acquisition
requests; runtime, engine and operation-control changes they need.
httpx2 moves from the dev extra to runtime dependencies, because the
routing providers use it outside tests.

Historical disclosure (Phase B, F04, 24 September). routing/service.py
separates historical_context(), which reconstructs a retained decision's
evidence under current permissions without requiring the old execution
generation, from prepared_context(), which still admits new work only
for the current workspace and generation. An unchanged decision stays
readable after a restart; replaying its old request still answers 409.

Research samples (Phase A, F02, 24 September). GET
/sources/research-samples/{id}/resolve returns
oida/research-sample-location/v1 after the existing expiry, deletion
and digest checks; symlinked sample files are refused and digest reads
are bounded by the sample byte limit.

Full suite on this tree: 845 passed, 25 skipped, 17 subtests passed.
Ruff reports ten F811 findings, all pytest fixtures imported from a
sibling test module in two new test files; the pattern is intentional.
Local only.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
On 24 September a one-second, caption-only listening spent 395 s inside
one MOSS pass (17:52:59–17:59:34 UTC) while its caller's 360-second
window ran out, so the inquiry it was meant to reach never ran. The
caption was about 250 tokens, far under the 1024-token ceiling, so the
time went to waiting for the engine or to slow generation, and nothing
retained could say which: the engine's wall time was never persisted.

Every MPS pass now records a generation block in its pass provenance:
engine_wait_ms (time waiting for the lock that serializes model load and
inference on the one device), generate_ms, new_tokens, max_new_tokens,
stop_reason (eos, max_new_tokens, deadline, other) and deadline_bound.

The listen routes (/gateway/listen, /gateway/listen-window) accept an
optional deadline_at in epoch seconds, refused if already passed (409)
or more than four hours away (400), and run the operation under it.
Under a deadline the engine waits for its lock at most until then,
refuses to start a generation with under a second left, passes the
remaining time to transformers as max_time, and discards the output of
a generation the deadline stopped. DeadlineReached, a kind of
OperationCancelled, names which of these happened; the operation
receipt says cancelled with reason deadline. Operations.run binds a
deadline even without an operation id. Without deadline_at nothing
changes: admitted work runs to completion, as before.

Eight tests (the generation record, max_time, a generation the deadline
stopped, a bounded wait, too little time left, the receipt, the
no-deadline path, the route checks). Full suite 853 passed, 25 skipped,
17 subtests. Local only.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
A listening on 24 September took 77 s, of which MOSS generated for 43;
nothing recorded the other 34. Every Phase 2b run was the first after a
restart, so each paid a cold model load, and a load hashed the 10.4 GB
of MOSS weights twice, before and after from_pretrained: 5.4 s each on
this M1 Max. A swap between Instruct and Thinking paid it again.

- Listen responses carry timings (oida/listen-timings/v1): prepare,
  dsp, interpret, model_load, generate, specialists, memory_similarity,
  remember and library_retain, collected only inside a listening.
- Each pass's generation record adds cold_load, load_ms, inventory_ms
  and preprocess_ms, so a load is never read as generation time.
- WeightHashCache keeps a file's SHA-256 while its device, inode, size,
  mtime and ctime are unchanged; any write forces a fresh hash, and the
  check after loading re-reads identities instead of bytes. How the
  bytes were verified goes in weights_verification beside the pass,
  never inside the weights block, so model identity and input bindings
  do not depend on it.

Tests: 5 new; 863 passed, 25 skipped. Local only.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Phase 2b sent deadlines to file listenings only. The capture route now
accepts deadline_at: a window that cannot fit before it is refused with
409 before anything starts; a capture still running at the deadline is
stopped; its listening runs under the deadline like any other, and a
listening stopped there publishes nothing. The acquisition receipt keeps
the deadline and says reason_code deadline when it was the cause. The
scheduled-job flag no longer depends on which deadline is set.

Tests: 4 new; 863 passed overall. Local only.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…ery trace

The first Phase 3 cycle recorded its stages: memory_similarity 7.0 s and
remember 4.9 s of an 81.6 s listening. The Testing workspace holds 82
traces totalling 438 MB, and similar_to_event listed and deep-copied
all of them, once to note similar sounds and again when remembering.

The store now keeps each trace's similarity vector and preview per file
name, modification time and size, persisted in akousmata/cache so a
restart does not parse the traces again; a changed file is read afresh
and a removed one dropped. On a copy of the Testing traces a search took
2.5-4.3 s before and 2-3 ms now, with the same ranking; the first build
after this change takes 1.9 s once.

Tests: 2 new; 865 passed, 25 skipped. Local only.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
GERM checks every memory a library listing depends on. Reading each
routing archive view on its own sent 68 requests and about 10 MB of
records per listing on 24 September, only to compare one digest each.
POST /reasoning/workspace/routing/archive/digests takes up to 500 ids
and returns each view's state and the SHA-256 GERM computes over the
record (sorted keys, compact, UTF-8), computed exactly as the single
view is and carrying no record content.

Tests: 1 new; 866 passed, 25 skipped. Local only.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
A pass on 24 September ran at 0.6 tokens/s, and nothing retained could
say why. That evening this M1 Max had 38.7 of 39.9 GB of swap in use,
a long-running MOSS process outside the Testing stack held 25 GB, and
the Testing owner's own model was 10 of 13 GB compressed. In-stack
generation ran at about 7 tokens/s against 11-12 standalone; a longer
LISTENING.md orientation (565 prompt tokens against 21) accounts for
about 8 of those, measured.

Each pass's generation record now carries host_memory at its start and
end: available memory, swap in use and the kernel's pressure level
(1 normal, 2 warning, 4 critical). It names no content and is omitted
when the reading fails.

Tests: 2 new; 868 passed, 25 skipped. Local only.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…lidated context

The admitted local planner (local_ecology, Qwen3.5-4B) was evaluated
within an 8192-token prompt and its worker refuses anything longer. On
24 September a five-second listening of the coastal dawn render gave it
24 evidence items (20 undetermined claims among them), 20 choices and
the inlined schema: 8647 prompt tokens, and every situated decision it
was asked for failed with 'Local model failed to produce a valid bounded
plan' (found by keeping the worker's error log, which the gateway
deletes).

For a provider listed in BOUNDED_CONTEXT, the situated owner now keeps
the anchor, then summaries and references, then claims in their order,
within 8000 characters, and at most 20 choices. Whole items are sent or
withheld, never rewritten; the decision records evidence_bound (offered,
sent, withheld refs, choices) and its evidence is what was sent. Only
the local planner is bounded. Measured with its tokenizer, the refused
request fits in 7344 tokens this way. The worker and gateway are
unchanged, so the planner's admission still holds.

Tests: 4 new; 872 passed, 25 skipped. Local only.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…e deadline

Runtime check, 24 September: a listening sent with a deadline six
seconds away, while another listening held the audio model, returned
its 409 after 31 s. A stack dump of the same scene in a standalone app
showed it blocked in prepare_input_binding, which took the model lock
with a plain 'with self._lock' before generate's bounded wait (Phase 2b)
was ever reached. The unit test missed it because its engine double
replaces preparation.

Both now share _locked_until_deadline(). Re-run in the standalone app:
the waiter returned at 5.0 s, 'operation deadline reached while waiting
for the audio model; nothing was generated'; the holder completed.

Tests: 1 new; 873 passed, 25 skipped. Local only.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
run_listen_event gave every listening one fixed 120 s dispatch bound
(13 September, for external providers), checked before each pass. On
this M1 Max a two-pass field listening in a Phase 3 modulated loop was
refused at 190 s with 'Listening cancelled or deadline exceeded' while
its Telar window ran to 1800 s: the caption pass ran long and the
events pass was never dispatched.

dispatch_deadline() now uses the caller's deadline when one was sent,
and otherwise 120 s per requested pass. A deadline still bounds every
pass; a listening with no deadline is no longer cut at two minutes
whatever its route.

Tests: 1 new; 874 passed, 25 skipped. Local only.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
The host lease is shared with a running stack; the suite now uses its
own directory for it, so it neither waits behind a live listening nor
holds one up. 874 passed, 25 skipped. Local only.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Every local-planner failure reached Oida as 'Local model failed to
produce a valid bounded plan', because the gateway deletes the worker's
log with its temporary directory. Two situated decisions on
24 September failed that way; the cause of the first was found only by
running a copy of the gateway that kept the log (the prompt exceeded
the validated 8192 tokens).

The 503 now names the worker's refusal from a fixed list (prompt too
long, output budget exhausted, no complete JSON, schema mismatch, no
evidence or action offered) and otherwise says unknown. Nothing from
the log is quoted, since it may contain model output. The worker is
unchanged; the gateway's new hash needs the installer to re-provision
the deployment, which re-hashes it without a new evaluation.

Tests: 1 new; 875 passed, 25 skipped. Local only.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
emeisazam and others added 12 commits September 24, 2026 22:02
The local worker recognises three task families from the schema Oída actually
sends (situated Decision, router CandidateAnswer, inquiry ReasoningResponse)
and narrows each to its offer: candidate ids for routing, packet refs for
inquiry. Routing repeats the governing instructions after the untrusted
context. oida/reasoning/bounded.py holds the per-provider context bounds now
shared by the situated path, the prompt compiler and the router.

Evaluated offline (listening-stack-worklog/p3-planner-reeval-2-20260925,
evaluation-3: 24/24); not yet admitted by listening-stack, and not yet
runtime-qualified on the router or the inquiry.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
The gateway reads the request's task family (planning, routing, inquiry) and
refuses one the deployment's evaluation did not admit. A deployment without a
task list was provisioned before routing and inquiry were evaluated and admits
planning only. Prose that named Telar now names Khipu, its definite name since
25 September 2026; telar/... contract ids are unchanged.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…er setting

local_ecology is registered at startup from its admitted deployment and was
never a persisted provider setting, so the orchestrator treated it as 'not
explicitly enabled' and every inquiry routed to it fell back to
local_structured (seen at runtime, S10, 25 Sept). It now counts as enabled
when that registration exists; its gateway still refuses a task family the
deployment did not admit. Locality is local (registration requires loopback).

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
A record's own state never depends on its relations; auditum_view resolves
them only to list them. archive_state resolves the anchor exactly as the view
does (permission, validation, forgetting receipt) and nothing else, and
/routing/archive/digests uses it: GERM's check of 113 memories spent about
2.3 s here resolving every relation of every one (25 September).

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…ations

A memory render's playback check asks for the state and digest of up to 110
records of ~300 KB each on every request. archive_states reads them in one
query and memoizes, by the SHA-256 of each record's stored text, only what
those bytes determine: identity, retained event, schema validity, canonical
digest. Policy (event_policy, the covenant check, forgetting receipts) is
applied afresh to every record on every request, in archive_state's order;
a test holds the batch equal to archive_state across withholding and edits.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
- effective_freshness is evaluated against the receiving clock and declared
  expiry, and persisted in source-admission metadata. Source snapshots, hashes,
  producer freshness and claim boundaries are preserved; a stale, future or
  archive observation stays an attributable account and is not made current.
- MASA lineage conformance cases and a Cosmoaudition freshness fixture, each
  with its origin record and licence.
- akousma 0.8.3, Akousmata 0.8.2 and akouo-contract 0.10.0 as reviewed wheels
  under vendor/ (SHA256SUMS; byte-identical to Khipu's), replacing editable
  sibling checkouts; an AnyIO minimum; scripts/audit_dependencies.py with a
  dated, expiring advisory exception register and its test.

The sonicfield_oida-0.11.1 wheel that listening-stack vendors for its owner
tests predates the freshness change: its oida/observation_source.py differs from
this commit. Checkpoint of 26 Sept 2026 work; 892 passed, 63 skipped, run in
the existing environment without syncing (it carries the MOSS extras).

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
The release (0.11.2 to 0.12.1: local owner events, finite playlists, native
decoder diagnostics, bounded source reads, patched optional dependencies) was
built from the audit checkpoints that started at 3233f4f. Files only the
release changed past that point take the release version; files the
LISTENING.md commit also changed are merged on 3233f4f as base, so both the
release work and primary inscriptions, textual sounding, revisable LISTENING.md
files and paged representation memory are kept. Vendors akouo-contract 0.12.1,
akousma 0.10.1 and akousmata 0.9.1; third-party lock versions equal the
release's.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Re-checked 13 October 2026: the Torch 2.10.0 pin and lock are unchanged,
Torch is reached only through optional extras, the affected APIs are not
called directly, and pip-audit 2.10.1 on the full locked graph reports
only the two reviewed advisories. The policy file is not part of any
built artifact.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
CI verifies the vendored wheels with `shasum -c vendor/SHA256SUMS` from the
repository root, as the published file was written. The ship's vendor update
wrote bare file names, so the check could not open them. The wheels and their
digests are unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@emeisazam
emeisazam merged commit 7d6b7eb into main Oct 14, 2026
6 checks passed
@emeisazam
emeisazam deleted the release/ship-2026-10-14 branch October 14, 2026 10:49
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant