Skip to main content

Workstream 04: Presence And Reach

Status On develop​

  • Workstream 04 is only partially shipped on develop.

Paired Research​

Branch-local #751 Audio Vertical Slice​

The feat/751-ptt-audio-impl branch adds a Partial, provider-free push-to-talk (PTT) vertical slice in backend/src/guardian/audio_ingress.py. This is branch-local work and is not shipped develop truth. The authenticated /api/audio/ptt and /api/audio/ingress routes use #750 server-owned session, message, attachment, and request identities, persist one SQLite audio_ingress_jobs row per idempotency key, and expose owner-bound status, confirm, process, and cancel routes. Quarantined uploads are checked by actual container signatures and duration, decoded with bounded local ffprobe/ffmpeg when needed, and normalized to mono 16 kHz PCM16 WAV at no more than 2 MiB. Short generated WAV fixtures prove the same path without a live microphone. Raw and normalized files are private, removed on success, failure, cancel, or restart recovery, and have a 15-minute retention deadline. Cleanup failures are durable degraded states with private paths retained for a bounded retry; the operator receipt reports that raw bytes remain until cleanup succeeds. Separate capture and model consent handles are carried into the signed #750 attachment receipt.

The pure validator still checks standard base64 shape and metadata-reported byte count, the 10 MiB audio cap, one stream, the MIME/container/codec allowlist, metadata-reported duration up to 60 seconds, normalized-WAV metadata up to 2 MiB, consent freshness, and request/attachment identity conflicts. Transcript text from the intercepted transport is untrusted and process-local; only its digest crosses the job/API boundary. The operator supplies the final text and digest, which are persisted through the canonical session message path after digest-bound confirmation.

The payload builder emits only the documented OpenRouter input_audio content shape. It performs no network call, decoding, codec inspection, shell command, Whisper/Piper/VLM invocation, local-model fallback, or canonical persistence. The default provider state is unverified, so an API key, model capability, route health, and live consent/runtime proof are required before a later adapter can treat a request as accepted for execution. Receipts contain IDs, digests, bounded metadata, consent handles, and provider state; raw audio and transcripts are explicitly excluded. Duration and normalized-WAV limits remain metadata assertions until a governed decoder/attachment owner supplies the runtime proof.

trusted_adapter_id, provider_proof_reference, and consent_proof_reference are handles supplied by that later trusted adapter; the pure validator checks their shape but cannot establish their authenticity or perform a live provider/consent check. A ready provider without all three handles returns degraded with trusted_adapter_proof_required, so callers cannot treat caller-asserted provider or consent metadata as execution proof.

The transport is an explicitly intercepted, provider-free test boundary and is admitted through the shared bounded remote-inference broker; the default worker has no transport and cannot make a provider call. A server-owned transport lease is claimed only after a same-transaction consent check, and consent revocation invalidates pending claims; a callback that races a committed revocation is reported as an unknown outcome. Confirmation reserves the canonical message and job fence atomically, rechecks the durable owner and operator-session lifetime inside that reservation transaction, and restart recovery reconciles the pair. An already-admitted processing request that discovers a revoked session records a typed blocked receipt; unauthenticated direct calls do not mutate the job. The focused browser seam in frontend/src/components/chat/PttAudioControl.tsx requires a deliberate microphone grant, keeps model consent separate, prefers WebM/Opus then MP4, and confirms operator-supplied text by the returned digest without receiving unconfirmed transcript text from the API. Delayed recorder-stop callbacks are discarded when capture generation, session, or the browser capture gate is no longer current. This slice makes no speech-quality, live-provider, GPU, VLM, or live-microphone claim. The input shape remains compatible with the existing audio ingress contract and the documented OpenRouter audio shape for a future separately governed adapter.

