Realtime call teardown previously depended on an object-identity guard
that silently skipped ending the call record when bridge instances were
replaced, and had no transport-liveness backstop: a WS close that never
propagated left an answered call running forever. Bindings are now
socket-bound with current-generation terminal ownership, predecessor
audio is retired on successor admission (the overlapping-voices bug),
a 30s media-inactivity watchdog with 2s grace ends calls whose
transport dies silently, and every realtime call end is logged with
its cause.
* feat(agents): unify agent status into a durable progress_card
Replace the write-only update_plan to-do tool and the fragmented plan
rendering with one durable status artifact per session: progress_card
({plan?, markdown?}, replace-on-write, 8 KiB markdown / 50-step caps).
Cards persist in a lazy-additive session_progress_cards table in the
per-agent DB (no schema-version bump), broadcast progressCard.changed,
and render from the store with exactly one live placement per view
(session rail when visible, else the composer-adjacent bar); transcripts
collapse to one-line receipts, and the sidebar hovercard shows other
sessions' cards inline (markdown + <progress>, DOMPurify allowlist, no
iframes). The three stream-derived plan renderers and their dedup
heuristics are deleted.
Codex runs disable the native plan tool per thread
(tools.update_plan.enabled=false) and receive progress_card via the
dynamic-tool bridge; compaction restore now reinjects the card (steps +
bounded markdown). Card writes still emit the legacy plan stream event so
native apps and channels keep working until their per-platform
migrations. Policy names map update_plan -> progress_card; the shipped
tools.updatePlan=false kill switch is honored.
Net -277 production LOC; -480 test LOC.
* test(agents): regenerate Codex prompt snapshots for update_plan thread-config disable
* chore(protocol): allowlist progressCard.changed for native apps pending card migration
* fix(ci): repair progress card integration checks
* fix(codex): canonicalize native progress cards
* test(gateway): reconcile progress card method order
* test(codex): stabilize native approval fixture
* fix(agents): preserve contextual reply correlation
Carry prepared reply policy into embedded and CLI message tools so targetless direct replies retain transport correlation and Reef thread identity.\n\nCloses #125279
* fix(reef): preserve unthreaded reply correlation
Keep reply-only inbound messages unthreaded unless the transport supplies a thread, while still anchoring new exchanges to their initiating envelope.\n\nRefs #125279
Plugins holding a remote URL had no non-deprecated Plugin SDK path to turn it into managed media; saveMediaSource was only reachable through the deprecated media-runtime barrel while docs pointed at media-store. Re-export it from the focused subpath and move the bundled qa-channel plugin off the deprecated barrel. Maintainer decision: full saveMediaSource (local path + HTTP(S)) is the supported media-store contract.
Fixes#125259
Show an explicit waiting acknowledgment when sessions_yield ends an otherwise-silent interactive turn, while keeping private resume context out of channel delivery and preserving existing visible replies.
Co-authored-by: Ayaan Zaidi <hi@obviy.us>
* fix(agents): report interrupted tool outcomes honestly
Prevent restart recovery from claiming that an interrupted tool call completed when no successful matching result was recorded.
* fix(agents): keep ambiguous recovery restart-safe
Classify failed replay-unsafe tool results at the shared restart-recovery owner so interrupted side effects remain unavailable until their external state is verified.
* fix(agents): distinguish missing tool outcomes
Carry the existing missing_tool_result fact into projected Codex transcripts so restart recovery restricts only genuinely unknown outcomes, while confirmed failures remain retryable.
Slack appends task_update details/output per update for the same id (only title/status replace); the native progress stream re-sent every row each snapshot, so bash rows accumulated "completedcompleted…". Reconcile now emits only changed rows with append-only field deltas, keeps status words out of details, and puts the once-emitted result (file delta or failing exit) in output.
* refactor(gateway,ui): one bounded display projection; delete marker strip sites
Persisted transcripts are marker-free since the write-boundary projection
(#124793), the historical migration (#124888), and TTS facts (#124913), so
display surfaces stop compensating. sessions.list.lastMessagePreview and its
siblings (sessions.preview/describe, TUI picker, sessions_list tool, MCP) now
share one bounded role-aware projection (240 chars, tool/system/thinking and
suppressed control replies excluded, directive-only rows fall through). The
web reply chip reads the typed openclawDelivery fact instead of parsing text;
chat.history preserves the field to the UI. Post-hoc display strips are
deleted across web/TUI/MCP/sessions-list; live streaming cleaners stay.
Stale gateway-protocol preview comments corrected; no schema change.
Assertion-safety baseline pruned for shrunk files (sanctioned direction).
Production net -173, tests net -137. Fixes the sidebar [[reply_to_current]]
preview leak and the empty-code-pill overstrip of quoted markers.
* fix(agents): preserve restart recovery transcript reads
* refactor(gateway): remove obsolete transcript exports
* fix(gateway): normalize injected delivery directives
* fix(ci): scope projection and recovery checks
* chore(ci): shrink plugin SDK surface budgets
* test: deflake loaded side question and worker checks
* test: align display projection CI fixtures
* style: format display projection fixture
* fix(gateway): bound startup history materialization
Apply SQLite byte limits before loading history payloads and share a yielded, fingerprinted Claude CLI snapshot across concurrent startup clients. Preserve marker, cursor, redaction, and external identity semantics, and clarify that shrink-only ratchet updates need no separate approval.
* test(browser): await all lazy command groups
* fix(gateway): bound history snapshot state
* fix(gateway): preserve oversized history responsiveness