Three suites pinned the shape `_emit_progress` had before the voice existed: an
owner's plain note carried no `progress_meta` at all, a transport-wait note's
meta held exactly the incident pair, and the loop's emitter fakes declared
`*, incident=None` positionally, so the round-narration call raised TypeError
instead of reaching them.
Each is updated to the fact it was actually testing. The initiator suite now
asserts the owner's frame carries only the voice, which still proves the wake
label cannot leak onto it. The transport-wait note pins `narration: False`
beside its unchanged toast pair. The loop fakes take `**_meta`, mirroring an
emitter whose optional facts a test double should not have to track.
Co-authored-by: Ouroboros <311266734+ouroboros-agent@users.noreply.github.com>
Implement the ten owner-approved routing steps on integration base 4101c46d.
Remove the retired ephemeral Swarm actor, its routing-only orchestration,
wait/history projections and UI family. Keep native conversations parallel,
Presence custody, P1 free collection and dialogue, P4 receipts, P5 terminal
honesty and P7 shutdown behavior.
Use the existing promotion/reservation path with exact canonical owner text,
attachments, origin and room binding. Preserve first-Main client identity.
Retain complete generic tool invocation/error observations in existing metrics
and authored summaries so one UI seam keeps addressing-only cards hidden on
reconnect/reload; old records preserve their historical fallback. Preserve raw
assistant salvage bytes through the provider-death path.
Protected scope: ouroboros/tools/registry.py, registry_core.py,
registry_guards.py and tool_context.py lose only the extinct CW3 subject and
its final context field, per raw batch2 Q5, batch3 1A and PR-3. Other live
guards remain. size_ratchet_manifest.py is script-generated shrink-only
maintenance; loop_forced_finalization stays in its existing BAND on this base.
No BIBLE, SYSTEM, SAFETY, runtime policy or frozen ABI change relative to base.
Owner 2026-09-12 16:29 explicitly approved the additive generic counts in
existing metrics and authored-summary/history, with no new store/API/model.
Prepared source commits 8c516c0c through 741631d and staged tree 9f0aac remain
preserved in their original clone; this is the private combined candidate.
Validation: targeted host/P1/P4/P5/Presence/provider tests, 117 shared JS
regressions plus addressing narration, Ruff F, docs/generated inventories,
and both real size-ratchet nodes pass. Final cold browser scenarios and
external authority run on this immutable candidate after this checkpoint.
(cherry picked from commit 8416d94472f5326627c0b9ac59fa03d6d6e7d6d0)
A managed task's owner-visible transport-wait texts stay the base's:
the entry note and the recovery note. The local-fallback adoption and
error-kind-change closures now emit their owner note only for an
interactive episode, whose turn has no progress row to show the
closure; a managed episode keeps its durable network_wait ended row and
its ordinary progress. Tests assert the managed texts against the
literal base wordings for every closure; docstrings and the
architecture paragraph say which notes belong to which class.
Wave-4 hygiene, prose only. The signed-attribution comment and the matching test docstring blamed a host suspend, but time.monotonic() does not advance across a suspend; the reachable cause is a process stall inside a sleep (GC pause, CPU starvation, a long blocking call). The interactive-bound test docstring now quotes the shipped wording, this turn, instead of chat turn.
Review wave 3 fix. The branch that ends an episode after the deadline admission gate refused a redial now uses the same signed-lateness attribution as the other exits, so a bound that expired earlier keeps interactive_wait_window_exhausted while the refusal stays visible in the llm_not_dispatched row; a managed episode still ends with deadline_refused_dispatch and no note. Test covers both orderings and the managed control through that branch. reconcile_transport_wait's docstring states the note split precisely (recovery, local adoption and error-kind change for all episodes; exhaustion separately noted only for interactive turns).
Review wave 2 fixes. transport_wait_step decides which rail binds from the SIGNED remaining windows, so when a host suspend inside a sleep overshoots both the owner deadline and the interactive bound, the ended detail names the rail that expired earlier; only the value used for sleeping and telemetry is clamped, the positive deadline case keeps dispatch_window_remaining_sec's numbers, and managed episodes behave identically. The error-kind-change note says what the code knows (the redial got past the connect phase). The two owner-mailbox tests write their entry from inside the first failing dispatch instead of a timer, so a cold process cannot drain it before the episode exists; the spent-windows tie test becomes both expiry orderings through both exits. loop.py docstring nit is byte-neutral (manifest unchanged).
Review wave 1 fixes. The typed task_incident/toast_once pair now rides only an ephemeral turn's notes (a direct turn already renders live-card rows), keyed by the millisecond entry stamp so two episodes of one turn inside the same wall second stay distinct. Both silent episode closures (local fallback adoption, error-kind change) emit an owner note for every episode, with the pair for ephemeral ones. Interactive wordings say "this turn" (the class covers owner-chat, Presence, and ephemeral turns). run_llm_loop's emit_progress annotation matches the incident= keyword the loop passes; loop.py shrinks by two bytes and the manifest records the exact value. Tests pin the ephemeral-only pair, the same-second key distinctness, the closure notes across managed/direct/ephemeral, the frozen managed wordings, and the never-recovering mid-chain latch reaching the no-resend terminal for managed and both interactive kinds.
Rewrite the fail-fast pins to the new contract (interactive turns wait, redial for free, and terminalize with interactive_wait_window_exhausted through the no-resend source) and add the interactive suite: raw idle bound measured from entry, None-aware minimum with an explicit deadline including the spent-deadline tie, final free redial with the 3 s margin at the bound, managed tasks keep no local bound, a direct turn's mailbox message wakes the sleep and reaches the round top, cancellation-free notes, the incident toast on entry/recovery/exhaustion with distinct one-shot keys, the agent progress seam, malformed metadata, and a zero bound.