Shipped On develop​

  • browser-based guardian cockpit as the only supported browser shell
  • WebSocket conversation path
  • native macOS observer daemon for screen and OCR ingest
  • daemon screen analysis can use configured local or remote inference routes; preserved captures expose provider-neutral image/output/analysis artifacts, while the removed codex exec path remains only as deprecated artifact-read compatibility under #739
  • screen captures can be preserved as durable local artifacts for future re-analysis, pairing each allowed image with redacted provider output and normalized JSON behind localhost-only observer artifact endpoints
  • observer refresh pipeline across time, calendar, git, goals, and screen context
  • proactive delivery gating and queued-bundle delivery inside the current product
  • first coherent desktop presence surface built on daemon status, capture-mode visibility, pending native-notification state, a safe test-notification path, desktop-notification fallback when browser delivery is unavailable, browser-side controls for pending native notifications, a first learning-driven native-channel preference layer, one continuity snapshot that exposes daemon state, deferred bundle items, pending native notifications, and recent interventions together, plus action-card continuation payloads and an actionable cockpit desktop-shell card with dismiss/follow-up/continue controls
  • native daemon status now separates configured-off, offline, alive-but-not-posting, and macOS Automation-permission failures in the observer continuity payload, Settings native-presence card, and ./manage.sh -e dev daemon status receipt
  • cross-surface continuity now also exposes explicit open-thread and continue flows across native notifications, queued interventions, and recent interventions
  • route-health snapshots now expose whether browser websocket and native delivery are actually reachable at runtime, including ready, fallback, and unavailable states with operator-readable repair hints instead of only static route bindings
  • queued-bundle native delivery now preserves same-thread resume when every deferred item belongs to the same session, and the shared continuity snapshot now carries one continuation contract across notifications, queued insights, and recent interventions
  • the shared continuity snapshot now also synthesizes continuity health, grouped follow-through threads, and explicit recovery actions, and the cockpit desktop shell now uses that richer contract instead of reconstructing cross-surface recovery from raw notifications, queued items, and route rows
  • the shared continuity snapshot now also carries imported capability-family attention and typed source-adapter degradation, so browser/native route health is no longer the only reach surface visible in observer continuity or cockpit recovery flows
  • broader reach continuity now also propagates into the operator timeline and Activity Ledger, so typed source-adapter and imported-reach recovery is not stranded in the observer endpoint or cockpit-only surfaces
  • observer continuity now also carries explicit presence-surface inventory across channel adapters, messaging connectors, node adapters, and observer definitions, with ready versus attention summaries, follow-up prompts, repair hints, and the same presence recovery surfaced into cockpit triage, the desktop shell, the threaded operator timeline, and the Activity Ledger
  • observer continuity now also carries inventory-backed browser-provider and node-adapter reach surfaces with selected-versus-fallback state, network or daemon prerequisites, and the same repair or follow-up recovery contract propagated into cockpit triage, the desktop shell, the threaded operator timeline, and the Activity Ledger
  • cross-surface continuity now also lands in an explicit operator continuity graph that ties notification and deferred-guardian follow-through back to session, workflow, approval, artifact, and intervention state instead of leaving the thread graph implicit across APIs
  • backend reach/integration proof now runs through isolated per-file backend shard execution instead of one shared shard-wide pytest process, reducing async teardown contamination in CI
  • browser and desktop execution proof now also has a dedicated benchmark lane: replayable browser-task receipts, desktop notification-action replay, cross-surface continuity, and operator-visible computer-use failure taxonomy now live in the named computer_use_browser_desktop suite plus the operator computer-use benchmark surface instead of staying spread across isolated continuity or daemon seams
  • M4 channel proof now also has a named deterministic benchmark lane, channels_presence_device_pairing, covering channel identity boundaries, device pairing and revocation fail-closed visibility, external-channel continuity, mutation boundaries, and abuse/failure review receipts; this is benchmark proof of boundary posture, not a claim that broad live mobile or messaging transports are production-ready
  • Batch BY reach/browser/voice hardening now also has named deterministic lanes: production_reach_channel_hardening, browser_computer_use_reliability_v2, and guardian_safe_voice_media_runtime, plus /api/operator/production-reach-browser-voice, covering paired external messaging identity, revocation, approval handoff, privacy redaction, degraded recovery, browser provider truth, session partitioning, crash recovery, page-drift replay blocking, and guarded voice/media correction/deletion/revocation paths without claiming broad live reach, voice parity, or safe browser automation
  • Batch CE live broad reach and production voice/media proof now adds live_broad_reach_channel_attestation, production_voice_media_provider_runtime, cross_surface_continuity_recovery, plus /api/operator/live-reach-media-proof, covering live/recorded-live mobile-push and messaging provider receipts, evidence mode, consent, pairing, revocation, rate limits, abuse handling, approval handoff, STT/TTS/media-analysis capture boundaries, correction/deletion, provider-failure fallback, and cross-surface thread/memory/approval continuity without claiming broad reach, complete channel coverage, OpenClaw-class reach, voice parity, multimodal parity, production STT/TTS solved, production mobile execution solved, always-available operation, production readiness, or full parity
  • Batch CL broad reach, production voice/media, and mobile execution proof now adds broad_channel_sla_operations, production_voice_media_quality_gates, mobile_execution_continuity, plus /api/operator/production-reach-voice-mobile, covering provider windows, rate-limit and abuse handling, degraded recovery, coverage-gap claim boundaries, STT/TTS/media quality and latency gates, correction/deletion privacy boundaries, provider-regression fallback, notification approval handoff, mobile action continuity, thread/memory recovery, offline recovery, and revocation fail-closed behavior without claiming OpenClaw-class reach, voice parity, multimodal parity, always-available operation, production readiness, or full parity
  • Batch CU broad-reach field operations and voice/media quality operations now add broad_reach_field_operations, voice_media_quality_operations, always_available_reach_slo, plus /api/operator/broad-reach-field-ops, covering provider/channel field matrices, consent and revocation fail-closed checks, abuse/rate-limit drills, degraded recovery, continuity IDs, metadata-only redacted receipt boundaries, voice/media quality and latency gates, correction/deletion/privacy controls, bounded SLO windows, provider-failure and offline recovery, coverage gaps, and blocked claims without claiming OpenClaw-class reach, complete channel coverage, voice parity, multimodal parity, always-available operation, production readiness, or full parity
  • Batch DC selected-channel reach/media campaign proof now adds always_available_reach_operations_v1, voice_media_parity_runtime_v1, mobile_cross_surface_continuity_v1, reach_degraded_recovery_field_campaign, plus /api/operator/always-available-reach-media, covering selected mobile/messaging/native/browser/web campaign windows, pairing/revocation, rate-limit and abuse recovery, 14-day equivalent degraded-recovery metrics, voice/media quality and latency receipts, correction/deletion/privacy controls, provider-regression fallback, cross-surface continuity, false/missed delivery metrics, operator repair, redacted receipts, and blocked claims without claiming OpenClaw-class reach, complete channel coverage, always-available operation, voice/media parity, production readiness, or full parity
  • Batch CH browser-provider usability proof now adds managed_browser_provider_attestation, live_multi_operator_usability_study, browser_computer_use_recovery_drill, plus /api/operator/browser-provider-usability-proof, covering local/managed/remote browser provider identity, evidence mode, session partitioning, credential and download/upload boundaries, provider degradation, recorded-live multi-operator usability metrics, and fail-closed browser recovery drills without claiming safe autonomous browser/computer-use, full browser parity, best cockpit, solved operator control, production readiness, or full parity
  • the one excellent reach-channel canary now selects native notifications as the only canary channel and exposes one_excellent_reach_channel_canary, /api/operator/one-reach-channel-canary, and the cockpit benchmark-proof card for pairing, revocation, health, retry/fallback, same-thread continuity, memory/context continuity, approval handoff, audit trail, degraded-state UI, and explicit rejection of Slack/Discord/Telegram/channel sprawl until one channel meets the bar

Web Ingress Contract (Partial On The Epic Branch)​

The #750 web slice adds a typed, server-owned seraph.chat.message.v1 envelope to REST /api/chat and WebSocket /ws/chat. Seraph binds the envelope to the authenticated principal, operator session, device label, and canonical conversation before model dispatch; a supplied idempotency_key or message_id produces a session-scoped UUID5 server message identity. If both aliases are supplied, their normalized opaque values must match or the ingress is rejected before session reservation. The redacted envelope and SHA-256 content/key digests are persisted in the user Message.metadata_json, and accepted, duplicate, and identity-conflict receipts are written to the canonical audit path without message content. REST and WebSocket turns reject empty or whitespace-only message content before reservation, audit, or model dispatch.

Retries that reuse the same identity in the same session receive a deterministic 409/error receipt before model dispatch. Reuse with changed content or bound metadata is rejected as an identity conflict, and an explicit unknown session is rejected rather than created. The branch-local #750 slice now projects the same conversation, thread, owner, operator-session, device, channel, transport, correlation, causation, and redacted attachment metadata into REST responses, WebSocket frames, session history, approvals, and native-notification receipts. Session.id remains the sole conversation key; these fields are lineage receipts rather than a second conversation store. Session ownership and operator-session validity are checked again before native outbox claim, and deleted or revoked conversations are cancelled with an explicit degraded reason so a restart cannot dispatch stale work.

Native notifications use the existing SQLite outbox and delivery-attempt tables. An idempotency key is bound to one payload digest, so retries across queue instances or process restarts return the same notification row. Lease expiry, daemon failure, and ambiguous handoff become operator-visible unknown recovery receipts with preserved attempt and fencing metadata; revoked, expired, missing, or deleted owners remain cancelled and visible to recovery. Attachment references retain only bounded public metadata such as an attachment id, media type, hash, size, duration, voice-note flag, and quarantine status; file paths, provider URLs, and credentials are discarded. No live Telegram, macOS provider, or other external adapter is claimed by this slice; those adapters still require their own authenticated transport and runtime proof.

Telegram Transport (Branch-Local #752 Partial)​

The feat/752-telegram-contract contract is now exercised by a provider-free local transport adapter. Telegram transit remains an external channel and both the telegram_transit and openrouter_inference consent grants are stored and rechecked on replay, receipt, and delivery. Pairing, the allow-listed operator/chat identity, cursor, replay ledger, canonical Session/Message handoff, and Telegram outbox are durable in the workspace SQLite database. Pairing state is bound to the authenticated operator principal and operator session; cross-owner or cross-session calls fail closed. The scoped synthetic bot token is stored in the encrypted vault and status exposes only a fingerprint/configured flag.

The adapter accepts updates and delivery outcomes only through an injected, recording HTTP-like transport. Its bounded getUpdates path uses the durable cursor and has no public webhook; it opens no Telegram or model connection and does not claim a live bot. A supplied bot token is write-only at the API edge, stored under a hashed owner/chat vault reference, and represented in status by configuration and fingerprint metadata only. Text and quarantined voice metadata preserve the canonical #750 conversation lineage; voice remains a degraded #751 handoff until the governed audio worker supplies validated bytes and transcript confirmation. Bounded timeout, 429, 5xx, lease/fence, revocation, and terminal receipts remain operator-visible. Delivery readback includes redacted attempt history; timeout or lease ambiguity remains unknown until an explicit operator reconciliation, and the browser conversation remains the continuity surface.

Paired Telegram Task Controls (Branch-Local #920 Partial)​

The task inspector can queue and deliver a neutral notice through the existing paired Telegram outbox. The notice contains no task title, body, source, goal text, or approval arguments. An explicit Review status (send metadata) callback returns status enums and revision metadata, bounded to 1,024 bytes. After the canonical callback transaction commits, the existing transport automatically attempts to deliver Review details/buttons and Deny/Cancel outcomes through their durable outbox records. The callback and poll receipt report canonical decision status, delivery status and spinner acknowledgment separately. Delivery uncertainty preserves the decision and the same outbox; callback replay cannot resend an Unknown delivery or repeat a task action. The current pending approval can expose Deny this request; a running task can expose Cancel this attempt. Approval, retry, unblock and uncertain-effect settlement continue in the authenticated cockpit. This boundary is telegram.task-control.v1, with an explicit no_learning outcome.

Each opaque callback expires within five minutes and no later than the current operator session, pairing, transit consent or approval. Callback data is within the Telegram Bot API's 1–64 byte limit, checked against the official API on October 3, 2026. Raw nonces remain only in private outbox markup; public outbox readback exposes no button authority. The canonical writer rechecks the current authenticated owner, operator session, paired actor and private chat, root identity, goal/task revisions, proven message delivery and exact approval or original attempt binding. Admission permits at most 20 consumed callbacks per minute and an 8,192-byte callback payload. Message identifiers alone grant no authority. Syntactically valid rejected or stale callback query IDs receive a best-effort empty spinner acknowledgment using only the current owner's scoped token, active pairing and unexpired transit consent. Acknowledgment neither grants task authority nor discloses private reasons; revoked or unavailable credentials can still prevent this transport operation.

Deny consumes the nonce and resolves the exact pending approval in one SQLite writer, shared with the cockpit approval API. Cancel consumes the nonce and records the original canonical cancel intent in the same writer; the existing dispatcher performs cleanup afterward. Restart or replay reads only that stored intent and original attempt, without creating another intent or dispatching cleanup again. Cancellation is confirmed only when canonical task and attempt readback prove it; entered work or lost cleanup responses remain Unknown. An uncertain Telegram send remains a separate Unknown delivery outcome, blocks task callbacks and is never automatically resent. The operator can send an explicit fresh notice from the inspector, retiring its old pending controls.

The provider-free validation uses actual authenticated APIs, file-backed SQLite, encrypted synthetic pairing tokens, canonical approvals, native runtime admission/cancellation, and durable outbox records with intercepted Telegram HTTP. Native cancellation tests pause execution before child dispatch or before child effects, then exercise the real cancellation service and conservative Unknown readback. Owner/root changes, nonce races, stale revisions, revoked pairing, expiry, out-of-order updates, attempt-fence drift, send response loss, acknowledgment loss and restart are covered. The managed cockpit journey uses the recording adapter, with an isolated workspace and nonlocal network denial. Live Telegram delivery, bot polling and account interoperability remain unverified; this branch-local implementation is Partial, pending independent review and the integration path to develop.

Working On Now​

  • this workstream shipped native-desktop-shell-v1
  • this workstream shipped cross-surface-continuity-and-notification-controls
  • this workstream now ships cross-surface-continuity-v2
  • this workstream now ships native-desktop-shell-v2
  • this workstream now ships native-channel-expansion-v1
  • this workstream now ships native-channel-expansion-v2
  • this workstream now ships production-reach-hardening-v1
  • this workstream now also ships cross-surface-recovery-summary-v1
  • this workstream now also ships broader-channel-adapter-surface-v1
  • this workstream now also ships reach-evals-and-integration-hardening-v2
  • this workstream now also ships cross-surface-presence-contracts-v1
  • this workstream now also ships broader-reach-inventory-continuity-v2
  • this workstream now also ships m4-channels-presence-device-pairing-benchmark-proof-v1
  • this workstream now also ships native-daemon-permission-recovery-v1
  • this workstream now also ships one-excellent-reach-channel-canary
  • this workstream now also ships live-reach-media-proof-v1
  • this workstream now also ships production-reach-voice-mobile-proof-v1
  • this workstream now also ships broad-reach-field-operations-proof-v1
  • this workstream now also ships browser-provider-usability-proof-v1

Native Daemon Operations​

ADR-008 defines macOS and Linux as peer core-host targets. The native daemon and macOS permission guidance below describe the existing Mac-specific implementation, not verified Linux capture. Selected task context remains Planned until its typed attachment, local privacy preview and per-platform adapter receipts are implemented. That attachment path must not enter general screenshot observation or automatic analysis. Missing optional capture services must not prevent core operation.

Native desktop presence is optional and is controlled by DAEMON_ENABLED in the selected .env.* file. DAEMON_ENABLED=false is a configured-off state, not a daemon crash. Enable it with DAEMON_ENABLED=true, then use ./manage.sh -e dev daemon start, ./manage.sh -e dev daemon status, and ./manage.sh -e dev daemon logs for local operation.

The daemon writes its operator receipt to SERAPH_DAEMON_STATUS_FILE, defaulting to the local workspace daemon-status.json. /api/observer/daemon-status and /api/observer/continuity expose that receipt as daemon state, screen-analysis readiness, last error, error kind, status reason, and recovery hint.

macOS permission failures are operator-visible. -1743, -10827, and System Events Apple Events denial are classified as automation_permission_denied with a recovery hint to grant Automation access in System Settings > Privacy & Security > Automation to the terminal application running Seraph, then restart the daemon. Window-title presence also requires Accessibility permission. OCR or screenshot analysis requires Screen Recording or Screen & System Audio Recording permission.

Branch-local #749 pairing ingress contract​

The feat/749-pairing-contract branch adds a Partial server-side contract in backend/src/extensions/node_pairing.py. It is not shipped truth on develop and it does not claim a live Mac edge. The immutable request and state snapshots cover device, pairing, request, capture timestamp, monotonic sequence, content hash, media type, bounded size, policy version, capability scope, data purpose, and a scoped credential fingerprint. Pure validation returns the stable accepted, duplicate, out_of_order, expired, revoked, oversized, blocked, or retryable states. The bounded replay ledger advances only after an accepted request and never stores a raw token.

Pairing lifecycle transitions are operator-owned pair, rotate, revoke, and expire snapshots. Rotation retires the previous fingerprint; revocation and expiry remove the active fingerprint. The ingress capability allow-list is read/observation-oriented and explicitly rejects action authority. Receipts contain metadata, digests, policy and state facts while redacting source paths, content, raw credentials, and full credential fingerprints. This contract does not authenticate a transport or read an artifact; callers still need to verify the payload hash before governed ingestion.

The remaining #749 boundaries are an authenticated HTTPS/origin protocol, server-side artifact persistence and readback, real paired-Mac receipts, durable integration with the node state store, and operator UI/runtime wiring. Those boundaries must remain visibly blocked or partial until their own focused implementation and runtime evidence exists. No local GPU, VLM, or model/provider call is required by this contract.

Branch-local #749 paired edge completion​

The feat/749-paired-mac-edge-final slice adds a Partial provider-free local vertical behind the same contract. It is not shipped develop truth and does not claim macOS permission, hardware, Telegram, OpenRouter, GPU, VLM, or cloud-provider readiness. Pairing returns a raw credential once, stores only an opaque vault reference and scoped fingerprint, and protects state writes with a file lock plus revision/CAS. Pair, reconnect, rotate, expire, and revoke remain operator-owned; revocation changes the lifecycle field used by ingress validation so the next request is rejected immediately.

The daemon adapter in daemon/paired_edge.py posts heartbeat and capture envelopes over the configured local HTTP origin with bearer authentication, origin and device headers, request/device/pairing ids, monotonic sequence, capture time, hash, MIME, size, policy, and scope. The server independently checks the credential, owner, hash, and size before applying the pure pairing replay contract. Accepted bytes receive a server-owned edge_art_* artifact and readback id; a reported Mac path is never used as an artifact id or persisted as a source path. accepted, duplicate, out_of_order, expired, revoked, oversized, blocked, and retryable responses have stable HTTP/status mappings.

Disconnects use a private bounded durable JSON spool (count, bytes, age, retries, exponential backoff, retention, sequence ordering, and request-id dedupe). The capture blocklist runs before bytes are posted, and cloud/model egress is disabled by default. Node adapter and observer continuity payloads expose paired/revoked state, last seen/ingest times, spool and recovery telemetry, degraded state, revision, and disabled action authority. The demonstrated local receipt is backend/tests/test_paired_edge_local_journey.py plus daemon/tests/test_paired_edge_transport.py; it uses synthetic bytes and an in-process loopback/ASGI origin only.

Platform limits remain explicit: a real Mac capture producer, macOS permission prompts, device discovery, hosted provider transport, and production rollout still require separate implementation and review. The local proof does not turn those limits into readiness claims.

Still To Do On develop​

  • richer interruption channels outside the browser/native desktop shell, imported capability reach, and typed source-adapter continuity layer
  • broad always-available mobile and messaging transports remain future work; the current M4, one-channel canary, Batch BY hardening proof, Batch CE live/recorded-live proof, Batch CL channel-SLA/voice-quality/mobile-continuity proof, Batch CU field-operation/SLO proof, Batch DC selected-channel campaign proof, and Batch CH browser-provider/usability receipts pin native-notification identity, paired external messaging, mobile-push and messaging provider receipts, channel SLA windows, abuse/rate-limit handling, voice/media quality gates, mobile execution continuity, field-operation continuity IDs, 14-day equivalent degraded-recovery metrics, metadata-only redacted receipt boundaries, browser provider identity/evidence mode, browser session and credential boundaries, revocation, mutation-boundary, continuity, approval, privacy, degraded-state, voice/media provider fallback, browser fail-closed recovery, and review receipts without claiming Slack, Discord, Telegram, full voice parity, always-available mobile execution, safe autonomous browser/computer-use, or full browser reach at production scale
  • broader external communication channels
  • better cross-surface continuity between ambient observation and deliberate interaction beyond the new synthesized continuity summary, imported reach/source-adapter recovery, thread groups, recovery actions, action-card continuation model, and desktop-shell follow-through controls

Non-Goals​

  • channel sprawl before timing quality is strong
  • ambient delivery without stronger trust and interruption controls

Acceptance Checklist​

  • Seraph can observe and update state outside the immediate chat loop
  • Seraph can proactively surface output in the current product
  • Seraph has at least one real non-browser presence path outside the browser tab
  • Seraph now has a coherent first desktop presence surface rather than only a browser app plus hidden daemon fallback
  • browser and native pending-notification state now have a first shared control surface
  • browser and native continuity now share one operator-readable snapshot for daemon, notification, queued-bundle, and recent intervention state
  • browser and native continuity now also share one explicit continuation contract plus runtime route-health state instead of reconstructing thread or fallback semantics per surface
  • the cockpit now exposes a first actionable desktop shell surface for pending alerts, queued items, and recent interventions
  • native continuation payloads can now resume work back into the cockpit instead of only showing a passive notification
  • M4 benchmark proof names identity, pairing, revocation, mutation, external-continuity, and abuse/failure review boundaries for channel/device reach
  • the native-notification canary now proves one selected reach channel with explicit no-sprawl boundaries, approval handoff, memory/context continuity, retry/fallback, and degraded-state receipts
  • guardian-safe multimodal and voice now has a dedicated proof gate: guardian_safe_multimodal_voice and /api/operator/guardian-safe-multimodal-voice require voice, TTS/STT, browser vision, image/media analysis, and media delivery families to expose owner, trust, permissions, capture/provider/privacy receipts, continuity, correction/deletion, revocation, and guardian-value reasons before being treated as reach
  • Batch BY adds guardian_safe_voice_media_runtime receipts for guarded voice/STT and browser-vision runtime paths with guardian-value reasons, transcript or media-summary privacy, operator correction, deletion, and revocation fail-closed checks
  • Batch CE adds live/recorded-live reach/media receipts for mobile push, external messaging, STT, TTS, media analysis, consent, pairing, revocation, provider failure, correction/deletion, and cross-surface thread/memory/approval continuity
  • Batch CL adds broad-channel SLA, voice/media quality-gate, and mobile-execution continuity receipts for provider windows, abuse/rate-limit handling, degraded recovery, coverage-gap claim boundaries, provider-regression fallback, notification approval handoff, thread/memory recovery, offline recovery, and revocation fail-closed behavior
  • Batch CU adds broad-reach field-operation, voice/media quality-operation, and bounded SLO receipts for provider/channel field matrices, consent/revocation fail-closed checks, abuse/rate-limit drills, degraded recovery, continuity IDs, metadata-only redacted receipt boundaries, voice/media correction/deletion/privacy controls, provider-failure/offline recovery, coverage gaps, and blocked claims
  • Batch DC adds selected-channel reach/media campaign, voice/media runtime, cross-surface continuity, and degraded-recovery field-campaign receipts for pairing/revocation, rate-limit and abuse recovery, 14-day equivalent windows, false/missed delivery metrics, operator repair, redacted receipt boundaries, and blocked claims
  • Batch CH adds browser-provider attestation and recovery receipts for local/managed/remote provider identity, evidence mode, session partitioning, credential/download/upload boundaries, provider degradation, and fail-closed recovery drills
  • broad always-available mobile, messaging, voice, STT/TTS, multimodal transport execution, safe autonomous browser/computer-use, or full browser parity is not claimed by these proof lanes

Batch I Branch Review Log​

Slice: production reach hardening v1​

  • status: complete on feat/production-reach-hardening-batch-i-v1, intended for the aggregate Batch I PR for #234
  • root cause addressed:
    • channel routing only surfaced configured bindings and active adapter ownership, not whether websocket or native delivery were actually reachable at runtime, so operators and delivery audit could not distinguish ready, fallback, and unavailable states
    • native queued-bundle delivery always reopened ambiently even when every deferred item belonged to the same session, so bundle delivery could break cross-surface thread continuity at the moment the queue drained
    • the continuity snapshot derived queued bundle thread metadata only from recent intervention lookups and could drop the still-correct queued session_id when an intervention fell outside the recent window
  • delivered in this slice:
    • runtime route-health payloads for channel routing and observer continuity, including per-route summaries, selected transport, fallback/unavailable state, and repair hints
    • runtime-aware delivery selection that uses currently reachable transports rather than static configured order alone
    • same-thread native bundle continuation when queued items share one session, plus explicit continuation metadata for queued insights and recent interventions
    • cockpit/settings reach visibility sourced from the same continuity snapshot contract
  • validation:
    • python3 -m py_compile backend/src/extensions/channel_routing.py backend/src/api/extensions.py backend/src/observer/delivery.py backend/src/api/observer.py backend/tests/test_delivery.py backend/tests/test_observer_api.py backend/tests/test_extensions_api.py
    • cd backend && .venv/bin/python -m pytest tests/test_delivery.py -k "falls_back_to_native_when_browser_runtime_is_unavailable or preserves_shared_thread_continuity or deliver_queued_bundle_formats_correctly or no_active_channel_adapters_retains_queue" -q
    • cd backend && .venv/bin/python -m pytest tests/test_observer_api.py::TestObserverAPI::test_observer_continuity_snapshot tests/test_extensions_api.py::test_channel_routing_defaults_surface_active_adapters -q
    • cd backend && .venv/bin/python -m pytest tests/test_delivery.py -k "preserves_shared_thread_continuity or partitions_mixed_sessions_into_separate_notifications" tests/test_observer_api.py::TestObserverAPI::test_observer_continuity_recovers_queued_thread_from_intervention_outside_recent_window -q
    • cd backend && .venv/bin/python -c "import asyncio, json; from src.evals.harness import run_runtime_evals; summary = asyncio.run(run_runtime_evals(['cross_surface_continuity_behavior'])); print(json.dumps({'failed': summary.failed, 'details': summary.results[0].details}, indent=2))"
    • cd frontend && NODE_OPTIONS=--experimental-require-module npx vitest run src/components/settings/DaemonStatus.test.tsx
    • cd frontend && NODE_OPTIONS=--experimental-require-module npx vitest run src/components/cockpit/CockpitView.test.tsx
    • cd frontend && npm run build
  • review follow-up captured during validation:
    • the new runtime-health path now reads ws_manager.active_count, so delivery tests that only mocked broadcast results needed explicit active-count fixtures to model a real connected browser runtime
    • the synthetic “no active adapters” bundle-failure contract now correctly reports inactive+inactive because route health records the actual unavailable transports instead of collapsing everything to the old websocket-disabled code
    • GitHub CI then exposed the same contract drift inside the eval harness: several reach and delivery scenarios were still using bare websocket or daemon mocks with non-scalar state, so runtime reach inspection could read MagicMock values as transport health instead of explicit connected/disconnected state
    • that follow-up was fixed in the Batch I branch by normalizing non-scalar websocket and daemon runtime inputs at the channel_routing helper boundary and by pinning explicit active_count fixtures in eval scenarios that are meant to model a live browser websocket path
    • reviewer: Einstein (019d39cb-8f3b-7e83-8874-9659016bf404)
    • reviewer findings fixed on the same branch:
      • mixed-session native bundle delivery was still collapsing unrelated sessions into one ambient notification, so the native bundle path now partitions queued items by session before enqueuing notifications and preserves thread-specific continuation for each session-owned group
      • queued insights without a stored session_id could still lose thread recovery once the source intervention fell outside the latest-8 recent window, so the continuity snapshot now performs a direct intervention fallback lookup for missing thread context instead of trusting recency alone
      • the cockpit desktop shell was truncating route-health visibility to the first two routes, so bundle_delivery and later routes are now rendered instead of being silently hidden
    • full uv run pytest tests/test_eval_harness.py::test_runtime_eval_scenarios_expose_expected_details tests/test_eval_harness.py::test_run_runtime_evals_passes_all_scenarios -q is still failing in this environment for unrelated authenticated-provider scenarios outside Batch I; the Batch I proof therefore uses the scenario-specific cross_surface_continuity_behavior harness run above instead of claiming an unrelated full-harness green result
    • a subagent review was requested against the uncommitted Batch I reach-hardening diff for bugs, regressions, and hallucinated assumptions; if that review does not return before PR preparation, this branch record should rely on the direct review findings plus the targeted validation above instead of claiming an unreturned clean review

Batch AP Branch Review Log​

Slice: cross-surface presence contracts v1​

  • status: complete on feat/production-reach-cross-surface-batch-ap-v1, intended for the aggregate Batch AP PR for #346
  • root cause addressed:
    • broader reach continuity still treated route health, imported capability attention, and typed source-adapter degradation as the only actionable non-thread surfaces, so messaging connectors, channel adapters, node adapters, and observer definitions could still disappear behind separate inventories instead of showing up in the same operator recovery loop
    • observer continuity, cockpit triage, and the desktop shell did not carry a truthful presence-surface-ready versus attention summary, so follow-up-capable surfaces could remain invisible while only repair-oriented reach issues surfaced
    • the operator timeline and Activity Ledger were still missing the presence-surface counts and recovery kinds needed to keep the widened reach contract visible outside the observer endpoint and cockpit shell
  • delivered in this slice:
    • explicit presence-surface inventory in observer continuity across channel adapters, messaging connectors, node adapters, and observer definitions, including ready versus attention summaries, repair hints, and follow-up prompts
    • cockpit desktop-shell and triage visibility for presence repair plus follow-up flows, including a new top-presence summary line and direct follow-up drafting for ready surfaces
    • threaded operator timeline and Activity Ledger continuity metadata for presence-surface counts and presence recovery actions
    • deterministic backend and frontend coverage for the widened continuity contract, plus the pre-batch backend shard fix for the cross_surface_continuity_behavior eval-harness routing seam
  • validation:
    • python3 -m py_compile backend/scripts/run_backend_test_shard.py backend/src/api/activity.py backend/src/api/observer.py backend/src/api/operator.py backend/src/evals/harness.py backend/tests/test_activity_api.py backend/tests/test_eval_harness.py backend/tests/test_observer_api.py backend/tests/test_operator_api.py backend/tests/test_run_backend_test_shard.py
    • cd backend && .venv/bin/python -m pytest tests/test_run_backend_test_shard.py -q
    • cd backend && .venv/bin/python -m pytest tests/test_observer_api.py -q -k "surfaces_imported_reach_and_source_adapter_attention or partial_namespace_items"
    • cd backend && .venv/bin/python -m pytest tests/test_operator_api.py tests/test_activity_api.py -q -k "surfaces_observer_recovery_actions"
    • cd backend && .venv/bin/python -m pytest tests/test_eval_harness.py -q -k "test_main_lists_available_scenarios"
    • cd frontend && NODE_OPTIONS=--experimental-require-module npx vitest run src/components/cockpit/seraphPresence.test.ts src/components/cockpit/CockpitView.test.tsx -t "surfaces active triage for approvals, workflows, queued guardian items, and reach failures|deriveSeraphPresenceState"
    • cd frontend && npm run build
    • cd docs && npm run build
  • review follow-up captured during validation:
    • the first triage proof assumed imported-reach follow-through would still land in the top visible rows after the new presence surfaces were added, but that ordering guarantee was no longer truthful once the widened continuity contract legitimately displaced lower-priority rows
    • the first desktop-shell pass truncated recovery rows early enough that the new presence_follow_up action could be produced by the backend but never rendered, so the recovery list now exposes enough rows for the new ready-surface follow-up contract to remain actionable
    • the observer continuity hardening from the pre-batch fix is folded into this slice because partial intervention rows were still failing response validation on missing legacy string fields, and that would have made the new broader continuity contract brittle under older stored payloads

Batch AZ Branch Review Log​

Slice: broader reach inventory continuity v2​

  • status: complete on feat/reach-cross-surface-batch-az-v1, intended for the aggregate Batch AZ PR for #364
  • root cause addressed:
    • broader reach continuity still left packaged browser-provider reach stranded in provider inventory instead of surfacing it through the same observer continuity and recovery contract as other reach surfaces
    • node adapters only showed up through generic contribution rows, so selected-versus-fallback reach truth, daemon prerequisites, and guarded follow-up posture were missing from the continuity payload
    • recovery actions only treated messaging and channel surfaces as follow-up-capable, so the widened reach inventory could still stop short of cockpit, timeline, and ledger follow-through control even when the observer payload carried the right reach state
  • delivered in this slice:
    • inventory-backed browser-provider presence surfaces with selected-versus-fallback state, provider kind, execution mode, and network or daemon prerequisite truth
    • inventory-backed node-adapter presence surfaces with adapter kind, runtime-state follow-up eligibility, and daemon or network prerequisite truth
    • the same presence-follow-up recovery contract widened to browser-provider and node-adapter surfaces, so observer continuity can drive cockpit triage, the desktop shell, the threaded operator timeline, and the Activity Ledger from the same richer reach inventory
    • deterministic observer and eval-harness proof for the widened reach inventory contract
  • validation:
    • python3 -m py_compile backend/src/api/observer.py backend/src/evals/harness.py backend/tests/test_observer_api.py backend/tests/test_eval_harness.py
    • cd backend && .venv/bin/python -m pytest tests/test_observer_api.py -q -k "presence_surface_payload or continuity_surfaces_imported_reach_and_source_adapter_attention"
    • cd backend && .venv/bin/python -m pytest tests/test_eval_harness.py -q -k "cross_surface_continuity_behavior or test_main_lists_available_scenarios"
    • cd docs && npm run build -- --out-dir /tmp/seraph-docs-build-az
    • git diff --check
  • review follow-up captured during validation:
    • verified subagent review found that removing browser providers and node adapters from the generic presence path made planned, overridden, and invalid packaged reach disappear whenever inventory rows were absent or sanitized, so observer continuity now preserves those generic fallback attention surfaces and lets richer inventory rows overwrite them only when they exist
    • verified subagent review also found that the first browser-provider follow-up proof asserted an impossible packaged ready state, so the continuity contract now treats selected staged_local_fallback providers as the truthful guarded follow-up path and pins that fallback-aware behavior in tests and the eval harness
    • the first inventory-backed observer pass also imported default_manifest_roots_for_workspace and settings from the wrong modules and referenced package_label_by_id before constructing it locally, so those direct validation bugs were fixed on the same branch before the review follow-up landed

Batch AZ Branch Review Log​

Slice: broader reach inventory continuity v2​

  • status: complete on feat/reach-cross-surface-batch-az-v1, intended for the aggregate Batch AZ PR for #364
  • root cause addressed:
    • broader reach continuity still left packaged browser providers out of the explicit presence-surface inventory, so selected browser reach and degraded remote-browser fallback could remain invisible in the same recovery loop that already carried messaging and adapter continuity
    • node adapters were still represented only through the generic presence surface contract, so companion or device reach could not expose adapter-specific follow-up or daemon/network prerequisite truth
    • the reach eval proof still only pinned the earlier messaging/adapter presence contract, so browser-provider and node-adapter continuity could drift without a deterministic observer or eval-harness seam catching it
  • delivered in this slice:
    • inventory-backed browser-provider presence surfaces in observer continuity, including selected versus fallback state, execution mode, provider kind, and network/daemon prerequisite truth
    • inventory-backed node-adapter presence surfaces in observer continuity, including adapter kind, staged-link readiness, and network/daemon prerequisite truth
    • the same broader reach follow-up and repair contract now extends through browser-provider and node-adapter surfaces instead of stopping at generic messaging or adapter inventory
    • deterministic backend proof for the widened observer continuity payload and the cross-surface continuity eval details that consume it
  • validation:
    • python3 -m py_compile backend/src/api/observer.py backend/src/evals/harness.py backend/tests/test_observer_api.py backend/tests/test_eval_harness.py
    • cd backend && .venv/bin/python -m pytest tests/test_observer_api.py -q -k "presence_surface_payload or continuity_surfaces_imported_reach_and_source_adapter_attention"
    • cd backend && .venv/bin/python -m pytest tests/test_eval_harness.py -q -k "cross_surface_continuity_behavior or test_main_lists_available_scenarios"
    • cd docs && npm run build -- --no-minify
    • git diff --check
  • review follow-up captured during validation:
    • the first inventory-backed observer pass referenced a package-label lookup that was never built inside _observer_presence_surface_payload(), so browser-provider and node-adapter continuity would have failed before returning any payload; the branch now builds that lookup directly from list_extensions() before constructing inventory-backed surfaces
    • a subagent review was requested twice for this Batch AZ diff, but both review passes timed out without returning findings before PR preparation; this branch record therefore relies on the direct validation findings above instead of claiming an unreturned clean review