#!/usr/bin/env python3
"""
Pairling Mac daemon.

Runtime endpoints use per-device scoped Authorization: Bearer tokens:
  POST /open?path=<abs>&app=sublime|finder       open path on Mac
  GET  /sessions?active_within_min=<n>           list recent sessions from continuous-claude PG
  POST /sessions/remove body:JSON                hide a closed session using a durable Mac tombstone
  POST /sessions/delete-transcript body:JSON     move a closed session transcript to Mac Trash
  GET  /recent-projects?active_within_min=<n>    list recent project paths without transcript enrichment
  GET  /transcript?session=<id>&since=<bytes>    stream transcript JSONL since byte offset
  GET  /terminal-stream?session=<id>&since=<bytes> stream live terminal output since byte offset
  GET  /corpus?since=<unix-ts>                   list transcripts modified after ts
  GET  /session-meta?session=<id>                effort/model/type/sentinel-mode/etc
  GET  /personal-context                         contents of ~/.claude/personal-context.md
  POST /llm-route?model=...                    prompt-only route; fails closed without an isolated backend
  POST /llm-route-stream?model=...             same route streamed as SSE when a safe backend exists
  GET  /worker-stats?since_min=<n>               counts of automated worker sessions
  GET  /push/status                              APNs relay/provider registration state
  POST /push/preferences body:JSON               store per-device push preferences
  POST /push/test body:JSON                      queue a bounded push diagnostic event
  POST /push/live-activity-token body:JSON       store APNs Live Activity token privately
  POST /push/live-activity-test body:JSON        send/queue bounded Live Activity APNs test
  GET  /sentinel/status                          worker/token sentinel classification state
  GET  /sentinel/preferences                     worker/token sentinel preferences
  POST /sentinel/preferences body:JSON           update sentinel thresholds/cooldowns
  POST /sentinel/snooze body:JSON                snooze a sentinel dedupe key
  POST /sentinel/evaluate-now body:JSON          classify now and emit at most one sentinel push
  GET  /sentinel/events?since=<epoch>            local sentinel event ledger
  GET  /safety/status                            future Safety Monitor install/approval state
  GET  /safety/events?since=<id>                 redacted safety summaries, fixture-backed in phase 0
  POST /safety/ack body:JSON                     acknowledge visible safety summaries
  GET  /aperture-cli/status                      read-only Aperture CLI launcher status
  GET  /aperture-cli/providers                   read-only active Aperture provider/model inventory
  GET  /aperture-cli/launch-contexts             read-only generated Pairling launch contexts
  POST /aperture-cli/open body:JSON              proof-bound raw Aperture CLI TUI on the Mac
  GET  /workstate-feed?run=<path>&since=<iso>&limit=<n> read-only substrate workstate feed
  GET  /model-status?run=<path>&since=<iso>&limit=<n> read-only substrate model arbiter status
  GET  /substrate-status?run=<path>&since=<iso>&limit=<n> read-only operational substrate status
  GET  /substrate-feed?run=<path>&since=<iso>&limit=<n> read-only operational substrate feed
  POST /worker-kill body:JSON                    SIGTERM workers by id or filter:"stale"
  POST /pairling-tools/run body:JSON             daemon-first MCP tool router
  GET  /phone-tools/activity?limit=N             durable, privacy-bounded tool history
  POST /phone-tools/availability body:JSON       foreground iPhone tool-listener availability

The credential-bearing runtime is always loopback-only behind pairling-connectd.
"""
from __future__ import annotations

import atexit
import base64
import codecs
import ctypes
import errno
import fcntl
import hashlib
import html
import ipaddress
import json
import math
import os
import stat
import re
import copy
import secrets
import shlex
import signal
import socket
import socketserver
import sqlite3
import stat
import struct
import subprocess
import sys
import traceback
from contextlib import contextmanager
from datetime import datetime, timezone
from http.server import BaseHTTPRequestHandler, ThreadingHTTPServer
from pathlib import Path
from types import MappingProxyType
from urllib.parse import urlparse, parse_qs, quote, unquote
from pairling_assurance_policy import relay_claims_required
from public_diagnostics import redact_public_diagnostic, redact_public_text
from safe_filesystem import (
    UnsafeFilesystemPath,
    authorize_path,
    ensure_directory_fd,
    open_child_directory_fd,
    open_child_regular_file_fd,
    open_directory_fd,
    open_regular_file_fd,
)
from pairling_automation import (
    AutomationHelperClient,
    AutomationHelperMutationIndeterminate,
    AutomationHelperUnavailableError,
    terminal_permissions_summary,
)

_DAEMON_SCRIPT_PATH = Path(__file__).resolve()
_MAC_RUNTIME_ROOT = str(_DAEMON_SCRIPT_PATH.parent.parent)
if _MAC_RUNTIME_ROOT not in sys.path:
    sys.path.insert(0, _MAC_RUNTIME_ROOT)

try:
    from runtime_contract import (
        AUTH_MODE as RUNTIME_AUTH_MODE,
        CONTRACT_VERSION as RUNTIME_CONTRACT_VERSION,
        DAEMON_LABEL as RUNTIME_DAEMON_LABEL,
        DEFAULT_DEVICE_SCOPES as RUNTIME_DEFAULT_DEVICE_SCOPES,
        LEGACY_TOKEN_RELATIVE_PATH,
        LOCAL_MCP_DISPATCH_SCOPE,
        PAIR_ACTIVATION_CONTRACT,
        PAIR_ACTIVATION_RESULT_CONTRACT,
        PAIR_CLAIM_REQUEST_CONTRACT,
        PAIR_CLAIM_RESULT_CONTRACT,
        PAIRING_CONTRACTS,
        PORT as RUNTIME_PORT,
        RUNTIME_NAME as RUNTIME_NAME,
        TAILSCALE_VARIANT as RUNTIME_TAILSCALE_VARIANT,
    )
    from runtime_paths import app_support_root, devices_db_path, pairdrop_root
    from pairling_devices import DeviceAuthResult, DeviceRegistry, DeviceRegistryError
    from pairling_connectd_status import (
        advertised_pairling_connect_routes,
        fetch_connectd_status,
        open_connectd_auth,
        redacted_connectd_summary,
    )
    from pairling_pairing import (
        DEFAULT_PAIR_TTL_SECONDS,
        DEFAULT_SMOKE_LEASE_TTL_SECONDS,
        PairingError,
        PairingStore,
        ReauthStore,
    )
    from pairdrop_store import PairDropStore, PairDropStoreError
except Exception:
    RUNTIME_AUTH_MODE = "scoped-device-bearer"
    RUNTIME_CONTRACT_VERSION = "pairling-runtime-v1"
    RUNTIME_DAEMON_LABEL = "dev.pairling.companiond"
    RUNTIME_DEFAULT_DEVICE_SCOPES = frozenset()
    LEGACY_TOKEN_RELATIVE_PATH = ".claude/scripts/.notify-token"
    LOCAL_MCP_DISPATCH_SCOPE = "pairling-tools:dispatch"
    PAIR_ACTIVATION_CONTRACT = "pairling.psk.activate.v1"
    PAIR_ACTIVATION_RESULT_CONTRACT = "pairling.psk.activate.result.v1"
    PAIR_CLAIM_REQUEST_CONTRACT = "pairling.psk.claim.request.v2"
    PAIR_CLAIM_RESULT_CONTRACT = "pairling.psk.claim.result.v2"
    PAIRING_CONTRACTS = {
        "request": PAIR_CLAIM_REQUEST_CONTRACT,
        "claim_result": PAIR_CLAIM_RESULT_CONTRACT,
        "activation": PAIR_ACTIVATION_CONTRACT,
        "activation_result": PAIR_ACTIVATION_RESULT_CONTRACT,
    }
    RUNTIME_PORT = 7773
    RUNTIME_NAME = "pairling-mac-runtime"
    RUNTIME_TAILSCALE_VARIANT = "embedded_tsnet"
    DeviceAuthResult = None
    DeviceRegistry = None
    advertised_pairling_connect_routes = None
    fetch_connectd_status = None
    open_connectd_auth = None
    redacted_connectd_summary = None
    DEFAULT_PAIR_TTL_SECONDS = 180
    DEFAULT_SMOKE_LEASE_TTL_SECONDS = 600
    PairingError = None
    PairingStore = None
    ReauthStore = None
    try:
        from runtime_paths import app_support_root, devices_db_path, pairdrop_root
    except Exception:
        app_support_root = None
        devices_db_path = None
        pairdrop_root = lambda: Path(
            os.environ.get("PAIRLING_PAIRDROP_ROOT", str(Path.home() / "PairDrop"))
        ).expanduser().resolve(strict=False)
    PairDropStore = None
    PairDropStoreError = ValueError

PAIRING_ACTIVATION_CONTRACT = PAIR_ACTIVATION_CONTRACT

try:
    from compose_recording_store import (
        ComposeRecordingStore,
        ComposeRecordingStoreError,
    )
except Exception:
    ComposeRecordingStore = None
    ComposeRecordingStoreError = ValueError

PUBLIC_RUNTIME_FIELDS = (
    "name",
    "runtime_version",
    "source_revision",
    "contract_version",
    "compat_mode",
    "launchd_label",
    "port",
    "tailscale_variant",
    "verified",
)


def _public_runtime_info(info: dict) -> dict:
    """Project runtime metadata without relying on optional runtime helpers."""
    if not isinstance(info, dict):
        raise TypeError("runtime metadata must be an object")
    projected = {
        "name": info.get("name") or RUNTIME_NAME,
        "runtime_version": info.get("runtime_version"),
        "source_revision": info.get("source_revision"),
        "contract_version": (
            info.get("contract_version") or RUNTIME_CONTRACT_VERSION
        ),
        "compat_mode": info.get("compat_mode") or "pairling-v1",
        "launchd_label": info.get("launchd_label") or RUNTIME_DAEMON_LABEL,
        "port": info.get("port") or PORT,
        "tailscale_variant": (
            info.get("tailscale_variant") or RUNTIME_TAILSCALE_VARIANT
        ),
        "verified": bool(info.get("verified")),
    }
    return {field: projected[field] for field in PUBLIC_RUNTIME_FIELDS}



try:
    from runtime_manifest import (
        build_manifest_payload as _build_manifest_payload,
        build_runtime_info as _build_runtime_info,
        classify_ptybroker_identity as _classify_ptybroker_identity,
        ptybroker_payload_sha256 as _ptybroker_payload_sha256,
    )
except Exception:
    _build_manifest_payload = None
    _build_runtime_info = None
    _classify_ptybroker_identity = None
    _ptybroker_payload_sha256 = None

_RELAY_CLAIM_VERIFIER_IMPORT_ERROR: Exception | None = None
try:
    from pairling_relay_claims import RelayClaimVerifier
except Exception as exc:
    _RELAY_CLAIM_VERIFIER_IMPORT_ERROR = exc
    RelayClaimVerifier = None


def _initialize_relay_claim_verifier(verifier_type, pairing_store):
    if verifier_type is None:
        return None, _RELAY_CLAIM_VERIFIER_IMPORT_ERROR
    if pairing_store is None:
        return None, None
    try:
        return (
            verifier_type.from_environment(mac_install_id=pairing_store.install_id),
            None,
        )
    except Exception as exc:
        return None, exc

try:
    from push_dispatcher import PairlingPushDispatcher, PushDispatcherError
except Exception:
    PairlingPushDispatcher = None
    PushDispatcherError = None

try:
    from request_proof import ReplayCache, verify_request_proof
except Exception:
    ReplayCache = None
    verify_request_proof = None

try:
    from integrations.aperture_cli import command_for_context as _aperture_cli_command_for_context
    from integrations.aperture_cli import contexts_payload as _aperture_cli_contexts_payload
    from integrations.aperture_cli import provider_payload as _aperture_cli_provider_payload
    from integrations.aperture_cli import status_payload as _aperture_cli_status_payload
    from integrations.aperture_cli import validate_launch_context as _aperture_cli_validate_launch_context
except Exception:
    _aperture_cli_command_for_context = None
    _aperture_cli_contexts_payload = None
    _aperture_cli_provider_payload = None
    _aperture_cli_status_payload = None
    _aperture_cli_validate_launch_context = None

try:
    from llm_route import llm_route_model_family, run_remote_llm
except Exception:
    llm_route_model_family = None
    run_remote_llm = None

try:
    from pairling_tools import (
        PHONE_TOOL_AVAILABILITY,
        PHONE_TOOL_WORK_QUEUE,
        audit_detail_for_tool_run,
        current_worker_id,
        run_pairling_tool,
    )
except Exception:
    PHONE_TOOL_AVAILABILITY = None
    PHONE_TOOL_WORK_QUEUE = None
    audit_detail_for_tool_run = None
    current_worker_id = None

try:
    from live_activity_publisher import LiveActivityTurnStatePublisher
except Exception:
    LiveActivityTurnStatePublisher = None

try:
    from fleet_activity_publisher import FleetActivityPublisher
except Exception:
    FleetActivityPublisher = None

try:
    import fd_watchdog
except Exception:
    fd_watchdog = None

try:
    from standard_push_publisher import MacHealthAlertPublisher, SentinelBackgroundEvaluator, TurnStateAlertPublisher
except Exception:
    MacHealthAlertPublisher = None
    SentinelBackgroundEvaluator = None
    TurnStateAlertPublisher = None

try:
    from safety_monitor import SafetyMonitorBridge
except Exception:
    SafetyMonitorBridge = None

try:
    from pty_broker_client import (
        PTYBrokerClient,
        PTYBrokerOutcomeUnknownError,
        ensure_pty_broker_token,
    )
    from pty_broker_client import _read_frame as _broker_read_frame
    from pty_broker_client import _write_frame as _broker_write_frame
except Exception:
    PTYBrokerClient = None
    PTYBrokerOutcomeUnknownError = RuntimeError
    ensure_pty_broker_token = None
    _broker_read_frame = None
    _broker_write_frame = None

try:
    from session_events import EventHub as _SessionEventHub, FileWatcher as _SessionFileWatcher
except Exception:
    _SessionEventHub = None
    _SessionFileWatcher = None

try:
    from session_event_log import SessionEventLog as _SessionEventLog
    from session_event_ingest import (
        OMP_PARSER_VERSION as _OMP_PARSER_VERSION,
        SUPPORTED_TRANSCRIPT_PROVIDERS as _SUPPORTED_TRANSCRIPT_PROVIDERS,
        SessionLogIngestor as _SessionLogIngestor,
        UnsupportedTranscriptProviderError as _UnsupportedTranscriptProviderError,
    )
except Exception:
    _SessionEventLog = None
    _SessionLogIngestor = None
    _OMP_PARSER_VERSION = 1
    _SUPPORTED_TRANSCRIPT_PROVIDERS = frozenset({"claude", "codex"})

    class _UnsupportedTranscriptProviderError(ValueError):
        code = "unsupported_provider"
        capability = "session_transcript"

        def __init__(self, provider: str) -> None:
            self.provider = str(provider or "").strip().lower() or "unknown"
            super().__init__(
                f"Provider {self.provider} does not support deep transcript ingestion."
            )

try:
    from codex_approval import classify_codex_approval
except Exception:
    classify_codex_approval = None

try:
    from terminal_text_sanitizer import (
        TERMINAL_TEXT_MAX_CHARS,
        TERMINAL_TEXT_SUBMIT_MAX_CHARS,
        sanitize_terminal_text_input as _sanitize_terminal_text_input,
    )
except Exception:
    TERMINAL_TEXT_MAX_CHARS = 8000
    TERMINAL_TEXT_SUBMIT_MAX_CHARS = 2000

    def _sanitize_terminal_text_input(text: str, *, allow_newline: bool, max_chars: int) -> tuple[str | None, dict | None]:
        if "\x1b[200~" in text or "\x1b[201~" in text:
            return None, {"code": "bracketed_paste_delimiter", "message": "bracketed paste delimiters are not accepted from clients", "status": 400}
        for ch in text:
            code = ord(ch)
            if ch == "\n":
                if allow_newline:
                    continue
                return None, {"code": "multi_line_text", "message": "terminal text must be single-line", "status": 400}
            if ch == "\t" and allow_newline:
                continue
            if code == 0x1B:
                return None, {"code": "escape_not_allowed", "message": "ESC is not accepted in terminal text", "status": 400}
            if code in {0x061C, 0x200E, 0x200F} or 0x202A <= code <= 0x202E or 0x2066 <= code <= 0x2069:
                return None, {"code": "bidi_control_not_allowed", "message": "Unicode bidi controls are not accepted in terminal text", "status": 400}
            if code < 0x20:
                return None, {"code": "c0_not_allowed", "message": "C0 control characters are not accepted in terminal text", "status": 400}
            if code == 0x7F or 0x80 <= code <= 0x9F:
                return None, {"code": "c1_or_del_not_allowed", "message": "DEL and C1 control characters are not accepted in terminal text", "status": 400}
        cleaned = text.strip()
        if not cleaned:
            return None, {"code": "empty_text", "message": "terminal text cannot be empty", "status": 400}
        if len(cleaned) > max_chars:
            return None, {"code": "text_too_long", "message": f"terminal text exceeds {max_chars} chars", "status": 413}
        return cleaned, None

try:
    from sentinel_notifications import SentinelNotificationCenter, SentinelNotificationError
except Exception:
    SentinelNotificationCenter = None
    SentinelNotificationError = None

try:
    from managed_provider_sessions import (
        ManagedProviderDriverUnavailable as _ManagedProviderDriverUnavailable,
        ManagedProviderAuthUnavailable as _ManagedProviderAuthUnavailable,
        ManagedProviderProfileStale as _ManagedProviderProfileStale,
        ManagedProviderVersionUnavailable as _ManagedProviderVersionUnavailable,
        ManagedProviderSessionCollision as _ManagedProviderSessionCollision,
        ManagedProviderSessionManager as _ManagedProviderSessionManager,
        ManagedProviderSessionStore as _ManagedProviderSessionStore,
        managed_provider_launch_profile as _managed_provider_launch_profile,
    )
except Exception:
    _ManagedProviderDriverUnavailable = RuntimeError
    _ManagedProviderAuthUnavailable = RuntimeError
    _ManagedProviderProfileStale = RuntimeError
    _ManagedProviderVersionUnavailable = RuntimeError
    _ManagedProviderSessionCollision = RuntimeError
    _ManagedProviderSessionManager = None
    _ManagedProviderSessionStore = None
    _managed_provider_launch_profile = None

try:
    from session_control_gateway import (
        SessionControlGateway as _SessionControlGateway,
        SessionControlGatewayError as _SessionControlGatewayError,
        SessionControlPeer as _SessionControlPeer,
    )
    from session_control_trust import (
        AuthorityPublicKey as _SessionControlPublicKey,
        PinnedP256TrustStore as _SessionControlTrustStore,
        SessionControlAuthority as _SessionControlAuthority,
        derive_device_principal as _derive_session_control_principal,
    )
except Exception:
    _SessionControlGateway = None
    _SessionControlGatewayError = RuntimeError
    _SessionControlPeer = None
    _SessionControlPublicKey = None
    _SessionControlTrustStore = None
    _SessionControlAuthority = None
    _derive_session_control_principal = None

try:
    from providers.base import (
        TerminalLaunchProfile as _TerminalLaunchProfile,
        managed_child_environment as _managed_child_environment,
        provider_detail_payload,
        provider_snapshot_payload,
        resolve_executable as _provider_resolve_executable,
    )
    from providers.registry import (
        known_provider_ids as _provider_known_ids,
        get_provider as _provider_get,
        provider_descriptors as _provider_registry_descriptors,
        provider_ids as _provider_registry_ids,
        probe_all as _provider_probe_all,
        session_capable_provider_ids as _provider_session_capable_ids,
    )
    from providers.omp import (
        saved_sessions as _omp_saved_sessions,
        session_runtime_metadata as _omp_session_runtime_metadata,
        terminal_session_records as _omp_terminal_session_records,
    )
    from providers.visibility import (
        read_excluded as _provider_visibility_read_excluded,
        set_provider_included as _provider_visibility_set_included,
    )
    from providers.builtin_commands import (
        entries as _builtin_catalog_entries,
        catalog_meta as _builtin_catalog_meta,
    )
    from providers.catalog_state import annotate_first_seen as _catalog_annotate_first_seen
    from providers.pending_review import collect as _pending_review_collect
    from keep_awake import KeepAwakeManager as _KeepAwakeManager
except Exception:
    provider_detail_payload = None
    provider_snapshot_payload = None
    _TerminalLaunchProfile = None
    _managed_child_environment = None
    _provider_get = None
    _provider_resolve_executable = None
    _omp_terminal_session_records = None
    _omp_session_runtime_metadata = None
    _omp_saved_sessions = None
    _provider_known_ids = None
    _provider_registry_descriptors = None
    _provider_registry_ids = None
    _provider_probe_all = None
    _provider_visibility_read_excluded = None
    _provider_visibility_set_included = None
    _builtin_catalog_entries = None
    _builtin_catalog_meta = None
    _provider_session_capable_ids = None
    _catalog_annotate_first_seen = None
    _pending_review_collect = None
    _KeepAwakeManager = None


def _provider_child_environment() -> dict[str, str]:
    if _managed_child_environment is not None:
        return _managed_child_environment(source=os.environ, home=str(HOME))
    return {
        "HOME": str(HOME),
        "LANG": os.environ.get("LANG", "en_US.UTF-8"),
        "PATH": os.environ.get("PATH", "/usr/bin:/bin:/usr/sbin:/sbin"),
        "TMPDIR": os.environ.get("TMPDIR", "/tmp"),
    }

try:
    from providers.controls import (
        ControlContractError as _ProviderControlContractError,
        ProviderControlBinding as _ProviderControlBinding,
        ProviderOperationCorrelation as _ProviderOperationCorrelation,
    )
    from providers.operations import (
        operation_manifest_payload as _provider_operation_manifest_payload,
    )
    from providers.registry import (
        get_control_driver as _provider_get_control_driver,
        get_provider as _provider_get_adapter,
    )
    from provider_control_service import (
        ProviderControlService as _ProviderControlService,
        ProviderControlServiceError as _ProviderControlServiceError,
    )
    _PROVIDER_CONTROL_SERVICE = _ProviderControlService()
except Exception:
    _ProviderControlContractError = ValueError
    _ProviderControlBinding = None
    _ProviderOperationCorrelation = None
    _provider_operation_manifest_payload = None
    _provider_get_control_driver = None
    _provider_get_adapter = None
    _ProviderControlServiceError = RuntimeError
    _PROVIDER_CONTROL_SERVICE = None

import postures

from workstate_feed_contract import (
    DEFAULT_SINCE as WORKSTATE_FEED_DEFAULT_SINCE,
    WorkstateFeedError,
    fetch_workstate_feed as _fetch_workstate_feed,
)
from model_status_contract import (
    DEFAULT_SINCE as MODEL_STATUS_DEFAULT_SINCE,
    ModelStatusError,
    fetch_model_status as _fetch_model_status,
)
from substrate_status_contract import (
    DEFAULT_SINCE as SUBSTRATE_STATUS_DEFAULT_SINCE,
    SubstrateStatusError,
    fetch_substrate_feed as _fetch_substrate_feed,
    fetch_substrate_status as _fetch_substrate_status,
)

# launchd gives subprocesses a minimal PATH; prepend user tool locations so
# provider and runtime binaries resolve reliably.
_USER_HOME = str(Path.home())
os.environ["PATH"] = (
    f"{_USER_HOME}/.local/bin:{_USER_HOME}/bin:"
    "/usr/local/bin:/opt/homebrew/bin:/usr/bin:/bin:/usr/sbin:/sbin:"
    + os.environ.get("PATH", "")
)

PORT = RUNTIME_PORT
HOME = Path.home()
DEFAULT_COORDINATOR_HOST = (
    os.environ.get("PAIRLING_HOSTNAME")
    or os.environ.get("COMPANION_COORDINATOR_HOST")
    or os.uname().nodename.split(".")[0]
    or "pairling-mac"
)
LEGACY_TOKEN_FILE = HOME / LEGACY_TOKEN_RELATIVE_PATH
CLAUDE_PROJECTS_DIR = HOME / ".claude" / "projects"
PROJECTS_DIR = CLAUDE_PROJECTS_DIR / re.sub(r"[/._]", "-", str(HOME))
QUEUE_DIR = HOME / ".claude" / "hooks" / "queue"
COMPANION_DIR = HOME / ".claude" / "companion"
CONTROL_SOCKET_PATH = Path(
    os.environ.get("PAIRLING_CONTROL_SOCKET", str(COMPANION_DIR / "control.sock"))
).expanduser()
ORCHESTRATIONS_ROUTE = "/orchestrations"
ORCHESTRATIONS_DIR = COMPANION_DIR / "orchestrations"
HANDOFFS_DIR = COMPANION_DIR / "handoffs"
CROSS_PROVIDER_DIR = COMPANION_DIR / "cross-provider"
SUBLIME_APP = "Sublime Text"
CODEX_SESSIONS_DIR = HOME / ".codex" / "sessions"
OMP_SESSIONS_DIR = HOME / ".omp" / "agent" / "sessions"
CODEX_SESSION_INDEX = HOME / ".codex" / "session_index.jsonl"
CODEX_HISTORY = HOME / ".codex" / "history.jsonl"
TURN_STATE_DIR = HOME / ".claude" / "turn-state"
# deepfield blurt target: verbatim voice captures land in the idea
# observatory's inbox. Fail-closed when the repo is absent (foreign installs).
DEEPFIELD_INBOX_DIR = HOME / "projects" / "deepfield" / "observations" / "inbox"


class _UnsafeDeepfieldPathError(OSError):
    """The observation destination failed no-follow or ownership validation."""


def _deepfield_directory_flags() -> int:
    nofollow = getattr(os, "O_NOFOLLOW", None)
    directory = getattr(os, "O_DIRECTORY", None)
    if nofollow is None or directory is None:
        raise _UnsafeDeepfieldPathError("no-follow directory opens are unavailable")
    return os.O_RDONLY | nofollow | directory | getattr(os, "O_CLOEXEC", 0)


def _open_owned_deepfield_directory(
    path: Path | str,
    *,
    dir_fd: int | None = None,
) -> int:
    try:
        descriptor = os.open(path, _deepfield_directory_flags(), dir_fd=dir_fd)
    except FileNotFoundError:
        raise
    except OSError as exc:
        raise _UnsafeDeepfieldPathError("unsafe Deepfield directory") from exc
    try:
        directory_stat = os.fstat(descriptor)
        if not stat.S_ISDIR(directory_stat.st_mode):
            raise _UnsafeDeepfieldPathError("Deepfield path is not a directory")
        if directory_stat.st_uid != os.getuid():
            raise _UnsafeDeepfieldPathError("Deepfield directory has an unexpected owner")
        return descriptor
    except Exception:
        os.close(descriptor)
        raise


def _deepfield_repository_root() -> Path:
    if (
        not DEEPFIELD_INBOX_DIR.is_absolute()
        or any(part in {"", ".", ".."} for part in DEEPFIELD_INBOX_DIR.parts)
        or DEEPFIELD_INBOX_DIR.name != "inbox"
        or DEEPFIELD_INBOX_DIR.parent.name != "observations"
    ):
        raise _UnsafeDeepfieldPathError("invalid Deepfield inbox path")
    return DEEPFIELD_INBOX_DIR.parent.parent


def _open_deepfield_repository_root() -> int:
    return _open_owned_deepfield_directory(_deepfield_repository_root())


def _open_or_create_deepfield_directory(name: str, *, parent_fd: int) -> int:
    if not name or name in {".", ".."} or "/" in name:
        raise _UnsafeDeepfieldPathError("invalid Deepfield directory component")
    try:
        return _open_owned_deepfield_directory(name, dir_fd=parent_fd)
    except FileNotFoundError:
        try:
            os.mkdir(name, mode=0o700, dir_fd=parent_fd)
        except FileExistsError:
            pass
        return _open_owned_deepfield_directory(name, dir_fd=parent_fd)


def _open_deepfield_inbox_directory() -> int:
    current_fd = _open_deepfield_repository_root()
    try:
        for component in ("observations", "inbox"):
            next_fd = _open_or_create_deepfield_directory(
                component,
                parent_fd=current_fd,
            )
            os.close(current_fd)
            current_fd = next_fd
        return current_fd
    except Exception:
        os.close(current_fd)
        raise


AGENT_REGISTRY_DB = COMPANION_DIR / "agent-sessions.sqlite"
CONTROL_RECEIPT_DB = COMPANION_DIR / "control-receipts.sqlite"
TERMINAL_CAPTURE_DIR = COMPANION_DIR / "terminal-capture"
TERMINAL_CAPTURE_MAP_DIR = TERMINAL_CAPTURE_DIR / "by-tty"
PTY_BROKER_SOCKET = COMPANION_DIR / "pty-broker.sock"
PTY_BROKER_TOKEN = ensure_pty_broker_token(COMPANION_DIR) if ensure_pty_broker_token else ""

# ----- Session event infrastructure (Phase 1 of the viewer evolution) ------
# One in-process hub; wakeup sources publish, SSE handlers subscribe. All
# construction is lazy or thread-free at import so tests stay hermetic.
# The daemon's main import block sits further down this file, so threading
# is imported here for the locks below.
import threading

SESSION_EVENT_HUB = _SessionEventHub() if _SessionEventHub else None
BROKER_GLOBAL_TOPIC = "broker:global"
_SESSION_FILE_WATCHER = None
_SESSION_FILE_WATCHER_LOCK = threading.Lock()
_BROKER_OUTPUT_LISTENER = None
_BROKER_OUTPUT_LISTENER_LOCK = threading.Lock()

MANAGED_PROVIDER_SESSION_DB = COMPANION_DIR / "managed-provider-sessions.sqlite"
MANAGED_PROVIDER_SESSION_STORE = None
MANAGED_PROVIDER_SESSION_MANAGER = None
# Private aliases remain injectable for focused daemon tests.
_MANAGED_PROVIDER_SESSION_STORE = None
_MANAGED_PROVIDER_SESSION_MANAGER = None
_MANAGED_PROVIDER_SESSION_LOCK = threading.RLock()
SESSION_CONTROL_GATEWAY = None
_SESSION_CONTROL_GATEWAY = None
_SESSION_CONTROL_AUTHORITY = None
_SESSION_CONTROL_GATEWAY_LOCK = threading.RLock()

def _ensure_session_file_watcher():
    global _SESSION_FILE_WATCHER
    if _SessionFileWatcher is None or SESSION_EVENT_HUB is None:
        return None
    with _SESSION_FILE_WATCHER_LOCK:
        if _SESSION_FILE_WATCHER is None:
            _SESSION_FILE_WATCHER = _SessionFileWatcher(SESSION_EVENT_HUB)
        return _SESSION_FILE_WATCHER


class _BrokerOutputListener(threading.Thread):
    """One persistent subscribe_output connection to the PTY broker.

    Output notifications publish to terminal:{session_id}; connect,
    disconnect, and gap transitions publish to BROKER_GLOBAL_TOPIC so
    stream handlers can fall back to their degraded drain honestly while
    the broker is unreachable.
    """

    def __init__(self, hub, *, connect=None, backoff_seconds: float = 1.0) -> None:
        super().__init__(name="broker-output-listener", daemon=True)
        self._hub = hub
        self._connect = connect or self._default_connect
        self._backoff = max(0.05, float(backoff_seconds))
        self._stopped = threading.Event()
        self._sock = None
        self.healthy = False

    @staticmethod
    def _default_connect():
        sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
        sock.connect(str(PTY_BROKER_SOCKET))
        return sock

    def stop(self) -> None:
        self._stopped.set()
        sock = self._sock
        if sock is not None:
            try:
                sock.close()
            except OSError:
                pass

    def run(self) -> None:
        while not self._stopped.is_set():
            try:
                sock = self._connect()
            except Exception:
                self._publish_health(False)
                if self._stopped.wait(self._backoff):
                    return
                continue
            self._sock = sock
            try:
                _broker_write_frame(sock, {"op": "subscribe_output", "token": PTY_BROKER_TOKEN})
                hello = _broker_read_frame(sock)
                if not hello.get("subscribed"):
                    raise RuntimeError("broker refused output subscription")
                self._publish_health(True)
                while not self._stopped.is_set():
                    frame = _broker_read_frame(sock)
                    kind = frame.get("event")
                    if kind == "output":
                        session_id = str(frame.get("session_id") or "")
                        if session_id:
                            event = {
                                "type": "broker_output",
                                "session_id": session_id,
                                "raw_offset": int(frame.get("raw_offset") or 0),
                                "feed_at": frame.get("feed_at"),
                            }
                            identities = _session_event_identity_keys(None, session_id)
                            if not identities:
                                identities = {session_id}
                            for identity in identities:
                                self._hub.publish(f"terminal:{identity}", event)
                    elif kind == "output_gap":
                        self._hub.publish(BROKER_GLOBAL_TOPIC, {
                            "type": "broker_gap",
                            "dropped": int(frame.get("dropped") or 0),
                        })
            except Exception:
                pass
            finally:
                try:
                    sock.close()
                except OSError:
                    pass
                self._sock = None
            self._publish_health(False)
            if self._stopped.wait(self._backoff):
                return

    def _publish_health(self, connected: bool) -> None:
        if connected == self.healthy:
            return
        self.healthy = connected
        self._hub.publish(BROKER_GLOBAL_TOPIC, {
            "type": "broker_connected" if connected else "broker_disconnected",
        })


def _ensure_broker_output_listener():
    global _BROKER_OUTPUT_LISTENER
    if SESSION_EVENT_HUB is None or _broker_read_frame is None or PTY_BROKER is None:
        return None
    with _BROKER_OUTPUT_LISTENER_LOCK:
        if _BROKER_OUTPUT_LISTENER is None:
            _BROKER_OUTPUT_LISTENER = _BrokerOutputListener(SESSION_EVENT_HUB)
            _BROKER_OUTPUT_LISTENER.start()
        return _BROKER_OUTPUT_LISTENER


# ----- Contract v2: durable session event log --------------------------------
_SESSION_EVENT_LOG = None
_SESSION_EVENT_LOG_LOCK = threading.Lock()
_SESSION_LOG_INGESTOR = None
_SESSION_LOG_INGESTOR_LOCK = threading.Lock()
SESSION_EVENTS_V2_SCHEMA_VERSION = 2
SESSION_EVENTS_V2_RAW_INLINE_MAX = 32 * 1024
SESSION_EVENTS_V2_RAW_STREAM_CHUNK = 1024 * 1024
# Payload text/content fields cap here on the wire (full value on the
# content endpoint); keeps any single SSE event under the transcript cap.
SESSION_EVENTS_V2_CONTENT_INLINE_MAX = 64 * 1024
SESSION_EVENTS_V2_INPUT_INLINE_MAX = 64 * 1024
# History is loaded repeatedly as the user scrolls. Keep any one page small
# enough that a pathological tool result cannot make the phone hold tens of
# megabytes of JSON at once.
SESSION_EVENTS_V2_PAGE_MAX_BYTES = 4 * 1024 * 1024
SESSION_EVENTS_V2_PAGE_MAX_ROWS = 200
# Bound the SQLite text columns selected before payload JSON is decoded. A
# single provider row can exceed this and is still served alone so cursors move.
SESSION_EVENTS_V2_SOURCE_READ_MAX_BYTES = 8 * 1024 * 1024
# A cold stream replays at most this many events; older history pages via
# once=1 after an explicit backlog_gap notice.
SESSION_EVENTS_V2_BACKLOG_LIMIT = 300
# The dashboard-grade summary plane: registry, turn-state, and approval
# write sites publish compact events here at write time; /device-events
# summaries mode is its wire.
SESSION_SUMMARIES_TOPIC = "session-summaries"


def _ensure_session_event_log():
    global _SESSION_EVENT_LOG
    if _SessionEventLog is None:
        return None
    with _SESSION_EVENT_LOG_LOCK:
        if _SESSION_EVENT_LOG is None:
            _SESSION_EVENT_LOG = _SessionEventLog(COMPANION_DIR / "session-events.sqlite")
        return _SESSION_EVENT_LOG


def _ensure_session_log_ingestor():
    global _SESSION_LOG_INGESTOR
    log = _ensure_session_event_log()
    watcher = _ensure_session_file_watcher()
    if log is None or SESSION_EVENT_HUB is None or _SessionLogIngestor is None:
        return None
    with _SESSION_LOG_INGESTOR_LOCK:
        if _SESSION_LOG_INGESTOR is None:
            _SESSION_LOG_INGESTOR = _SessionLogIngestor(
                log, SESSION_EVENT_HUB, watcher,
                normalize_codex=lambda data, native_id: _normalize_codex_ndjson(data, native_id, include_event_fallback=False),
            )
        return _SESSION_LOG_INGESTOR

def _managed_event_publisher(session_id: str, event: dict) -> None:
    if SESSION_EVENT_HUB is None:
        return
    payload = {
        "type": "managed_provider_event",
        "session_id": session_id,
        "seq": int(event.get("seq") or 0),
        "kind": event.get("kind"),
    }
    for topic in (
        f"log:{session_id}",
        f"transcript:{session_id}",
        f"turn:{session_id}",
        SESSION_SUMMARIES_TOPIC,
    ):
        SESSION_EVENT_HUB.publish(topic, payload)


def _ambient_session_identity_exists(session_id: str) -> bool:
    provider, native_id = _parse_agent_session_ref(session_id)
    if not native_id:
        return False
    try:
        if _agent_registry_get(provider, native_id) is not None:
            return True
    except Exception:
        # Collision checks fail closed when the ambient registry is unreadable.
        return True
    try:
        broker = PTY_BROKER.get(_qualified_session_id(provider, native_id)) if PTY_BROKER else None
        if broker is not None:
            return True
    except Exception:
        return True
    return False


def _structured_provider_control_driver(provider: str, binding_id: str):
    """Resolve one driver through its adapter's explicit launch contract."""
    try:
        from providers.controls import ProviderControlBinding
        from providers.registry import get_control_driver, get_provider

        adapter = get_provider(provider, home=HOME)
        if adapter is None:
            raise _ManagedProviderDriverUnavailable(
                f"{provider} has no structured provider adapter"
            )
        descriptor = getattr(adapter, "descriptor", None)
        contract = getattr(descriptor, "managed_launch", None)
        if contract is None:
            raise _ManagedProviderDriverUnavailable(
                f"{provider} has no reviewed managed-launch contract"
            )
        probe = adapter.probe()
        availability = probe.availability
        diagnostics = probe.diagnostics
        if str(getattr(availability, "provider_id", "") or "") != provider:
            raise _ManagedProviderDriverUnavailable(
                f"{provider} probe returned a different provider identity"
            )
        setup = contract.setup_diagnostic(
            availability,
            version=getattr(diagnostics, "version", None),
        )
        if setup is not None:
            message = f"{provider}: {setup.message}"
            if setup.category == "version":
                raise _ManagedProviderVersionUnavailable(message)
            if setup.category == "authentication":
                raise _ManagedProviderAuthUnavailable(message)
            if setup.category == "configuration":
                raise _ManagedProviderProfileStale(message)
            raise _ManagedProviderDriverUnavailable(message)
        version_resolver = getattr(
            adapter, "managed_launch_provider_version", None
        )
        provider_version = (
            version_resolver()
            if callable(version_resolver)
            else getattr(diagnostics, "version", None)
        )
        if not isinstance(provider_version, str) or not provider_version.strip():
            raise _ManagedProviderVersionUnavailable(
                f"{provider} managed launch has no reviewed provider version"
            )
        binding = ProviderControlBinding(
            provider_id=provider,
            provider_version=provider_version,
            provider_channel=contract.control_channel,
            binding_id=binding_id,
        )
        driver = get_control_driver(binding, home=HOME)
        if driver is None:
            raise _ManagedProviderDriverUnavailable(
                f"{provider} has no reviewed structured control driver"
            )
        if getattr(driver, "binding", None) != binding:
            raise _ManagedProviderDriverUnavailable(
                f"{provider} returned a binding-mismatched control driver"
            )
        if getattr(driver, "safe_launch_profile", True) is False:
            raise _ManagedProviderProfileStale(
                f"{provider} managed launch profile is stale"
            )
        if contract.require_post_launch_verification:
            verify_launch = getattr(driver, "verify_managed_launch", None)
            if not callable(verify_launch):
                raise _ManagedProviderProfileStale(
                    f"{provider} managed launch verification is unavailable"
                )
            safe_profile = getattr(driver, "safe_launch_profile", None)
            provider_profile = getattr(driver, "profile", None)
            safe_profile_reviewed = (
                isinstance(safe_profile, dict)
                and safe_profile.get("reviewed") is True
                and safe_profile.get("provider_id") == provider
            )
            profile_digest = getattr(provider_profile, "safe_launch_digest", None)
            acp_profile_reviewed = (
                isinstance(profile_digest, str)
                and re.fullmatch(r"[a-f0-9]{64}", profile_digest) is not None
            )
            if not safe_profile_reviewed and not acp_profile_reviewed:
                raise _ManagedProviderProfileStale(
                    f"{provider} managed launch proof is not reviewed"
                )
        return driver
    except _ManagedProviderDriverUnavailable:
        raise
    except Exception as exc:
        raise _ManagedProviderDriverUnavailable(
            f"{provider} structured driver resolution failed"
        ) from exc


def _provider_spawn_contract(
    probe_result,
) -> tuple[list[str], list[dict], list[dict]]:
    """Return exact advertised backends, profiles, and typed setup diagnostics."""
    availability = getattr(probe_result, "availability", None)
    descriptor = getattr(probe_result, "descriptor", None)
    provider = str(getattr(availability, "provider_id", "") or "")
    backends: list[str] = []
    profiles: list[dict] = []
    setup_diagnostics: list[dict] = []
    terminal_contract = getattr(descriptor, "terminal_launch", None)
    if (
        provider
        and bool(getattr(availability, "launchable", False))
        and provider in _agent_provider_ids()
        and terminal_contract is not None
    ):
        backends.extend(terminal_contract.backends)
    managed_contract = getattr(descriptor, "managed_launch", None)
    if managed_contract is None:
        return backends, profiles, setup_diagnostics
    driver = None
    try:
        driver = _structured_provider_control_driver(
            provider,
            "availability_" + secrets.token_hex(16),
        )
        if not callable(getattr(driver, "launch_session", None)):
            raise _ManagedProviderDriverUnavailable(
                f"{provider} has no reviewed structured launch method"
            )
        if _managed_provider_launch_profile is None:
            raise _ManagedProviderProfileStale(
                f"{provider} managed profile builder is unavailable"
            )
        profile = _managed_provider_launch_profile(
            driver,
            provider,
            display_name=str(
                getattr(availability, "display_name", "") or provider
            ),
        )
        profiles.append(profile)
        backends.append("managed_provider")
    except _ManagedProviderDriverUnavailable as exc:
        code = str(
            getattr(exc, "code", None) or "managed_provider_unavailable"
        )
        category = {
            "managed_provider_auth_unavailable": "authentication",
            "managed_provider_version_unavailable": "version",
            "managed_provider_profile_stale": "configuration",
        }.get(code, "availability")
        setup_diagnostics.append(
            {
                "code": code,
                "category": category,
                "message": (
                    "Managed launch is unavailable until this provider's "
                    "reviewed setup contract is satisfied."
                ),
                "setup_actions": list(
                    getattr(availability, "setup_actions", ()) or ()
                ),
            }
        )
    except Exception:
        setup_diagnostics.append(
            {
                "code": "managed_provider_unavailable",
                "category": "availability",
                "message": (
                    "Managed launch is unavailable because its reviewed "
                    "profile could not be constructed."
                ),
                "setup_actions": list(
                    getattr(availability, "setup_actions", ()) or ()
                ),
            }
        )
    finally:
        if driver is not None:
            try:
                driver.close()
            except Exception:
                pass
    return backends, profiles, setup_diagnostics


def _reviewed_terminal_launch_contract(provider: str):
    if _provider_registry_descriptors is None:
        return None
    try:
        descriptors = _provider_registry_descriptors()
    except Exception:
        return None
    matches = [
        descriptor
        for descriptor in descriptors
        if str(getattr(descriptor, "provider_id", "") or "") == provider
    ]
    if len(matches) != 1:
        return None
    return getattr(matches[0], "terminal_launch", None)


def _reviewed_provider_launch_command(
    provider: str,
    project: str,
    backend: str,
) -> tuple[str, bool]:
    """Build one exact reviewed terminal command without a provider fallback."""
    contract = _reviewed_terminal_launch_contract(provider)
    if contract is None or backend not in contract.backends:
        raise ValueError("provider has no reviewed command for this spawn backend")
    profile = contract.profile
    if profile is _TerminalLaunchProfile.CODEX_WORKSPACE:
        command = (
            f"exec codex -c check_for_update_on_startup=false "
            f"-C {shlex.quote(project)} --add-dir {shlex.quote(project)}"
            if backend == "broker"
            else (
                f"cd {shlex.quote(project)} && exec codex "
                f"-C {shlex.quote(project)} --add-dir {shlex.quote(project)}"
            )
        )
        return command, backend == "terminal_app"
    if profile is _TerminalLaunchProfile.CLAUDE_PHONE:
        command = _direct_claude_phone_command()
        if not command:
            raise ValueError("reviewed Claude launch command is unavailable")
        if backend == "terminal_app":
            command = f"cd {shlex.quote(project)} && {command}"
        return command, False
    if profile is _TerminalLaunchProfile.OMP_WORKSPACE:
        command = (
            f"exec omp --cwd {shlex.quote(project)}"
            if backend == "broker"
            else f"cd {shlex.quote(project)} && exec omp"
        )
        return command, backend == "terminal_app"
    raise ValueError("provider launch profile is not implemented")


def _recover_managed_provider_fork(reservation: dict):
    """Recover a prepared fork only through the central exact-proof contract."""
    if (
        _PROVIDER_CONTROL_SERVICE is None
        or _ProviderOperationCorrelation is None
        or not isinstance(reservation, dict)
    ):
        return None
    manager = MANAGED_PROVIDER_SESSION_MANAGER
    store = MANAGED_PROVIDER_SESSION_STORE
    parent_session_id = str(
        reservation.get("parent_session_id") or ""
    )
    if manager is None or store is None or not parent_session_id:
        return None
    driver = manager.driver(parent_session_id)
    truth = store.session_truth(parent_session_id)
    if driver is None or not isinstance(truth, dict):
        return None
    if (
        truth.get("binding_id") != reservation.get("parent_binding_id")
        or truth.get("capability_generation")
        != reservation.get("parent_capability_generation")
        or truth.get("session_instance_id")
        != reservation.get("parent_session_instance_id")
        or truth.get("provider_id") != reservation.get("provider")
        or truth.get("provider_version")
        != reservation.get("provider_version")
        or truth.get("provider_channel")
        != reservation.get("provider_channel")
        or truth.get("provider_profile_id")
        != reservation.get("provider_profile_id")
    ):
        return None
    provider_operation_id = str(
        reservation.get("provider_operation_id") or ""
    )
    if not provider_operation_id:
        return None
    correlation = _ProviderOperationCorrelation(
        provider_operation_id=provider_operation_id,
        provider_cursor=reservation.get("provider_cursor"),
    )
    execution = _PROVIDER_CONTROL_SERVICE.recover(
        {
            "driver": driver,
            "session_id": parent_session_id,
            "session_truth": truth,
        },
        operation_id="session.fork",
        binding_id=str(reservation["parent_binding_id"]),
        capability_generation=int(
            reservation["parent_capability_generation"]
        ),
        client_action_id=str(reservation["client_action_id"]),
        correlation=correlation,
    )
    return None if execution is None else execution.result


def _ensure_managed_provider_session_store():
    global MANAGED_PROVIDER_SESSION_STORE, _MANAGED_PROVIDER_SESSION_STORE
    injected = _MANAGED_PROVIDER_SESSION_STORE
    if injected is not None:
        return injected
    if MANAGED_PROVIDER_SESSION_STORE is not None:
        return MANAGED_PROVIDER_SESSION_STORE
    if _ManagedProviderSessionStore is None:
        return None
    with _MANAGED_PROVIDER_SESSION_LOCK:
        if MANAGED_PROVIDER_SESSION_STORE is None:
            MANAGED_PROVIDER_SESSION_STORE = _ManagedProviderSessionStore(
                MANAGED_PROVIDER_SESSION_DB
            )
        _MANAGED_PROVIDER_SESSION_STORE = MANAGED_PROVIDER_SESSION_STORE
        return MANAGED_PROVIDER_SESSION_STORE


def _ensure_managed_provider_session_manager():
    global MANAGED_PROVIDER_SESSION_MANAGER, _MANAGED_PROVIDER_SESSION_MANAGER
    injected = _MANAGED_PROVIDER_SESSION_MANAGER
    if injected is not None:
        return injected
    if MANAGED_PROVIDER_SESSION_MANAGER is not None:
        return MANAGED_PROVIDER_SESSION_MANAGER
    store = _ensure_managed_provider_session_store()
    if store is None or _ManagedProviderSessionManager is None:
        return None
    with _MANAGED_PROVIDER_SESSION_LOCK:
        if MANAGED_PROVIDER_SESSION_MANAGER is None:
            manager = _ManagedProviderSessionManager(
                store,
                driver_factory=_structured_provider_control_driver,
                ambient_identity_exists=_ambient_session_identity_exists,
                event_publisher=_managed_event_publisher,
                fork_recovery=_recover_managed_provider_fork,
            )
            MANAGED_PROVIDER_SESSION_MANAGER = manager
            _MANAGED_PROVIDER_SESSION_MANAGER = manager
            manager.reconcile()
        _MANAGED_PROVIDER_SESSION_MANAGER = MANAGED_PROVIDER_SESSION_MANAGER
        return MANAGED_PROVIDER_SESSION_MANAGER


def _session_control_runtime_revision() -> str:
    runtime = _runtime_info_snapshot()
    identity = {
        "runtime_version": runtime.get("runtime_version"),
        "source_revision": runtime.get("source_revision"),
        "contract_version": runtime.get("contract_version")
        or RUNTIME_CONTRACT_VERSION,
        "script_sha256": runtime.get("script_sha256"),
    }
    return "sha256:" + hashlib.sha256(
        json.dumps(
            identity,
            sort_keys=True,
            separators=(",", ":"),
            ensure_ascii=False,
        ).encode("utf-8")
    ).hexdigest()


def _ensure_session_control_gateway():
    global SESSION_CONTROL_GATEWAY, _SESSION_CONTROL_GATEWAY
    global _SESSION_CONTROL_AUTHORITY
    injected = _SESSION_CONTROL_GATEWAY
    if injected is not None:
        return injected
    if SESSION_CONTROL_GATEWAY is not None:
        return SESSION_CONTROL_GATEWAY
    manager = _ensure_managed_provider_session_manager()
    store = _ensure_managed_provider_session_store()
    if (
        manager is None
        or store is None
        or _PROVIDER_CONTROL_SERVICE is None
        or _SessionControlGateway is None
        or _SessionControlAuthority is None
    ):
        return None
    with _SESSION_CONTROL_GATEWAY_LOCK:
        if SESSION_CONTROL_GATEWAY is None:
            if _SESSION_CONTROL_AUTHORITY is None:
                _SESSION_CONTROL_AUTHORITY = (
                    _SessionControlAuthority.load_or_create()
                )

            def resolve_target(session_id: str):
                row = store.get(session_id)
                if not isinstance(row, dict):
                    return None
                provider = str(row.get("provider") or "").strip().lower()
                if not provider:
                    return None
                return _provider_control_managed_target(session_id, provider)

            SESSION_CONTROL_GATEWAY = _SessionControlGateway(
                manager=manager,
                service=_PROVIDER_CONTROL_SERVICE,
                authority=_SESSION_CONTROL_AUTHORITY,
                target_resolver=resolve_target,
                runtime_revision=_session_control_runtime_revision(),
            )
        _SESSION_CONTROL_GATEWAY = SESSION_CONTROL_GATEWAY
        return SESSION_CONTROL_GATEWAY


class _SessionControlAttachmentResolver:
    def __init__(self, handler) -> None:
        self._handler = handler

    def prepare_attachment_handles(self, records, **kwargs):
        return self._handler._pairdrop_store().prepare_attachment_handles(
            records,
            **kwargs,
        )


def _session_control_peer(handler, *, attachments: bool = False):
    auth = getattr(handler, "pairling_auth", None)
    device_id = str(getattr(auth, "device_id", "") or "").strip()
    authenticated_install_id = str(
        getattr(auth, "install_id", "") or ""
    ).strip()
    mac_install_id = str(
        getattr(PAIRING_STORE, "install_id", "") or ""
    ).strip()
    if (
        auth is None
        or not getattr(auth, "ok", False)
        or not device_id
        or not authenticated_install_id
        or not mac_install_id
        or authenticated_install_id != mac_install_id
        or _SessionControlPeer is None
        or _derive_session_control_principal is None
    ):
        raise _SessionControlGatewayError(
            "authenticated_principal_invalid",
            "session-control transport principal is unavailable",
            status=401,
            error_class="authority",
        )
    proof_verifier = None
    signature_verifier = None
    encoded_key = (
        DEVICE_REGISTRY.get_se_pubkey(device_id)
        if DEVICE_REGISTRY is not None
        else None
    )
    if encoded_key:
        try:
            public_key = _SessionControlPublicKey.from_x963(
                base64.b64decode(encoded_key, validate=True),
                hardware_backed=True,
            )
            trust = _SessionControlTrustStore([public_key])
        except Exception as exc:
            raise _SessionControlGatewayError(
                "client_authority_invalid",
                "paired device control-authority key is invalid",
                status=409,
                error_class="authority",
            ) from exc
        proof_verifier = trust.verify_proof_token
        signature_verifier = trust.verify_envelope_signature
    attachment_resolver = (
        _SessionControlAttachmentResolver(handler)
        if attachments and PairDropStore is not None
        else None
    )
    return _SessionControlPeer(
        principal_id=_derive_session_control_principal(
            mac_install_id,
            device_id,
        ),
        granted_scopes=frozenset(getattr(auth, "scopes", ()) or ()),
        source_device_id=device_id,
        source_install_id=authenticated_install_id,
        proof_verifier=proof_verifier,
        signature_verifier=signature_verifier,
        attachment_resolver=attachment_resolver,
    )


def _managed_session_rows(
    *,
    provider_filter: str = "all",
    live_only: bool = False,
    active_within_min: int | None = None,
    limit: int = 500,
    poll_live: bool = True,
) -> list[dict]:
    manager = _ensure_managed_provider_session_manager()
    if manager is None:
        return []
    try:
        return manager.list_rows(
            provider=provider_filter,
            live_only=live_only,
            active_within_min=active_within_min,
            limit=limit,
            poll_live=poll_live,
        )
    except Exception:
        return []


def _merge_managed_session_rows(
    ambient_rows: list[dict], managed_rows: list[dict]
) -> list[dict]:
    """Merge without allowing a managed record to commandeer ambient truth."""
    merged = list(ambient_rows)
    owned_ids = {
        str(row.get("id") or _qualified_session_id(
            str(row.get("provider") or "claude"),
            str(row.get("native_id") or row.get("id") or ""),
        ))
        for row in ambient_rows
    }
    store = None
    for row in managed_rows:
        session_id = str(row.get("id") or row.get("session_id") or "")
        if not session_id or session_id in owned_ids:
            if store is None:
                store = _ensure_managed_provider_session_store()
            if store is not None:
                try:
                    store.mark_driver_unavailable(
                        session_id,
                        reason="ambient session owns this provider identity",
                    )
                except Exception:
                    pass
            continue
        merged.append(row)
        owned_ids.add(session_id)
    return merged


def _managed_transcript_ndjson(
    session_id: str, *, since: int = 0, limit: int = 500
) -> tuple[bytes, int, int]:
    store = _ensure_managed_provider_session_store()
    if store is None or store.get(session_id) is None:
        return b"", max(0, int(since)), 0
    manager = _ensure_managed_provider_session_manager()
    if manager is not None:
        manager.poll(session_id)
    rows = store.history(
        session_id,
        since_seq=max(0, int(since)),
        limit=max(1, min(int(limit), 1000)),
    )
    lines = [
        json.dumps(
            {
                "schema_version": 1,
                "session_id": session_id,
                **row,
            },
            ensure_ascii=False,
            separators=(",", ":"),
        ).encode("utf-8") + b"\n"
        for row in rows
    ]
    next_since = int(rows[-1]["seq"]) if rows else max(0, int(since))
    return b"".join(lines), next_since, store.last_seq(session_id)


def _managed_session_events_v2_page(
    session_id: str, *, since_seq: int = 0, limit: int = 200
) -> dict:
    store = _ensure_managed_provider_session_store()
    row = store.get(session_id) if store is not None else None
    if row is None:
        raise KeyError(session_id)
    manager = _ensure_managed_provider_session_manager()
    if manager is not None:
        manager.poll(session_id)
    row = store.get(session_id)
    if row is None:
        raise KeyError(session_id)
    events = store.history(
        session_id,
        since_seq=max(0, int(since_seq)),
        limit=max(1, min(int(limit), SESSION_EVENTS_V2_PAGE_MAX_ROWS)),
    )
    wire_rows = []
    for event in events:
        payload = dict(event.get("payload") or {})
        metadata = dict(event.get("metadata") or {})
        if metadata:
            payload["provider_metadata"] = metadata
        wire_rows.append(_session_event_v2_wire_row(session_id, {
            "seq": int(event["seq"]),
            "kind": event["kind"],
            "payload": payload,
            "ingested_at": float(event["observed_at"]),
            "raw": None,
        }))
    last_seq = store.last_seq(session_id)
    return {
        "schema_version": SESSION_EVENTS_V2_SCHEMA_VERSION,
        "session_key": session_id,
        "events": wire_rows,
        "last_seq": last_seq,
        "generation": int(row["capability_generation"]),
        "first_seq": wire_rows[0]["seq"] if wire_rows else None,
        "has_more_before": bool(wire_rows and wire_rows[0]["seq"] > 1),
        "page_limited_by_bytes": False,
        "page_limited_by_source_bytes": False,
        "source_bytes": sum(_wire_json_size(item) for item in wire_rows),
    }


def _managed_session_runtime_truth(
    session_id: str, expected_source_revision: str | None = None
) -> dict | None:
    store = _ensure_managed_provider_session_store()
    row = store.get(session_id) if store is not None else None
    if row is None:
        return None
    manager = _ensure_managed_provider_session_manager()
    if manager is not None:
        manager.poll(session_id)
        row = store.get(session_id) or row
    provider = str(row["provider"])
    native_id = str(row["native_id"])
    controllable = row.get("control_state") == "controllable"
    readable_state = str(row.get("readable_state") or "stale")
    last_seen_at = float(row.get("updated_at") or row.get("last_heartbeat") or 0)
    stream = {
        "byte_stream_available": False,
        "surface_stream_available": False,
        "transcript_stream_available": True,
        "source": "managed_provider_events",
        "backend": "normalized_events",
        "can_control": controllable,
        "can_send_text": controllable,
        "can_interrupt": controllable,
        "can_terminate": controllable,
        "fallback_reason": row.get("blocked_reason"),
    }
    terminal = {
        "state": "not_applicable",
        "backend": "none",
        "selected_surface": "none",
        "surface_agreement": "not_applicable",
        "v1": None,
        "v2": None,
        "pending_input": None,
        "pending_input_detection": {
            "status": "not_applicable",
            "parser_version": None,
            "surface": "managed_provider_events",
            "confidence": None,
            "reason": "structured provider sessions have no terminal surface",
        },
        "stream": stream,
        "user_message": row.get("working_on") or "Structured provider session",
    }
    blocked_reason = row.get("blocked_reason")
    control = {
        "state": "eligible" if controllable else "read_only",
        "basis_surface": "managed_provider_events",
        "schema_version": 1,
        "screen_hash": None,
        "nonce": None,
        "generation": int(row["capability_generation"]),
        "visible_surface_matches_control_basis": controllable,
        "blocked_reason": blocked_reason,
        "supported_actions": ["provider_control"],
    }
    registry = {
        "state": row.get("turn_state"),
        "readable_state": readable_state,
        "control_state": row.get("control_state"),
        "working_on": row.get("working_on"),
        "stale_seconds": max(0, int(_time.time() - last_seen_at)) if last_seen_at else 0,
        "source_freshness": (
            "managed_driver_live" if controllable else "managed_driver_unavailable"
        ),
        "last_seen_at": last_seen_at or None,
        "project": row.get("project"),
        "binding_id": row.get("binding_id"),
        "capability_generation": int(row["capability_generation"]),
        "session_instance_id": row.get("session_instance_id"),
    }
    return {
        "schema_version": 1,
        "session_id": session_id,
        "provider": provider,
        "native_id": native_id,
        "project": row.get("project"),
        "checked_at": _time.time(),
        "runtime": _runtime_freshness_truth(
            expected_source_revision=expected_source_revision
        ),
        "registry": registry,
        "process": {
            "state": "driver_owned" if controllable else "driver_unavailable",
            "source": "managed_provider_session_store",
            "identity_verified": controllable,
            "session_instance_id": registry["session_instance_id"],
        },
        "turn": {
            "state": row.get("turn_state"),
            "source": "managed_provider_events",
            "observed_at": last_seen_at or None,
            "age_seconds": max(0, _time.time() - last_seen_at) if last_seen_at else None,
            "reconciled_role": "primary",
        },
        "transcript": {
            "state": "archived" if readable_state == "closed" else "live",
            "http_status": 200,
            "reason": None,
            "durable": True,
            "searchable": True,
            "latest_offset": store.last_seq(session_id),
            "path": None,
            "source": "managed_provider_events",
            "user_message": None,
        },
        "terminal": terminal,
        "stream": stream,
        "control": control,
        "summary": {
            "primary_label": row.get("working_on") or "Structured provider session",
            "secondary_label": blocked_reason or "",
            "tone": "normal" if controllable else "muted",
            "requires_attention": row.get("turn_state") == "blocked",
            "blocks_control": not controllable,
            "selected_surface": "none",
            "degradation_codes": (
                [] if controllable else ["provider_driver_unavailable"]
            ),
            "contradiction_codes": [],
        },
        "contradictions": [],
        "degradations": [],
    }


def _truncate_utf8(text: str, limit: int) -> str:
    encoded = text.encode("utf-8", errors="replace")
    if len(encoded) <= limit:
        return text
    return encoded[:limit].decode("utf-8", errors="ignore")


def _compact_json_text(value) -> str:
    try:
        return json.dumps(value, ensure_ascii=False, separators=(",", ":"))
    except (TypeError, ValueError):
        return str(value)


def _wire_json_size(value) -> int:
    return len(json.dumps(value, separators=(",", ":")).encode("utf-8"))


def _session_event_v2_wire_row(session_key: str, row: dict) -> dict:
    payload = dict(row["payload"] or {})
    for field in ("content", "text"):
        value = payload.get(field)
        if isinstance(value, str):
            size = len(value.encode("utf-8", errors="replace"))
            if size > SESSION_EVENTS_V2_CONTENT_INLINE_MAX:
                payload[field] = _truncate_utf8(value, SESSION_EVENTS_V2_CONTENT_INLINE_MAX)
                payload[f"{field}_truncated"] = True
                payload[f"{field}_bytes"] = size
    if "input" in payload:
        input_text = _compact_json_text(payload["input"])
        input_size = len(input_text.encode("utf-8", errors="replace"))
        if input_size > SESSION_EVENTS_V2_INPUT_INLINE_MAX:
            payload["input"] = {
                "preview": _truncate_utf8(input_text, SESSION_EVENTS_V2_INPUT_INLINE_MAX),
                "truncated": True,
            }
            payload["input_truncated"] = True
            payload["input_bytes"] = input_size
    wire = {
        "schema_version": SESSION_EVENTS_V2_SCHEMA_VERSION,
        "session_key": session_key,
        "seq": row["seq"],
        "kind": row["kind"],
        "payload": payload,
        "ingested_at": row["ingested_at"],
        "emitted_at": _time.time(),
    }
    raw = row.get("raw")
    if raw is None:
        wire["raw"] = None
        if payload.get("raw_preserved") is True:
            wire["raw_elided"] = True
            wire["raw_bytes"] = max(0, int(payload.get("raw_bytes") or 0))
            if payload.get("raw_sha256"):
                wire["raw_sha256"] = str(payload["raw_sha256"])
    elif len(raw.encode("utf-8", errors="replace")) <= SESSION_EVENTS_V2_RAW_INLINE_MAX:
        wire["raw"] = raw
    else:
        # Never silently dropped: named and fetchable, the item 9 rule.
        wire["raw"] = None
        wire["raw_elided"] = True
        wire["raw_bytes"] = len(raw.encode("utf-8", errors="replace"))
    if _wire_json_size(wire) > SSE_TRANSCRIPT_MAX_EVENT_BYTES:
        full_payload_bytes = _wire_json_size(payload)
        compact_payload = {}
        for key in (
            "source_uuid", "role", "ts", "block_index", "call_id", "name",
            "is_error", "subtype", "bytes", "content_bytes", "text_bytes", "input_bytes",
        ):
            if key not in payload:
                continue
            value = payload[key]
            compact_payload[key] = _truncate_utf8(value, 2 * 1024) if isinstance(value, str) else value
        for field in ("content", "text"):
            if isinstance(payload.get(field), str):
                compact_payload[field] = _truncate_utf8(payload[field], 8 * 1024)
                compact_payload[f"{field}_truncated"] = True
        if "input" in payload:
            compact_payload["input"] = {
                "preview": _truncate_utf8(_compact_json_text(payload["input"]), 8 * 1024),
                "truncated": True,
            }
            compact_payload["input_truncated"] = True
        compact_payload["wire_payload_truncated"] = True
        compact_payload["wire_payload_bytes"] = full_payload_bytes
        wire["payload"] = compact_payload
        if wire.get("raw") is not None:
            wire["raw_bytes"] = len(str(wire["raw"]).encode("utf-8", errors="replace"))
            wire["raw"] = None
            wire["raw_elided"] = True
        if _wire_json_size(wire) > SSE_TRANSCRIPT_MAX_EVENT_BYTES:
            final_payload = {
                "source_uuid": _truncate_utf8(str(payload.get("source_uuid") or ""), 512),
                "role": _truncate_utf8(str(payload.get("role") or ""), 64),
                "call_id": _truncate_utf8(str(payload.get("call_id") or ""), 512),
                "name": _truncate_utf8(str(payload.get("name") or ""), 512),
                "wire_payload_truncated": True,
                "wire_payload_bytes": full_payload_bytes,
            }
            kind = str(row.get("kind") or "")
            if kind == "tool_call":
                final_payload["input"] = {"preview": "Input is too large for the live stream."}
                final_payload["input_truncated"] = True
                final_payload["input_bytes"] = int(payload.get("input_bytes") or full_payload_bytes)
            elif kind == "tool_result":
                final_payload["content"] = "Tool output is too large for the live stream."
                final_payload["content_truncated"] = True
                final_payload["content_bytes"] = int(payload.get("content_bytes") or full_payload_bytes)
            elif kind in ("block_text", "block_thinking", "partial_text"):
                final_payload["text"] = "Transcript content is too large for the live stream."
                final_payload["text_truncated"] = True
                final_payload["text_bytes"] = int(payload.get("text_bytes") or full_payload_bytes)
            wire["payload"] = final_payload
    return wire


def _publish_session_event(topic: str, event: dict) -> None:
    """The daemon never polls its own writes: every self-write site calls
    this at the moment it writes. Publishing must never break the write."""
    hub = SESSION_EVENT_HUB
    if hub is None:
        return
    try:
        hub.publish(topic, event)
    except Exception:
        pass


def _bounded_session_event_cursor(cursor: int, last_seq: int) -> tuple[int, dict | None]:
    cursor = max(0, int(cursor))
    last_seq = max(0, int(last_seq))
    if last_seq - cursor <= SESSION_EVENTS_V2_BACKLOG_LIMIT:
        return cursor, None
    bounded = max(0, last_seq - SESSION_EVENTS_V2_BACKLOG_LIMIT)
    return bounded, {"from_seq": cursor, "to_seq": bounded}


def _session_live_event_wait_timeout(terminal_silent_streak: int) -> float:
    """Stay eager during activity, then align wakeups with the 1s fallback."""
    return 0.25 if int(terminal_silent_streak or 0) < 3 else 1.0


# ----- Shared runtime-truth workers ----------------------------------------
# One truth probe thread per (session, expected revision), shared by every
# live stream on that session. Three viewers of one session used to run
# three identical 1 Hz probe threads; the probe is the dominant per-stream
# cost, so sharing it makes extra viewers nearly free.
_TRUTH_WORKERS_LOCK = threading.Lock()
_TRUTH_WORKERS: dict = {}
SESSION_TRUTH_KEEPER_INTERVAL_SECONDS = 10.0


def _session_event_identity_keys(handler, raw_session: str) -> set[str]:
    """Return every exact identity that may publish events for one session.

    A broker-backed session can be requested through its bootstrap id after the
    registry has promoted it to a canonical id. The broker still publishes PTY
    output under its original id, while hooks publish turn state under the
    canonical id. Subscribe to all proven identities so neither side goes deaf
    during or after that promotion.
    """
    provider, native_id = _parse_agent_session_ref(raw_session)
    if not native_id:
        return set()
    requested = _qualified_session_id(provider, native_id)
    identities = {requested}
    try:
        canonical_native_id = _agent_registry_resolve_native_alias(provider, native_id)
    except Exception:
        canonical_native_id = native_id
    canonical = _qualified_session_id(provider, canonical_native_id)
    identities.add(canonical)

    registry_row = _agent_registry_get(provider, canonical_native_id)
    durable_send_scope_id = _durable_send_scope_id_from_registry_row(
        registry_row,
        provider=provider,
        native_id=canonical_native_id,
    )
    if durable_send_scope_id:
        identities.add(durable_send_scope_id)
    durable_broker_id = _durable_broker_id_from_registry_row(
        registry_row,
        provider=provider,
        native_id=canonical_native_id,
    )
    durable_provider, durable_native_id = _parse_agent_session_ref(
        durable_broker_id or ""
    )
    if durable_provider == provider and durable_native_id:
        identities.add(_qualified_session_id(provider, durable_native_id))

    broker_lookup = getattr(handler, "_broker_session_for", None)
    if callable(broker_lookup):
        try:
            broker_found = broker_lookup(canonical)
        except Exception:
            broker_found = None
        if broker_found:
            public_id, broker_session = broker_found
            public_provider, public_native_id = _parse_agent_session_ref(str(public_id or ""))
            if public_provider == provider and public_native_id:
                identities.add(_qualified_session_id(provider, public_native_id))
            broker_id = _broker_session_id(broker_session)
            broker_provider, broker_native_id = _parse_agent_session_ref(broker_id)
            if broker_provider == provider and broker_native_id:
                identities.add(_qualified_session_id(provider, broker_native_id))
    return identities


def _session_mutation_receipt_identity(handler, raw_session: str) -> tuple[str, dict | None]:
    """Return one stable mutation scope and its exact registry row."""
    provider, native_id = _parse_agent_session_ref(raw_session)
    if not native_id:
        return "", None
    registry_row = _agent_registry_get(provider, native_id)
    if registry_row is None:
        registry_row = _agent_registry_row_for_send_scope_id(
            provider,
            _qualified_session_id(provider, native_id),
        )
    if registry_row is None:
        registry_row = _agent_registry_row_for_broker_id(
            provider,
            _qualified_session_id(provider, native_id),
        )
    canonical_native_id = str(
        (registry_row or {}).get("native_id") or native_id
    )
    durable_send_scope_id = _durable_send_scope_id_from_registry_row(
        registry_row,
        provider=provider,
        native_id=canonical_native_id,
    )
    if durable_send_scope_id:
        return durable_send_scope_id, registry_row
    durable_broker_id = _durable_broker_id_from_registry_row(
        registry_row,
        provider=provider,
        native_id=canonical_native_id,
    )
    durable_provider, durable_native_id = _parse_agent_session_ref(
        durable_broker_id or ""
    )
    if durable_provider == provider and durable_native_id:
        return _qualified_session_id(provider, durable_native_id), registry_row

    broker_lookup = getattr(handler, "_broker_session_for", None)
    if callable(broker_lookup):
        try:
            broker_found = broker_lookup(
                _qualified_session_id(provider, canonical_native_id)
            )
        except Exception:
            broker_found = None
        if broker_found:
            _public_id, broker_session = broker_found
            broker_id = _broker_session_id(broker_session)
            broker_provider, broker_native_id = _parse_agent_session_ref(broker_id)
            if broker_provider == provider and broker_native_id:
                return _qualified_session_id(provider, broker_native_id), registry_row
    return _qualified_session_id(provider, canonical_native_id), registry_row


def _session_mutation_receipt_scope(handler, raw_session: str) -> str:
    """Return one stable provider-qualified scope for a session mutation."""
    return _session_mutation_receipt_identity(handler, raw_session)[0]


def _session_truth_event_requires_probe(wake: dict | None, current_truth: dict | None) -> bool:
    """Filter noisy transcript appends from expensive terminal truth probes."""
    if not isinstance(wake, dict):
        return False
    kind = str(wake.get("type") or "")
    if kind not in {"file_changed", "file_rotated", "transcript_resolved"}:
        return True
    if kind in {"file_rotated", "transcript_resolved"}:
        return True
    transcript = (current_truth or {}).get("transcript") or {}
    current_path = str(transcript.get("path") or "")
    event_path = str(wake.get("path") or "")
    # An append on the already-known file rides the dedicated transcript tail.
    # Missing/new paths alter runtime truth and need one full reconciliation.
    return not current_path or (bool(event_path) and event_path != current_path)


def _session_truth_fast_v2_result(handler, raw_session: str, current_result):
    """Refresh terminal v2 state without rebuilding unrelated session truth.

    Broker output is the hot path. The full truth builder also resolves the
    transcript, reopens the registry several times, samples the process, and
    reads both terminal surfaces. None of that is needed to surface a newly
    rendered prompt or advance the terminal generation. Return None when the
    compact refresh cannot be proven so the worker falls back to a full probe.
    """
    if not isinstance(current_result, tuple) or len(current_result) != 3:
        return None
    current_truth, slim_truth, digest = current_result
    if not isinstance(current_truth, dict):
        return None
    try:
        v2 = handler._broker_surface_v2_snapshot(raw_session)
    except Exception:
        return None
    if not isinstance(v2, dict):
        return None
    terminal = current_truth.get("terminal")
    required_dicts = (
        current_truth.get("registry"),
        current_truth.get("turn"),
        current_truth.get("transcript"),
        current_truth.get("runtime"),
        current_truth.get("process"),
        terminal,
    )
    if not all(isinstance(value, dict) for value in required_dicts):
        return None
    stream = terminal.get("stream")
    capabilities = set(v2.get("capabilities") or [])
    if (
        not isinstance(stream, dict)
        or v2.get("source") == "unavailable"
        or not ({"cells", "text_snapshot"} & capabilities)
    ):
        return None
    # Rebuild only derived truth from cached facts and the fresh v2 surface.
    # v1 is omitted on this hot path because its cached screen is older than
    # v2 by construction and comparing them could invent a contradiction.
    refreshed_turn = dict(current_truth["turn"])
    refreshed_turn.pop("reconciled_role", None)
    refreshed_truth = _session_runtime_truth_from_parts(
        session_id=str(current_truth.get("session_id") or raw_session),
        registry=current_truth["registry"],
        turn=refreshed_turn,
        transcript=current_truth["transcript"],
        v1_surface=None,
        v2_surface=v2,
        runtime=current_truth["runtime"],
        stream=stream,
        process=current_truth["process"],
    )
    # Only the v2 surface was sampled. Preserve the full probe's timestamp so
    # terminal traffic cannot make cached registry, process, transcript, turn,
    # and runtime facts look newly verified.
    refreshed_truth["checked_at"] = current_truth.get("checked_at")
    refreshed_slim = _session_runtime_truth_stream_payload(refreshed_truth)
    refreshed_digest = _session_runtime_truth_stream_digest(refreshed_slim)
    return refreshed_truth, refreshed_slim, refreshed_digest


def _session_truth_worker_topics(handler, raw_session: str) -> tuple[set[str], set[str]]:
    identities = _session_event_identity_keys(handler, raw_session)
    # A broker disconnect or output gap invalidates every session's terminal
    # control truth. Subscribe each shared worker to that low-volume global
    # topic so it reconciles immediately instead of waiting for the keeper.
    topics = {BROKER_GLOBAL_TOPIC}
    for identity in identities:
        provider_key, native_key = _parse_agent_session_ref(identity)
        topics.update({
            f"terminal:{identity}",
            f"transcript:{identity}",
            f"turn:{identity}",
            f"turn:{provider_key}:{native_key}",
            f"approvals:{provider_key}:{native_key}",
            f"approvals:{provider_key}:{identity}",
        })
    return identities, topics


def _acquire_shared_truth_worker(handler, session_id: str, expected_source_revision) -> tuple[dict, object]:
    key = (session_id, expected_source_revision or "")
    with _TRUTH_WORKERS_LOCK:
        entry = _TRUTH_WORKERS.get(key)
        if entry is not None:
            entry["refs"] += 1
            return entry["slot"], key
        stop = threading.Event()
        slot: dict = {"result": None, "error": None, "fatal": False, "recovery_seq": 0}
        entry = {"slot": slot, "refs": 1, "stop": stop}
        _TRUTH_WORKERS[key] = entry

    def _worker() -> None:
        # Truth on the event plane: the probe fires when the session's own
        # topics fire (output, transcript, turn state, approvals) and on a
        # slow keeper for fields with no event source, instead of a fixed
        # 1 Hz clock per session. The keeper is the self-healing reconciler.
        subscription = None
        subscribed_identities: set[str] = set()
        if SESSION_EVENT_HUB is not None:
            subscribed_identities, topics = _session_truth_worker_topics(
                handler,
                session_id,
            )
            subscription = SESSION_EVENT_HUB.subscribe_many(sorted(topics))
        keeper_interval = SESSION_TRUTH_KEEPER_INTERVAL_SECONDS
        last_probe = 0.0
        try:
            while not stop.is_set():
                now = _time.time()
                debounce_remaining = max(0.0, 0.2 - (now - last_probe))
                if debounce_remaining and stop.wait(debounce_remaining):
                    return
                last_probe = _time.time()
                try:
                    truth = handler._session_runtime_truth(session_id, expected_source_revision=expected_source_revision)
                    slim = _session_runtime_truth_stream_payload(truth)
                    recovered = slot.get("error") is not None
                    slot["result"] = (truth, slim, _session_runtime_truth_stream_digest(slim))
                    slot["error"] = None
                    if recovered:
                        slot["recovery_seq"] = int(slot.get("recovery_seq") or 0) + 1
                except ValueError as e:
                    slot["error"] = ("bad_session", str(e)[:200])
                    slot["fatal"] = True
                    return
                except Exception as e:
                    slot["error"] = ("session_runtime_truth_unavailable", str(e)[:200])
                if SESSION_EVENT_HUB is not None:
                    refreshed_identities, refreshed_topics = _session_truth_worker_topics(
                        handler,
                        session_id,
                    )
                    if refreshed_identities != subscribed_identities:
                        if subscription is not None:
                            subscription.close()
                        subscription = SESSION_EVENT_HUB.subscribe_many(
                            sorted(refreshed_topics)
                        )
                        subscribed_identities = refreshed_identities
                if subscription is None:
                    stop.wait(1.0)
                    continue
                keeper_deadline = _time.monotonic() + keeper_interval
                should_probe = False
                while not stop.is_set() and _time.monotonic() < keeper_deadline:
                    remaining = max(0.0, keeper_deadline - _time.monotonic())
                    wake = subscription.get(timeout=min(2.0, remaining))
                    fast_v2_due = False
                    while wake is not None:
                        if str(wake.get("type") or "") == "broker_output":
                            fast_v2_due = True
                        elif _session_truth_event_requires_probe(wake, slot.get("result", (None,))[0] if slot.get("result") else None):
                            should_probe = True
                        wake = subscription.get(timeout=0)
                    if should_probe:
                        break
                    if fast_v2_due:
                        refreshed = _session_truth_fast_v2_result(
                            handler,
                            session_id,
                            slot.get("result"),
                        )
                        if refreshed is None:
                            should_probe = True
                            break
                        slot["result"] = refreshed
        finally:
            if subscription is not None:
                subscription.close()

    thread = threading.Thread(target=_worker, name=f"shared-truth-{session_id[:20]}", daemon=True)
    entry["thread"] = thread
    thread.start()
    return slot, key


def _release_shared_truth_worker(key) -> None:
    with _TRUTH_WORKERS_LOCK:
        entry = _TRUTH_WORKERS.get(key)
        if entry is None:
            return
        entry["refs"] -= 1
        if entry["refs"] > 0:
            return
        _TRUTH_WORKERS.pop(key, None)
    entry["stop"].set()
PTY_BROKER = PTYBrokerClient(PTY_BROKER_SOCKET, PTY_BROKER_TOKEN) if PTYBrokerClient and PTY_BROKER_TOKEN else None
_SESSION_LIVE_BROKER_TAIL_CACHE_LOCK = threading.Lock()
_SESSION_LIVE_BROKER_TAIL_CACHE: dict[tuple[int, str, int], tuple[float, object]] = {}
SESSION_LIVE_BROKER_TAIL_CACHE_TTL_SECONDS = 0.05
SESSION_LIVE_BROKER_TAIL_CACHE_LIMIT = 512


def _session_live_broker_raw_tail(broker_id: str, since: int):
    """Collapse simultaneous readers asking for the same broker byte range."""
    broker = PTY_BROKER
    if broker is None:
        return None
    key = (id(broker), str(broker_id), max(0, int(since or 0)))
    now = _time.monotonic()
    with _SESSION_LIVE_BROKER_TAIL_CACHE_LOCK:
        cached = _SESSION_LIVE_BROKER_TAIL_CACHE.get(key)
        if cached is not None and now - cached[0] <= SESSION_LIVE_BROKER_TAIL_CACHE_TTL_SECONDS:
            return cached[1]

        # Keep the broker request under the same lock. This is a short local
        # Unix-socket call and makes the cache single-flight: readers arriving
        # together cannot all miss and repeat the same request.
        tail = broker.raw_tail(str(broker_id), since=key[2])
        _SESSION_LIVE_BROKER_TAIL_CACHE[key] = (_time.monotonic(), tail)
        if len(_SESSION_LIVE_BROKER_TAIL_CACHE) > SESSION_LIVE_BROKER_TAIL_CACHE_LIMIT:
            cutoff = _time.monotonic() - SESSION_LIVE_BROKER_TAIL_CACHE_TTL_SECONDS
            stale = [
                cache_key
                for cache_key, (stored_at, _) in _SESSION_LIVE_BROKER_TAIL_CACHE.items()
                if stored_at < cutoff
            ]
            for cache_key in stale:
                _SESSION_LIVE_BROKER_TAIL_CACHE.pop(cache_key, None)
            while len(_SESSION_LIVE_BROKER_TAIL_CACHE) > SESSION_LIVE_BROKER_TAIL_CACHE_LIMIT:
                oldest = min(
                    _SESSION_LIVE_BROKER_TAIL_CACHE,
                    key=lambda cache_key: _SESSION_LIVE_BROKER_TAIL_CACHE[cache_key][0],
                )
                _SESSION_LIVE_BROKER_TAIL_CACHE.pop(oldest, None)
        return tail


APP_SUPPORT_ROOT = app_support_root() if app_support_root else Path(os.environ.get(
    "PAIRLING_APP_SUPPORT_ROOT",
    str(HOME / "Library" / "Application Support" / "Pairling"),
))
SESSION_TOMBSTONES_PATH = APP_SUPPORT_ROOT / "sessions" / "tombstones.json"
_SESSION_TOMBSTONES_LOCK = threading.RLock()
PROJECT_MIRROR_DIR = APP_SUPPORT_ROOT / "project-mirror"
PROJECT_MIRROR_STATE = PROJECT_MIRROR_DIR / "state.json"
PROJECT_MIRROR_CONFLICTS = PROJECT_MIRROR_DIR / "conflicts.json"
PROJECT_MIRROR_CONTRACT = "pairling-project-mirror-v1"

DEVICE_REGISTRY = DeviceRegistry(devices_db_path()) if DeviceRegistry and devices_db_path else None
PAIRING_STORE = (
    PairingStore(APP_SUPPORT_ROOT / "pair", DEVICE_REGISTRY, runtime_port=PORT)
    if PairingStore and DEVICE_REGISTRY
    else None
)
REAUTH_STORE = ReauthStore(DEVICE_REGISTRY) if ReauthStore and DEVICE_REGISTRY else None
_PAIRDROP_STORE_SINGLETON = None
_PAIRDROP_STORE_SINGLETON_LOCK = threading.Lock()
(
    RELAY_CLAIM_VERIFIER,
    RELAY_CLAIM_VERIFIER_ERROR,
) = _initialize_relay_claim_verifier(RelayClaimVerifier, PAIRING_STORE)

SAFETY_MONITOR = SafetyMonitorBridge(APP_SUPPORT_ROOT, HOME) if SafetyMonitorBridge else None
PUSH_DISPATCHER = (
    PairlingPushDispatcher(APP_SUPPORT_ROOT / "push-devices.json")
    if PairlingPushDispatcher
    else None
)
SENTINEL_NOTIFICATIONS = (
    SentinelNotificationCenter(APP_SUPPORT_ROOT, push_dispatcher=PUSH_DISPATCHER)
    if SentinelNotificationCenter
    else None
)
LIVE_ACTIVITY_PUBLISHER = None
STANDARD_TURN_PUSH_PUBLISHER = None
MAC_HEALTH_PUSH_PUBLISHER = None
SENTINEL_PUSH_PUBLISHER = None
FLEET_ACTIVITY_PUBLISHER = None
PUSH_DELIVERY_RETRY_WORKER = None
PUSH_DELIVERY_RETRY_INTERVAL_SECONDS = 5.0
# The sentinel session id the fleet Live Activity registers its push token
# under (mirror of FleetLiveActivityController.fleetSessionKey). The fleet
# publisher targets this key so the dispatcher resolves the fleet token.
FLEET_ACTIVITY_SESSION_ID = "fleet"


def _session_tombstone_key(provider: str, native_id: str) -> str:
    return f"{str(provider or '').strip().lower()}:{str(native_id or '').strip()}"


class SessionTombstoneStoreError(RuntimeError):
    pass


def _read_session_tombstones_unlocked() -> dict:
    try:
        payload = json.loads(SESSION_TOMBSTONES_PATH.read_text(encoding="utf-8"))
    except FileNotFoundError:
        return {"schema_version": 1, "items": {}}
    except (OSError, ValueError, json.JSONDecodeError) as error:
        raise SessionTombstoneStoreError(
            f"cannot read durable session removals: {type(error).__name__}"
        ) from error
    if not isinstance(payload, dict):
        raise SessionTombstoneStoreError("durable session removals are not a JSON object")
    items = payload.get("items") if isinstance(payload, dict) else None
    if not isinstance(items, dict):
        raise SessionTombstoneStoreError("durable session removals have no items object")
    invalid = [
        key for key, value in items.items()
        if not isinstance(key, str) or not isinstance(value, dict)
    ]
    if invalid:
        raise SessionTombstoneStoreError("durable session removals contain an invalid receipt")
    return {
        "schema_version": 1,
        "items": {str(key): dict(value) for key, value in items.items()},
    }


def _read_session_tombstones() -> dict:
    with _SESSION_TOMBSTONES_LOCK:
        return _read_session_tombstones_unlocked()


def _write_session_tombstones_unlocked(payload: dict) -> None:
    path = SESSION_TOMBSTONES_PATH
    path.parent.mkdir(parents=True, exist_ok=True)
    tmp = path.with_name(f"{path.name}.tmp.{os.getpid()}.{secrets.token_hex(4)}")
    try:
        with open(tmp, "w", encoding="utf-8") as handle:
            json.dump(payload, handle, indent=2, sort_keys=True)
            handle.write("\n")
            handle.flush()
            os.fsync(handle.fileno())
        os.chmod(tmp, 0o600)
        os.replace(tmp, path)
        try:
            directory_fd = os.open(path.parent, os.O_RDONLY)
        except OSError:
            directory_fd = None
        if directory_fd is not None:
            try:
                os.fsync(directory_fd)
            finally:
                os.close(directory_fd)
    finally:
        try:
            tmp.unlink(missing_ok=True)
        except OSError:
            pass


def _session_tombstone(provider: str, native_id: str) -> dict | None:
    key = _session_tombstone_key(provider, native_id)
    with _SESSION_TOMBSTONES_LOCK:
        item = _read_session_tombstones_unlocked().get("items", {}).get(key)
        return dict(item) if isinstance(item, dict) else None


def _clear_session_tombstone_for_reopen(provider: str, native_id: str) -> bool:
    """A new live registration must never inherit an old removal receipt."""
    key = _session_tombstone_key(provider, native_id)
    with _SESSION_TOMBSTONES_LOCK:
        payload = _read_session_tombstones_unlocked()
        if key not in payload.get("items", {}):
            return False
        payload["items"].pop(key, None)
        _write_session_tombstones_unlocked(payload)
        return True


@contextmanager
def _session_tombstone_reopen_guard():
    """Restore cleared removal receipts if the paired DB commit fails."""
    with _SESSION_TOMBSTONES_LOCK:
        originals: dict[str, dict | None] = {}

        def track(provider: str, native_id: str) -> None:
            key = _session_tombstone_key(provider, native_id)
            if key in originals:
                return
            item = _read_session_tombstones_unlocked().get("items", {}).get(key)
            originals[key] = dict(item) if isinstance(item, dict) else None

        try:
            yield track
        except Exception:
            try:
                payload = _read_session_tombstones_unlocked()
                items = payload.setdefault("items", {})
                restored = False
                for key, item in originals.items():
                    if isinstance(item, dict) and key not in items:
                        items[key] = dict(item)
                        restored = True
                if restored:
                    _write_session_tombstones_unlocked(payload)
            except Exception as restore_error:
                raise SessionTombstoneStoreError(
                    "cannot restore durable session removal after registry rollback"
                ) from restore_error
            raise


def _record_session_tombstone(
    provider: str,
    native_id: str,
    *,
    action: str,
    updates: dict | None = None,
) -> dict:
    key = _session_tombstone_key(provider, native_id)
    now = _time.time()
    with _SESSION_TOMBSTONES_LOCK:
        payload = _read_session_tombstones_unlocked()
        items = payload.setdefault("items", {})
        existing = items.get(key) if isinstance(items.get(key), dict) else {}
        item = dict(existing)
        item.update({
            "provider": provider,
            "native_id": native_id,
            "removed_at": float(item.get("removed_at") or now),
            "updated_at": now,
            "action": action,
        })
        if isinstance(updates, dict):
            item.update(updates)
        items[key] = item
        _write_session_tombstones_unlocked(payload)
        return dict(item)


def _session_tombstone_keys() -> set[str]:
    return set(_read_session_tombstones().get("items", {}))


def _session_row_identity(row: dict) -> tuple[str, str]:
    provider = str(row.get("provider") or "").strip().lower()
    native_id = str(row.get("native_id") or "").strip()
    raw_id = str(row.get("id") or "").strip()
    if not native_id and raw_id:
        parsed_provider, parsed_native = _parse_agent_session_ref(raw_id)
        provider = provider or parsed_provider
        native_id = parsed_native
    return provider or "claude", native_id


def _filter_tombstoned_session_rows(rows: list[dict]) -> list[dict]:
    try:
        tombstones = _session_tombstone_keys()
    except SessionTombstoneStoreError:
        # Do not resurrect archives whose removal state cannot be proven, but
        # do not erase live work from the dashboard either. An explicit
        # closed_at=None comes from the runtime registry and is the only state
        # strong enough to survive an unreadable removal ledger.
        return [
            row for row in rows
            if (
                "closed_at" in row
                and row.get("closed_at") is None
                and not row.get("virtual_transcript_record")
            )
        ]
    if not tombstones:
        return rows
    visible: list[dict] = []
    for row in rows:
        key = _session_tombstone_key(*_session_row_identity(row))
        if key not in tombstones:
            visible.append(row)
            continue
        # A registration reopens the row by clearing closed_at. Never let an
        # older removal receipt hide live work, even if receipt cleanup failed.
        if (
            "closed_at" in row
            and row.get("closed_at") is None
            and not row.get("virtual_transcript_record")
        ):
            visible.append(row)
    return visible


def _rollback_session_tombstone(provider: str, native_id: str, *, operation_id: str) -> bool:
    key = _session_tombstone_key(provider, native_id)
    with _SESSION_TOMBSTONES_LOCK:
        payload = _read_session_tombstones_unlocked()
        item = payload.get("items", {}).get(key)
        if not isinstance(item, dict) or item.get("operation_id") != operation_id:
            return False
        previous = item.get("rollback_receipt")
        if isinstance(previous, dict):
            payload["items"][key] = previous
        else:
            payload["items"].pop(key, None)
        _write_session_tombstones_unlocked(payload)
        return True


def _session_transcript_delete_is_pending_or_done(provider: str, native_id: str) -> bool:
    try:
        item = _session_tombstone(provider, native_id)
    except SessionTombstoneStoreError:
        return True
    return bool(item and item.get("action") in {"delete_pending", "transcript_deleted"})


def _stable_sessions_stream_rows(rows: list[dict]) -> list[dict]:
    stable_rows: list[dict] = []
    for row in rows:
        stable_row = {
            key: value for key, value in row.items() if key != "stale_seconds"
        }
        native_id = str(row.get("native_id") or "")
        if row.get("provider") == "codex" and native_id.startswith("terminal-"):
            # The terminal scanner renews this placeholder's registry lease on
            # every safety pass. That proves the same process is still alive;
            # it is not a provider turn and must not reorder the dashboard or
            # wake every sessions stream. Canonical Codex rows retain their
            # heartbeat in the digest, and every other placeholder field still
            # participates in change detection.
            stable_row.pop("last_heartbeat", None)
        stable_rows.append(stable_row)
    return stable_rows


def _invalidate_session_list_caches() -> None:
    global _runtime_snapshot_cache_generation
    with _runtime_snapshot_cache_lock:
        _runtime_snapshot_cache_generation += 1
        _record_runtime_snapshot_invalidation_for_current_thread()
        _runtime_snapshot_cache.clear()
    _SESSION_TRANSCRIPT_STATS_CACHE.clear()
    _clear_codex_rollout_caches()
    # A loader can begin after the first generation change but before the
    # dependent transcript caches finish clearing. Advance the generation
    # again so that loader cannot publish data derived from the old inputs.
    with _runtime_snapshot_cache_lock:
        _runtime_snapshot_cache_generation += 1
        _record_runtime_snapshot_invalidation_for_current_thread()
        _runtime_snapshot_cache.clear()


def _broker_value(session, key: str, default=None):
    if isinstance(session, dict):
        value = session.get(key, default)
        return default if value is None else value
    return getattr(session, key, default)


def _broker_session_id(session) -> str:
    return str(_broker_value(session, "session_id", "") or "")


def _broker_slave_tty(session) -> str:
    return str(_broker_value(session, "slave_tty", "") or "")


def _broker_pid(session) -> int:
    try:
        return int(_broker_value(session, "pid", 0) or 0)
    except Exception:
        return 0


def _broker_session_matches_spawn_request(
    session,
    *,
    broker_id: str,
    provider: str,
    native_id: str,
) -> bool:
    """Verify the broker result before its durable registry row exists."""
    return bool(
        broker_id
        and provider
        and native_id
        and _broker_session_id(session) == broker_id
        and str(_broker_value(session, "provider", "") or "").lower() == provider
        and str(_broker_value(session, "native_id", "") or "") == native_id
    )


def _broker_spawn_provider_identity(
    session,
    *,
    broker_id: str,
    provider: str,
    native_id: str,
    project: str,
    timeout: float = 10.0,
) -> dict | None:
    """Prove a live provider process before publishing a broker launch."""
    if not _broker_session_matches_spawn_request(
        session,
        broker_id=broker_id,
        provider=provider,
        native_id=native_id,
    ):
        return None
    current_session = session

    def current_liveness() -> str:
        liveness_probe = getattr(current_session, "ownership_liveness", None)
        if callable(liveness_probe):
            return str(liveness_probe() or "")
        liveness = str(_broker_value(current_session, "liveness", "") or "")
        if liveness:
            return liveness
        alive = _broker_value(current_session, "alive", None)
        return "alive" if alive is True else ("gone" if alive is False else "")

    if current_liveness() != "alive":
        return None
    broker_pid = _broker_pid(current_session)
    broker_tty = _broker_slave_tty(current_session)
    if broker_pid <= 0 or not broker_tty:
        return None
    canonical_project = os.path.realpath(project)
    deadline = _time.monotonic() + max(0.0, timeout)
    while True:
        probe_ok, rows = _scan_provider_process_rows(provider)
        if probe_ok:
            matches = [
                row for row in rows
                if str(row.get("tty") or "") == broker_tty
                and os.path.realpath(str(row.get("project") or "")) == canonical_project
                and _process_is_descendant_of(
                    int(row.get("pid") or 0),
                    broker_pid,
                )
            ]
            match_pids = {
                int(row.get("pid") or 0)
                for row in matches
                if int(row.get("pid") or 0) > 0
            }
            roots = [
                row for row in matches
                if not any(
                    other_pid != int(row.get("pid") or 0)
                    and _process_is_descendant_of(
                        int(row.get("pid") or 0), other_pid
                    )
                    for other_pid in match_pids
                )
            ]
            if len(roots) == 1:
                return roots[0]
        if _time.monotonic() >= deadline:
            return None
        try:
            refreshed = (
                PTY_BROKER.get(broker_id)
                if PTY_BROKER is not None
                else None
            )
        except Exception:
            return None
        if refreshed is None or not _broker_session_matches_spawn_request(
            refreshed,
            broker_id=broker_id,
            provider=provider,
            native_id=native_id,
        ):
            return None
        current_session = refreshed
        if current_liveness() != "alive":
            return None
        _time.sleep(0.05)


def _terminate_fresh_broker_or_raise_unknown(
    broker_id: str,
    *,
    context: str,
) -> None:
    """Require confirmed cleanup when a fresh broker launch cannot publish."""
    try:
        result = (
            PTY_BROKER.terminate(broker_id)
            if PTY_BROKER is not None
            else None
        )
    except Exception as error:
        raise PTYBrokerOutcomeUnknownError(
            f"{context}; broker cleanup failed: "
            f"{type(error).__name__}: {str(error)[:120]}"
        ) from error
    if not isinstance(result, dict) or not result.get("ok"):
        raise PTYBrokerOutcomeUnknownError(
            f"{context}; broker cleanup could not be confirmed"
        )


def _broker_session_owns_identity(session, provider: str, native_id: str) -> bool:
    """Prove that a broker session is owned by the requested provider session."""
    broker_id = _broker_session_id(session)
    if not broker_id:
        return False
    session_provider = str(_broker_value(session, "provider", "") or "").lower()
    session_native_id = str(_broker_value(session, "native_id", "") or "")
    canonical_native_id = _agent_registry_resolve_native_alias(provider, native_id)
    row = _agent_registry_get(provider, canonical_native_id)
    if row is None or row.get("closed_at") is not None:
        return False
    metadata = _registry_metadata_from_row(row)
    durable_broker_id = str(metadata.get("broker_id") or "")
    durable_native_ids = {
        str(value or "")
        for value in (
            native_id,
            canonical_native_id,
            row.get("native_id"),
            metadata.get("broker_native_id"),
            metadata.get("pending_native_id"),
        )
        if str(value or "")
    }
    return bool(
        durable_broker_id
        and durable_broker_id == broker_id
        and session_provider == provider
        and session_native_id in durable_native_ids
    )


def _registry_owned_broker_session(
    provider: str,
    native_id: str,
    row: dict | None = None,
):
    """Return the live broker session proven by one durable registry row."""
    if PTY_BROKER is None:
        return None
    row = row or _agent_registry_get(provider, native_id)
    if row is None or row.get("closed_at") is not None:
        return None
    broker_id = str(
        _registry_metadata_from_row(row).get("broker_id") or ""
    ).strip()
    if not broker_id:
        return None
    try:
        session = PTY_BROKER.get(broker_id)
    except Exception:
        return None
    return (
        session
        if session is not None
        and _broker_session_owns_identity(session, provider, native_id)
        else None
    )


def _broker_interrupt_for_draining_runtime(broker_id: str) -> dict:
    """Allow exact Ctrl+C only while a same-Mac previous-runtime PTY drains."""
    if PTY_BROKER is None:
        return {"ok": False, "reason": "broker unavailable", "status": 503}
    if _broker_runtime_relation() not in {"current", "stale_deferred"}:
        return {
            "ok": False,
            "reason": "broker runtime identity is not verified",
            "error_code": "broker_runtime_identity_unverified",
            "status": 409,
            "pty_written": False,
            "write_outcome": "none",
        }
    try:
        return PTY_BROKER.interrupt(broker_id)
    except RuntimeError as exc:
        message = str(exc).strip().lower()
        drain_rpc_missing = (
            message == "unknown broker op: interrupt"
            or message == "unsupported broker op: interrupt"
            or message == "unsupported op: interrupt"
        )
        if not drain_rpc_missing:
            raise
        return PTY_BROKER.control(
            broker_id,
            {"type": "key", "key": "ctrl_c"},
        )


def _broker_atomic_control_context(
    pair: dict | None,
    *,
    broker_id: str = "",
) -> dict | None:
    """Validate the current broker's atomic v1/v2 control contract."""
    if not isinstance(pair, dict):
        return None
    v1 = pair.get("v1")
    v2 = pair.get("v2")
    control_proof = pair.get("control_proof")
    if not all(isinstance(value, dict) for value in (v1, v2, control_proof)):
        return None
    generations = [
        v1.get("generation"),
        v2.get("generation"),
        control_proof.get("generation"),
    ]
    if not all(isinstance(value, int) and not isinstance(value, bool) for value in generations):
        return None
    if len(set(generations)) != 1:
        return None
    if type(v2.get("schema_version")) is not int or v2.get("schema_version") != 2:
        return None
    if v2.get("source") != "broker_vt" or v2.get("backend") != "pty_broker":
        return None
    capabilities = v2.get("capabilities")
    if not isinstance(capabilities, list) or "control_receipts" not in capabilities:
        return None
    for value in (v2, control_proof):
        if not str(value.get("screen_hash") or "").strip():
            return None
        if not str(value.get("nonce") or "").strip():
            return None
    proof_session_id = str(control_proof.get("session_id") or "").strip()
    if not proof_session_id or (broker_id and proof_session_id != broker_id):
        return None
    return {
        "v1": v1,
        "v2": v2,
        "control_proof": control_proof,
        "broker_id": proof_session_id,
    }


CURRENT_PTY_BROKER_PROTOCOL_VERSION = 2
CURRENT_PTY_BROKER_CODE_VERSION = "pty-broker-v2"


def _broker_runtime_relation(status_override: dict | None = None) -> str:
    """Classify the live broker against this exact verified runtime."""
    if (
        PTY_BROKER is None
        or not hasattr(PTY_BROKER, "status")
        or _classify_ptybroker_identity is None
    ):
        return "incompatible"
    if status_override is None:
        try:
            status = PTY_BROKER.status()
        except Exception:
            return "incompatible"
    else:
        status = status_override
    status_key = tuple(
        status.get(key) if isinstance(status, dict) else None
        for key in (
            "pid",
            "runtime_root",
            "script_path",
            "source_revision",
            "protocol_version",
            "code_version",
            "script_sha256",
            "payload_sha256",
            "live_session_count",
            "restart_blocker_count",
        )
    )
    now = _time.monotonic()
    with _BROKER_RUNTIME_RELATION_CACHE_LOCK:
        if (
            _BROKER_RUNTIME_RELATION_CACHE["status_key"] == status_key
            and now - float(_BROKER_RUNTIME_RELATION_CACHE["checked_at"] or 0)
            <= BROKER_RUNTIME_RELATION_CACHE_SECONDS
        ):
            return str(_BROKER_RUNTIME_RELATION_CACHE["relation"])
    runtime_info = _runtime_info_snapshot()
    install_root = str(runtime_info.get("install_root") or "").strip()
    source_revision = str(runtime_info.get("source_revision") or "").strip()
    if (
        not bool(runtime_info.get("verified"))
        or runtime_info.get("source_dirty") is not False
        or not install_root
        or not source_revision
    ):
        relation = "incompatible"
        with _BROKER_RUNTIME_RELATION_CACHE_LOCK:
            _BROKER_RUNTIME_RELATION_CACHE.update(
                status_key=status_key,
                checked_at=now,
                relation=relation,
            )
        return relation
    runtime_root = os.path.realpath(install_root)
    desired = {
        "runtime_root": runtime_root,
        "script_path": os.path.realpath(
            os.path.join(runtime_root, "companiond", "pty_broker_service.py")
        ),
        "source_revision": source_revision,
        "protocol_version": CURRENT_PTY_BROKER_PROTOCOL_VERSION,
        "code_version": CURRENT_PTY_BROKER_CODE_VERSION,
        "payload_sha256": (
            _ptybroker_payload_sha256(runtime_root)
            if _ptybroker_payload_sha256 is not None
            else None
        ),
    }
    try:
        relation, _reasons = _classify_ptybroker_identity(status, desired)
    except Exception:
        relation = "incompatible"
    if relation not in {"current", "stale_deferred"}:
        relation = "incompatible"
    with _BROKER_RUNTIME_RELATION_CACHE_LOCK:
        _BROKER_RUNTIME_RELATION_CACHE.update(
            status_key=status_key,
            checked_at=now,
            relation=relation,
        )
    return relation


def _broker_is_current_runtime() -> bool:
    return _broker_runtime_relation() == "current"


def _broker_supports_current_atomic_control(
    broker_relation: str | None = None,
) -> bool:
    """Return true only for the broker contract used by mutating endpoints."""
    return bool(
        PTY_BROKER is not None
        and (broker_relation or _broker_runtime_relation()) == "current"
        and hasattr(PTY_BROKER, "snapshot_pair")
        and hasattr(PTY_BROKER, "control")
        and hasattr(PTY_BROKER, "send_text")
        and hasattr(PTY_BROKER, "terminate")
    )


def _broker_reconcile_session_after_unknown(
    broker_id: str,
    *,
    provider: str,
    native_id: str,
    timeout_seconds: float = 2.0,
):
    deadline = _time.monotonic() + max(0.0, timeout_seconds)
    while True:
        try:
            session = PTY_BROKER.get(broker_id) if PTY_BROKER is not None else None
        except Exception:
            session = None
        if session is not None and _broker_session_matches_spawn_request(
            session,
            broker_id=broker_id,
            provider=provider,
            native_id=native_id,
        ):
            return session
        if _time.monotonic() >= deadline:
            return None
        _time.sleep(0.05)


def _broker_atomic_control_context_for_id(
    broker_id: str,
    *,
    public_session_id: str = "",
) -> dict | None:
    if (
        PTY_BROKER is None
        or not broker_id
        or not hasattr(PTY_BROKER, "snapshot_pair")
        or not _broker_is_current_runtime()
    ):
        return None
    try:
        pair = PTY_BROKER.snapshot_pair(
            broker_id,
            public_session_id=public_session_id or broker_id,
        )
    except Exception:
        return None
    return _broker_atomic_control_context(pair, broker_id=broker_id)


def _broker_send_text_with_truth(
    broker_id: str,
    text: str,
    *,
    public_session_id: str,
) -> tuple[dict, int | None, str | None]:
    """Send through a current broker and preserve exact write outcome truth."""
    if not _broker_is_current_runtime():
        return ({
            "ok": False,
            "reason": "broker_requires_current_runtime",
            "error_code": "broker_requires_current_runtime",
            "status": 409,
            "pty_written": False,
            "write_outcome": "none",
            "outcome_indeterminate": False,
        }, None, "broker_read_only")
    if _broker_atomic_control_context_for_id(
        broker_id,
        public_session_id=public_session_id,
    ) is None:
        return ({
            "ok": False,
            "reason": "broker_atomic_control_unavailable",
            "error_code": "broker_atomic_control_unavailable",
            "status": 409,
            "pty_written": False,
            "write_outcome": "none",
            "outcome_indeterminate": False,
        }, None, "broker_atomic_control_unavailable")
    try:
        result = PTY_BROKER.send_text(broker_id, text)
    except PTYBrokerOutcomeUnknownError as exc:
        return ({
            "ok": False,
            "reason": "broker_apply_outcome_unknown",
            "error_code": "broker_apply_outcome_unknown",
            "error": f"{type(exc).__name__}: {str(exc)[:160]}",
            "status": 502,
            "pty_written": None,
            "write_outcome": "unknown",
            "outcome_indeterminate": True,
        }, None, "broker_response_lost")
    except Exception as exc:
        return ({
            "ok": False,
            "reason": "broker_unavailable",
            "error_code": "broker_unavailable",
            "error": f"{type(exc).__name__}: {str(exc)[:160]}",
            "status": 503,
            "pty_written": False,
            "write_outcome": "none",
            "outcome_indeterminate": False,
        }, None, "broker_unavailable")
    if not isinstance(result, dict):
        result = {
            "ok": False,
            "reason": "invalid_broker_response",
            "error_code": "invalid_broker_response",
            "status": 502,
            "pty_written": None,
            "write_outcome": "unknown",
            "outcome_indeterminate": True,
        }
    source_offset_after = None
    source_offset_reason = None
    if result.get("ok"):
        try:
            tail = PTY_BROKER.raw_tail(broker_id, since=0)
        except Exception as exc:
            tail = None
            source_offset_reason = f"raw_tail_unavailable:{type(exc).__name__}"
        if tail:
            source_offset_after = tail[1]
        elif source_offset_reason is None:
            source_offset_reason = "no_broker_log"
    return result, source_offset_after, source_offset_reason


def _broker_raw_log_path(session) -> Path | None:
    raw = _broker_value(session, "raw_log_path", None)
    if isinstance(raw, Path):
        return raw
    if raw:
        return Path(str(raw))
    return None

def _ensure_handoff_storage_directory() -> None:
    """Create handoff storage without following any path component symlink."""
    for path in (COMPANION_DIR, HANDOFFS_DIR):
        directory_fd = ensure_directory_fd(path, root=HOME, mode=0o700)
        os.close(directory_fd)


QUEUE_DIR.mkdir(parents=True, exist_ok=True)
ORCHESTRATIONS_DIR.mkdir(parents=True, exist_ok=True)
_ensure_handoff_storage_directory()
ORCHESTRATIONS_DIR.chmod(0o700)
CROSS_PROVIDER_DIR.mkdir(parents=True, exist_ok=True)
TURN_STATE_DIR.mkdir(parents=True, exist_ok=True)
TERMINAL_CAPTURE_DIR.mkdir(parents=True, exist_ok=True)
TERMINAL_CAPTURE_MAP_DIR.mkdir(parents=True, exist_ok=True)


def _bind_host() -> str:
    """Keep the credential-bearing runtime behind the local connectd gateway."""
    return "127.0.0.1"

# Simple per-session rate limit for exact terminal mutations.
# Threshold: one mutation per session per second. Bursts of five per second across all
# sessions. Mitigates RCE blast radius if token leaks.
import threading
import time as _time

BROKER_RUNTIME_RELATION_CACHE_SECONDS = 0.5
_BROKER_RUNTIME_RELATION_CACHE_LOCK = threading.Lock()
_BROKER_RUNTIME_RELATION_CACHE = {
    "status_key": None,
    "checked_at": 0.0,
    "relation": "incompatible",
}
_PTYBROKER_HANDOVER_WORKER_LOCK = threading.Lock()
_PTYBROKER_HANDOVER_WORKER: threading.Thread | None = None


def _ptybroker_restart_blocker_count(status: dict) -> int | None:
    raw = status.get("restart_blocker_count")
    if type(raw) is not int or raw < 0:
        return None
    return raw


def _ptybroker_handover_command(expected_pid: int) -> list[str] | None:
    runtime_info = _runtime_info_snapshot()
    if not runtime_info.get("verified"):
        return None
    release_root = _DAEMON_SCRIPT_PATH.parent.parent
    reported_root = str(runtime_info.get("install_root") or "").strip()
    if not reported_root or os.path.realpath(reported_root) != str(release_root):
        return None
    installer = release_root / "mac" / "install" / "install-runtime.sh"
    try:
        if installer.is_symlink() or not installer.is_file():
            return None
    except OSError:
        return None
    if not os.access(installer, os.X_OK):
        return None
    return [
        str(installer),
        "reconcile-ptybroker",
        "--expected-pid",
        str(expected_pid),
    ]


def _run_ptybroker_handover_reconciler(
    *,
    sleep_fn=None,
    run_fn=None,
    max_checks: int | None = None,
) -> str:
    """Replace one exact previous-runtime broker after its PTYs drain."""
    sleep_fn = sleep_fn or _time.sleep
    run_fn = run_fn or subprocess.run
    observed_zero_pid = 0
    zero_samples = 0
    checks = 0
    while max_checks is None or checks < max_checks:
        checks += 1
        if PTY_BROKER is None:
            return "incompatible"
        try:
            status = PTY_BROKER.status()
        except Exception:
            observed_zero_pid = 0
            zero_samples = 0
            sleep_fn(1.0)
            continue
        relation = _broker_runtime_relation(status)
        if relation == "current":
            return "current"
        if relation != "stale_deferred":
            return "incompatible"
        pid = status.get("pid") if isinstance(status, dict) else None
        blockers = (
            _ptybroker_restart_blocker_count(status)
            if isinstance(status, dict)
            else None
        )
        if type(pid) is not int or pid <= 0 or blockers is None:
            return "incompatible"
        if blockers != 0:
            observed_zero_pid = 0
            zero_samples = 0
            sleep_fn(1.0)
            continue
        if pid == observed_zero_pid:
            zero_samples += 1
        else:
            observed_zero_pid = pid
            zero_samples = 1
        if zero_samples < 2:
            sleep_fn(0.5)
            continue

        command = _ptybroker_handover_command(pid)
        if command is None:
            return "runtime_unverified"
        try:
            completed = run_fn(
                command,
                capture_output=True,
                text=True,
                timeout=90,
            )
        except (OSError, subprocess.SubprocessError):
            completed = None
        observed_zero_pid = 0
        zero_samples = 0
        with _BROKER_RUNTIME_RELATION_CACHE_LOCK:
            _BROKER_RUNTIME_RELATION_CACHE.update(
                status_key=None,
                checked_at=0.0,
                relation="incompatible",
            )
        if completed is not None and completed.returncode == 0:
            sleep_fn(0.25)
            continue
        detail = str(getattr(completed, "stderr", "") or "")[-500:]
        print(
            f"[broker-handover] reconcile retry required: {detail or 'installer unavailable'}",
            file=sys.stderr,
            flush=True,
        )
        sleep_fn(2.0)
    return "deferred"


def _start_ptybroker_handover_reconciler() -> threading.Thread | None:
    global _PTYBROKER_HANDOVER_WORKER
    if PTY_BROKER is None:
        return None
    with _PTYBROKER_HANDOVER_WORKER_LOCK:
        if (
            _PTYBROKER_HANDOVER_WORKER is not None
            and _PTYBROKER_HANDOVER_WORKER.is_alive()
        ):
            return _PTYBROKER_HANDOVER_WORKER
        worker = threading.Thread(
            target=_run_ptybroker_handover_reconciler,
            name="pairling-ptybroker-handover",
            daemon=True,
        )
        _PTYBROKER_HANDOVER_WORKER = worker
        worker.start()
        return worker

_inject_rate_lock = threading.Lock()
_inject_rate_state: dict[str, list[float]] = {}  # session_id -> [timestamps]
_request_rate_lock = threading.Lock()
_request_rate_state: dict[str, list[float]] = {}
_REQUEST_RATE_MAX_KEYS = 4096
_pairing_rate_lock = threading.Lock()
_pairing_rate_state: dict[str, list[float]] = {}
_PAIRING_RATE_MAX_KEYS = 1024
_invalid_proof_rate_lock = threading.Lock()
_invalid_proof_rate_state: dict[str, list[float]] = {}
_INVALID_PROOF_RATE_MAX_KEYS = 1024
_INJECT_RATE_MAX_KEYS = 4096
PAIRDROP_REQUEST_PROOF_CHUNK_BYTES = 512 * 1024
REQUEST_PROOF_TRANSFER_FLOOR_BYTES = 4 * 1024 * 1024 * 1024
REQUEST_PROOF_CACHE_MAX_ENTRIES = 131_072
REQUEST_PROOF_CACHE_MAX_ENTRIES_PER_DEVICE = 16_384
REQUEST_PROOF_CACHE_PATH = APP_SUPPORT_ROOT / "request-proofs.sqlite"
_proof_replay_cache = (
    ReplayCache(
        database_path=REQUEST_PROOF_CACHE_PATH,
        max_entries=REQUEST_PROOF_CACHE_MAX_ENTRIES,
        max_entries_per_device=REQUEST_PROOF_CACHE_MAX_ENTRIES_PER_DEVICE,
    )
    if ReplayCache is not None
    else None
)
SSE_MAX_EVENT_BYTES = 64 * 1024
SSE_TRANSCRIPT_MAX_EVENT_BYTES = 256 * 1024
SSE_TERMINAL_CHUNK_BYTES = 48 * 1024
SSE_SURFACE_CHUNK_BYTES = 32 * 1024
SSE_SURFACE_MAX_TRANSFER_BYTES = 32 * 1024 * 1024
TRANSCRIPT_INITIAL_STREAM_BYTES = 900_000
# Upper bound for the /transcript exact-range mode (max_bytes param), sized to
# admit multi-megabyte tool-result lines without opening an unbounded read.
TRANSCRIPT_RANGE_FETCH_MAX_BYTES = 8 * 1024 * 1024
TRANSCRIPT_TAIL_SCAN_BYTES = 512 * 1024
CODEX_ROLLOUT_META_SCAN_BYTES = 2 * 1024 * 1024
TRANSCRIPT_STATS_MAX_SCAN_BYTES = 512 * 1024
RUNTIME_SNAPSHOT_CACHE_SECONDS = 2.0
PROVIDER_STATUS_CACHE_SECONDS = 8.0
FILESYSTEM_DIRECTORIES_CACHE_SECONDS = 2.0
RECENT_PROJECTS_CACHE_SECONDS = 5.0
CODEX_ROLLOUT_PATHS_CACHE_SECONDS = 5.0
AUTH_RESULT_CACHE_SECONDS = max(0.0, float(os.environ.get("PAIRLING_AUTH_RESULT_CACHE_SECONDS", "1.0")))
AUTH_RESULT_CACHE_MAX = max(16, int(os.environ.get("PAIRLING_AUTH_RESULT_CACHE_MAX", "512")))
RUNTIME_MAX_ACTIVE_FAST_REQUESTS = max(2, int(os.environ.get("PAIRLING_RUNTIME_MAX_ACTIVE_FAST_REQUESTS", "4")))
RUNTIME_MAX_ACTIVE_REQUESTS = max(4, int(os.environ.get("PAIRLING_RUNTIME_MAX_ACTIVE_REQUESTS", "12")))
RUNTIME_MAX_ACTIVE_UPLOADS = max(1, int(os.environ.get("PAIRLING_RUNTIME_MAX_ACTIVE_UPLOADS", "2")))
RUNTIME_MAX_ACTIVE_DASHBOARD_STREAMS = max(2, int(os.environ.get("PAIRLING_RUNTIME_MAX_ACTIVE_DASHBOARD_STREAMS", "8")))
# Default raised 6 -> 24 with load-test evidence (mac/tools/stream_load_test.py,
# 2026-07-06): 24 concurrent live-events streams across 8 busy sessions held
# append-to-delivery p95 at 17.5 ms with zero admission refusals once streams
# became event-driven and truth probes became per-session instead of
# per-connection. The env override and 503 shedding remain the safety valve.
RUNTIME_MAX_ACTIVE_STREAMS = max(2, int(os.environ.get(
    "PAIRLING_RUNTIME_MAX_ACTIVE_DETAIL_STREAMS",
    os.environ.get("PAIRLING_RUNTIME_MAX_ACTIVE_STREAMS", "24"),
)))
RUNTIME_MAX_ACTIVE_AUX_STREAMS = max(2, int(os.environ.get("PAIRLING_RUNTIME_MAX_ACTIVE_AUX_STREAMS", "4")))
RUNTIME_MAX_ACTIVE_CONNECTIONS = max(
    (
        RUNTIME_MAX_ACTIVE_FAST_REQUESTS
        + RUNTIME_MAX_ACTIVE_REQUESTS
        + RUNTIME_MAX_ACTIVE_DASHBOARD_STREAMS
        + RUNTIME_MAX_ACTIVE_STREAMS
        + RUNTIME_MAX_ACTIVE_AUX_STREAMS
        + RUNTIME_MAX_ACTIVE_UPLOADS
    ),
    int(os.environ.get("PAIRLING_RUNTIME_MAX_ACTIVE_CONNECTIONS", "28")),
)
TERMINAL_APP_SNAPSHOT_TIMEOUT_SECONDS = max(
    0.5,
    min(5.0, float(os.environ.get("PAIRLING_TERMINAL_APP_SNAPSHOT_TIMEOUT_SECONDS", "3.0"))),
)
TERMINAL_SURFACE_V2_NONCE_SALT = os.urandom(16).hex()
LAST_HUMAN_ACTIVITY_AT = 0.0
DAEMON_STARTED_AT = _time.time()
BOUND_HOST = ""
DAEMON_VERSION = "2026-05-07"

_sessions_health_lock = threading.Lock()
_sessions_health: dict[str, object] = {
    "last_scan_at": 0.0,
    "last_snapshot_count": 0,
    "inventory_state": "cold",
    "inventory_checked_at": 0.0,
}


def _sse_json_event(event: str, payload: dict, *, max_bytes: int = SSE_MAX_EVENT_BYTES) -> tuple[bytes, dict | None]:
    data = json.dumps(payload, separators=(",", ":")).encode("utf-8")
    if len(data) <= max_bytes:
        return b"event: " + event.encode("utf-8") + b"\ndata: " + data + b"\n\n", None
    diagnostic = {
        "ok": False,
        "reason": "event_too_large",
        "event": event,
        "max_event_bytes": max_bytes,
        "actual_event_bytes": len(data),
    }
    diag = json.dumps(diagnostic, separators=(",", ":")).encode("utf-8")
    return b"event: error\ndata: " + diag[:max_bytes] + b"\n\n", diagnostic


def _sse_write_json_event(wfile, event: str, payload: dict, *, max_bytes: int = SSE_MAX_EVENT_BYTES, stats_key: str | None = None) -> bool:
    body, diagnostic = _sse_json_event(event, payload, max_bytes=max_bytes)
    try:
        wfile.write(body)
        wfile.flush()
        if stats_key is not None and diagnostic is None:
            _stream_stats_record(stats_key, len(body), payload)
        return diagnostic is None
    except (BrokenPipeError, ConnectionResetError, ValueError):
        # Buffered writers raise ValueError after their socket has closed.
        # Treat it like the other normal client-disconnect signals.
        return False


def _sse_write_chunked_json_event(
    wfile,
    event: str,
    payload: dict,
    *,
    stats_key: str | None = None,
) -> bool:
    encoded = json.dumps(payload, separators=(",", ":")).encode("utf-8")
    if len(encoded) > SSE_SURFACE_MAX_TRANSFER_BYTES:
        return _sse_write_json_event(
            wfile,
            "error",
            {
                "reason": "surface_transfer_too_large",
                "message": "The terminal frame exceeded Pairling's bounded transfer limit.",
                "actual_bytes": len(encoded),
                "max_bytes": SSE_SURFACE_MAX_TRANSFER_BYTES,
                "retryable": True,
            },
        ) and False
    digest = hashlib.sha256(encoded).hexdigest()
    transfer_id = f"surface-{digest[:24]}"
    chunks = [
        encoded[index:index + SSE_SURFACE_CHUNK_BYTES]
        for index in range(0, len(encoded), SSE_SURFACE_CHUNK_BYTES)
    ] or [b""]
    if not _sse_write_json_event(
        wfile,
        "surface_begin",
        {
            "transfer_id": transfer_id,
            "surface_event": event,
            "total_bytes": len(encoded),
            "sha256": digest,
            "chunk_count": len(chunks),
        },
    ):
        return False
    for index, chunk in enumerate(chunks):
        if not _sse_write_json_event(
            wfile,
            "surface_chunk",
            {
                "transfer_id": transfer_id,
                "index": index,
                "b64": base64.b64encode(chunk).decode("ascii"),
            },
        ):
            return False
    if not _sse_write_json_event(
        wfile,
        "surface_end",
        {"transfer_id": transfer_id},
    ):
        return False
    if stats_key is not None:
        _stream_stats_record(stats_key, len(encoded), payload)
    return True


# ----- Stream instrumentation (Phase 0 of the session viewer evolution) -----
# Counts and lag are daemon-side truths on one wall clock. observed_at is when
# the daemon noticed the state; emitted_at is when the event hit the wire. The
# delta is the daemon's internal delivery lag, which the poll-to-wakeup work
# is expected to shrink; cross-device latency is measured client-side.
_STREAM_STATS_LOCK = threading.Lock()
_STREAM_STATS: dict[str, dict] = {}
_STREAM_EMIT_LAG_MS: list = []
_STREAM_EMIT_LAG_MAX_SAMPLES = 2048
_STREAM_STATS_STARTED_AT = _time.time()


def _stream_stats_record(event_type: str, byte_count: int, payload: dict) -> None:
    # The lag origin prefers the source arrival time (broker feed_at inside
    # the event payload) over observed_at, because observed_at is stamped at
    # envelope build and hides the poll wait in front of it.
    inner = payload.get("payload") if isinstance(payload.get("payload"), dict) else {}
    origin = inner.get("feed_at") if isinstance(inner.get("feed_at"), (int, float)) else payload.get("observed_at")
    emitted = payload.get("emitted_at")
    lag_ms = None
    if isinstance(origin, (int, float)) and isinstance(emitted, (int, float)):
        lag_ms = max(0.0, (float(emitted) - float(origin)) * 1000.0)
    with _STREAM_STATS_LOCK:
        row = _STREAM_STATS.setdefault(str(event_type), {"events": 0, "bytes": 0})
        row["events"] += 1
        row["bytes"] += max(0, int(byte_count))
        if lag_ms is not None:
            _STREAM_EMIT_LAG_MS.append(lag_ms)
            if len(_STREAM_EMIT_LAG_MS) > _STREAM_EMIT_LAG_MAX_SAMPLES:
                del _STREAM_EMIT_LAG_MS[:_STREAM_EMIT_LAG_MAX_SAMPLES // 2]


def _stream_stats_reset() -> None:
    global _STREAM_STATS_STARTED_AT
    with _STREAM_STATS_LOCK:
        _STREAM_STATS.clear()
        _STREAM_EMIT_LAG_MS.clear()
        _STREAM_STATS_STARTED_AT = _time.time()


def _lag_percentile(sorted_values: list, fraction: float) -> float | None:
    if not sorted_values:
        return None
    index = min(len(sorted_values) - 1, max(0, int(round(fraction * (len(sorted_values) - 1)))))
    return round(sorted_values[index], 3)


def _semaphore_active(semaphore, limit: int) -> int | None:
    value = getattr(semaphore, "_value", None)
    if not isinstance(value, int):
        return None
    return max(0, limit - value)


def _stream_stats_snapshot() -> dict:
    with _STREAM_STATS_LOCK:
        by_event_type = {key: dict(row) for key, row in _STREAM_STATS.items()}
        lags = sorted(_STREAM_EMIT_LAG_MS)
        started_at = _STREAM_STATS_STARTED_AT
    return {
        "started_at": started_at,
        "by_event_type": by_event_type,
        "emit_lag_ms": {
            "p50": _lag_percentile(lags, 0.50),
            "p95": _lag_percentile(lags, 0.95),
            "samples": len(lags),
        },
        "active_streams": {
            "session": _semaphore_active(_STREAM_ADMISSION_SEMAPHORE, RUNTIME_MAX_ACTIVE_STREAMS),
            "dashboard": _semaphore_active(_DASHBOARD_STREAM_ADMISSION_SEMAPHORE, RUNTIME_MAX_ACTIVE_DASHBOARD_STREAMS),
            "aux": _semaphore_active(_AUX_STREAM_ADMISSION_SEMAPHORE, RUNTIME_MAX_ACTIVE_AUX_STREAMS),
            "limits": {
                "session": RUNTIME_MAX_ACTIVE_STREAMS,
                "dashboard": RUNTIME_MAX_ACTIVE_DASHBOARD_STREAMS,
                "aux": RUNTIME_MAX_ACTIVE_AUX_STREAMS,
            },
        },
    }


def _bounded_terminal_stream_chunk(
    data: bytes,
    *,
    last_offset: int,
    total_bytes: int,
    clean_text,
) -> tuple[bytes, dict]:
    max_len = min(len(data), SSE_TERMINAL_CHUNK_BYTES)
    while max_len > 0:
        candidate = data[:max_len]
        leading_gap = 0
        while leading_gap < len(candidate) and 0x80 <= candidate[leading_gap] <= 0xBF:
            leading_gap += 1
        decodable = candidate[leading_gap:]
        decoder = codecs.getincrementaldecoder("utf-8")(errors="replace")
        decoder.decode(decodable, final=False)
        pending, _ = decoder.getstate()
        complete_len = len(decodable) - len(pending) if pending else len(decodable)
        consumed_len = leading_gap + complete_len
        if consumed_len <= 0:
            max_len = max_len // 2
            continue
        send_data = candidate[:consumed_len]
        text_data = candidate[leading_gap:consumed_len]
        payload = {
            "next_since": last_offset + len(send_data),
            "total_bytes": total_bytes,
            "text": clean_text(text_data),
        }
        if leading_gap:
            # A broker ring gap or a legacy cursor can resume inside a UTF-8
            # scalar. The missing lead byte cannot be recovered, so advance
            # over its continuation bytes and surface the loss as a gap.
            payload["gap_bytes"] = leading_gap
        _, diagnostic = _sse_json_event("chunk", payload, max_bytes=SSE_MAX_EVENT_BYTES)
        if diagnostic is None:
            return send_data, payload
        max_len = max_len // 2
    send_data = b""
    return send_data, {
        "next_since": last_offset,
        "total_bytes": total_bytes,
        "text": "",
    }


_TERMINAL_OSC_RE = re.compile(r"\x1b\][^\x07\x1b]*(?:\x07|\x1b\\)")
_TERMINAL_STRING_RE = re.compile(r"\x1b[P^_].*?(?:\x1b\\)", re.DOTALL)
_TERMINAL_CSI_RE = re.compile(r"\x1b\[[0-?]*[ -/]*[@-~]")
_TERMINAL_SINGLE_ESC_RE = re.compile(r"\x1b[@-Z\\-_]")
_TERMINAL_C0_DISPLAY_RE = re.compile(r"[\x00-\x08\x0b\x0c\x0e-\x1f\x7f]")


def _clean_terminal_display_text(text: str) -> str:
    text = text.replace("^D\x08\x08", "")
    text = text.replace("\r\n", "\n").replace("\r", "\n")
    text = _TERMINAL_OSC_RE.sub("", text)
    text = _TERMINAL_STRING_RE.sub("", text)
    text = _TERMINAL_CSI_RE.sub("", text)
    text = _TERMINAL_SINGLE_ESC_RE.sub("", text)
    text = _TERMINAL_C0_DISPLAY_RE.sub("", text)
    return "\n".join(line.rstrip() for line in text.split("\n"))


def _terminal_display_lines(buffer: str, payload: dict) -> tuple[str, list[str]]:
    if payload.get("reset") or int(payload.get("gap_bytes") or 0) > 0:
        buffer = ""
    text = _clean_terminal_display_text(str(payload.get("text") or ""))
    if not text:
        return buffer, []
    buffer += text
    lines: list[str] = []
    while "\n" in buffer:
        line, buffer = buffer.split("\n", 1)
        lines.append(line)
    return buffer, lines


_HEALTH_PROBE_CACHE_SECONDS = 30.0
_PAIRLING_CONNECT_STATUS_MISS_GRACE_SECONDS = 60.0
_HEALTH_PAYLOAD_CACHE_SECONDS = 5.0
REQUEST_READ_TIMEOUT_SECONDS = 15.0
_health_probe_cache_lock = threading.Lock()
_health_probe_cache: dict[str, tuple[float, object]] = {}
_health_payload_cache_lock = threading.Lock()
_health_payload_cache: dict[tuple, tuple[float, dict]] = {}


class _RuntimeSnapshotKeyLock:
    def __init__(self) -> None:
        self.lock = threading.Lock()
        self.users = 0


_runtime_snapshot_cache_lock = threading.Lock()
_runtime_snapshot_cache: dict[tuple, tuple[float, object]] = {}
_runtime_snapshot_key_locks: dict[tuple, _RuntimeSnapshotKeyLock] = {}
_runtime_snapshot_cache_generation = 0
_runtime_snapshot_thread_state = threading.local()
_auth_result_cache_lock = threading.Lock()
_auth_result_cache: dict[tuple, tuple[float, object]] = {}
_auth_result_cache_generation = 0
_client_workflow_audit_lock = threading.Lock()
_client_workflow_audit_last: dict[tuple[str, ...], float] = {}
_CLIENT_WORKFLOW_AUDIT_INTERVAL_SECONDS = 300.0
_CLIENT_WORKFLOW_AUDIT_MAX_KEYS = 2048
_CLIENT_APP_BUILD_HEADER = "X-Pairling-App-Build"
_CLIENT_SOURCE_REVISION_HEADER = "X-Pairling-App-Source-Revision"
_FAST_ADMISSION_SEMAPHORE = threading.BoundedSemaphore(RUNTIME_MAX_ACTIVE_FAST_REQUESTS)
_REQUEST_ADMISSION_SEMAPHORE = threading.BoundedSemaphore(RUNTIME_MAX_ACTIVE_REQUESTS)
_UPLOAD_ADMISSION_SEMAPHORE = threading.BoundedSemaphore(RUNTIME_MAX_ACTIVE_UPLOADS)
_DASHBOARD_STREAM_ADMISSION_SEMAPHORE = threading.BoundedSemaphore(RUNTIME_MAX_ACTIVE_DASHBOARD_STREAMS)
_STREAM_ADMISSION_SEMAPHORE = threading.BoundedSemaphore(RUNTIME_MAX_ACTIVE_STREAMS)
_AUX_STREAM_ADMISSION_SEMAPHORE = threading.BoundedSemaphore(RUNTIME_MAX_ACTIVE_AUX_STREAMS)
_CONNECTION_ADMISSION_SEMAPHORE = threading.BoundedSemaphore(RUNTIME_MAX_ACTIVE_CONNECTIONS)


def _runtime_snapshot_invalidation_count_for_current_thread() -> int:
    return int(
        getattr(_runtime_snapshot_thread_state, "invalidation_count", 0) or 0
    )


def _record_runtime_snapshot_invalidation_for_current_thread() -> None:
    _runtime_snapshot_thread_state.invalidation_count = (
        _runtime_snapshot_invalidation_count_for_current_thread() + 1
    )


_STREAM_ENDPOINTS = {
    "/health-stream",
    "/sessions-stream",
    "/session-live-events",
    "/session-events-v2",
    "/device-events",
    "/transcript-stream",
    "/terminal-stream",
    "/terminal-surface-stream",
    "/terminal-surface-stream-v2",
    "/session-runtime-truth-stream",
    "/terminal-workspace-stream",
    "/activity-stream",
    "/commands-stream",
    "/invocations-stream",
    "/turn-state-stream",
    "/llm-route-stream",
}
_DASHBOARD_STREAM_ENDPOINTS = {
    "/health-stream",
    "/sessions-stream",
}
_AUX_STREAM_ENDPOINTS = {
    "/activity-stream",
    "/commands-stream",
    "/invocations-stream",
    "/llm-route-stream",
}
_FAST_ENDPOINTS = {"/health", "/healthz", "/readyz", "/routez", "/manifest"}


def _is_orchestration_stream_path(path: str) -> bool:
    prefix = f"{ORCHESTRATIONS_ROUTE}/"
    suffix = "/stream"
    if not path.startswith(prefix) or not path.endswith(suffix):
        return False
    inner = path[len(prefix):-len(suffix)]
    return bool(inner) and "/" not in inner


class _RuntimeAdmission:
    def __init__(self, semaphore: threading.BoundedSemaphore | None, allowed: bool, reason: str | None = None):
        self._semaphore = semaphore
        self.allowed = allowed
        self.reason = reason
        self._released = False

    def release(self) -> None:
        if self._released or self._semaphore is None:
            return
        try:
            self._semaphore.release()
        except ValueError:
            pass
        self._released = True


COMMAND_STREAM_MAX_SECONDS = 60.0
_COMMAND_STREAM_LEASES_LOCK = threading.Lock()
_COMMAND_STREAM_LEASES: dict[str, threading.Event] = {}


def _replace_command_stream_lease(device_id: str) -> threading.Event:
    lease = threading.Event()
    with _COMMAND_STREAM_LEASES_LOCK:
        previous = _COMMAND_STREAM_LEASES.get(device_id)
        _COMMAND_STREAM_LEASES[device_id] = lease
        if previous is not None:
            previous.set()
    return lease


def _release_command_stream_lease(device_id: str, lease: threading.Event) -> None:
    with _COMMAND_STREAM_LEASES_LOCK:
        if _COMMAND_STREAM_LEASES.get(device_id) is lease:
            _COMMAND_STREAM_LEASES.pop(device_id, None)

PUBLIC_ENDPOINTS = {"/health", "/healthz", "/readyz", "/manifest", "/pair/psk-claim-v2", "/pair/psk-activate", "/pair/reauth-challenge", "/pair/reauth-claim"}

LOCAL_CONTROL_PATHS = {
    "/pair/start",
    "/connect/auth/open",
    "/routez",
}

# Internal hook tier: loopback-only endpoints used by Claude Code hooks to
# write the session registry without device pairing. Gated by client IP AND
# the shared-secret token file the daemon mints at boot — these never count
# toward (or weaken) device Bearer auth.
INTERNAL_LOOPBACK_PATHS = {
    "/pair/start",
    "/internal/session-register",
    "/internal/session-heartbeat",
    "/internal/session-close",
    "/internal/active-sessions",
    "/internal/permission-request",
}
INTERNAL_HOOK_TOKEN_FILE = COMPANION_DIR / "internal-hook-token"


def _read_internal_hook_token(path: Path) -> str:
    nofollow = getattr(os, "O_NOFOLLOW", None)
    if nofollow is None:
        return ""
    flags = os.O_RDONLY | nofollow | getattr(os, "O_CLOEXEC", 0)
    try:
        descriptor = os.open(path, flags)
    except OSError:
        return ""
    try:
        metadata = os.fstat(descriptor)
        if (
            not stat.S_ISREG(metadata.st_mode)
            or metadata.st_uid != os.getuid()
            or stat.S_IMODE(metadata.st_mode) != 0o600
            or metadata.st_nlink != 1
            or metadata.st_size < 64
            or metadata.st_size > 65
        ):
            return ""
        with os.fdopen(descriptor, "r", encoding="utf-8", closefd=False) as stream:
            value = stream.read(66).strip()
    except (OSError, UnicodeError):
        return ""
    finally:
        os.close(descriptor)
    return value if re.fullmatch(r"[0-9a-f]{64}", value or "") else ""


def _ensure_internal_hook_token() -> str:
    """Mint (or read) the loopback hook token. 32-byte hex, mode 600.
    Created at boot so hooks can read it without racing the first request."""
    existing = _read_internal_hook_token(INTERNAL_HOOK_TOKEN_FILE)
    if existing:
        return existing
    token = secrets.token_hex(32)
    temporary_path: Path | None = None
    try:
        INTERNAL_HOOK_TOKEN_FILE.parent.mkdir(parents=True, exist_ok=True)
        temporary_path = INTERNAL_HOOK_TOKEN_FILE.with_name(
            f"{INTERNAL_HOOK_TOKEN_FILE.name}.tmp-{secrets.token_hex(8)}"
        )
        flags = (
            os.O_WRONLY
            | os.O_CREAT
            | os.O_EXCL
            | getattr(os, "O_CLOEXEC", 0)
            | getattr(os, "O_NOFOLLOW", 0)
        )
        descriptor = os.open(temporary_path, flags, 0o600)
        try:
            with os.fdopen(descriptor, "w", encoding="utf-8", closefd=False) as stream:
                stream.write(token)
                stream.flush()
            os.fchmod(descriptor, 0o600)
            os.fsync(descriptor)
        finally:
            os.close(descriptor)
        os.replace(temporary_path, INTERNAL_HOOK_TOKEN_FILE)
        temporary_path = None
        if _read_internal_hook_token(INTERNAL_HOOK_TOKEN_FILE) != token:
            return ""
    except OSError:
        return ""
    finally:
        if temporary_path is not None:
            try:
                temporary_path.unlink()
            except OSError:
                pass
    return token


INTERNAL_HOOK_TOKEN = _ensure_internal_hook_token()


SPAWN_SETTINGS_PATH = COMPANION_DIR / "pairling-spawn-settings.json"


def _ensure_spawn_settings() -> None:
    """Write the per-spawn claude settings overlay (the PermissionRequest producer
    hook) into a Pairling-managed file passed to phone-spawned sessions via
    --settings. This keeps the user's GLOBAL ~/.claude/settings.json UNTOUCHED:
    the hook exists ONLY in sessions Pairling spawns, and the permission posture
    is still inherited from the user's own settings (we add an observer hook,
    never a mode). --settings hooks are auto-trusted (no review gate)."""
    payload = {
        "hooks": {
            "PermissionRequest": [
                {"hooks": [{
                    "type": "command",
                    "command": "node $HOME/.claude/hooks/dist/permission-request.mjs",
                    "timeout": 10,
                }]}
            ]
        }
    }
    try:
        SPAWN_SETTINGS_PATH.parent.mkdir(parents=True, exist_ok=True)
        tmp = SPAWN_SETTINGS_PATH.with_name(SPAWN_SETTINGS_PATH.name + ".tmp")
        with open(tmp, "w", encoding="utf-8") as fh:
            json.dump(payload, fh, indent=2)
            fh.flush()
            os.fsync(fh.fileno())
        os.replace(tmp, SPAWN_SETTINGS_PATH)
    except OSError:
        pass


_ensure_spawn_settings()


def _claude_interactive_exec_prefix() -> str:
    """Run an interactive Claude process with its signed-in user credential."""
    return "exec env -u CLAUDE_CODE_OAUTH_TOKEN"


def _direct_claude_phone_command() -> str:
    """Launch Claude's interactive TUI for a direct phone session.

    CLAUDE_CODE_OAUTH_TOKEN is intended for automated, non-interactive calls.
    Claude Code can accept that token for print mode while rejecting it in the
    interactive TUI. Pairling's TUI launches therefore remove only that ambient
    token and let Claude use the user's normal signed-in credential store.
    """
    return (
        f"{_claude_interactive_exec_prefix()} "
        "PAIRLING_PHONE_SESSION=1 "
        f"claude --settings {shlex.quote(str(SPAWN_SETTINGS_PATH))}"
    )


def _session_backend() -> str:
    """Which store serves claude session reads: 'pg' (Docker Postgres) or
    'sqlite' (daemon-owned agent registry). Rollback at any point is
    PAIRLING_SESSION_BACKEND=pg in the LaunchAgent env + kickstart."""
    backend = os.environ.get("PAIRLING_SESSION_BACKEND", "").strip().lower()
    if backend in ("pg", "sqlite"):
        return backend
    return "sqlite"

# In-process replacement for the PG LISTEN session_ready channel: the
# internal register endpoint sets the per-session event, /turn-state-stream
# waiters block on it instead of an asyncpg connection.
_SESSION_READY_EVENTS: dict[str, threading.Event] = {}
_SESSION_READY_EVENTS_LOCK = threading.Lock()


def _session_ready_event(session_id: str) -> threading.Event:
    with _SESSION_READY_EVENTS_LOCK:
        evt = _SESSION_READY_EVENTS.get(session_id)
        if evt is None:
            evt = threading.Event()
            _SESSION_READY_EVENTS[session_id] = evt
        return evt


def _signal_session_ready(session_id: str) -> None:
    with _SESSION_READY_EVENTS_LOCK:
        evt = _SESSION_READY_EVENTS.get(session_id)
        if evt is not None:
            evt.set()
        # Bound the dict: drop already-signalled events beyond a small cap.
        if len(_SESSION_READY_EVENTS) > 256:
            for key in [k for k, v in _SESSION_READY_EVENTS.items() if v.is_set()][:128]:
                _SESSION_READY_EVENTS.pop(key, None)


def _discard_session_ready_event(session_id: str) -> None:
    with _SESSION_READY_EVENTS_LOCK:
        _SESSION_READY_EVENTS.pop(session_id, None)


SESSION_CONTROL_ROUTE_PREFIX = "/session-control/v1/"
SESSION_CONTROL_ROUTES = frozenset({
    "/session-control/v1/negotiate",
    "/session-control/v1/snapshot",
    "/session-control/v1/execute",
    "/session-control/v1/recover",
    "/session-control/v1/events",
})
SESSION_CONTROL_MEDIA_TYPE = "application/vnd.pairling.session-control+json"


READ_ONLY_PICKER_ENDPOINTS = frozenset({
    "/pickers/permissions",
    "/pickers/hooks",
    "/pickers/memory",
})


POST_ONLY_ENDPOINTS = {
    "/pair/start",
    "/pair/psk-claim-v2",
    "/pair/psk-activate",
    "/pair/reauth-challenge",
    "/pair/reauth-claim",
    "/pair/revoke",
    "/pair/rotate-token",
    "/pair/bind-node",
    "/aperture-cli/open",
    "/open",
    "/llm-route",
    "/llm-route-stream",
    "/pairling-tools/run",
    "/phone-tools/availability",
    "/phone-tools/next",
    "/phone-tools/result",
    "/worker-kill",
    "/push/preferences",
    "/push/test",
    "/push/live-activity-token",
    "/push/live-activity-test",
    "/sentinel/snooze",
    "/sentinel/evaluate-now",
    "/safety/ack",
    "/safety/request-activation",
    "/safety/open-full-disk-access",
    "/safety/evidence-test",
    "/spawn-session",
    "/mirror/flush",
    "/mirror/resume",
    "/compose/recordings/sync",
    "/send-text",
    "/terminal-control",
    "/provider-controls/execute",
    "/session-control/v1/negotiate",
    "/session-control/v1/execute",
    "/session-control/v1/recover",
    "/terminal-input",
    "/push/permission/allow",
    "/push/permission/deny",
    "/sigint",
    "/sigterm",
    "/upload",
    "/deepfield/observation",
    "/sessions/remove",
    "/sessions/delete-transcript",
    "/sessions/race/prepare",
    "/pairdrop/maintenance/cleanup-partials",
    "/pairdrop/uploads",
}


def _is_post_only_endpoint(path: str) -> bool:
    return (
        path in POST_ONLY_ENDPOINTS
        or (
            path.startswith("/sessions/race/")
            and path.endswith("/finish")
        )
    )

GET_OR_POST_ENDPOINTS = {
    "/onestream-handoff",
    "/sentinel/preferences",
}

HIGH_RISK_ENDPOINTS = {
    "/aperture-cli/open",
    "/open",
    "/llm-route",
    "/llm-route-stream",
    "/push/permission/allow",
    "/push/permission/deny",
    "/pairling-tools/run",
    "/worker-kill",
    "/push/preferences",
    "/push/test",
    "/push/live-activity-token",
    "/push/live-activity-test",
    "/providers/visibility",
    "/sentinel/snooze",
    "/sentinel/evaluate-now",
    "/safety/request-activation",
    "/safety/open-full-disk-access",
    "/safety/evidence-test",
    "/safety/ack",
    "/onestream-handoff",
    "/spawn-session",
    "/mirror/flush",
    "/mirror/resume",
    "/compose/recordings/sync",
    "/send-text",
    "/terminal-control",
    "/provider-controls/execute",
    "/session-control/v1/execute",
    "/session-control/v1/recover",
    "/terminal-input",
    "/sigint",
    "/sigterm",
    "/upload",
    "/deepfield/observation",
    "/sessions/remove",
    "/sessions/delete-transcript",
    "/sessions/race/prepare",
    "/pair/revoke",
    "/pair/rotate-token",
    "/pairdrop/files",
    "/pairdrop/maintenance/cleanup-partials",
    "/pairdrop/uploads",
}

PROOF_REQUIRED_ENDPOINTS = HIGH_RISK_ENDPOINTS | {
    "/onestream-handoff",
    "/sentinel/preferences",
    "/safety/ack",
    "/safety/request-activation",
    "/safety/open-full-disk-access",
    "/safety/evidence-test",
    "/phone-tools/availability",
    "/phone-tools/next",
    "/phone-tools/result",
    # Minimal proof-required POST whose only purpose is to trip the interactive
    # provenance bind in _maybe_persist_tailnet_node_id. The iOS post-pair proof
    # probes the embedded route with GET (never proof-required), so the bind for
    # an untagged D2 interactive node never fired. A proof-required POST here
    # reaches proof_verified=True and binds the device's tailnet_node_id.
    "/pair/bind-node",
}

MAX_REQUEST_BODY_BYTES = 1_000_000
MAX_FUNNEL_BOOTSTRAP_BODY_BYTES = 16 * 1024
MAX_COMPOSE_SYNC_BODY_BYTES = 2 * 1024 * 1024
MAX_UPLOAD_BODY_BYTES = 100 * 1024 * 1024
MAX_PAIRDROP_SMALL_BODY_BYTES = 10 * 1024 * 1024
MAX_PAIRDROP_UPLOAD_CHUNK_BYTES = 1024 * 1024
ONESTREAM_HANDOFF_MAX_TRANSCRIPT_BYTES = 128 * 1024
ONESTREAM_HANDOFF_MAX_PROMPT_BYTES = 8 * 1024
ONESTREAM_HANDOFF_MAX_METADATA_BYTES = 256
ONESTREAM_HANDOFF_MAX_STORED_BYTES = (
    ONESTREAM_HANDOFF_MAX_TRANSCRIPT_BYTES
    + ONESTREAM_HANDOFF_MAX_PROMPT_BYTES
    + 4096
)
ONESTREAM_HANDOFF_MAX_RESPONSE_BYTES = 256 * 1024
ONESTREAM_HANDOFF_MAX_PENDING = 32
ONESTREAM_HANDOFF_MAX_TOTAL_BYTES = 256 * 1024
ONESTREAM_HANDOFF_TTL_SECONDS = 7 * 24 * 60 * 60
ONESTREAM_HANDOFF_MAX_DIRECTORY_SCAN = 1_000
ONESTREAM_HANDOFF_FILENAME_RE = re.compile(r"onestream-[0-9a-f]{12}\.json")


def _open_handoffs_directory_fd() -> int:
    """Open the exact handoff directory through the authorized home root."""
    return open_directory_fd(HANDOFFS_DIR, root=HOME)


def _onestream_handoff_names(directory_fd: int) -> list[str]:
    names: list[str] = []
    with os.scandir(directory_fd) as entries:
        for index, entry in enumerate(entries):
            if index >= ONESTREAM_HANDOFF_MAX_DIRECTORY_SCAN:
                break
            if ONESTREAM_HANDOFF_FILENAME_RE.fullmatch(entry.name):
                names.append(entry.name)
    names.sort()
    return names


def _read_onestream_handoff_record(
    directory_fd: int,
    filename: str,
) -> tuple[dict[str, Any], int, float] | None:
    if ONESTREAM_HANDOFF_FILENAME_RE.fullmatch(filename) is None:
        return None
    flags = os.O_RDONLY | getattr(os, "O_NOFOLLOW", 0)
    try:
        file_fd = os.open(filename, flags, dir_fd=directory_fd)
    except OSError:
        return None
    try:
        metadata = os.fstat(file_fd)
        if (
            not stat.S_ISREG(metadata.st_mode)
            or metadata.st_size < 0
            or metadata.st_size > ONESTREAM_HANDOFF_MAX_STORED_BYTES
        ):
            return None
        chunks: list[bytes] = []
        remaining = ONESTREAM_HANDOFF_MAX_STORED_BYTES + 1
        while remaining > 0:
            chunk = os.read(file_fd, min(64 * 1024, remaining))
            if not chunk:
                break
            chunks.append(chunk)
            remaining -= len(chunk)
    except OSError:
        return None
    finally:
        os.close(file_fd)
    body = b"".join(chunks)
    if len(body) > ONESTREAM_HANDOFF_MAX_STORED_BYTES:
        return None
    try:
        payload = json.loads(body)
    except (UnicodeDecodeError, json.JSONDecodeError, RecursionError):
        return None
    if not isinstance(payload, dict):
        return None
    expected_id = str(payload.get("handoff_id") or payload.get("handoffId") or "")
    if expected_id != filename[:-5]:
        return None
    return payload, len(body), metadata.st_mtime


def _onestream_handoff_records(
    directory_fd: int,
    *,
    cleanup: bool,
) -> list[tuple[str, dict[str, Any], int, float]]:
    now = _time.time()
    records: list[tuple[str, dict[str, Any], int, float]] = []
    for filename in _onestream_handoff_names(directory_fd):
        loaded = _read_onestream_handoff_record(directory_fd, filename)
        if loaded is None:
            continue
        record, byte_count, modified_at = loaded
        raw_created_at = (
            record.get("received_at")
            or record.get("created_at")
            or record.get("createdAt")
            or modified_at
        )
        try:
            created_at = float(raw_created_at)
        except (TypeError, ValueError):
            created_at = modified_at
        if not math.isfinite(created_at):
            created_at = modified_at
        expired = now - created_at > ONESTREAM_HANDOFF_TTL_SECONDS
        consumed = bool(
            record.get("consumed")
            or record.get("consumed_at")
            or record.get("consumedAt")
        )
        if expired or consumed:
            if cleanup:
                try:
                    os.unlink(filename, dir_fd=directory_fd)
                except OSError:
                    pass
            continue
        records.append((filename, record, byte_count, created_at))
    records.sort(key=lambda item: item[3])
    return records[:ONESTREAM_HANDOFF_MAX_PENDING]


def _write_onestream_handoff_record(
    filename: str,
    body: bytes,
) -> None:
    if ONESTREAM_HANDOFF_FILENAME_RE.fullmatch(filename) is None:
        raise ValueError("invalid handoff filename")
    if len(body) > ONESTREAM_HANDOFF_MAX_STORED_BYTES:
        raise ValueError("handoff record is too large")
    directory_fd = _open_handoffs_directory_fd()
    temporary_name = f".{filename}.{secrets.token_hex(8)}.tmp"
    temporary_exists = False
    lock_fd = -1
    try:
        lock_flags = (
            os.O_RDWR
            | os.O_CREAT
            | getattr(os, "O_NOFOLLOW", 0)
        )
        lock_fd = os.open(
            ".onestream-handoff.lock",
            lock_flags,
            0o600,
            dir_fd=directory_fd,
        )
        lock_metadata = os.fstat(lock_fd)
        if not stat.S_ISREG(lock_metadata.st_mode):
            raise OSError(errno.ELOOP, "unsafe handoff lock")
        fcntl.flock(lock_fd, fcntl.LOCK_EX)
        records = _onestream_handoff_records(directory_fd, cleanup=True)
        if len(records) >= ONESTREAM_HANDOFF_MAX_PENDING:
            raise OSError(errno.ENOSPC, "handoff capacity exhausted")
        if (
            sum(record[2] for record in records) + len(body)
            > ONESTREAM_HANDOFF_MAX_TOTAL_BYTES
        ):
            raise OSError(errno.ENOSPC, "handoff storage quota exhausted")

        flags = (
            os.O_WRONLY
            | os.O_CREAT
            | os.O_EXCL
            | getattr(os, "O_NOFOLLOW", 0)
        )
        file_fd = os.open(temporary_name, flags, 0o600, dir_fd=directory_fd)
        temporary_exists = True
        try:
            remaining = memoryview(body)
            while remaining:
                written = os.write(file_fd, remaining)
                if written <= 0:
                    raise OSError(errno.EIO, "short handoff write")
                remaining = remaining[written:]
            os.fsync(file_fd)
        finally:
            os.close(file_fd)
        os.replace(
            temporary_name,
            filename,
            src_dir_fd=directory_fd,
            dst_dir_fd=directory_fd,
        )
        temporary_exists = False
        os.fsync(directory_fd)
    finally:
        if temporary_exists:
            try:
                os.unlink(temporary_name, dir_fd=directory_fd)
            except OSError:
                pass
        if lock_fd >= 0:
            try:
                fcntl.flock(lock_fd, fcntl.LOCK_UN)
            finally:
                os.close(lock_fd)
        os.close(directory_fd)



MAX_SAFETY_ACK_IDS = 100
MAX_SAFETY_ACK_ID_BYTES = 256

def _bounded_utf8_text(value: object, field: str, maximum_bytes: int, *, required: bool = False) -> str:
    if value is None:
        text = ""
    elif isinstance(value, str):
        text = value.strip()
    else:
        raise ValueError(f"{field} must be a string")
    byte_count = len(text.encode("utf-8"))
    if required and not text:
        raise ValueError(f"{field} is required")
    if byte_count > maximum_bytes:
        raise ValueError(f"{field} exceeds {maximum_bytes} UTF-8 bytes")
    return text




def _pairdrop_file_id_from_path(path: str) -> str | None:
    prefix = "/pairdrop/files/"
    if not path.startswith(prefix):
        return None
    suffix = path[len(prefix):].strip("/")
    if not suffix or "/" in suffix:
        return None
    return suffix


def _postures_item_slug(path: str) -> str | None:
    # SPEC-p6 §2.2: /postures/{slug}. Slug validity (charset, no traversal)
    # is enforced again by the store; this only shapes the route.
    prefix = "/postures/"
    if not path.startswith(prefix):
        return None
    suffix = path[len(prefix):].strip("/")
    if not suffix or "/" in suffix:
        return None
    return suffix


def _is_pairdrop_file_item_path(path: str) -> bool:
    return _pairdrop_file_id_from_path(path) is not None


def _pairdrop_file_content_id(path: str) -> str | None:
    prefix = "/pairdrop/files/"
    suffix = "/content"
    if not path.startswith(prefix) or not path.endswith(suffix):
        return None
    inner = path[len(prefix):-len(suffix)].strip("/")
    if not inner or "/" in inner:
        return None
    return inner


def _pairdrop_attach_file_id(path: str) -> str | None:
    prefix = "/pairdrop/files/"
    suffix = "/attach"
    if not path.startswith(prefix) or not path.endswith(suffix):
        return None
    inner = path[len(prefix):-len(suffix)].strip("/")
    if not inner or "/" in inner:
        return None
    return inner


def _pairdrop_upload_id_from_path(path: str) -> str | None:
    prefix = "/pairdrop/uploads/"
    if not path.startswith(prefix):
        return None
    suffix = path[len(prefix):].strip("/")
    if not suffix or "/" in suffix:
        return None
    return suffix


def _pairdrop_upload_bytes_id(path: str) -> str | None:
    prefix = "/pairdrop/uploads/"
    suffix = "/bytes"
    if not path.startswith(prefix) or not path.endswith(suffix):
        return None
    inner = path[len(prefix):-len(suffix)].strip("/")
    if not inner or "/" in inner:
        return None
    return inner


def _pairdrop_upload_complete_id(path: str) -> str | None:
    prefix = "/pairdrop/uploads/"
    suffix = "/complete"
    if not path.startswith(prefix) or not path.endswith(suffix):
        return None
    inner = path[len(prefix):-len(suffix)].strip("/")
    if not inner or "/" in inner:
        return None
    return inner


def _is_pairdrop_upload_path(path: str) -> bool:
    return (
        path == "/pairdrop/uploads"
        or _pairdrop_upload_id_from_path(path) is not None
        or _pairdrop_upload_bytes_id(path) is not None
        or _pairdrop_upload_complete_id(path) is not None
    )


def _is_pairdrop_path(path: str) -> bool:
    return path == "/pairdrop/events" or path.startswith("/pairdrop/")


def _requires_pairling_connect_gateway(path: str) -> bool:
    return _is_pairdrop_path(path) or path == "/compose/recordings/sync"


def _pairdrop_gateway_provenance_ok(headers, client_address=None) -> bool:
    if not _loopback_client_address(client_address) or not INTERNAL_HOOK_TOKEN:
        return False
    getter = headers.get if hasattr(headers, "get") else lambda key, default=None: default
    gateway = str(getter("X-Pairling-Connect-Gateway", "") or "").strip()
    presented = str(getter("X-Pairling-Internal-Token", "") or "").strip()
    return (
        gateway == "pairling-connectd"
        and bool(presented)
        and secrets.compare_digest(presented, INTERNAL_HOOK_TOKEN)
    )


def _pairling_connect_gateway_claimed(headers) -> bool:
    """Treat any claimed gateway hop as remote traffic until it authenticates."""
    getter = headers.get if hasattr(headers, "get") else lambda key, default=None: default
    return bool(str(getter("X-Pairling-Connect-Gateway", "") or "").strip())

def _unauthenticated_request_allowed(path: str, headers, client_address=None) -> bool:
    if path in PUBLIC_ENDPOINTS:
        return True
    if path != "/power-state" or not _loopback_client_address(client_address):
        return False
    return not _pairling_connect_gateway_claimed(headers)


def _pairling_connect_gateway_rejection(path: str, headers, client_address=None) -> dict | None:
    if not _requires_pairling_connect_gateway(path):
        return None
    if _pairdrop_gateway_provenance_ok(headers, client_address):
        return None
    is_compose = path == "/compose/recordings/sync"
    return {
        "code": (
            "compose_connect_gateway_required"
            if is_compose else "pairdrop_connect_gateway_required"
        ),
        "message": (
            "Compose sync requires Pairling Connect gateway provenance"
            if is_compose else "PairDrop requires Pairling Connect gateway provenance"
        ),
    }


def _is_pairdrop_mutation(path: str, method: str) -> bool:
    method = method.upper()
    return (
        (method == "POST" and path == "/pairdrop/files")
        or (method == "DELETE" and _is_pairdrop_file_item_path(path))
        or (method == "POST" and _pairdrop_attach_file_id(path) is not None)
        or (method == "POST" and path == "/pairdrop/maintenance/cleanup-partials")
        or (method == "POST" and path == "/pairdrop/uploads")
        or (method == "PUT" and _pairdrop_upload_bytes_id(path) is not None)
        or (method == "POST" and _pairdrop_upload_complete_id(path) is not None)
        or (method == "DELETE" and _pairdrop_upload_id_from_path(path) is not None)
    )


def _required_scopes_for_request(path: str, method: str) -> set[str]:
    method = method.upper()
    if path == "/pairdrop/files" and method == "GET":
        return {"files:read"}
    if path == "/pairdrop/files" and method == "POST":
        return {"files:write"}
    if path == "/pairdrop/events" and method == "GET":
        return {"files:read"}
    if _pairdrop_file_content_id(path) is not None and method == "GET":
        return {"files:read"}
    if _is_pairdrop_file_item_path(path) and method == "GET":
        return {"files:read"}
    if _is_pairdrop_file_item_path(path) and method == "DELETE":
        return {"files:delete"}
    if _pairdrop_attach_file_id(path) is not None and method == "POST":
        return {"files:write"}
    if path == "/pairdrop/maintenance/cleanup-partials" and method == "POST":
        return {"files:write"}
    if path == "/pairdrop/uploads" and method == "POST":
        return {"files:write"}
    if _is_pairdrop_upload_path(path):
        return {"files:write"}
    if path in {
        "/session-control/v1/negotiate",
        "/session-control/v1/snapshot",
        "/session-control/v1/events",
    }:
        return {"sessions:read"}
    if path in {
        "/session-control/v1/execute",
        "/session-control/v1/recover",
    }:
        return {"provider:control"}
    if path == "/providers/visibility":
        # Read rides the same scope as /provider-status; the toggle is a
        # settings mutation (SPEC-p1 §2.3).
        return {"health:read"} if method == "GET" else {"pair:admin"}
    if path in {"/provider-controls/snapshot", "/provider-controls/stream"}:
        return {"sessions:read"}
    if path == "/provider-controls/execute":
        return {"provider:control"}
    if path == "/status":
        return {"sessions:read", "transcript:read"}
    if path in {"/health", "/healthz", "/readyz", "/routez", "/health-stream", "/power-state", "/provider-status", "/aperture-cli/status", "/aperture-cli/providers", "/aperture-cli/launch-contexts"}:
        return {"health:read"}
    if path == "/manifest":
        return {"manifest:read"}
    if path == "/sessions/remove":
        return {"pair:admin"}
    if path == "/sessions/delete-transcript":
        return {"pair:admin", "files:delete"}
    if path == "/compose/recordings/sync":
        return {"files:write"}
    if path == "/sessions/race/prepare" or (path.startswith("/sessions/race/") and path.endswith("/finish")):
        return {"session:spawn"}
    if path.startswith("/sessions/race/"):
        return {"sessions:read"}
    if path in {"/sessions", "/sessions-visible", "/sessions-stream", "/recent-projects", "/filesystem/directories", "/session-meta", "/activity", "/activity-stream", "/fleet/digest", "/phone-tools/activity"}:
        return {"sessions:read"}
    if path in {"/search", "/transcript", "/transcript-stream", "/session-live-events", "/session-events-v2", "/session-events-v2-raw", "/session-events-v2-content", "/device-events", "/terminal-stream", "/terminal-stream-diagnostics", "/terminal-surface", "/terminal-surface-stream", "/terminal-surface-v2", "/terminal-surface-stream-v2", "/session-runtime-truth", "/session-runtime-truth-stream", "/terminal-workspace", "/terminal-workspace-stream", "/corpus"}:
        return {"transcript:read"}
    if path.startswith("/sessions/") and path.endswith("/export"):
        return {"transcript:read"}
    if path in {"/workers", "/worker-stats"}:
        return {"worker:read"}
    if path == "/worker-kill":
        return {"worker:control"}
    if path == "/push/status":
        return {"health:read"}
    if path in {"/push/preferences", "/push/test", "/push/live-activity-token", "/push/live-activity-test"}:
        return {"push:manage"}
    if path in {"/push/permission/allow", "/push/permission/deny"}:
        return {"approval:decide"}
    if path == "/sentinel/preferences":
        return {"worker:read"} if method == "GET" else {"pair:admin"}
    if path in {"/sentinel/status", "/sentinel/events"}:
        return {"worker:read"}
    if path in {"/sentinel/snooze", "/sentinel/evaluate-now"}:
        return {"pair:admin"}
    if path in {"/safety/status", "/safety/events"}:
        return {"health:read"}
    if path in {"/safety/ack", "/safety/request-activation", "/safety/open-full-disk-access", "/safety/evidence-test"}:
        return {"pair:admin"}
    if path == "/aperture-cli/open":
        return {"pair:admin"}
    if path in {"/send-text", "/terminal-control", "/terminal-input"}:
        return {"session:send"}
    if path in {"/sigint", "/sigterm"}:
        return {"session:signal"}
    if path == "/spawn-session":
        return {"session:spawn"}
    if path == "/onestream-handoff":
        return {"sessions:read"} if method == "GET" else {"session:spawn"}
    if path in {"/llm-route", "/llm-route-stream"}:
        return {"llm:route"}
    if path == "/pairling-tools/run":
        return {"pairling-tools:run"}
    if path in {"/phone-tools/availability", "/phone-tools/next", "/phone-tools/result"}:
        return {"phone-tools:reverse"}
    if path == "/deepfield/observation":
        return {"files:write"}
    if path == "/upload":
        return {"files:upload"}
    if path.startswith("/pair/") or path.startswith("/pickers/") or path.startswith("/mirror/"):
        return {"pair:admin"}
    if path == "/personal-context":
        return {"files:read", "manifest:read"}
    if path in {"/commands", "/commands-stream", "/invocations", "/invocations-stream", "/tokens"}:
        return {"manifest:read"}
    if path == "/postures":
        # SPEC-p6 §2.2: reads ride the personal-context posture; the write is
        # a user-file mutation.
        return {"manifest:read"} if method == "GET" else {"files:write"}
    if _postures_item_slug(path) is not None:
        return {"files:delete"} if method == "DELETE" else {"manifest:read"}
    if path == ORCHESTRATIONS_ROUTE or path.startswith(f"{ORCHESTRATIONS_ROUTE}/"):
        return {"session:spawn" if method == "POST" else "sessions:read"}
    if path.startswith("/workstate") or path.startswith("/model-status") or path.startswith("/substrate"):
        return {"sessions:read"}
    return {"sessions:read"} if method == "GET" else {"pair:admin"}

AUTHORIZATION_ADVERTISEMENT_CONTRACT = "pairling.authorization.v1"
AUTHORIZATION_ADVERTISEMENT_TTL_SECONDS = 120.0
AUTHORIZATION_CONTROL_ROUTES = {
    "approval.decide": (
        ("POST", "/push/permission/allow"),
        ("POST", "/push/permission/deny"),
    ),
    "session.send": (("POST", "/send-text"),),
    "session.signal": (("POST", "/sigint"),),
    "session.spawn": (("POST", "/spawn-session"),),
    "provider.control": (("POST", "/provider-controls/execute"),),
    "worker.control": (("POST", "/worker-kill"),),
    "llm.route": (("POST", "/llm-route"),),
    "pairling-tools.run": (("POST", "/pairling-tools/run"),),
    "phone-tools.reverse": (("POST", "/phone-tools/result"),),
    "push.manage": (("POST", "/push/preferences"),),
    "files.upload": (("POST", "/upload"),),
    "files.write": (("POST", "/deepfield/observation"),),
    "files.delete": (("DELETE", "/sessions/delete-transcript"),),
    "pair.admin": (("POST", "/sessions/remove"),),
}


def _authorization_controls_for_scopes(scopes: Iterable[str]) -> list[str]:
    granted = frozenset(str(scope) for scope in scopes)
    return sorted(
        control
        for control, routes in AUTHORIZATION_CONTROL_ROUTES.items()
        if all(
            _required_scopes_for_request(path, method).issubset(granted)
            for method, path in routes
        )
    )


def _self_device_target(auth_result, requested_device_id) -> tuple[str | None, dict | None]:
    authenticated_device_id = str(getattr(auth_result, "device_id", "") or "").strip()
    if not authenticated_device_id:
        return None, {
            "status": 401,
            "code": "device_identity_required",
            "message": "An authenticated device identity is required.",
        }
    requested = str(requested_device_id or "").strip()
    if requested and requested != authenticated_device_id:
        return None, {
            "status": 403,
            "code": "device_target_mismatch",
            "message": "A paired device can only manage its own device record.",
        }
    return authenticated_device_id, None


def _pairling_tools_payload_for_auth(auth_result, payload: dict) -> tuple[dict | None, dict | None]:
    requested = str(payload.get("iphone_device_id") or "").strip()
    scopes = set(getattr(auth_result, "scopes", []) or [])
    if LOCAL_MCP_DISPATCH_SCOPE in scopes:
        return dict(payload), None
    device_id, error = _self_device_target(auth_result, requested)
    if error is not None:
        return None, error
    strategy = str(payload.get("strategy") or "auto")
    if strategy == "mac_only":
        return None, {
            "status": 403,
            "code": "remote_mac_fallback_forbidden",
            "message": "Paired devices cannot send model prompts to the Mac fallback.",
        }
    scoped_payload = dict(payload)
    scoped_payload["iphone_device_id"] = device_id
    scoped_payload["strategy"] = "iphone_only"
    scoped_payload.pop("mac_model", None)
    return scoped_payload, None


def _bearer_token(headers) -> str | None:
    auth = headers.get("Authorization", "")
    if auth.startswith("Bearer "):
        token = auth[7:].strip()
        return token or None
    return None


def _client_address_host(client_address) -> str:
    if isinstance(client_address, (tuple, list)) and client_address:
        return str(client_address[0])
    return str(client_address or "")


def _loopback_client_address(client_address) -> bool:
    return _client_address_host(client_address) in ("127.0.0.1", "::1")


def _internal_route_probe_request(path: str, headers, client_address) -> bool:
    if path != "/routez" or not _loopback_client_address(client_address) or not INTERNAL_HOOK_TOKEN:
        return False
    presented = str(headers.get("X-Pairling-Internal-Token") or "").strip()
    return bool(presented) and secrets.compare_digest(presented, INTERNAL_HOOK_TOKEN)


def _local_authorization_request(headers, client_address) -> bool:
    """Authenticate local CLI-only operations against the per-boot secret."""
    if not _loopback_client_address(client_address) or not INTERNAL_HOOK_TOKEN:
        return False
    presented = str(headers.get("X-Pairling-Internal-Token") or "").strip()
    return bool(presented) and secrets.compare_digest(presented, INTERNAL_HOOK_TOKEN)


def _funnel_origin_request(headers, client_address) -> bool:
    """Recognize a restriction-only marker injected by the loopback gateway."""
    if not _loopback_client_address(client_address):
        return False
    getter = headers.get if hasattr(headers, "get") else lambda key, default=None: default
    return str(getter("X-Pairling-Funnel-Origin", "") or "").strip() == "1"

def _pair_claim_requires_app_attest(headers, client_address) -> bool:
    return _funnel_origin_request(headers, client_address) or not _loopback_client_address(client_address)


def _relay_claim_assurance():
    required = relay_claims_required()
    if required and RELAY_CLAIM_VERIFIER is None:
        raise PairingError(
            "attested_claim_unavailable",
            503,
            "relay claim verifier unavailable",
        ) from RELAY_CLAIM_VERIFIER_ERROR
    return required, RELAY_CLAIM_VERIFIER


def _connectd_peer_node_id(headers) -> str:
    getter = headers.get if hasattr(headers, "get") else lambda key, default=None: default
    value = str(getter("X-Pairling-Peer-Node", "") or "").strip()
    if not value or len(value) > 128:
        return ""
    if not re.fullmatch(r"[A-Za-z0-9_-]+", value):
        return ""
    return value


def _connectd_peer_provenance(headers) -> str:
    """Parse the connectd-injected X-Pairling-Peer-Provenance header strictly.

    connectd strips any client-supplied copy first, so when this header is
    present it is trustworthy. Missing, empty, and unknown values are invalid.

    * header EXACTLY "tagged" (tag:pairling-phone minted node), "interactive"
      (untagged Pairling iOS D2 node), or "ssh_gateway" (SPEC-p5: the
      loopback SSH-tunnel gateway; carries no tailnet identity) -> return
      that exact value.
    * every other value -> return "" and refuse identity binding.
    """
    getter = headers.get if hasattr(headers, "get") else lambda key, default=None: default
    raw = getter("X-Pairling-Peer-Provenance", "")
    value = str(raw).strip()
    if value in ("tagged", "interactive", "ssh_gateway"):
        return value
    return ""


def _maybe_persist_tailnet_node_id(headers, client_address, auth_result, proof_verified=False) -> bool:
    if DEVICE_REGISTRY is None or auth_result is None or not getattr(auth_result, "ok", False):
        return False
    device_id = str(getattr(auth_result, "device_id", "") or "").strip()
    if not device_id:
        return False
    if not _loopback_client_address(client_address):
        return False
    if not _pairdrop_gateway_provenance_ok(headers, client_address):
        return False
    provenance = _connectd_peer_provenance(headers)
    node_id = _connectd_peer_node_id(headers)
    if not node_id:
        return False
    if provenance == "tagged":
        # tag:pairling-phone minted node: bearer auth is sufficient to bind.
        pass
    elif provenance == "interactive":
        # Untagged, less-trusted Pairling iOS D2 node: bind only after the
        # request also passed request-proof, never on bearer auth alone.
        if not proof_verified:
            return False
    elif provenance == "ssh_gateway":
        # SPEC-p5: the SSH pipe carries no tailnet identity. A peer-node
        # header alongside ssh_gateway provenance can only be forged —
        # never bind from it.
        return False
    else:
        # Present-but-invalid provenance value: reject. Do NOT downgrade to the
        # legacy path just because the value is unrecognized.
        return False
    try:
        return bool(DEVICE_REGISTRY.set_tailnet_node_id_if_absent(device_id, node_id))
    except Exception:
        return False


def _auth_cache_key(token: str, *, method: str, path: str, required_scopes: set[str]) -> tuple | None:
    if AUTH_RESULT_CACHE_SECONDS <= 0:
        return None
    if method.upper() not in {"GET", "HEAD"}:
        return None
    if _requires_request_proof(path, method):
        return None
    token_hash = hashlib.sha256(token.encode("utf-8")).hexdigest()
    return (token_hash, method.upper(), path, tuple(sorted(required_scopes)))


def _bind_auth_result_to_local_install(auth_result):
    if auth_result is None or not getattr(auth_result, "ok", False):
        return auth_result
    local_install_id = str(getattr(PAIRING_STORE, "install_id", "") or "").strip()
    if not local_install_id:
        return DeviceAuthResult(
            ok=False,
            status=503,
            reason="server_identity_unavailable",
            device_id=getattr(auth_result, "device_id", None),
            install_id=getattr(auth_result, "install_id", None),
        )
    authenticated_install_id = str(getattr(auth_result, "install_id", "") or "").strip()
    if authenticated_install_id and secrets.compare_digest(
        authenticated_install_id,
        local_install_id,
    ):
        return auth_result
    return DeviceAuthResult(
        ok=False,
        status=403,
        reason="install_id_mismatch",
        device_id=getattr(auth_result, "device_id", None),
        install_id=authenticated_install_id or None,
    )


def _authenticate_device(token: str, *, required_scopes: set[str], path: str, method: str):
    if DEVICE_REGISTRY is None:
        return None
    cache_key = _auth_cache_key(token, method=method, path=path, required_scopes=required_scopes)
    now = _time.time()
    cache_generation = None
    if cache_key is not None:
        with _auth_result_cache_lock:
            cache_generation = _auth_result_cache_generation
            cached = _auth_result_cache.get(cache_key)
            if cached is not None and now - cached[0] < AUTH_RESULT_CACHE_SECONDS:
                credential_expires_at = getattr(cached[1], "credential_expires_at", None)
                if credential_expires_at is None or now < float(credential_expires_at):
                    bound_result = _bind_auth_result_to_local_install(cached[1])
                    if getattr(bound_result, "ok", False):
                        return bound_result
                    _auth_result_cache.pop(cache_key, None)
                    return bound_result
                _auth_result_cache.pop(cache_key, None)

    auth_kwargs = {
        "required_scopes": required_scopes,
        "path": path,
    }
    # A freshly claimed credential may prove only the read-only route identity
    # before the phone durably saves it and acknowledges activation. No other
    # endpoint accepts a pending bearer.
    if path == "/routez" and method.upper() == "GET":
        auth_kwargs["allow_pending"] = True
    auth_result = DEVICE_REGISTRY.authenticate(token, **auth_kwargs)
    auth_result = _bind_auth_result_to_local_install(auth_result)
    if cache_key is not None and getattr(auth_result, "ok", False):
        with _auth_result_cache_lock:
            if cache_generation == _auth_result_cache_generation:
                _auth_result_cache[cache_key] = (now, auth_result)
                if len(_auth_result_cache) > AUTH_RESULT_CACHE_MAX:
                    for old_key in list(_auth_result_cache.keys())[: max(1, AUTH_RESULT_CACHE_MAX // 4)]:
                        _auth_result_cache.pop(old_key, None)
    return auth_result


def _validated_client_release_headers(headers) -> dict[str, str] | None:
    getter = headers.get if hasattr(headers, "get") else lambda key, default=None: default
    app_build = str(getter(_CLIENT_APP_BUILD_HEADER, "") or "").strip()
    source_revision = str(getter(_CLIENT_SOURCE_REVISION_HEADER, "") or "").strip().lower()
    if not re.fullmatch(r"[0-9]{1,12}", app_build):
        return None
    if not re.fullmatch(r"(?:[0-9a-f]{40}|[0-9a-f]{64})", source_revision):
        return None
    return {
        "app_build": app_build,
        "app_source_revision": source_revision,
    }


def _client_workflow_route_family(path: str) -> str | None:
    clean_path = str(path or "").split("?", 1)[0]
    if clean_path in _FAST_ENDPOINTS or clean_path in {"/health-stream", "/power-state"}:
        return None
    first_segment = next((part for part in clean_path.split("/") if part), "")
    if not first_segment or not re.fullmatch(r"[a-z0-9-]{1,48}", first_segment):
        return "/other"
    if first_segment.startswith("session") or first_segment in {
        "activity",
        "commands-stream",
        "corpus",
        "device-events",
        "recent-projects",
        "terminal-stream",
        "terminal-surface",
        "terminal-surface-v2",
        "terminal-surface-stream",
        "terminal-surface-stream-v2",
        "terminal-workspace",
        "terminal-workspace-stream",
        "transcript",
        "transcript-stream",
        "turn-state-stream",
    }:
        return "/sessions"
    if first_segment == "pairdrop":
        return "/pairdrop"
    if first_segment in {
        "aperture-cli",
        "compose",
        "deepfield",
        "filesystem",
        "fleet",
        "invocations",
        "keep-awake",
        "llm-route",
        "model-status",
        "onestream-handoff",
        "open",
        "orchestrations",
        "pair",
        "pairling-tools",
        "personal-context",
        "phone-tools",
        "pickers",
        "postures",
        "providers",
        "push",
        "safety",
        "send-text",
        "sentinel",
        "sigint",
        "sigterm",
        "spawn-session",
        "status",
        "substrate-feed",
        "substrate-status",
        "tokens",
        "upload",
        "worker-kill",
        "workers",
    }:
        return f"/{first_segment}"
    return "/other"


def _maybe_audit_authenticated_client_workflow(
    *,
    auth_result,
    headers,
    client_address,
    path: str,
    method: str,
    proof_verified: bool,
) -> bool:
    if DEVICE_REGISTRY is None or auth_result is None or not getattr(auth_result, "ok", False):
        return False
    device_id = str(getattr(auth_result, "device_id", "") or "").strip()
    release = _validated_client_release_headers(headers)
    route_family = _client_workflow_route_family(path)
    if not device_id or release is None or route_family is None:
        return False

    transport = (
        "pairling_connectd"
        if _pairdrop_gateway_provenance_ok(headers, client_address)
        else "direct"
    )
    method_value = str(method or "GET").upper()
    key = (
        device_id,
        release["app_build"],
        release["app_source_revision"],
        route_family,
        method_value,
        transport,
    )
    now = _time.time()
    with _client_workflow_audit_lock:
        last_at = _client_workflow_audit_last.get(key)
        if last_at is not None and now - last_at < _CLIENT_WORKFLOW_AUDIT_INTERVAL_SECONDS:
            return False
        _client_workflow_audit_last[key] = now
        if len(_client_workflow_audit_last) > _CLIENT_WORKFLOW_AUDIT_MAX_KEYS:
            oldest_keys = sorted(
                _client_workflow_audit_last,
                key=_client_workflow_audit_last.get,
            )[: max(1, _CLIENT_WORKFLOW_AUDIT_MAX_KEYS // 4)]
            for old_key in oldest_keys:
                _client_workflow_audit_last.pop(old_key, None)

    detail = {
        **release,
        "method": method_value,
        "transport": transport,
        "proof_verified": bool(proof_verified),
        "device_identity_source": "bearer_auth",
        "release_identity_source": "client_reported",
    }
    provenance = _connectd_peer_provenance(headers) if transport == "pairling_connectd" else None
    if provenance:
        detail["peer_provenance"] = provenance
    try:
        DEVICE_REGISTRY.record_audit(
            "client.workflow.request",
            device_id=device_id,
            outcome="authenticated",
            path=route_family,
            detail=detail,
        )
    except Exception:
        with _client_workflow_audit_lock:
            if _client_workflow_audit_last.get(key) == now:
                _client_workflow_audit_last.pop(key, None)
        return False
    return True


def _clear_client_workflow_audit_for_tests() -> None:
    with _client_workflow_audit_lock:
        _client_workflow_audit_last.clear()


def _path_and_query(parsed) -> str:
    return parsed.path + (f"?{parsed.query}" if parsed.query else "")


def _requires_request_proof(path: str, method: str) -> bool:
    if path in SESSION_CONTROL_ROUTES:
        return True
    if method not in {"POST", "PUT", "PATCH", "DELETE"}:
        return False
    return (
        _is_pairdrop_mutation(path, method)
        or path in PROOF_REQUIRED_ENDPOINTS
        or path.startswith("/pickers/")
        or path == ORCHESTRATIONS_ROUTE
        or path.startswith(f"{ORCHESTRATIONS_ROUTE}/")
        # SPEC-p6 §2.2: posture mutations prove the request body.
        or (path == "/postures" and method == "POST")
        or (_postures_item_slug(path) is not None and method == "DELETE")
        # /sessions/race/{id}/finish is destructive — it removes worktrees and
        # deletes branches, with force it discards uncommitted work. It is
        # templated, so the exact PROOF_REQUIRED_ENDPOINTS set (which only
        # covers /sessions/race/prepare) misses it. Without this rule the
        # destructive finish sat below the tier of the far less destructive
        # prepare. The client already signs every race POST; require it here.
        or (method == "POST" and path.startswith("/sessions/race/") and path.endswith("/finish"))
    )


def _is_high_risk_endpoint(path: str) -> bool:
    return (
        path in HIGH_RISK_ENDPOINTS
        or _is_pairdrop_mutation(path, "POST")
        or _is_pairdrop_upload_path(path)
        or _is_pairdrop_mutation(path, "DELETE")
        or path == ORCHESTRATIONS_ROUTE
        or path.startswith(f"{ORCHESTRATIONS_ROUTE}/")
        or path == "/postures"
        or _postures_item_slug(path) is not None
        # The destructive templated race finish, matching /sessions/race/prepare
        # which is high-risk by exact listing.
        or path.startswith("/sessions/race/") and path.endswith("/finish")
    )


def _rate_limit_for_high_risk_endpoint(path: str) -> int:
    if path == "/pairling-tools/run":
        return 30
    if path == ORCHESTRATIONS_ROUTE or path.startswith(f"{ORCHESTRATIONS_ROUTE}/"):
        return 30
    if path == "/terminal-input":
        # Type mode streams keystrokes; the default 120/min would cap typing
        # at two keys a second. The client coalesces (~50ms flush) so real
        # rates sit far below this ceiling — it exists to stay a ceiling.
        return 2400
    if _pairdrop_upload_bytes_id(path) is not None:
        # The iOS resumable uploader sends 512 KiB proof-bound chunks. A 4 GiB
        # object needs 8,192 requests, so the generic mutation ceiling would
        # stop a valid upload near 60 MiB. The rate key collapses all chunk paths
        # into one authenticated-device bucket so random upload IDs cannot mint
        # fresh limits. The store separately enforces ownership, serialization,
        # total bytes, and reserved disk capacity.
        return 20_000
    return 120


def _rate_limit_key_path(path: str) -> str:
    if _pairdrop_upload_bytes_id(path) is not None:
        return "/pairdrop/uploads/*/bytes"
    if _pairdrop_upload_complete_id(path) is not None:
        return "/pairdrop/uploads/*/complete"
    if _pairdrop_upload_id_from_path(path) is not None:
        return "/pairdrop/uploads/*"
    if _pairdrop_attach_file_id(path) is not None:
        return "/pairdrop/files/*/attach"
    if _pairdrop_file_content_id(path) is not None:
        return "/pairdrop/files/*/content"
    if _pairdrop_file_id_from_path(path) is not None:
        return "/pairdrop/files/*"
    return path


def _parse_single_byte_range(raw: str, total: int) -> tuple[int, int, bool]:
    if not raw:
        return 0, max(total - 1, 0), False
    match = re.fullmatch(r"bytes=(\d*)-(\d*)", raw)
    if not match:
        raise PairDropStoreError("bad_range")
    first, last = match.group(1), match.group(2)
    if first == "" and last == "":
        raise PairDropStoreError("bad_range")
    if len(first) > 20 or len(last) > 20:
        raise PairDropStoreError("bad_range")
    try:
        if first == "":
            suffix_len = int(last)
            if suffix_len <= 0:
                raise PairDropStoreError("range_not_satisfiable")
            start = max(total - suffix_len, 0)
            end = total - 1
        else:
            start = int(first)
            end = int(last) if last else total - 1
    except ValueError as exc:
        raise PairDropStoreError("bad_range") from exc
    if total <= 0 or start >= total or end < start:
        raise PairDropStoreError("range_not_satisfiable")
    end = min(end, total - 1)
    return start, end, True


def _pairdrop_attachment_filename(raw: str) -> str:
    base = os.path.basename(str(raw or "").strip())
    safe = re.sub(r"[^A-Za-z0-9_. -]", "_", base).strip(" ._")
    if not safe:
        return "pairdrop-file"
    return safe[:120].replace("\\", "_").replace('"', "_")


def _pairdrop_content_disposition(raw: str) -> str:
    display_name = str(raw or "pairdrop-file")[:120]
    fallback = _pairdrop_attachment_filename(display_name)
    encoded = quote(display_name, safe="")
    return f"attachment; filename=\"{fallback}\"; filename*=UTF-8''{encoded}"


def _pairdrop_safe_content_type(raw: str) -> str:
    value = str(raw or "").strip()
    if re.fullmatch(r"[A-Za-z0-9!#$&^_.+-]+/[A-Za-z0-9!#$&^_.+-]+", value):
        return value
    return "application/octet-stream"


def _bounded_rate_check(
    *,
    state: dict[str, list[float]],
    lock: threading.Lock,
    key: str,
    max_per_min: int,
    max_keys: int,
    evict_oldest: bool,
) -> tuple[bool, int]:
    now = _time.time()
    window_start = now - 60
    with lock:
        if key not in state and len(state) >= max_keys:
            for existing_key, existing_timestamps in list(state.items()):
                fresh = [stamp for stamp in existing_timestamps if stamp > window_start]
                if fresh:
                    state[existing_key] = fresh
                else:
                    state.pop(existing_key, None)
            if key not in state and len(state) >= max_keys:
                if not evict_oldest:
                    return False, 60
                oldest_key = min(
                    state,
                    key=lambda candidate: max(state[candidate], default=float("-inf")),
                )
                state.pop(oldest_key, None)
        timestamps = [stamp for stamp in state.get(key, []) if stamp > window_start]
        if len(timestamps) >= max_per_min:
            oldest = min(timestamps)
            state[key] = timestamps
            return False, max(1, math.ceil(60 - (now - oldest)))
        timestamps.append(now)
        state[key] = timestamps
    return True, 0


def _request_rate_check(key: str, max_per_min: int = 120) -> tuple[bool, int]:
    return _bounded_rate_check(
        state=_request_rate_state,
        lock=_request_rate_lock,
        key=key,
        max_per_min=max_per_min,
        max_keys=_REQUEST_RATE_MAX_KEYS,
        evict_oldest=False,
    )


def _pairing_rate_check(key: str, max_per_min: int = 5) -> tuple[bool, int]:
    return _bounded_rate_check(
        state=_pairing_rate_state,
        lock=_pairing_rate_lock,
        key=key,
        max_per_min=max_per_min,
        max_keys=_PAIRING_RATE_MAX_KEYS,
        evict_oldest=True,
    )


def _request_origin_key(headers, client_address) -> str:
    origin = ""
    if _pairdrop_gateway_provenance_ok(headers, client_address):
        origin = _connectd_peer_node_id(headers) or "connectd"
    if not origin:
        origin = _client_address_host(client_address) or "unknown"
    return hashlib.sha256(origin.encode("utf-8")).hexdigest()


def _invalid_proof_rate_check(token: str, headers, client_address) -> tuple[bool, int]:
    origin_key = _request_origin_key(headers, client_address)
    token_key = hashlib.sha256(str(token or "").encode("utf-8")).hexdigest()
    return _bounded_rate_check(
        state=_invalid_proof_rate_state,
        lock=_invalid_proof_rate_lock,
        key=f"invalid_proof:{origin_key}:{token_key}",
        max_per_min=20,
        max_keys=_INVALID_PROOF_RATE_MAX_KEYS,
        evict_oldest=True,
    )


def _reauth_rate_check(device_id: str, headers, client_address) -> tuple[bool, int]:
    """Bound unauthenticated recovery work by both caller and target.

    connectd is the trusted source of the tailnet node header. Hash both values
    before using them as in-memory keys so attacker-controlled identifiers have
    fixed storage cost and never appear in diagnostics.
    """
    origin = ""
    if _pairdrop_gateway_provenance_ok(headers, client_address):
        origin = _connectd_peer_node_id(headers)
    if not origin:
        origin = _client_address_host(client_address) or "unknown"
    origin_key = hashlib.sha256(origin.encode("utf-8")).hexdigest()
    target_key = hashlib.sha256(str(device_id or "").encode("utf-8")).hexdigest()
    allowed, retry_after = _request_rate_check(
        f"pair_reauth:origin:{origin_key}",
        max_per_min=20,
    )
    if not allowed:
        return False, retry_after
    return _request_rate_check(
        f"pair_reauth:target:{target_key}",
        max_per_min=10,
    )


def _clear_auth_result_cache() -> None:
    global _auth_result_cache_generation
    with _auth_result_cache_lock:
        _auth_result_cache.clear()
        _auth_result_cache_generation += 1


def _runtime_info_snapshot() -> dict:
    if _build_runtime_info is not None:
        try:
            return _build_runtime_info(
                _DAEMON_SCRIPT_PATH,
                launchd_label=RUNTIME_DAEMON_LABEL,
            )
        except Exception as exc:
            return {
                "name": RUNTIME_NAME,
                "runtime_version": "legacy",
                "contract_version": RUNTIME_CONTRACT_VERSION,
                "source_revision": "unknown",
                "installed_at": None,
                "install_root": str(_DAEMON_SCRIPT_PATH.parent),
                "compat_mode": "pairling-v1",
                "launchd_label": RUNTIME_DAEMON_LABEL,
                "port": PORT,
                "tailscale_variant": RUNTIME_TAILSCALE_VARIANT,
                "verified": False,
                "manifest_path": None,
                "manifest_error": f"{type(exc).__name__}: {exc}",
            }
    return {
        "name": RUNTIME_NAME,
        "runtime_version": os.environ.get("COMPANION_RUNTIME_VERSION", "legacy"),
        "contract_version": RUNTIME_CONTRACT_VERSION,
        "source_revision": os.environ.get("COMPANION_SOURCE_REVISION", "unknown"),
        "installed_at": os.environ.get("COMPANION_INSTALLED_AT"),
        "install_root": str(_DAEMON_SCRIPT_PATH.parent),
        "compat_mode": "pairling-v1",
        "launchd_label": RUNTIME_DAEMON_LABEL,
        "port": PORT,
        "tailscale_variant": RUNTIME_TAILSCALE_VARIANT,
        "verified": False,
        "manifest_path": None,
        "manifest_error": "runtime manifest helpers unavailable",
    }


def _sessions_stream_source() -> dict:
    runtime_info = _runtime_info_snapshot()
    install_id = getattr(PAIRING_STORE, "install_id", "") if PAIRING_STORE else ""
    return {
        "schema_version": 1,
        "install_id": str(install_id or ""),
        "runtime_port": PORT,
        "runtime_version": runtime_info.get("runtime_version"),
        "contract_version": runtime_info.get("contract_version") or RUNTIME_CONTRACT_VERSION,
    }


_AGENT_REGISTRY_SCHEMA_LOCK = threading.Lock()
# Keyed by database path: a process that repoints AGENT_REGISTRY_DB (tests
# do) must migrate the fresh file too, or its inserts fail on the
# migration-added columns.
_AGENT_REGISTRY_MIGRATED_PATHS: set = set()


def _agent_registry_bootstrap_schema(conn) -> None:
    """Idempotent schema bootstrap + extension migration.

    Runs the column/index migration once per daemon process (guarded by
    _AGENT_REGISTRY_MIGRATED_PATHS); the base CREATE TABLE/INDEX statements are
    cheap no-ops and run on every connection like they always have.
    """
    conn.execute(
        """
        CREATE TABLE IF NOT EXISTS agent_sessions (
            provider TEXT NOT NULL,
            native_id TEXT NOT NULL,
            project TEXT NOT NULL,
            pid INTEGER,
            terminal_tty TEXT,
            state TEXT NOT NULL DEFAULT 'running',
            started_at REAL NOT NULL,
            last_heartbeat REAL NOT NULL,
            closed_at REAL,
            metadata_json TEXT,
            PRIMARY KEY (provider, native_id)
        )
        """
    )
    conn.execute(
        "CREATE INDEX IF NOT EXISTS idx_agent_sessions_provider_live "
        "ON agent_sessions(provider, closed_at, last_heartbeat)"
    )
    # Per-tool approval queue (Lock-Screen "Permission request" card, Phase 2).
    # Same daemon-owned DB. NO deadline/expiry columns by design: an unanswered
    # prompt hangs at its native dialog forever until the user acts (Allow
    # keystroke / in-app). Rows are recorded by the PermissionRequest hook via
    # POST /internal/permission-request and resolved by the Allow path (Phase 3).
    conn.execute(
        """
        CREATE TABLE IF NOT EXISTS pending_approvals (
            request_nonce   TEXT PRIMARY KEY,
            provider        TEXT NOT NULL,
            session_id      TEXT NOT NULL,
            native_id       TEXT,
            broker_id       TEXT,
            terminal_tty    TEXT,
            tool_name       TEXT NOT NULL,
            tool_input_json TEXT NOT NULL,
            command_preview TEXT,
            permission_mode TEXT,
            screen_hash     TEXT,
            screen_generation INTEGER,
            screen_nonce    TEXT,
            screen_bound_at REAL,
            state           TEXT NOT NULL DEFAULT 'pending',
            owner_instance  TEXT,
            created_at      REAL NOT NULL,
            resolved_at     REAL
        )
        """
    )
    conn.execute(
        "CREATE INDEX IF NOT EXISTS idx_pending_approvals_session "
        "ON pending_approvals(session_id, state)"
    )
    db_path = str(AGENT_REGISTRY_DB)
    if db_path in _AGENT_REGISTRY_MIGRATED_PATHS:
        return
    with _AGENT_REGISTRY_SCHEMA_LOCK:
        if db_path in _AGENT_REGISTRY_MIGRATED_PATHS:
            return
        existing = {
            row[1] for row in conn.execute("PRAGMA table_info(agent_sessions)").fetchall()
        }
        if "claude_uuid" not in existing:
            conn.execute("ALTER TABLE agent_sessions ADD COLUMN claude_uuid TEXT")
        if "working_on" not in existing:
            conn.execute("ALTER TABLE agent_sessions ADD COLUMN working_on TEXT")
        approval_columns = {
            row[1] for row in conn.execute("PRAGMA table_info(pending_approvals)").fetchall()
        }
        if "screen_hash" not in approval_columns:
            conn.execute("ALTER TABLE pending_approvals ADD COLUMN screen_hash TEXT")
        if "screen_generation" not in approval_columns:
            conn.execute(
                "ALTER TABLE pending_approvals ADD COLUMN screen_generation INTEGER"
            )
        if "screen_nonce" not in approval_columns:
            conn.execute("ALTER TABLE pending_approvals ADD COLUMN screen_nonce TEXT")
        if "screen_bound_at" not in approval_columns:
            conn.execute("ALTER TABLE pending_approvals ADD COLUMN screen_bound_at REAL")
        if "owner_instance" not in approval_columns:
            conn.execute("ALTER TABLE pending_approvals ADD COLUMN owner_instance TEXT")
        conn.execute(
            "CREATE INDEX IF NOT EXISTS idx_agent_sessions_claude_uuid "
            "ON agent_sessions(provider, claude_uuid)"
        )
        _AGENT_REGISTRY_MIGRATED_PATHS.add(db_path)


# Schema bootstrap runs once per database path per process. Re-running the
# DDL on every connection cost real CPU once stream handlers started opening
# registry connections at per-second cadences per subscriber. Keyed by path
# so tests that repoint AGENT_REGISTRY_DB still bootstrap their fresh file.
_REGISTRY_BOOTSTRAPPED_PATHS: set = set()


@contextmanager
def _agent_registry_conn():
    db_path = str(AGENT_REGISTRY_DB)
    conn = sqlite3.connect(db_path)
    try:
        conn.row_factory = sqlite3.Row
        # WAL + busy_timeout are mandatory before claude-volume writes land
        # here: hooks POST register/heartbeat from many processes while the
        # daemon reads, and the default rollback journal serializes hard.
        conn.execute("PRAGMA journal_mode=WAL")
        conn.execute("PRAGMA busy_timeout=3000")
        conn.execute("PRAGMA synchronous=NORMAL")
        if db_path not in _REGISTRY_BOOTSTRAPPED_PATHS:
            _agent_registry_bootstrap_schema(conn)
            _REGISTRY_BOOTSTRAPPED_PATHS.add(db_path)
        yield conn
        conn.commit()
    except Exception:
        conn.rollback()
        raise
    finally:
        conn.close()


def _approval_command_preview(tool_name: str, tool_input: dict) -> str:
    """Render the one-line card text from a tool call's structured input."""
    try:
        if tool_name == "Bash":
            return str(tool_input.get("command") or "").strip()[:300]
        if tool_name in ("Edit", "Write", "MultiEdit", "NotebookEdit"):
            fp = str(tool_input.get("file_path") or tool_input.get("notebook_path") or "").strip()
            base = os.path.basename(fp) if fp else ""
            return f"{tool_name} {base}".strip()[:300]
        if tool_name == "WebFetch":
            url = str(tool_input.get("url") or "").strip()
            try:
                host = urlparse(url).netloc or url
            except Exception:
                host = url
            return f"Fetch {host}".strip()[:300]
        return tool_name[:300]
    except Exception:
        return tool_name[:300]


def _approval_resolve_session(provider: str, session_id: str) -> tuple[str, str, str]:
    """Best-effort map a hook's session_id -> (native_id, broker_id, terminal_tty)
    from the agent_sessions registry. For claude the hook session_id is the
    claude_uuid; for codex it is the registry native_id. Empties on miss — the
    Phase 3 Allow path re-resolves against the live broker before answering."""
    try:
        with _agent_registry_conn() as conn:
            if provider == "claude":
                row = conn.execute(
                    "SELECT native_id, terminal_tty FROM agent_sessions "
                    "WHERE provider='claude' AND claude_uuid=? AND closed_at IS NULL "
                    "ORDER BY last_heartbeat DESC LIMIT 1",
                    (session_id,),
                ).fetchone()
            else:
                lookup_native = session_id
                parsed_provider, parsed_native = _parse_agent_session_ref(session_id)
                if parsed_provider == provider and parsed_native:
                    lookup_native = parsed_native
                row = conn.execute(
                    "SELECT native_id, terminal_tty FROM agent_sessions "
                    "WHERE provider=? AND native_id=? AND closed_at IS NULL "
                    "ORDER BY last_heartbeat DESC LIMIT 1",
                    (provider, lookup_native),
                ).fetchone()
            if not row:
                return ("", "", "")
            native_id = str(row["native_id"] or "")
            broker_id = _qualified_session_id(provider, native_id) if native_id else ""
            return (native_id, broker_id, str(row["terminal_tty"] or ""))
    except Exception:
        return ("", "", "")


def _approval_snapshot_proof(snapshot: dict | None) -> dict | None:
    """Return the exact broker frame identity needed for a permission write."""
    if not isinstance(snapshot, dict):
        return None
    screen_hash = str(snapshot.get("screen_hash") or "").strip()
    nonce = str(snapshot.get("nonce") or "").strip()
    try:
        generation = int(snapshot.get("generation"))
    except (TypeError, ValueError):
        return None
    if not screen_hash or not nonce or generation < 0:
        return None
    return {
        "screen_hash": screen_hash,
        "generation": generation,
        "nonce": nonce,
    }


def _approval_row_screen_proof(row: dict | None) -> dict | None:
    if not isinstance(row, dict):
        return None
    return _approval_snapshot_proof({
        "screen_hash": row.get("screen_hash"),
        "generation": row.get("screen_generation"),
        "nonce": row.get("screen_nonce"),
    })


def _approval_proof_matches(expected: dict | None, current: dict | None) -> bool:
    return bool(expected and current and all(
        expected.get(key) == current.get(key)
        for key in ("screen_hash", "generation", "nonce")
    ))


def _approval_normalize_terminal_text(value: object) -> str:
    return re.sub(r"\s+", " ", str(value or "")).strip().casefold()


def _approval_snapshot_matches_request(row: dict, snapshot: dict | None) -> bool:
    """Prove that a rendered selector is the tool request stored in ``row``.

    The exact frame proof prevents later writes to a different screen. This
    semantic check prevents binding that proof to an unrelated wizard which
    happened to be visible while the notify-only Claude hook was returning.
    """
    if not isinstance(snapshot, dict):
        return False
    pending = snapshot.get("pending_input")
    if not isinstance(pending, dict):
        return False
    state = str(pending.get("state") or "")
    if state not in {"awaiting_selection", "awaiting_confirmation"}:
        return False
    if state == "awaiting_selection":
        choices = pending.get("choices")
        if not isinstance(choices, list) or not choices:
            return False
        first = choices[0] if isinstance(choices[0], dict) else {}
        if str(first.get("id") or "") != "1" or not bool(first.get("selected")):
            return False

    rows_text = _approval_normalize_terminal_text("\n".join(_rows_from_broker_snapshot(snapshot)))
    if not rows_text:
        return False
    try:
        tool_input = json.loads(row.get("tool_input_json") or "{}")
    except Exception:
        tool_input = {}
    if not isinstance(tool_input, dict):
        tool_input = {}
    tool_name = str(row.get("tool_name") or "").strip()
    if tool_name == "Bash":
        command = _approval_normalize_terminal_text(tool_input.get("command"))
        return bool(command and command in rows_text)
    if tool_name in {"Edit", "Write", "MultiEdit", "NotebookEdit"}:
        file_path = str(tool_input.get("file_path") or tool_input.get("notebook_path") or "").strip()
        base = _approval_normalize_terminal_text(os.path.basename(file_path))
        return bool(base and base in rows_text and _approval_normalize_terminal_text(tool_name) in rows_text)
    preview = _approval_normalize_terminal_text(row.get("command_preview"))
    if preview and preview in rows_text:
        return True
    tool_marker = _approval_normalize_terminal_text(tool_name)
    return bool(tool_marker and tool_marker in rows_text)


def _pending_approval_bind_screen(request_nonce: str, snapshot: dict) -> bool:
    """Bind one open approval to one exact rendered broker frame."""
    proof = _approval_snapshot_proof(snapshot)
    row = _pending_approval_get(request_nonce)
    if not proof or not row or not _approval_snapshot_matches_request(row, snapshot):
        return False
    changed = False
    now = _time.time()
    try:
        with _agent_registry_conn() as conn:
            cur = conn.execute(
                "UPDATE pending_approvals SET screen_hash=?, screen_generation=?, "
                "screen_nonce=?, screen_bound_at=?, state=CASE WHEN state='pending' "
                "THEN 'attention' ELSE state END "
                "WHERE request_nonce=? AND state IN ('pending', 'attention') "
                "AND screen_hash IS NULL AND screen_generation IS NULL AND screen_nonce IS NULL",
                (proof["screen_hash"], proof["generation"], proof["nonce"], now, request_nonce),
            )
            changed = cur.rowcount > 0
    except Exception:
        return False
    if changed:
        _publish_approval_changed(request_nonce)
        row = _pending_approval_get(request_nonce) or row
        provider = str(row.get("provider") or "claude")
        native_id = str(row.get("native_id") or "")
        if not native_id:
            native_id, _broker, _tty = _approval_resolve_session(provider, str(row.get("session_id") or ""))
        if native_id:
            _write_agent_turn_state(
                provider,
                native_id,
                "attention",
                tool=str(row.get("command_preview") or row.get("tool_name") or "")[:80],
                event=f"{provider}_approval",
                request_nonce=request_nonce,
                mac_install_id=getattr(PAIRING_STORE, "install_id", "") if PAIRING_STORE else "",
            )
    return changed


def _pending_approval_capture_screen(request_nonce: str, *, timeout_s: float = 1.5) -> bool:
    """Wait briefly for a notify-only hook's native dialog, then bind it."""
    row = _pending_approval_get(request_nonce)
    if not row or PTY_BROKER is None:
        return False
    broker_id = str(row.get("broker_id") or "").strip()
    if not broker_id:
        _native, broker_id, _tty = _approval_resolve_session(
            str(row.get("provider") or "claude"), str(row.get("session_id") or "")
        )
    if not broker_id:
        return False
    deadline = _time.monotonic() + max(0.0, float(timeout_s))
    while True:
        context = _broker_atomic_control_context_for_id(
            broker_id,
            public_session_id=str(row.get("session_id") or broker_id),
        )
        snapshot = context.get("v2") if context is not None else None
        if isinstance(snapshot, dict) and _pending_approval_bind_screen(request_nonce, snapshot):
            return True
        if _time.monotonic() >= deadline:
            return False
        _time.sleep(0.05)


def _pending_approval_record(*, request_nonce: str, provider: str, session_id: str,
                             tool_name: str, tool_input: dict, command_preview: str = "",
                             permission_mode: str = "", broker_id: str = "",
                             state: str = "pending", screen_proof: dict | None = None) -> bool:
    """Idempotently record a pending tool approval (INSERT OR IGNORE on the
    hook-minted request_nonce). No deadline/expiry — by design. broker_id, when
    supplied by the hook (from the broker's PAIRLING_BROKER_SESSION_ID env), is the
    AUTHORITATIVE live broker session id — far more reliable than registry
    reconciliation, since the SessionStart tty capture fails for broker PTYs (the
    claude_uuid and the broker tty land on two unlinked rows)."""
    if provider == "codex":
        _requested_provider, requested_native_id = _parse_agent_session_ref(
            session_id
        )
        canonical_native_id = _agent_registry_resolve_native_alias(
            "codex", requested_native_id
        )
        if canonical_native_id:
            session_id = _qualified_session_id("codex", canonical_native_id)
    now = _time.time()
    native_id, resolved_broker, terminal_tty = _approval_resolve_session(provider, session_id)
    if not broker_id:
        broker_id = resolved_broker
    row_state = state if state in {"pending", "attention"} else "pending"
    proof = _approval_snapshot_proof(screen_proof)
    try:
        with _agent_registry_conn() as conn:
            conn.execute(
                """
                INSERT OR IGNORE INTO pending_approvals
                    (request_nonce, provider, session_id, native_id, broker_id,
                     terminal_tty, tool_name, tool_input_json, command_preview,
                     permission_mode, screen_hash, screen_generation, screen_nonce,
                     screen_bound_at, state, created_at, resolved_at)
                VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, NULL)
                """,
                (request_nonce, provider, session_id, native_id, broker_id,
                 terminal_tty, tool_name, json.dumps(tool_input)[:8000],
                 (command_preview or "")[:300], permission_mode,
                 proof.get("screen_hash") if proof else None,
                 proof.get("generation") if proof else None,
                 proof.get("nonce") if proof else None,
                 now if proof else None, row_state, now),
            )
        for key in {native_id, session_id}:
            if key:
                _publish_session_event(f"approvals:{provider}:{key}", {
                    "type": "approval_changed",
                    "request_nonce": request_nonce,
                })
        _publish_session_event(SESSION_SUMMARIES_TOPIC, {
            "type": "approval_changed",
            "provider": provider,
            "native_id": native_id or session_id,
            "request_nonce": request_nonce,
        })
        return True
    except Exception:
        return False


def _pending_approval_get(request_nonce: str) -> dict | None:
    try:
        with _agent_registry_conn() as conn:
            row = conn.execute(
                "SELECT * FROM pending_approvals WHERE request_nonce=?",
                (request_nonce,),
            ).fetchone()
            return dict(row) if row else None
    except Exception:
        return None


def _pending_approval_cas(request_nonce: str, expected: str, new: str) -> bool:
    """Compare-and-set the approval state. Returns True iff THIS call performed the
    transition — so a duplicate Allow (state already != expected) is a safe no-op."""
    try:
        with _agent_registry_conn() as conn:
            cur = conn.execute(
                "UPDATE pending_approvals SET state=?, resolved_at=?, "
                "owner_instance=CASE WHEN ? IN ('allowed', 'denying') "
                "THEN ? ELSE owner_instance END "
                "WHERE request_nonce=? AND state=?",
                (
                    new,
                    _time.time(),
                    new,
                    _CONTROL_RECEIPT_INSTANCE_ID,
                    request_nonce,
                    expected,
                ),
            )
            changed = cur.rowcount > 0
        if changed:
            _publish_approval_changed(request_nonce)
        return changed
    except Exception:
        return False


def _pending_approval_refresh_screen(
    request_nonce: str,
    *,
    expected_state: str,
    restored_state: str,
    snapshot: dict,
) -> bool:
    """Replace a repainted matching dialog's proof without accepting a tap."""
    proof = _approval_snapshot_proof(snapshot)
    row = _pending_approval_get(request_nonce)
    if not proof or not row or not _approval_snapshot_matches_request(row, snapshot):
        return False
    try:
        with _agent_registry_conn() as conn:
            cur = conn.execute(
                "UPDATE pending_approvals SET screen_hash=?, screen_generation=?, "
                "screen_nonce=?, screen_bound_at=?, state=?, resolved_at=NULL "
                "WHERE request_nonce=? AND state=?",
                (
                    proof["screen_hash"], proof["generation"], proof["nonce"],
                    _time.time(), restored_state, request_nonce, expected_state,
                ),
            )
            changed = cur.rowcount > 0
    except Exception:
        return False
    if changed:
        _publish_approval_changed(request_nonce)
    return changed


def _publish_approval_changed(request_nonce: str) -> None:
    row = _pending_approval_get(request_nonce)
    if not row:
        return
    provider = str(row.get("provider") or "")
    for key in {str(row.get("native_id") or ""), str(row.get("session_id") or "")}:
        if key:
            _publish_session_event(f"approvals:{provider}:{key}", {
                "type": "approval_changed",
                "request_nonce": request_nonce,
            })
    _publish_session_event(SESSION_SUMMARIES_TOPIC, {
        "type": "approval_changed",
        "provider": provider,
        "native_id": str(row.get("native_id") or row.get("session_id") or ""),
        "request_nonce": request_nonce,
    })


# Decision plumbing shared by the allow and deny lock-screen verbs. States:
# allow drives pending/attention -> allowed -> released; deny drives
# pending/attention -> denying -> denied. A decision arriving while the OTHER
# verb is mid-injection sees a 409 naming the in-flight decision. Module-level
# so contract tests can drive the handlers with a bare handler double.
_PERMISSION_DECISIONS = {
    "allow": {"in_flight": "allowed", "final": "released", "key": "enter", "noun": "approval"},
    "deny": {"in_flight": "denying", "final": "denied", "key": "escape", "noun": "denial"},
}
_PERMISSION_IN_FLIGHT_NOUNS = {"allowed": "approval", "denying": "denial"}


def _permission_in_flight_response(state: str) -> dict:
    noun = _PERMISSION_IN_FLIGHT_NOUNS[state]
    return {
        "ok": False,
        "state": state,
        "error": {
            "code": f"{noun}_in_progress",
            "message": f"permission {noun} is already being injected",
        },
    }


def _permission_stale_screen_response(*, state: str, broker_id: str, code: str,
                                      message: str, current_proof: dict | None = None) -> dict:
    payload = {
        "ok": False,
        "state": state,
        "broker_id": broker_id,
        "injected": {"ok": False, "reason": code, "pty_written": False},
        "error": {"code": code, "message": message},
    }
    if current_proof:
        payload["current_screen"] = current_proof
    return payload


FIRST_PROMPT_DELIVERY_TIMEOUT_SECONDS = 600.0
FIRST_PROMPT_CLOSED_CONFIRMATION_GRACE_SECONDS = 5.0
FIRST_PROMPT_RECONCILIATION_POLL_SECONDS = 1.0
FIRST_PROMPT_DELIVERY_DIR = COMPANION_DIR / "first-prompt-deliveries"
_FIRST_PROMPT_DELIVERY_LOCK = threading.RLock()
_FIRST_PROMPT_ACTIVE: set[str] = set()
_FIRST_PROMPT_RECEIPT_RETRY_REQUESTS: dict[str, dict] = {}
_FIRST_PROMPT_RECEIPT_RETRY_WORKER_ACTIVE = False
_FIRST_PROMPT_RECEIPT_RETRY_WORKER_GENERATION = 0
_FIRST_PROMPT_RECEIPT_RETRY_WAKE = threading.Event()


def _first_prompt_delivery_path(provider: str, native_id: str) -> Path:
    key = hashlib.sha256(f"{provider}\0{native_id}".encode()).hexdigest()
    return FIRST_PROMPT_DELIVERY_DIR / f"{key}.json"


def _read_first_prompt_delivery(provider: str, native_id: str) -> dict | None:
    path = _first_prompt_delivery_path(provider, native_id)
    try:
        value = json.loads(path.read_text())
    except (OSError, ValueError, json.JSONDecodeError):
        return None
    return value if isinstance(value, dict) else None


def _write_first_prompt_delivery(record: dict) -> None:
    provider = str(record.get("provider") or "")
    native_id = str(record.get("native_id") or "")
    if provider not in {"claude", "codex", "omp"} or not native_id:
        raise ValueError("invalid first-prompt delivery identity")
    path = _first_prompt_delivery_path(provider, native_id)
    path.parent.mkdir(parents=True, exist_ok=True, mode=0o700)
    os.chmod(path.parent, 0o700)
    payload = {**record, "updated_at": _time.time()}
    tmp = path.with_name(f"{path.name}.tmp.{os.getpid()}.{threading.get_ident()}")
    fd = os.open(tmp, os.O_WRONLY | os.O_CREAT | os.O_EXCL, 0o600)
    with os.fdopen(fd, "w", encoding="utf-8") as f:
        json.dump(payload, f, sort_keys=True)
        f.flush()
        os.fsync(f.fileno())
    os.replace(tmp, path)
    os.chmod(path, 0o600)


def _publish_first_prompt_delivery_receipt(record: dict) -> None:
    state = str(record.get("state") or "")
    if state not in {"delivered", "failed", "indeterminate"}:
        return
    provider = str(record.get("provider") or "")
    native_id = str(record.get("native_id") or "")
    if provider not in {"claude", "codex", "omp"} or not native_id:
        return
    receipt_state = {
        "delivered": "applied",
        "failed": "failed",
        "indeterminate": "indeterminate",
    }[state]
    recorded_pty_written = record.get("pty_written")
    if not isinstance(recorded_pty_written, bool):
        recorded_pty_written = (
            True if state == "delivered" else False if state == "failed" else None
        )
    receipt = _make_action_receipt(
        client_action_id=str(record.get("client_action_id") or "") or None,
        state=receipt_state,
        phases=_receipt_phases(
            validated=True,
            applied=state == "delivered",
            pty_written=recorded_pty_written,
        ),
        backend="first_prompt_delivery",
    )
    if state == "indeterminate" and recorded_pty_written is None:
        receipt["phases"]["pty_write_state"] = "unknown"
    _append_session_live_control_receipt(
        device_id=str(record.get("device_id") or "") or None,
        session_id=_qualified_session_id(provider, native_id),
        client_action_id=str(record.get("client_action_id") or "") or None,
        action_kind="first_prompt_delivery",
        audit_action={"type": "first_prompt_delivery", "state": state},
        receipt=receipt,
    )


def _run_first_prompt_delivery_receipt_retry_worker(
    worker_generation: int,
) -> None:
    global _FIRST_PROMPT_RECEIPT_RETRY_WORKER_ACTIVE

    try:
        while True:
            wait_seconds = 0.0
            request = None
            record = None
            with _FIRST_PROMPT_DELIVERY_LOCK:
                if not _FIRST_PROMPT_RECEIPT_RETRY_REQUESTS:
                    _FIRST_PROMPT_RECEIPT_RETRY_WAKE.clear()
                    if (
                        _FIRST_PROMPT_RECEIPT_RETRY_WORKER_GENERATION
                        == worker_generation
                    ):
                        _FIRST_PROMPT_RECEIPT_RETRY_WORKER_ACTIVE = False
                    return
                now = _time.monotonic()
                current_key, current_request = min(
                    _FIRST_PROMPT_RECEIPT_RETRY_REQUESTS.items(),
                    key=lambda item: float(item[1].get("next_attempt_at") or 0),
                )
                next_attempt_at = float(
                    current_request.get("next_attempt_at") or 0
                )
                if next_attempt_at > now:
                    wait_seconds = next_attempt_at - now
                    _FIRST_PROMPT_RECEIPT_RETRY_WAKE.clear()
                else:
                    request = dict(current_request)
                    request["retry_key"] = current_key
                    record = _read_first_prompt_delivery(
                        str(request.get("provider") or ""),
                        str(request.get("native_id") or ""),
                    )
                    if not isinstance(record, dict) or record.get("state") not in {
                        "delivered",
                        "failed",
                        "indeterminate",
                    }:
                        queued = _FIRST_PROMPT_RECEIPT_RETRY_REQUESTS.get(
                            current_key
                        )
                        if queued and queued.get("generation") == request.get(
                            "generation"
                        ):
                            _FIRST_PROMPT_RECEIPT_RETRY_REQUESTS.pop(
                                current_key, None
                            )
                        request = None

            if wait_seconds > 0:
                _FIRST_PROMPT_RECEIPT_RETRY_WAKE.wait(timeout=wait_seconds)
                continue
            if request is None or record is None:
                continue

            current_key = str(request["retry_key"])
            provider_value = str(request.get("provider") or "")
            native_id_value = str(request.get("native_id") or "")
            try:
                _publish_first_prompt_delivery_receipt(record)
            except Exception as exc:  # noqa: BLE001 - receipt retry is isolated
                print(
                    "[first-prompt] receipt retry failed for "
                    f"{provider_value}:{native_id_value}: "
                    f"{type(exc).__name__}: {str(exc)[:100]}",
                    file=sys.stderr,
                    flush=True,
                )
                with _FIRST_PROMPT_DELIVERY_LOCK:
                    queued = _FIRST_PROMPT_RECEIPT_RETRY_REQUESTS.get(
                        current_key
                    )
                    if queued and queued.get("generation") == request.get(
                        "generation"
                    ):
                        delay = min(
                            max(float(request.get("delay") or 0.25), 0.25) * 2,
                            30.0,
                        )
                        queued["delay"] = delay
                        queued["next_attempt_at"] = _time.monotonic() + delay
                continue

            with _FIRST_PROMPT_DELIVERY_LOCK:
                queued = _FIRST_PROMPT_RECEIPT_RETRY_REQUESTS.get(current_key)
                latest = _read_first_prompt_delivery(
                    provider_value, native_id_value
                )
                if (
                    queued
                    and queued.get("generation") == request.get("generation")
                    and latest == record
                ):
                    _FIRST_PROMPT_RECEIPT_RETRY_REQUESTS.pop(current_key, None)
                elif queued:
                    queued["delay"] = 0.25
                    queued["next_attempt_at"] = _time.monotonic()
                    _FIRST_PROMPT_RECEIPT_RETRY_WAKE.set()
    except Exception as exc:  # noqa: BLE001 - keep queued truth for a later ensure
        print(
            "[first-prompt] receipt retry worker stopped unexpectedly: "
            f"{type(exc).__name__}: {str(exc)[:100]}",
            file=sys.stderr,
            flush=True,
        )
    finally:
        with _FIRST_PROMPT_DELIVERY_LOCK:
            if (
                _FIRST_PROMPT_RECEIPT_RETRY_WORKER_GENERATION
                == worker_generation
            ):
                _FIRST_PROMPT_RECEIPT_RETRY_WORKER_ACTIVE = False
                if _FIRST_PROMPT_RECEIPT_RETRY_REQUESTS:
                    retry_at = _time.monotonic() + 0.25
                    for queued in _FIRST_PROMPT_RECEIPT_RETRY_REQUESTS.values():
                        queued["next_attempt_at"] = max(
                            float(queued.get("next_attempt_at") or 0),
                            retry_at,
                        )
                    try:
                        _ensure_first_prompt_delivery_receipt_retry_worker_locked()
                    except Exception as exc:  # noqa: BLE001 - truth stays queued
                        print(
                            "[first-prompt] could not restart receipt retry: "
                            f"{type(exc).__name__}: {str(exc)[:100]}",
                            file=sys.stderr,
                            flush=True,
                        )
            _FIRST_PROMPT_RECEIPT_RETRY_WAKE.set()


def _ensure_first_prompt_delivery_receipt_retry_worker_locked() -> None:
    """Start the one receipt worker while the delivery lock is held."""
    global _FIRST_PROMPT_RECEIPT_RETRY_WORKER_ACTIVE
    global _FIRST_PROMPT_RECEIPT_RETRY_WORKER_GENERATION

    if (
        _FIRST_PROMPT_RECEIPT_RETRY_WORKER_ACTIVE
        or not _FIRST_PROMPT_RECEIPT_RETRY_REQUESTS
    ):
        return
    _FIRST_PROMPT_RECEIPT_RETRY_WORKER_GENERATION += 1
    worker_generation = _FIRST_PROMPT_RECEIPT_RETRY_WORKER_GENERATION
    worker = threading.Thread(
        target=lambda: _run_first_prompt_delivery_receipt_retry_worker(
            worker_generation
        ),
        name="pairling-first-prompt-receipts",
        daemon=True,
    )
    _FIRST_PROMPT_RECEIPT_RETRY_WORKER_ACTIVE = True
    try:
        worker.start()
    except Exception:
        _FIRST_PROMPT_RECEIPT_RETRY_WORKER_ACTIVE = False
        raise


def _schedule_first_prompt_delivery_receipt_retry(
    provider: str,
    native_id: str,
) -> None:
    """Retry receipt storage without changing durable delivery truth."""
    retry_key = f"{provider}:{native_id}"
    start_error = None
    with _FIRST_PROMPT_DELIVERY_LOCK:
        previous = _FIRST_PROMPT_RECEIPT_RETRY_REQUESTS.get(retry_key) or {}
        generation = int(previous.get("generation") or 0) + 1
        _FIRST_PROMPT_RECEIPT_RETRY_REQUESTS[retry_key] = {
            "provider": provider,
            "native_id": native_id,
            "generation": generation,
            "delay": 0.25,
            "next_attempt_at": _time.monotonic(),
        }
        _FIRST_PROMPT_RECEIPT_RETRY_WAKE.set()
        try:
            _ensure_first_prompt_delivery_receipt_retry_worker_locked()
        except Exception as exc:  # noqa: BLE001 - durable truth remains queued
            start_error = exc

    if start_error is not None:
        print(
            "[first-prompt] could not start receipt retry for "
            f"{provider}:{native_id}: {type(start_error).__name__}: "
            f"{str(start_error)[:100]}",
            file=sys.stderr,
            flush=True,
        )


def _publish_first_prompt_delivery_receipt_or_retry(record: dict) -> None:
    try:
        _publish_first_prompt_delivery_receipt(record)
    except Exception as exc:  # noqa: BLE001 - never roll back provider delivery truth
        provider = str(record.get("provider") or "")
        native_id = str(record.get("native_id") or "")
        print(
            "[first-prompt] receipt publish failed for "
            f"{provider}:{native_id}: {type(exc).__name__}: {str(exc)[:100]}",
            file=sys.stderr,
            flush=True,
        )
        _schedule_first_prompt_delivery_receipt_retry(provider, native_id)


def _finish_first_prompt_delivery(
    provider: str,
    native_id: str,
    *,
    state: str,
    reason: str | None = None,
) -> None:
    with _FIRST_PROMPT_DELIVERY_LOCK:
        record = _read_first_prompt_delivery(provider, native_id) or {
            "schema_version": 1,
            "provider": provider,
            "native_id": native_id,
        }
        recorded_state = str(record.get("state") or "")
        is_noop_terminal_finish = (
            recorded_state in {"delivered", "failed"}
            or (recorded_state == "indeterminate" and state == "indeterminate")
        )
        if not is_noop_terminal_finish:
            record["state"] = state
            record["reason"] = reason
            record["finished_at"] = _time.time()
            # Keep the text for an indeterminate write so a later exact
            # transcript reconciliation can prove acceptance without resend.
            if state in {"delivered", "failed"}:
                record.pop("text", None)
            _write_first_prompt_delivery(record)
        published_record = dict(record)
    _publish_first_prompt_delivery_receipt_or_retry(published_record)


def _first_prompt_content_texts(content) -> list[str]:
    if isinstance(content, str):
        return [content]
    if not isinstance(content, list):
        return []
    texts: list[str] = []
    for block in content:
        if isinstance(block, str):
            texts.append(block)
            continue
        if not isinstance(block, dict):
            continue
        block_type = str(block.get("type") or "text")
        if block_type not in {"text", "input_text"}:
            continue
        value = block.get("text") or block.get("content")
        if isinstance(value, str):
            texts.append(value)
    return texts


def _first_prompt_line_has_exact_user_text(
    provider: str,
    native_id: str,
    raw_line: bytes,
    expected_text: str,
) -> bool:
    expected = expected_text.strip()
    if not expected or not raw_line.strip():
        return False
    if provider == "codex":
        rows = _normalize_codex_line(
            raw_line,
            native_id,
            include_event_messages=False,
        )
    elif provider == "claude":
        try:
            row = json.loads(raw_line)
        except (ValueError, json.JSONDecodeError):
            return False
        message = row.get("message") if isinstance(row.get("message"), dict) else {}
        rows = [row] if row.get("type") == "user" and message.get("role") == "user" else []
    elif provider == "omp":
        try:
            row = json.loads(raw_line)
        except (ValueError, json.JSONDecodeError):
            return False
        message = row.get("message") if isinstance(row.get("message"), dict) else {}
        rows = [row] if row.get("type") == "message" and message.get("role") == "user" else []
    else:
        return False
    for row in rows:
        message = row.get("message") if isinstance(row.get("message"), dict) else {}
        if message.get("role") != "user":
            continue
        texts = _first_prompt_content_texts(message.get("content"))
        candidates = texts + (["\n".join(texts)] if len(texts) > 1 else [])
        if any(candidate.strip() == expected for candidate in candidates):
            return True
    return False


def _first_prompt_transcript_boundary(provider: str, native_id: str) -> dict:
    resolved_native_id = _agent_registry_resolve_native_alias(provider, native_id)
    raw_session = _qualified_session_id(provider, resolved_native_id)
    handler = object.__new__(Handler)
    try:
        path = handler._resolve_session_transcript_path(
            provider,
            resolved_native_id,
            raw_session,
        )
    except (OSError, RuntimeError, _UnsupportedTranscriptProviderError):
        path = None
    transcript_session_id = resolved_native_id
    if provider == "claude":
        row = _agent_registry_get(provider, resolved_native_id) or {}
        transcript_session_id = str(row.get("claude_uuid") or "")
    try:
        offset = int(path.stat().st_size) if path is not None else 0
    except OSError:
        path = None
        offset = 0
    return {
        "resolved_native_id": resolved_native_id,
        "transcript_session_id": transcript_session_id,
        "transcript_path": str(path) if path is not None else None,
        "transcript_offset_before": offset,
    }


def _first_prompt_provider_confirmed(record: dict) -> bool:
    provider = str(record.get("provider") or "")
    native_id = str(record.get("native_id") or "")
    expected_text = str(record.get("text") or "")
    if provider not in {"claude", "codex", "omp"} or not native_id or not expected_text:
        return False
    if provider == "omp" and native_id.startswith("pending-"):
        try:
            _capture_sessions_provider_inventory("omp")
        except (OSError, RuntimeError):
            return False
    try:
        boundary = _first_prompt_transcript_boundary(provider, native_id)
    except (OSError, RuntimeError, _UnsupportedTranscriptProviderError):
        return False
    current_identity = str(boundary.get("transcript_session_id") or "")
    expected_identity = str(record.get("transcript_session_id") or "")
    if expected_identity and current_identity != expected_identity:
        exact_pending_promotion = (
            provider in {"codex", "omp"}
            and expected_identity.startswith("pending-")
            and _agent_registry_resolve_native_alias(
                provider, expected_identity
            ) == current_identity
        )
        if not exact_pending_promotion:
            return False
    current_path = str(boundary.get("transcript_path") or "")
    expected_path = str(record.get("transcript_path") or "")
    if not current_path or (expected_path and current_path != expected_path):
        return False
    offset = int(record.get("transcript_offset_before") or 0) if expected_path else 0
    try:
        with Path(current_path).open("rb") as transcript:
            transcript.seek(max(0, offset))
            for raw_line in transcript:
                if _first_prompt_line_has_exact_user_text(
                    provider,
                    str(boundary.get("resolved_native_id") or native_id),
                    raw_line,
                    expected_text,
                ):
                    return True
    except OSError:
        return False
    return False


def _first_prompt_surface_is_ready(provider: str, snapshot: dict | None) -> bool:
    """Return true only when the provider's normal composer is on screen."""
    if not isinstance(snapshot, dict) or isinstance(snapshot.get("pending_input"), dict):
        return False
    rows = snapshot.get("rows")
    if not isinstance(rows, list):
        return False
    if provider == "omp":
        stripped_rows = [str(row or "").strip() for row in rows]
        return any(row.startswith("╭") and row.endswith("╮") for row in stripped_rows) and any(
            row.startswith("╰") and row.endswith("╯") for row in stripped_rows
        )
    prompt_glyph = "›" if provider == "codex" else "❯" if provider == "claude" else ""
    if not prompt_glyph:
        return False
    choice = re.compile(rf"^{re.escape(prompt_glyph)}\s*\d+[.)](?:\s|$)")
    for row in rows:
        stripped = str(row or "").strip()
        if stripped == prompt_glyph:
            return True
        if stripped.startswith(prompt_glyph + " ") and not choice.match(stripped):
            return True
    return False


def _automation_helper_client() -> AutomationHelperClient:
    """Create the only local path permitted to control Apple Terminal."""
    return AutomationHelperClient()


def _terminal_permissions_summary(*, fresh: bool = True) -> dict:
    """Read the helper's non-prompting Terminal control capability safely."""
    return terminal_permissions_summary(
        fresh=fresh,
        client=_automation_helper_client(),
    )


def _pairing_terminal_permissions_error() -> dict | None:
    """Return the safe retryable pairing error unless Terminal control is ready."""
    terminal_permissions = _terminal_permissions_summary(fresh=True)
    if terminal_permissions.get("terminal_control_ready") is True:
        return None
    return {
        "ok": False,
        "error": {
            "code": "mac_permissions_needed",
            "message": "Finish Pairling setup on the Mac before pairing.",
        },
        "terminal_permissions": terminal_permissions,
    }


def _automation_helper_response(response: dict, *, mutation: bool) -> dict:
    """Translate the helper's typed result into the daemon's safe response shape."""
    helper = response.get("helper")
    result = response.get("result")
    outcome = response.get("mutationOutcome")
    if response.get("ok") is True:
        payload = {
            "ok": True,
            "helper": helper,
            "mutation_outcome": outcome,
        }
        if isinstance(result, dict):
            payload.update(result)
        return payload

    error = response.get("error") if isinstance(response.get("error"), dict) else {}
    code = str(error.get("code") or "automation_helper_unavailable")
    safe_message = str(
        error.get("safeMessage") or "Pairling automation helper is unavailable."
    )
    status = 409 if code in {
        "mac_permissions_needed",
        "accessibility_not_granted",
        "automation_not_determined",
        "automation_denied",
        "terminal_probe_failed",
    } else 503
    return {
        "ok": False,
        "reason": safe_message,
        "status": status,
        "error_code": code,
        "helper": helper,
        "mutation_outcome": outcome,
        "outcome_indeterminate": mutation and outcome == "outcome_unknown",
    }


def _automation_helper_failure(exc: Exception, *, mutation: bool) -> dict:
    code = str(getattr(exc, "code", "") or "automation_helper_unavailable")
    reason = str(getattr(exc, "safe_message", "") or "Pairling automation helper is unavailable.")
    outcome_indeterminate = mutation and isinstance(exc, AutomationHelperMutationIndeterminate)
    return {
        "ok": False,
        "reason": reason,
        "status": 409 if code == "mac_permissions_needed" else 503,
        "error_code": code,
        "mutation_outcome": "outcome_unknown" if outcome_indeterminate else "failed_before_mutation",
        "outcome_indeterminate": outcome_indeterminate,
    }


def _send_terminal_app_text_exact(tty: str, text: str) -> dict:
    """Submit validated text to one Terminal tab through Pairling.app."""
    sanitized, sanitize_error = _sanitize_terminal_text_input(
        text,
        allow_newline=True,
        max_chars=4000,
    )
    if sanitize_error is not None or sanitized is None:
        error = sanitize_error or {
            "code": "invalid_text",
            "message": "terminal text is invalid",
            "status": 400,
        }
        return {
            "ok": False,
            "reason": str(error["message"]),
            "code": str(error["code"]),
            "status": int(error["status"]),
        }
    if not re.match(r"^/dev/ttys[0-9]{3,}$", str(tty or "")):
        return {"ok": False, "reason": "invalid terminal tty", "status": 400}
    bracketed_paste = not _is_direct_slash_invocation_text(sanitized)
    try:
        response = _automation_helper_client().send_text(
            tty,
            sanitized,
            bracketed_paste=bracketed_paste,
            timeout_ms=3_000,
        )
    except (AutomationHelperMutationIndeterminate, AutomationHelperUnavailableError) as exc:
        return _automation_helper_failure(exc, mutation=True)
    return _automation_helper_response(response, mutation=True)

def _start_pairling_terminal_session(
    command: str,
    ownership_marker: str,
    *,
    timeout_ms: int = 15_000,
) -> dict:
    """Open one Pairling-owned Terminal tab through the signed helper."""
    try:
        response = _automation_helper_client().start_session(
            command,
            ownership_marker,
            timeout_ms=timeout_ms,
        )
    except (AutomationHelperMutationIndeterminate, AutomationHelperUnavailableError) as exc:
        return _automation_helper_failure(exc, mutation=True)
    return _automation_helper_response(response, mutation=True)


def _deliver_first_prompt_now(handler, *, provider: str, native_id: str, text: str) -> dict:
    """Deliver to the exact broker session or Terminal tty created by spawn."""
    raw_session = _qualified_session_id(provider, native_id)
    control_native_id = _agent_registry_resolve_native_alias(provider, native_id)
    reg = _agent_registry_get(provider, native_id) or _agent_registry_get(
        provider, control_native_id
    )
    if reg is not None and reg.get("closed_at") is not None:
        return {
            "ok": False,
            "reason": "provider process identity is no longer available",
            "error_code": "process_identity_unverified",
            "status": 409,
            "pty_written": False,
            "write_outcome": "none",
        }
    broker_found = handler._broker_session_for(raw_session)
    if broker_found and PTY_BROKER:
        _public_id, session = broker_found
        if not _broker_session_owns_identity(session, provider, native_id):
            return {"ok": False, "reason": "broker identity changed", "status": 409}
        broker_id = _broker_session_id(session)
        result, _source_offset, _source_reason = _broker_send_text_with_truth(
            broker_id,
            text,
            public_session_id=raw_session,
        )
        if result.get("ok"):
            _agent_registry_update_control(
                provider,
                control_native_id,
                pid=_broker_pid(session),
                terminal_tty=_broker_slave_tty(session),
                state="running",
                reopen=True,
            )
            if provider == "codex":
                _write_agent_turn_state(
                    "codex", control_native_id, "thinking",
                    started_at=_time.time(), event="first_prompt",
                )
        return result

    reg = reg or {}
    durable_broker_id = _durable_broker_id_from_registry_row(
        reg,
        provider=provider,
        native_id=native_id,
    )
    if durable_broker_id:
        return {
            "ok": False,
            "reason": "terminal broker is temporarily unavailable",
            "error_code": "broker_unavailable",
            "status": 503,
            "pty_written": False,
            "write_outcome": "none",
            "broker_id": durable_broker_id,
        }
    if not reg or reg.get("closed_at") is not None:
        return {
            "ok": False,
            "reason": "provider process identity is no longer available",
            "error_code": "process_identity_unverified",
            "status": 409,
            "pty_written": False,
            "write_outcome": "none",
        }
    pid = int(reg.get("pid") or reg.get("claude_pid") or 0)
    tty = str(reg.get("terminal_tty") or "")
    if (
        pid <= 0
        or not _process_alive(pid)
        or not _registry_process_birth_matches(reg, pid)
        or not _session_signal_target_is_verified(reg, provider, pid)
        or not _direct_terminal_binding_is_verified(reg, provider, pid)
    ):
        return {
            "ok": False,
            "reason": "provider process identity changed before prompt delivery",
            "error_code": "process_identity_unverified",
            "status": 409,
            "pty_written": False,
            "write_outcome": "none",
        }
    result = _send_terminal_app_text_exact(tty, text)
    if result.get("ok"):
        _agent_registry_update_control(
            provider,
            control_native_id,
            pid=pid,
            terminal_tty=tty,
            state="running",
            reopen=True,
        )
        if provider == "codex":
            _write_agent_turn_state(
                "codex", control_native_id, "thinking",
                started_at=_time.time(), event="first_prompt",
            )
    return result


def _schedule_first_prompt_delivery(
    *,
    provider: str,
    native_id: str,
    text: str,
    client_action_id: str | None = None,
    device_id: str | None = None,
) -> bool:
    """Durably wait for one exact provider composer, then submit once."""
    if not text or provider not in {"claude", "codex", "omp"}:
        return False
    delivery_key = f"{provider}:{native_id}"
    text_hash = hashlib.sha256(text.encode()).hexdigest()
    confirmation_only = False

    with _FIRST_PROMPT_DELIVERY_LOCK:
        existing = _read_first_prompt_delivery(provider, native_id)
        if existing is not None:
            if existing.get("text_hash") != text_hash:
                return False
            if delivery_key in _FIRST_PROMPT_ACTIVE:
                return True
            existing_state = str(existing.get("state") or "")
            if existing_state in {"delivered", "failed"}:
                return False
            if existing_state == "indeterminate":
                if not existing.get("text") or existing.get("pty_written") is False:
                    return False
            confirmation_only = existing_state in {
                "dispatching",
                "awaiting_provider",
                "indeterminate",
            }
            text = str(existing.get("text") or text)
        else:
            _write_first_prompt_delivery({
                "schema_version": 1,
                "provider": provider,
                "native_id": native_id,
                "client_action_id": client_action_id,
                "device_id": device_id,
                "text": text,
                "text_hash": text_hash,
                "state": "pending",
                "created_at": _time.time(),
            })
        _FIRST_PROMPT_ACTIVE.add(delivery_key)

    def set_pending(reason: str) -> None:
        with _FIRST_PROMPT_DELIVERY_LOCK:
            record = _read_first_prompt_delivery(provider, native_id) or {}
            record.update({
                "schema_version": 1,
                "provider": provider,
                "native_id": native_id,
                "client_action_id": client_action_id,
                "device_id": record.get("device_id") or device_id,
                "text": text,
                "text_hash": text_hash,
                "state": "pending",
                "reason": reason,
            })
            for key in (
                "transcript_path",
                "transcript_offset_before",
                "transcript_session_id",
                "pty_written",
                "write_outcome",
                "paste_render_confirmed",
                "submit_key_written",
            ):
                record.pop(key, None)
            _write_first_prompt_delivery(record)

    def mark_dispatching(boundary: dict) -> None:
        with _FIRST_PROMPT_DELIVERY_LOCK:
            record = _read_first_prompt_delivery(provider, native_id) or {}
            record.update({
                "schema_version": 1,
                "provider": provider,
                "native_id": native_id,
                "client_action_id": client_action_id,
                "device_id": record.get("device_id") or device_id,
                "text": text,
                "text_hash": text_hash,
                "state": "dispatching",
                "dispatch_started_at": _time.time(),
                "transcript_path": boundary.get("transcript_path"),
                "transcript_offset_before": int(
                    boundary.get("transcript_offset_before") or 0
                ),
                "transcript_session_id": boundary.get("transcript_session_id"),
            })
            _write_first_prompt_delivery(record)

    def copy_write_truth(record: dict, result: dict) -> None:
        for key in (
            "pty_written",
            "bytes_written",
            "bytes_expected",
            "write_outcome",
            "outcome_indeterminate",
            "paste_render_confirmed",
            "submit_key_written",
            "error_code",
        ):
            if key in result:
                record[key] = result.get(key)

    def mark_dispatch_result(result: dict, reason: str) -> None:
        with _FIRST_PROMPT_DELIVERY_LOCK:
            record = _read_first_prompt_delivery(provider, native_id) or {}
            record["reason"] = reason
            copy_write_truth(record, result)
            _write_first_prompt_delivery(record)

    def mark_awaiting_provider(result: dict) -> None:
        with _FIRST_PROMPT_DELIVERY_LOCK:
            record = _read_first_prompt_delivery(provider, native_id) or {}
            record.update({
                "state": "awaiting_provider",
                "reason": "terminal submit written; waiting for provider transcript",
                "provider_wait_started_at": _time.time(),
            })
            copy_write_truth(record, result)
            _write_first_prompt_delivery(record)

    def run() -> None:
        handler = object.__new__(Handler)
        preserved_terminal_record = None
        starting_record = _read_first_prompt_delivery(provider, native_id) or {}
        started_at = float(
            starting_record.get("dispatch_started_at")
            or starting_record.get("created_at")
            or _time.time()
        )
        deadline = started_at + FIRST_PROMPT_DELIVERY_TIMEOUT_SECONDS
        last_reason = "provider composer not ready"
        awaiting_provider = confirmation_only
        terminal_state = "indeterminate" if awaiting_provider else "failed"
        indeterminate_published = (
            str(starting_record.get("state") or "") == "indeterminate"
        )
        closed_seen_at = None
        try:
            while True:
                if awaiting_provider:
                    record = _read_first_prompt_delivery(provider, native_id) or {}
                    if _first_prompt_provider_confirmed(record):
                        _finish_first_prompt_delivery(
                            provider,
                            native_id,
                            state="delivered",
                            reason="provider transcript confirmed",
                        )
                        return
                    last_reason = "provider transcript confirmation timed out"
                    now = _time.time()
                    control_native_id = _agent_registry_resolve_native_alias(
                        provider, native_id
                    )
                    reg = _agent_registry_get(provider, native_id) or _agent_registry_get(
                        provider, control_native_id
                    )
                    if reg and reg.get("closed_at"):
                        last_reason = "session closed before provider transcript confirmation"
                        closed_seen_at = closed_seen_at or now
                        if now >= (
                            closed_seen_at
                            + FIRST_PROMPT_CLOSED_CONFIRMATION_GRACE_SECONDS
                        ):
                            break
                    if now >= deadline and not indeterminate_published:
                        _finish_first_prompt_delivery(
                            provider,
                            native_id,
                            state="indeterminate",
                            reason=last_reason,
                        )
                        indeterminate_published = True
                    _time.sleep(
                        FIRST_PROMPT_RECONCILIATION_POLL_SECONDS
                        if indeterminate_published
                        else 0.25
                    )
                    continue

                if _time.time() >= deadline:
                    break
                raw_session = _qualified_session_id(provider, native_id)
                try:
                    snapshot = (
                        handler._broker_surface_snapshot(raw_session)
                        or handler._terminal_app_surface_snapshot(
                            raw_session, automation_timeout=3.0,
                        )
                    )
                except (FileNotFoundError, RuntimeError, ProcessIdentityDriftError) as exc:
                    snapshot = None
                    last_reason = str(exc)[:120]
                if _first_prompt_surface_is_ready(provider, snapshot):
                    # Persist this boundary before touching the terminal. A
                    # restart from dispatching only resumes transcript checks.
                    boundary = _first_prompt_transcript_boundary(provider, native_id)
                    mark_dispatching(boundary)
                    result = _deliver_first_prompt_now(
                        handler,
                        provider=provider,
                        native_id=native_id,
                        text=text,
                    )
                    last_reason = str(result.get("reason") or "delivery failed")[:120]
                    mark_dispatch_result(result, last_reason)
                    if result.get("ok"):
                        mark_awaiting_provider(result)
                        awaiting_provider = True
                        terminal_state = "indeterminate"
                        continue
                    if result.get("outcome_indeterminate") or result.get("write_outcome") in {
                        "partial",
                        "unknown",
                    }:
                        terminal_state = "indeterminate"
                        break
                    if int(result.get("status") or 0) in {400, 404, 409, 410}:
                        terminal_state = "failed"
                        break
                    set_pending(last_reason)
                elif isinstance((snapshot or {}).get("pending_input"), dict):
                    pending = (snapshot or {}).get("pending_input") or {}
                    last_reason = f"waiting for {pending.get('kind') or pending.get('state') or 'provider input'}"

                control_native_id = _agent_registry_resolve_native_alias(provider, native_id)
                reg = _agent_registry_get(provider, native_id) or _agent_registry_get(
                    provider, control_native_id
                )
                if reg and reg.get("closed_at"):
                    last_reason = "session closed before delivery"
                    terminal_state = "failed"
                    break
                _time.sleep(0.25 if deadline - _time.time() > 570 else 1.0)
        except Exception as exc:  # noqa: BLE001 - a delivery worker must not stop the daemon
            last_reason = f"{type(exc).__name__}: {str(exc)[:100]}"
            # If the record reached dispatching, the process may have stopped
            # after writing. Preserve that uncertainty across restart. A
            # durable final result always wins over later bookkeeping errors.
            record = _read_first_prompt_delivery(provider, native_id) or {}
            recorded_state = str(record.get("state") or "")
            if recorded_state in {"delivered", "failed", "indeterminate"}:
                terminal_state = recorded_state
                last_reason = str(record.get("reason") or last_reason)
                preserved_terminal_record = dict(record)
            else:
                terminal_state = (
                    "indeterminate"
                    if recorded_state in {"dispatching", "awaiting_provider"}
                    else "failed"
                )
        finally:
            with _FIRST_PROMPT_DELIVERY_LOCK:
                _FIRST_PROMPT_ACTIVE.discard(delivery_key)
        if preserved_terminal_record is not None:
            _publish_first_prompt_delivery_receipt_or_retry(
                preserved_terminal_record
            )
        else:
            _finish_first_prompt_delivery(
                provider,
                native_id,
                state=terminal_state,
                reason=last_reason,
            )
        print(
            f"[first-prompt] delivery stopped for {provider}:{native_id}: {last_reason}",
            file=sys.stderr,
            flush=True,
        )

    try:
        threading.Thread(
            target=run,
            name=f"pairling-first-prompt-{provider}-{native_id[:8]}",
            daemon=True,
        ).start()
    except Exception:
        with _FIRST_PROMPT_DELIVERY_LOCK:
            _FIRST_PROMPT_ACTIVE.discard(delivery_key)
        return False
    return True


def _recover_pending_first_prompt_deliveries() -> None:
    try:
        paths = list(FIRST_PROMPT_DELIVERY_DIR.glob("*.json"))
    except OSError:
        return
    for path in paths:
        try:
            record = json.loads(path.read_text())
        except (OSError, ValueError, json.JSONDecodeError):
            continue
        if not isinstance(record, dict):
            continue
        provider = str(record.get("provider") or "")
        native_id = str(record.get("native_id") or "")
        state = str(record.get("state") or "")
        text = str(record.get("text") or "")
        if state == "indeterminate":
            _publish_first_prompt_delivery_receipt_or_retry(record)
            if text and record.get("pty_written") is not False:
                _schedule_first_prompt_delivery(
                    provider=provider,
                    native_id=native_id,
                    text=text,
                    client_action_id=str(record.get("client_action_id") or "") or None,
                    device_id=str(record.get("device_id") or "") or None,
                )
        elif state in {"pending", "dispatching", "awaiting_provider"} and text:
            _schedule_first_prompt_delivery(
                provider=provider,
                native_id=native_id,
                text=text,
                client_action_id=str(record.get("client_action_id") or "") or None,
                device_id=str(record.get("device_id") or "") or None,
            )
        elif state in {"dispatching", "awaiting_provider"}:
            _finish_first_prompt_delivery(
                provider,
                native_id,
                state="indeterminate",
                reason="daemon restarted without retained transcript confirmation text",
            )
        elif state in {"delivered", "failed"}:
            _publish_first_prompt_delivery_receipt_or_retry(record)


RACES_REGISTRY_PATH = APP_SUPPORT_ROOT / "races.json"

# Serializes read-modify-write of races.json. The registry is a single JSON
# file mutated by prepare (adds a race) and finish (marks one finished). The
# writes are individually atomic (tmp + os.replace), but the read-modify-write
# spans were not serialized, so two concurrent operations could each read the
# same state and the second write would clobber the first's record — leaving
# that race's worktrees on disk but lost from the registry, uncleanable
# through the daemon. Hold this only for the quick registry mutation, never
# during the slow git worktree operations.
_RACES_LOCK = threading.Lock()


def _races_read() -> dict:
    try:
        data = json.loads(RACES_REGISTRY_PATH.read_text())
        return data if isinstance(data, dict) else {"races": {}}
    except Exception:
        return {"races": {}}


def _races_write(data: dict) -> None:
    tmp = RACES_REGISTRY_PATH.with_suffix(".json.tmp")
    tmp.write_text(json.dumps(data, indent=2, sort_keys=True))
    os.replace(tmp, RACES_REGISTRY_PATH)


def _race_git(project: str, args: list[str], timeout: float = 10.0) -> tuple[bool, str, str]:
    try:
        project = _revalidate_canonical_user_directory(project, allow_tmp=False)
    except (FileNotFoundError, NotADirectoryError, PermissionError, RuntimeError, OSError, ValueError) as error:
        return False, "", f"project path is no longer safe: {error}"
    return _run_text(["git", "-C", project] + args, timeout=timeout)


def _race_prepare(project: str) -> dict:
    """Set up a session race: two worktrees off HEAD, both pre-trusted, so
    the same prompt can run twice and the trees diverge honestly.

    The worktrees live as siblings of the project (never inside it, which
    would dirty every future race), the branches live under races/, and the
    daemon only owns the lifecycle: the phone spawns into each path through
    the ordinary spawn-with-first-prompt flow, so every spawn safety check
    and the readiness-gated prompt delivery are reused, not re-implemented.

    Refuses a dirty tree: a race must start from one truth."""
    try:
        project = _canonical_user_directory(project, allow_tmp=False)
    except (FileNotFoundError, NotADirectoryError, PermissionError, RuntimeError, OSError, ValueError):
        return {"ok": False, "status": 400, "code": "not_a_git_repo", "message": "the project is not a safe git repository"}
    ok, out, err = _race_git(project, ["rev-parse", "--is-inside-work-tree"])
    if not ok or out.strip() != "true":
        return {"ok": False, "status": 400, "code": "not_a_git_repo", "message": "the project is not a git repository"}
    ok, out, _ = _race_git(project, ["status", "--porcelain"])
    if not ok:
        return {"ok": False, "status": 500, "code": "git_failed", "message": "git status failed"}
    if out.strip():
        return {"ok": False, "status": 409, "code": "dirty_tree", "message": "a race must start from a clean tree"}
    ok, head, _ = _race_git(project, ["rev-parse", "--short", "HEAD"])
    if not ok:
        return {"ok": False, "status": 500, "code": "git_failed", "message": "git rev-parse failed"}
    head = head.strip()

    race_id = "race_" + secrets.token_hex(4)
    base = project.rstrip("/")
    sides = {}
    for side in ("a", "b"):
        path = f"{base}-{race_id}-{side}"
        branch = f"races/{race_id}-{side}"
        ok, _, err = _race_git(project, ["worktree", "add", "-b", branch, path, "HEAD"], timeout=30.0)
        if not ok:
            # Roll back anything that landed before the failure.
            for done in sides.values():
                _race_git(project, ["worktree", "remove", "--force", done["path"]], timeout=30.0)
                _race_git(project, ["branch", "-D", done["branch"]])
            return {"ok": False, "status": 500, "code": "worktree_failed", "message": err.strip()[:200]}
        try:
            _pretrust_claude_project(path)
        except ClaudeProjectTrustError as error:
            current = {"path": path, "branch": branch}
            for done in [current, *sides.values()]:
                _race_git(project, ["worktree", "remove", "--force", done["path"]], timeout=30.0)
                _race_git(project, ["branch", "-D", done["branch"]])
            return {
                "ok": False,
                "status": error.status,
                "code": error.code,
                "message": str(error),
            }
        sides[side] = {"path": path, "branch": branch}

    with _RACES_LOCK:
        data = _races_read()
        data.setdefault("races", {})[race_id] = {
            "race_id": race_id,
            "project": project,
            "base_revision": head,
            "sides": sides,
            "created_at": _time.time(),
            "state": "open",
        }
        _races_write(data)
    return {"ok": True, "status": 200, "race_id": race_id, "base_revision": head, "sides": sides}


def _race_status(race_id: str) -> dict:
    record = _races_read().get("races", {}).get(race_id)
    if not record:
        return {"ok": False, "status": 404, "code": "unknown_race"}
    project = record["project"]
    sides = {}
    for side, info in record.get("sides", {}).items():
        path = info["path"]
        detail = {"path": path, "branch": info["branch"], "present": os.path.isdir(path)}
        if detail["present"]:
            ok, out, _ = _run_text(["git", "-C", path, "status", "--porcelain"], timeout=10.0)
            detail["dirty_files"] = len([line for line in out.splitlines() if line.strip()]) if ok else None
            ok, out, _ = _run_text(["git", "-C", path, "diff", "--stat", "HEAD"], timeout=10.0)
            detail["workdir_diffstat"] = out.strip()[-2000:] if ok else ""
            ok, out, _ = _run_text(["git", "-C", path, "log", "--oneline", f"{record['base_revision']}..HEAD"], timeout=10.0)
            detail["commits_ahead"] = len(out.splitlines()) if ok else None
        sides[side] = detail
    branch_a = record["sides"]["a"]["branch"]
    branch_b = record["sides"]["b"]["branch"]
    ok, out, _ = _race_git(project, ["diff", "--stat", f"{branch_a}..{branch_b}"], timeout=15.0)
    return {
        "ok": True,
        "status": 200,
        "race_id": race_id,
        "project": project,
        "base_revision": record["base_revision"],
        "state": record.get("state", "open"),
        "created_at": record.get("created_at"),
        "sides": sides,
        "cross_diffstat": out.strip()[-4000:] if ok else "",
    }


def _race_finish(race_id: str, *, force: bool) -> dict:
    """Archive a race: remove both worktrees and delete the race branches.

    Deliberately NOT a merge: the winner's work is merged from a terminal
    where the user holds the wheel, because agents may leave uncommitted
    work and destructive git stays deliberate. Without force, a side with
    uncommitted changes refuses removal."""
    data = _races_read()
    record = data.get("races", {}).get(race_id)
    if not record:
        return {"ok": False, "status": 404, "code": "unknown_race"}
    project = record["project"]
    removed = []
    for side, info in record.get("sides", {}).items():
        path = info["path"]
        if os.path.isdir(path):
            if not force:
                ok, out, _ = _run_text(["git", "-C", path, "status", "--porcelain"], timeout=10.0)
                if ok and out.strip():
                    return {
                        "ok": False,
                        "status": 409,
                        "code": "side_dirty",
                        "message": f"side {side} has uncommitted work; pass force to discard",
                        "side": side,
                    }
            args = ["worktree", "remove", path] if not force else ["worktree", "remove", "--force", path]
            ok, _, err = _race_git(project, args, timeout=30.0)
            if not ok:
                return {"ok": False, "status": 500, "code": "worktree_remove_failed", "message": err.strip()[:200]}
        _race_git(project, ["branch", "-D", info["branch"]])
        removed.append(side)
    # Re-read under the lock and mutate only this race, so the mark-finished
    # write cannot clobber a race that `prepare` added during the slow git
    # removes above.
    with _RACES_LOCK:
        data = _races_read()
        fresh = data.get("races", {}).get(race_id)
        if fresh is not None:
            fresh["state"] = "finished"
            fresh["finished_at"] = _time.time()
            _races_write(data)
    return {"ok": True, "status": 200, "race_id": race_id, "removed_sides": removed}


def _fleet_digest_payload(since_epoch: float, until_epoch: float) -> dict:
    """The morning logbook's structured half: per-window fleet facts from
    the registry, the approvals table, and the push audit. The daemon stays
    dumb on purpose: prose synthesis happens on the phone, so this payload
    is counts and names, never sentences."""
    sessions_started = 0
    sessions_closed = 0
    active_now = 0
    project_counts: dict[str, int] = {}
    try:
        with _agent_registry_conn() as conn:
            for row in conn.execute(
                "SELECT project, started_at, closed_at, last_heartbeat FROM agent_sessions "
                "WHERE started_at >= ? OR closed_at >= ? OR closed_at IS NULL",
                (since_epoch, since_epoch),
            ).fetchall():
                started = float(row["started_at"] or 0)
                closed = row["closed_at"]
                if since_epoch <= started <= until_epoch:
                    sessions_started += 1
                    name = os.path.basename(str(row["project"] or "").rstrip("/")) or "unknown"
                    project_counts[name] = project_counts.get(name, 0) + 1
                if closed is not None and since_epoch <= float(closed) <= until_epoch:
                    sessions_closed += 1
                if closed is None and (until_epoch - float(row["last_heartbeat"] or 0)) < 300:
                    active_now += 1
    except Exception:
        pass

    approvals_released = 0
    approvals_denied = 0
    approvals_pending = 0
    try:
        with _agent_registry_conn() as conn:
            for row in conn.execute(
                "SELECT state, resolved_at FROM pending_approvals "
                "WHERE resolved_at >= ? OR state IN ('pending', 'attention')",
                (since_epoch,),
            ).fetchall():
                state = str(row["state"] or "")
                resolved = row["resolved_at"]
                if state in ("pending", "attention"):
                    approvals_pending += 1
                elif resolved is not None and since_epoch <= float(resolved) <= until_epoch:
                    if state == "released":
                        approvals_released += 1
                    elif state == "denied":
                        approvals_denied += 1
    except Exception:
        pass

    pushes_sent = 0
    pushes_failed = 0
    if PUSH_DISPATCHER is not None:
        try:
            for event in PUSH_DISPATCHER.status().get("events", []):
                ts = float(event.get("ts") or 0)
                if not (since_epoch <= ts <= until_epoch):
                    continue
                outcome = str(event.get("outcome") or "")
                if not outcome or str(event.get("event") or "").endswith(".registered"):
                    continue
                if outcome in ("sent", "ok"):
                    pushes_sent += 1
                elif outcome not in ("disabled", "snoozed"):
                    pushes_failed += 1
        except Exception:
            pass

    top_projects = sorted(project_counts.items(), key=lambda kv: (-kv[1], kv[0]))[:8]
    return {
        "contract_version": "pairling-fleet-digest-v1",
        "since": since_epoch,
        "until": until_epoch,
        "sessions": {
            "started": sessions_started,
            "closed": sessions_closed,
            "active_now": active_now,
            "projects": [{"name": name, "sessions": count} for name, count in top_projects],
        },
        "approvals": {
            "released": approvals_released,
            "denied": approvals_denied,
            "pending_now": approvals_pending,
        },
        "pushes": {"sent": pushes_sent, "failed": pushes_failed},
    }


def _recover_orphaned_approval_decisions_on_startup() -> int:
    """Seal decisions whose terminal write result was lost with their process."""
    with _agent_registry_conn() as conn:
        cur = conn.execute(
            "UPDATE pending_approvals SET state='outcome_unknown', resolved_at=?, "
            "owner_instance=? WHERE state IN ('allowed', 'denying') "
            "AND (owner_instance IS NULL OR owner_instance<>?)",
            (
                _time.time(),
                _CONTROL_RECEIPT_INSTANCE_ID,
                _CONTROL_RECEIPT_INSTANCE_ID,
            ),
        )
        recovered = cur.rowcount
    return recovered


def _pending_approvals_open() -> list[dict]:
    try:
        with _agent_registry_conn() as conn:
            rows = conn.execute(
                "SELECT * FROM pending_approvals WHERE state IN ('pending', 'attention') "
                "ORDER BY created_at ASC LIMIT 500"
            ).fetchall()
            return [dict(row) for row in rows]
    except Exception:
        return []


def _pending_approval_resolve_terminal(request_nonce: str, new_state: str) -> bool:
    if new_state not in {"session_gone", "expired_session"}:
        return False
    try:
        with _agent_registry_conn() as conn:
            cur = conn.execute(
                "UPDATE pending_approvals SET state=?, resolved_at=? "
                "WHERE request_nonce=? AND state IN ('pending', 'attention')",
                (new_state, _time.time(), request_nonce),
            )
            changed = cur.rowcount > 0
        if changed:
            _publish_approval_changed(request_nonce)
        return changed
    except Exception:
        return False


_CLAUDE_CONFIG_LOCK = threading.RLock()


class ClaudeProjectTrustError(RuntimeError):
    def __init__(self, code: str, message: str, *, status: int) -> None:
        super().__init__(message)
        self.code = code
        self.status = status


def _pretrust_claude_project(project: str) -> bool:
    """Mark `project` trusted in ~/.claude.json before a headless claude spawn.

    Broker-owned PTYs have no human at the keyboard, so Claude Code's
    folder-trust prompt ("Is this a project you created or one you trust?")
    hangs the spawned session forever — the REPL never starts, hooks never
    fire, and the phone reports "spawned, but no heartbeat". The phone user
    explicitly chose this project for the spawn — that is the trust
    gesture — and the spawn handler has already validated the path is under
    $HOME or /tmp. Read-modify-write is atomic (tmp + fsync + os.replace)
    and preserves every other key in the file.
    """
    path = HOME / ".claude.json"
    lock_path = path.with_name(path.name + ".pairling-lock")
    tmp_path: Path | None = None
    lock_fd: int | None = None
    try:
        with _CLAUDE_CONFIG_LOCK:
            lock_fd = os.open(lock_path, os.O_RDWR | os.O_CREAT, 0o600)
            os.chmod(lock_path, 0o600)
            fcntl.flock(lock_fd, fcntl.LOCK_EX)

            if path.exists():
                original_mode = path.stat().st_mode & 0o777
                with open(path, "r", encoding="utf-8") as f:
                    data = json.load(f)
                if not isinstance(data, dict):
                    raise ClaudeProjectTrustError(
                        "claude_config_invalid",
                        "Claude's local configuration is not a JSON object. Repair ~/.claude.json on this Mac, then try again.",
                        status=409,
                    )
            else:
                original_mode = 0o600
                data = {}
            projects = data.get("projects")
            if not isinstance(projects, dict):
                projects = {}
                data["projects"] = projects
            # Claude Code canonicalizes the cwd before the trust lookup
            # (e.g. /tmp/x -> /private/tmp/x on macOS), so trust both the
            # literal path and its resolved form.
            candidates = {project}
            try:
                candidates.add(os.path.realpath(project))
            except OSError:
                pass
            changed = False
            for key in candidates:
                entry = projects.get(key)
                if not isinstance(entry, dict):
                    entry = {}
                    projects[key] = entry
                if entry.get("hasTrustDialogAccepted") is not True:
                    entry["hasTrustDialogAccepted"] = True
                    changed = True
            if not changed:
                return True

            tmp_path = path.with_name(
                f"{path.name}.pairling-tmp.{os.getpid()}."
                f"{threading.get_ident()}.{secrets.token_hex(4)}"
            )
            fd = os.open(tmp_path, os.O_WRONLY | os.O_CREAT | os.O_EXCL, original_mode)
            with os.fdopen(fd, "w", encoding="utf-8") as f:
                json.dump(data, f, indent=2)
                f.write("\n")
                f.flush()
                os.fsync(f.fileno())
            os.chmod(tmp_path, original_mode)
            os.replace(tmp_path, path)
            tmp_path = None

            directory_fd = os.open(path.parent, os.O_RDONLY)
            try:
                os.fsync(directory_fd)
            finally:
                os.close(directory_fd)
            return True
    except ClaudeProjectTrustError:
        raise
    except json.JSONDecodeError as error:
        raise ClaudeProjectTrustError(
            "claude_config_invalid",
            "Claude's local configuration is not valid JSON. Repair ~/.claude.json on this Mac, then try again.",
            status=409,
        ) from error
    except (OSError, ValueError) as error:
        raise ClaudeProjectTrustError(
            "claude_project_trust_unavailable",
            "Pairling could not safely update Claude's project trust on this Mac. Check the Claude configuration file, then try again.",
            status=503,
        ) from error
    finally:
        if tmp_path is not None:
            try:
                tmp_path.unlink(missing_ok=True)
            except OSError:
                pass
        if lock_fd is not None:
            try:
                fcntl.flock(lock_fd, fcntl.LOCK_UN)
            except OSError:
                pass
            os.close(lock_fd)


def _agent_registry_upsert(provider: str, native_id: str, project: str, *,
                           pid: int = 0, terminal_tty: str = "",
                           state: str = "running", metadata: dict | None = None,
                           claude_uuid: str = "", working_on: str = "") -> bool:
    # Conflict semantics mirror the PG sessions upsert exactly:
    # re-register reopens (closed_at = NULL), working_on is always replaced,
    # claude_uuid/tty/pid COALESCE so an empty re-register never blanks them,
    # started_at is preserved from the original insert.
    now = _time.time()
    stored_metadata = dict(metadata or {})
    if _provider_supports(provider, "terminal_control") and int(pid or 0) > 0:
        try:
            process_started_at = float(
                stored_metadata.get("process_started_at") or 0
            )
        except (TypeError, ValueError):
            process_started_at = 0.0
        if process_started_at <= 0:
            process_started_at = _process_start_epoch(int(pid))
        if process_started_at > 0:
            stored_metadata.setdefault("process_started_at", process_started_at)
    membership_changed = False
    try:
        # Serialize reopen with durable removal. If a registration arrives
        # during removal, it runs afterwards and clears the old receipt.
        with _session_tombstone_reopen_guard() as track_reopen:
            track_reopen(provider, native_id)
            with _agent_registry_conn() as conn:
                previous = conn.execute(
                    "SELECT project, pid, terminal_tty, closed_at "
                    "FROM agent_sessions WHERE provider = ? AND native_id = ?",
                    (provider, native_id),
                ).fetchone()
                conn.execute(
                    """
                    INSERT INTO agent_sessions
                        (provider, native_id, project, pid, terminal_tty, state,
                         started_at, last_heartbeat, closed_at, metadata_json,
                         claude_uuid, working_on)
                    VALUES (?, ?, ?, ?, ?, ?, ?, ?, NULL, ?, ?, ?)
                    ON CONFLICT(provider, native_id) DO UPDATE SET
                        project = excluded.project,
                        pid = COALESCE(NULLIF(excluded.pid, 0), agent_sessions.pid),
                        terminal_tty = COALESCE(NULLIF(excluded.terminal_tty, ''), agent_sessions.terminal_tty),
                        state = excluded.state,
                        last_heartbeat = excluded.last_heartbeat,
                        closed_at = NULL,
                        metadata_json = excluded.metadata_json,
                        claude_uuid = COALESCE(NULLIF(excluded.claude_uuid, ''), agent_sessions.claude_uuid),
                        working_on = excluded.working_on
                    """,
                    (
                        provider,
                        native_id,
                        project,
                        int(pid or 0),
                        terminal_tty or "",
                        state,
                        now,
                        now,
                        json.dumps(stored_metadata, sort_keys=True),
                        claude_uuid or "",
                        working_on or "",
                    ),
                )
                _clear_session_tombstone_for_reopen(provider, native_id)
                membership_changed = bool(
                    previous is None
                    or previous["closed_at"] is not None
                    or str(previous["project"] or "") != project
                    or (
                        int(pid or 0) > 0
                        and int(previous["pid"] or 0) != int(pid)
                    )
                    or (
                        bool(terminal_tty)
                        and str(previous["terminal_tty"] or "") != terminal_tty
                    )
                )
        if membership_changed:
            _invalidate_sessions_provider_inventory(provider)
        _publish_session_event(SESSION_SUMMARIES_TOPIC, {
            "type": "session_registered",
            "provider": provider,
            "native_id": native_id,
            "project": project,
            "state": state,
            "working_on": working_on or "",
            "heartbeat_at": now,
        })
        return True
    except Exception:
        return False


_LAST_REGISTRY_STALE_SWEEP = 0.0
_REGISTRY_STALE_SWEEP_INTERVAL = 600.0
REGISTRY_STALE_CLOSE_SECONDS = max(3600, int(os.environ.get("PAIRLING_REGISTRY_STALE_CLOSE_SECONDS", str(24 * 3600))))


def _agent_registry_close_stale(now: float | None = None) -> int:
    """Sessions that die without deregistering linger open forever and pile
    up as 'inactive' rows on the dashboard. Close anything whose heartbeat
    is older than the threshold; rate-limited so hot paths can call it."""
    global _LAST_REGISTRY_STALE_SWEEP
    now = now if now is not None else _time.time()
    if now - _LAST_REGISTRY_STALE_SWEEP < _REGISTRY_STALE_SWEEP_INTERVAL:
        return 0
    _LAST_REGISTRY_STALE_SWEEP = now
    cutoff = now - REGISTRY_STALE_CLOSE_SECONDS
    try:
        with _agent_registry_conn() as conn:
            candidates = [dict(row) for row in conn.execute(
                "SELECT * FROM agent_sessions "
                "WHERE closed_at IS NULL AND last_heartbeat < ? LIMIT 500",
                (cutoff,),
            ).fetchall()]
        stale = [
            row for row in candidates
            if not _session_has_verified_provider_process(row)
        ]
        closed = 0
        closed_providers: set[str] = set()
        with _agent_registry_conn() as conn:
            for row in stale:
                cursor = conn.execute(
                    "UPDATE agent_sessions SET closed_at = ?, state = 'stale_closed' "
                    "WHERE provider = ? AND native_id = ? AND closed_at IS NULL "
                    "AND last_heartbeat = ?",
                    (
                        now,
                        row.get("provider"),
                        row.get("native_id"),
                        row.get("last_heartbeat"),
                    ),
                )
                changed = cursor.rowcount or 0
                closed += changed
                if changed:
                    closed_providers.add(str(row.get("provider") or ""))
        if closed:
            for provider in closed_providers:
                _invalidate_sessions_provider_inventory(provider)
            _invalidate_session_list_caches()
            _publish_session_event(SESSION_SUMMARIES_TOPIC, {
                "type": "registry_swept",
                "closed": int(closed),
                "cutoff": cutoff,
            })
        return int(closed)
    except Exception:
        return 0


def _agent_registry_get(provider: str, native_id: str) -> dict | None:
    snapshot = _current_agent_registry_read_snapshot(provider)
    if snapshot is not None:
        return snapshot.get(native_id)
    try:
        with _agent_registry_conn() as conn:
            row = conn.execute(
                "SELECT * FROM agent_sessions WHERE provider = ? AND native_id = ? LIMIT 1",
                (provider, native_id),
            ).fetchone()
            return dict(row) if row else None
    except Exception:
        return None


def _agent_registry_get_by_tty(provider: str, terminal_tty: str) -> dict | None:
    if not terminal_tty:
        return None
    try:
        with _agent_registry_conn() as conn:
            row = conn.execute(
                "SELECT * FROM agent_sessions WHERE provider = ? AND terminal_tty = ? "
                "ORDER BY last_heartbeat DESC LIMIT 1",
                (provider, terminal_tty),
            ).fetchone()
            return dict(row) if row else None
    except Exception:
        return None


def _agent_registry_get_by_claude_uuid(provider: str, claude_uuid: str) -> dict | None:
    """Most-recent row for a claude_uuid. Two s-ids may transiently share a
    uuid (CLAUDE.md §6) — ORDER BY last_heartbeat DESC resolves the collision
    the same way the PG lookup does today."""
    if not claude_uuid:
        return None
    try:
        with _agent_registry_conn() as conn:
            row = conn.execute(
                "SELECT * FROM agent_sessions WHERE provider = ? AND claude_uuid = ? "
                "ORDER BY last_heartbeat DESC LIMIT 1",
                (provider, claude_uuid),
            ).fetchone()
            return dict(row) if row else None
    except Exception:
        return None


def _agent_registry_heartbeat_by_claude_uuid(provider: str, claude_uuid: str, *,
                                             terminal_tty: str = "", pid: int = 0) -> bool:
    """Heartbeat keyed on claude_uuid, mirroring the PG hook UPDATE:
    last_heartbeat advances; tty/pid only backfill when currently missing
    (existing value wins — opposite precedence from register's upsert).
    Returns False when no row matched, preserving UPDATE-no-op semantics."""
    if not claude_uuid:
        return False
    membership_changed = False
    try:
        matched_native_ids: list[str] = []
        with _session_tombstone_reopen_guard() as track_reopen:
            with _agent_registry_conn() as conn:
                matched = [dict(row) for row in conn.execute(
                    "SELECT * FROM agent_sessions WHERE provider = ? AND claude_uuid = ?",
                    (provider, claude_uuid),
                ).fetchall()]
                if not matched:
                    return False
                membership_changed = any(
                    row.get("closed_at") is not None
                    or (
                        bool(terminal_tty)
                        and not str(row.get("terminal_tty") or "")
                    )
                    or (
                        int(pid or 0) > 0
                        and int(row.get("pid") or 0) == 0
                    )
                    for row in matched
                )
                for row in matched:
                    native_id = str(row.get("native_id") or "")
                    if native_id:
                        track_reopen(provider, native_id)
                now = _time.time()
                cur = conn.execute(
                    "UPDATE agent_sessions SET last_heartbeat = ?, state = 'running', closed_at = NULL, "
                    "terminal_tty = COALESCE(NULLIF(terminal_tty, ''), NULLIF(?, ''), ''), "
                    "pid = COALESCE(NULLIF(pid, 0), NULLIF(?, 0), 0) "
                    "WHERE provider = ? AND claude_uuid = ?",
                    (now, terminal_tty or "", int(pid or 0), provider, claude_uuid),
                )
                for row in matched:
                    native_id = str(row.get("native_id") or "")
                    if not native_id:
                        continue
                    matched_native_ids.append(native_id)
                    effective_tty = str(row.get("terminal_tty") or terminal_tty or "")
                    effective_pid = int(row.get("pid") or pid or 0)
                    if effective_tty:
                        alias_close = conn.execute(
                            "UPDATE agent_sessions SET closed_at = ?, state = 'superseded' "
                            "WHERE provider = ? AND native_id LIKE 'terminal-%' "
                            "AND native_id != ? AND terminal_tty = ? AND closed_at IS NULL",
                            (now, provider, native_id, effective_tty),
                        )
                        membership_changed = bool(alias_close.rowcount) or membership_changed
                    elif effective_pid:
                        alias_close = conn.execute(
                            "UPDATE agent_sessions SET closed_at = ?, state = 'superseded' "
                            "WHERE provider = ? AND native_id LIKE 'terminal-%' "
                            "AND native_id != ? AND pid = ? AND closed_at IS NULL",
                            (now, provider, native_id, effective_pid),
                        )
                        membership_changed = bool(alias_close.rowcount) or membership_changed
                for native_id in matched_native_ids:
                    _clear_session_tombstone_for_reopen(provider, native_id)
        changed = cur.rowcount > 0
        if membership_changed:
            _invalidate_sessions_provider_inventory(provider)
            _invalidate_session_list_caches()
        return changed
    except Exception:
        return False


def _agent_registry_heartbeat_by_native_id(provider: str, native_id: str, *,
                                           terminal_tty: str = "", pid: int = 0) -> bool:
    if not provider or not native_id:
        return False
    membership_changed = False
    try:
        with _session_tombstone_reopen_guard() as track_reopen:
            track_reopen(provider, native_id)
            with _agent_registry_conn() as conn:
                previous = conn.execute(
                    "SELECT pid, terminal_tty, closed_at FROM agent_sessions "
                    "WHERE provider = ? AND native_id = ?",
                    (provider, native_id),
                ).fetchone()
                cur = conn.execute(
                    "UPDATE agent_sessions SET last_heartbeat = ?, state = 'running', closed_at = NULL, "
                    "terminal_tty = COALESCE(NULLIF(?, ''), terminal_tty), "
                    "pid = COALESCE(NULLIF(?, 0), pid) "
                    "WHERE provider = ? AND native_id = ?",
                    (_time.time(), terminal_tty or "", int(pid or 0), provider, native_id),
                )
                changed = cur.rowcount > 0
                if changed:
                    _clear_session_tombstone_for_reopen(provider, native_id)
                    membership_changed = bool(
                        previous is not None
                        and (
                            previous["closed_at"] is not None
                            or (
                                int(pid or 0) > 0
                                and int(previous["pid"] or 0) != int(pid)
                            )
                            or (
                                bool(terminal_tty)
                                and str(previous["terminal_tty"] or "")
                                != terminal_tty
                            )
                        )
                    )
            if membership_changed:
                _invalidate_sessions_provider_inventory(provider)
            return changed
    except Exception:
        return False


def _agent_registry_mark_closed_by_claude_uuid(provider: str, claude_uuid: str) -> bool:
    """Tombstone keyed on claude_uuid (SessionEnd hook path). Idempotent —
    only rows without an existing closed_at are touched, like the PG
    `AND closed_at IS NULL` clause."""
    if not claude_uuid:
        return False
    try:
        with _agent_registry_conn() as conn:
            cur = conn.execute(
                "UPDATE agent_sessions SET closed_at = ?, state = 'terminated' "
                "WHERE provider = ? AND claude_uuid = ? AND closed_at IS NULL",
                (_time.time(), provider, claude_uuid),
            )
            changed = cur.rowcount > 0
        if changed:
            _invalidate_sessions_provider_inventory(provider)
        return changed
    except Exception:
        return False


def _agent_registry_mark_closed_by_native_id(provider: str, native_id: str) -> bool:
    if not provider or not native_id:
        return False
    try:
        with _agent_registry_conn() as conn:
            cur = conn.execute(
                "UPDATE agent_sessions SET closed_at = ?, state = 'terminated' "
                "WHERE provider = ? AND native_id = ? AND closed_at IS NULL",
                (_time.time(), provider, native_id),
            )
            changed = cur.rowcount > 0
        if changed:
            _invalidate_sessions_provider_inventory(provider)
        return changed
    except Exception:
        return False


def _registry_metadata_from_row(row: dict | None) -> dict:
    if not row:
        return {}
    try:
        obj = json.loads(row.get("metadata_json") or "{}")
        return obj if isinstance(obj, dict) else {}
    except Exception:
        return {}


def _agent_registry_row_for_broker_id(provider: str, broker_id: str) -> dict | None:
    """Resolve one canonical registry row from its durable broker identity.

    Broker-owned Claude sessions begin life under a ``pending-*`` native id.
    Claude's SessionStart hook then creates the durable ``s-*`` id.  The
    canonical row retains the original broker id in metadata so requests that
    opened during that short bootstrap window can continue to resolve without
    guessing from project or transcript recency.
    """
    provider = str(provider or "").strip().lower()
    broker_id = str(broker_id or "").strip()
    if provider not in {"claude", "codex", "omp"} or broker_id != _qualified_session_id(
        provider, _parse_agent_session_ref(broker_id)[1]
    ):
        return None
    snapshot = _current_agent_registry_read_snapshot(provider)
    if snapshot is not None:
        return snapshot.row_for_broker_id(broker_id)
    try:
        with _agent_registry_conn() as conn:
            rows = conn.execute(
                "SELECT * FROM agent_sessions WHERE provider = ? "
                "AND CASE WHEN json_valid(metadata_json) "
                "THEN json_extract(metadata_json, '$.broker_id') END = ? "
                "ORDER BY CASE WHEN closed_at IS NULL THEN 0 ELSE 1 END, "
                "last_heartbeat DESC LIMIT 2",
                (provider, broker_id),
            ).fetchall()
    except Exception:
        return None
    matches = [
        dict(row)
        for row in rows
        if str(_registry_metadata_from_row(dict(row)).get("broker_id") or "") == broker_id
    ]
    live_matches = [row for row in matches if not row.get("closed_at")]
    if len(live_matches) == 1:
        return live_matches[0]
    return matches[0] if len(matches) == 1 else None


def _normalized_send_scope_id(provider: str, value: object) -> str:
    """Return one valid provider-qualified durable send identity."""
    provider = str(provider or "").strip().lower()
    scope_id = str(value or "").strip()
    scope_provider, scope_native_id = _parse_agent_session_ref(scope_id)
    if (
        provider not in {"claude", "codex", "omp"}
        or scope_provider != provider
        or not scope_native_id
        or not _safe_agent_native_id(scope_native_id)
    ):
        return ""
    return _qualified_session_id(provider, scope_native_id)


def _durable_send_scope_id_from_registry_row(
    row: dict | None,
    *,
    provider: str,
    native_id: str,
) -> str:
    """Return the identity used to retain sends across registry promotion."""
    metadata = _registry_metadata_from_row(row)
    send_scope_id = _normalized_send_scope_id(
        provider,
        metadata.get("send_scope_id"),
    )
    if send_scope_id:
        return send_scope_id
    # Broker identity is already provider-qualified and physically stable.
    # Keeping it as the fallback also repairs active sessions created before
    # send_scope_id was introduced when the runtime is upgraded in place.
    return _normalized_send_scope_id(provider, metadata.get("broker_id"))


def _agent_registry_row_for_send_scope_id(
    provider: str,
    send_scope_id: str,
) -> dict | None:
    """Resolve one live registry row from an exact durable send identity."""
    provider = str(provider or "").strip().lower()
    send_scope_id = _normalized_send_scope_id(provider, send_scope_id)
    if not send_scope_id:
        return None
    snapshot = _current_agent_registry_read_snapshot(provider)
    if snapshot is not None:
        return snapshot.row_for_send_scope_id(send_scope_id)
    try:
        with _agent_registry_conn() as conn:
            rows = conn.execute(
                "SELECT * FROM agent_sessions WHERE provider = ? "
                "AND closed_at IS NULL AND metadata_json LIKE ? "
                "ORDER BY last_heartbeat DESC",
                (provider, f"%{send_scope_id}%"),
            ).fetchall()
    except Exception:
        return None
    matches = [
        dict(row)
        for row in rows
        if _durable_send_scope_id_from_registry_row(
            dict(row),
            provider=provider,
            native_id=str(row["native_id"] or ""),
        ) == send_scope_id
    ]
    return matches[0] if len(matches) == 1 else None


def _durable_broker_id_from_registry_row(
    row: dict | None,
    *,
    provider: str,
    native_id: str,
) -> str | None:
    """Return a read-only ownership hint from durable session metadata.

    This hint is never enough to write to a PTY. It exists so a temporary
    broker lookup failure cannot make a broker-owned session fall through to
    Terminal.app control.
    """
    metadata = _registry_metadata_from_row(row)
    broker_id = str(metadata.get("broker_id") or "").strip()
    if metadata.get("capture_backend") != "pty_broker" and not broker_id:
        return None
    return broker_id or _qualified_session_id(provider, native_id)


class _AgentRegistryReadSnapshot:
    """One immutable provider view used by a session-list request.

    Session collection resolves the same native ids many times while shaping
    transcript, state, and terminal rows. Reading those identities from one
    SQLite snapshot keeps the result internally consistent and avoids opening
    a new connection for every lookup. Callers always receive mutable copies;
    the captured rows and indexes cannot be changed in place.
    """

    __slots__ = (
        "provider",
        "_rows",
        "_by_native_id",
        "_by_send_scope_id",
        "_by_broker_id",
        "_send_scope_counts",
        "_broker_live_counts",
        "_broker_total_counts",
    )

    def __init__(
        self,
        provider: str,
        rows: list[dict],
        *,
        send_scope_counts: dict[str, int] | None = None,
        broker_live_counts: dict[str, int] | None = None,
        broker_total_counts: dict[str, int] | None = None,
    ):
        self.provider = str(provider or "").strip().lower()
        ordered_rows = sorted(
            (dict(row) for row in rows if row.get("provider") == self.provider),
            key=lambda row: float(row.get("last_heartbeat") or 0),
            reverse=True,
        )
        frozen_rows = tuple(MappingProxyType(row) for row in ordered_rows)
        by_native_id = {}
        by_send_scope_id: dict[str, list[MappingProxyType]] = {}
        by_broker_id: dict[str, list[MappingProxyType]] = {}
        for row in frozen_rows:
            native_id = str(row.get("native_id") or "")
            if native_id:
                by_native_id.setdefault(native_id, row)
            if row.get("closed_at") is None:
                send_scope_id = _durable_send_scope_id_from_registry_row(
                    row,
                    provider=self.provider,
                    native_id=native_id,
                )
                if send_scope_id:
                    by_send_scope_id.setdefault(send_scope_id, []).append(row)
            raw_broker_id = str(
                _registry_metadata_from_row(row).get("broker_id") or ""
            )
            broker_id = _normalized_send_scope_id(
                self.provider,
                raw_broker_id,
            )
            if broker_id and raw_broker_id == broker_id:
                by_broker_id.setdefault(broker_id, []).append(row)

        self._rows = frozen_rows
        self._by_native_id = MappingProxyType(by_native_id)
        self._by_send_scope_id = MappingProxyType({
            key: tuple(matches) for key, matches in by_send_scope_id.items()
        })
        self._by_broker_id = MappingProxyType({
            key: tuple(matches) for key, matches in by_broker_id.items()
        })
        self._send_scope_counts = MappingProxyType(
            dict(send_scope_counts)
            if send_scope_counts is not None
            else {key: len(matches) for key, matches in by_send_scope_id.items()}
        )
        self._broker_live_counts = MappingProxyType(
            dict(broker_live_counts)
            if broker_live_counts is not None
            else {
                key: sum(row.get("closed_at") is None for row in matches)
                for key, matches in by_broker_id.items()
            }
        )
        self._broker_total_counts = MappingProxyType(
            dict(broker_total_counts)
            if broker_total_counts is not None
            else {key: len(matches) for key, matches in by_broker_id.items()}
        )

    @staticmethod
    def _copy(row) -> dict | None:
        return dict(row) if row is not None else None

    def get(self, native_id: str) -> dict | None:
        return self._copy(self._by_native_id.get(str(native_id or "")))

    def live(self, limit: int) -> list[dict]:
        cap = max(1, min(int(limit or 100), 1000))
        return [dict(row) for row in self._rows if row.get("closed_at") is None][:cap]

    def recent(self, since_min: int, limit: int) -> list[dict]:
        cutoff = _time.time() - max(1, int(since_min or 1)) * 60
        cap = max(1, min(int(limit or 300), 1000))
        return [
            dict(row)
            for row in self._rows
            if float(row.get("last_heartbeat") or 0) >= cutoff
        ][:cap]

    def row_for_send_scope_id(self, send_scope_id: str) -> dict | None:
        identity = str(send_scope_id or "")
        matches = self._by_send_scope_id.get(identity, ())
        if int(self._send_scope_counts.get(identity, 0)) != 1:
            return None
        return self._copy(matches[0]) if len(matches) == 1 else None

    def row_for_broker_id(self, broker_id: str) -> dict | None:
        identity = str(broker_id or "")
        matches = self._by_broker_id.get(identity, ())
        live_matches = [row for row in matches if row.get("closed_at") is None]
        if int(self._broker_live_counts.get(identity, 0)) == 1:
            if len(live_matches) != 1:
                return None
            return self._copy(live_matches[0])
        if int(self._broker_total_counts.get(identity, 0)) != 1:
            return None
        return self._copy(matches[0]) if len(matches) == 1 else None

    def _identity_counts_after_removing(
        self,
        rows: list[dict],
    ) -> tuple[dict[str, int], dict[str, int], dict[str, int]]:
        send_scope_counts = dict(self._send_scope_counts)
        broker_live_counts = dict(self._broker_live_counts)
        broker_total_counts = dict(self._broker_total_counts)

        def decrement(counts: dict[str, int], identity: str) -> None:
            if not identity or identity not in counts:
                return
            remaining = int(counts[identity]) - 1
            if remaining > 0:
                counts[identity] = remaining
            else:
                counts.pop(identity, None)

        for existing in rows:
            native_id = str(existing.get("native_id") or "")
            metadata = _registry_metadata_from_row(existing)
            if existing.get("closed_at") is None:
                decrement(
                    send_scope_counts,
                    _durable_send_scope_id_from_registry_row(
                        existing,
                        provider=self.provider,
                        native_id=native_id,
                    ),
                )
            raw_broker_id = str(metadata.get("broker_id") or "")
            broker_id = _normalized_send_scope_id(self.provider, raw_broker_id)
            if broker_id and raw_broker_id == broker_id:
                decrement(broker_total_counts, broker_id)
                if existing.get("closed_at") is None:
                    decrement(broker_live_counts, broker_id)
        return send_scope_counts, broker_live_counts, broker_total_counts

    def _identity_counts_after_adding(
        self,
        row: dict,
        send_scope_counts: dict[str, int],
        broker_live_counts: dict[str, int],
        broker_total_counts: dict[str, int],
    ) -> None:
        native_id = str(row.get("native_id") or "")
        metadata = _registry_metadata_from_row(row)
        if row.get("closed_at") is None:
            send_scope_id = _durable_send_scope_id_from_registry_row(
                row,
                provider=self.provider,
                native_id=native_id,
            )
            if send_scope_id:
                send_scope_counts[send_scope_id] = (
                    int(send_scope_counts.get(send_scope_id, 0)) + 1
                )
        raw_broker_id = str(metadata.get("broker_id") or "")
        broker_id = _normalized_send_scope_id(self.provider, raw_broker_id)
        if broker_id and raw_broker_id == broker_id:
            broker_total_counts[broker_id] = (
                int(broker_total_counts.get(broker_id, 0)) + 1
            )
            if row.get("closed_at") is None:
                broker_live_counts[broker_id] = (
                    int(broker_live_counts.get(broker_id, 0)) + 1
                )

    def replacing_after_write(self, row: dict) -> "_AgentRegistryReadSnapshot":
        """Return a new request view containing one freshly committed row.

        Codex promotion replaces a temporary pending identity with its canonical
        identity in one transaction. The request that performed that write must
        use the committed identity for the rest of its response instead of
        falling back to the snapshot captured before the transaction.
        """
        fresh = dict(row or {})
        if str(fresh.get("provider") or "").strip().lower() != self.provider:
            return self
        native_id = str(fresh.get("native_id") or "")
        if not native_id:
            return self
        replaced_native_ids = {native_id}
        pending_native_id = str(
            _registry_metadata_from_row(fresh).get("pending_native_id") or ""
        )
        if pending_native_id:
            replaced_native_ids.add(pending_native_id)
        replaced_rows = [
            dict(existing)
            for existing in self._rows
            if str(existing.get("native_id") or "") in replaced_native_ids
        ]
        rows = [
            dict(existing)
            for existing in self._rows
            if str(existing.get("native_id") or "") not in replaced_native_ids
        ]
        (
            send_scope_counts,
            broker_live_counts,
            broker_total_counts,
        ) = self._identity_counts_after_removing(replaced_rows)
        self._identity_counts_after_adding(
            fresh,
            send_scope_counts,
            broker_live_counts,
            broker_total_counts,
        )
        rows.append(fresh)
        return _AgentRegistryReadSnapshot(
            self.provider,
            rows,
            send_scope_counts=send_scope_counts,
            broker_live_counts=broker_live_counts,
            broker_total_counts=broker_total_counts,
        )


_agent_registry_read_snapshot_state = threading.local()


def _current_agent_registry_read_snapshot(
    provider: str,
) -> _AgentRegistryReadSnapshot | None:
    snapshot = getattr(_agent_registry_read_snapshot_state, "snapshot", None)
    if (
        isinstance(snapshot, _AgentRegistryReadSnapshot)
        and snapshot.provider == str(provider or "").strip().lower()
    ):
        return snapshot
    return None


_AGENT_REGISTRY_READ_SNAPSHOT_LIVE_LIMIT = 1000
_AGENT_REGISTRY_READ_SNAPSHOT_CLOSED_LIMIT = 1000


@contextmanager
def _agent_registry_read_snapshot(
    provider: str,
    active_within_min: int = 60 * 24,
):
    provider = str(provider or "").strip().lower()
    cutoff = _time.time() - max(1, int(active_within_min or 1)) * 60
    previous = getattr(_agent_registry_read_snapshot_state, "snapshot", None)
    if isinstance(previous, _AgentRegistryReadSnapshot) and previous.provider == provider:
        yield previous
        return
    snapshot = None
    try:
        with _agent_registry_conn() as conn:
            # Live rows have their own high cap, well above the supported 24
            # live lanes, so closed history can never crowd them out. Closed
            # history is limited to the request window and the same maximum
            # used by the public registry helpers.
            if not conn.in_transaction:
                conn.execute("BEGIN")
            live_rows = conn.execute(
                "SELECT * FROM agent_sessions WHERE provider = ? "
                "AND closed_at IS NULL ORDER BY last_heartbeat DESC LIMIT ?",
                (provider, _AGENT_REGISTRY_READ_SNAPSHOT_LIVE_LIMIT),
            ).fetchall()
            closed_rows = conn.execute(
                "SELECT * FROM agent_sessions WHERE provider = ? "
                "AND closed_at IS NOT NULL AND last_heartbeat >= ? "
                "ORDER BY last_heartbeat DESC LIMIT ?",
                (
                    provider,
                    cutoff,
                    _AGENT_REGISTRY_READ_SNAPSHOT_CLOSED_LIMIT,
                ),
            ).fetchall()
            identity_rows = conn.execute(
                "SELECT "
                "CASE WHEN json_valid(metadata_json) "
                "THEN json_extract(metadata_json, '$.send_scope_id') END "
                "AS send_scope_id, "
                "CASE WHEN json_valid(metadata_json) "
                "THEN json_extract(metadata_json, '$.broker_id') END "
                "AS broker_id, "
                "CASE WHEN closed_at IS NULL THEN 1 ELSE 0 END AS is_live, "
                "COUNT(*) AS row_count "
                "FROM agent_sessions WHERE provider = ? "
                "GROUP BY send_scope_id, broker_id, is_live",
                (provider,),
            ).fetchall()
        send_scope_counts: dict[str, int] = {}
        broker_live_counts: dict[str, int] = {}
        broker_total_counts: dict[str, int] = {}
        for identity_row in identity_rows:
            row_count = int(identity_row["row_count"] or 0)
            if row_count <= 0:
                continue
            raw_broker_id = str(identity_row["broker_id"] or "")
            broker_id = _normalized_send_scope_id(provider, raw_broker_id)
            is_live = bool(identity_row["is_live"])
            if broker_id and raw_broker_id == broker_id:
                broker_total_counts[broker_id] = (
                    broker_total_counts.get(broker_id, 0) + row_count
                )
                if is_live:
                    broker_live_counts[broker_id] = (
                        broker_live_counts.get(broker_id, 0) + row_count
                    )
            if is_live:
                send_scope_id = _normalized_send_scope_id(
                    provider,
                    identity_row["send_scope_id"],
                ) or broker_id
                if send_scope_id:
                    send_scope_counts[send_scope_id] = (
                        send_scope_counts.get(send_scope_id, 0) + row_count
                    )
        snapshot = _AgentRegistryReadSnapshot(
            provider,
            [dict(row) for row in [*live_rows, *closed_rows]],
            send_scope_counts=send_scope_counts,
            broker_live_counts=broker_live_counts,
            broker_total_counts=broker_total_counts,
        )
    except Exception:
        # Preserve the existing per-lookup fallback if the bounded snapshot
        # cannot be captured. Session truth must degrade, not disappear.
        snapshot = None
    _agent_registry_read_snapshot_state.snapshot = snapshot
    try:
        yield snapshot
    finally:
        _agent_registry_read_snapshot_state.snapshot = previous


@contextmanager
def _agent_registry_read_snapshot_disabled():
    previous = getattr(_agent_registry_read_snapshot_state, "snapshot", None)
    _agent_registry_read_snapshot_state.snapshot = None
    try:
        yield
    finally:
        _agent_registry_read_snapshot_state.snapshot = previous


def _agent_registry_read_snapshot_replace_after_write(
    provider: str,
    row: dict | None,
) -> None:
    snapshot = _current_agent_registry_read_snapshot(provider)
    if snapshot is None or not isinstance(row, dict):
        return
    _agent_registry_read_snapshot_state.snapshot = snapshot.replacing_after_write(row)


def _agent_registry_resolve_native_alias(provider: str, native_id: str) -> str:
    """Return the canonical native id for an exact promoted alias."""
    provider = str(provider or "").strip().lower()
    native_id = str(native_id or "").strip()
    if not native_id or provider not in {"claude", "codex", "omp"}:
        return native_id
    direct = _agent_registry_get(provider, native_id)
    if direct is not None and not direct.get("closed_at"):
        return native_id
    row = _agent_registry_row_for_send_scope_id(
        provider, _qualified_session_id(provider, native_id)
    )
    if row:
        return str(row.get("native_id") or native_id)
    row = _agent_registry_row_for_broker_id(
        provider, _qualified_session_id(provider, native_id)
    )
    return str(row.get("native_id") or native_id) if row else native_id


def _agent_registry_link_claude_launch_registration(
    canonical_native_id: str,
    project: str,
    *,
    pid: int,
    terminal_tty: str,
    claude_uuid: str,
    working_on: str,
) -> dict:
    """Atomically promote one exact pending Claude launch to its hook id."""
    canonical_native_id = str(canonical_native_id or "").strip()
    project = str(project or "").strip()
    pid = int(pid or 0)
    terminal_tty = str(terminal_tty or "").strip()
    claude_uuid = str(claude_uuid or "").strip()
    working_on = str(working_on or "")[:500]
    if (
        not _safe_session_id(canonical_native_id)
        or not project
        or pid <= 0
        or not claude_uuid
    ):
        return {"state": "not_applicable"}

    now = _time.time()
    try:
        with _session_tombstone_reopen_guard() as track_reopen:
            track_reopen("claude", canonical_native_id)
            with _agent_registry_conn() as conn:
                conn.execute("BEGIN IMMEDIATE")
                existing_raw = conn.execute(
                    "SELECT * FROM agent_sessions WHERE provider = 'claude' "
                    "AND native_id = ? LIMIT 1",
                    (canonical_native_id,),
                ).fetchone()
                existing = dict(existing_raw) if existing_raw else None
                existing_metadata = _registry_metadata_from_row(existing)
                existing_send_scope_id = _durable_send_scope_id_from_registry_row(
                    existing,
                    provider="claude",
                    native_id=canonical_native_id,
                )
                if existing_send_scope_id:
                    expected_pid = int(existing.get("pid") or 0) if existing else 0
                    existing_provider_tty = str(
                        existing_metadata.get("provider_tty") or ""
                    )
                    if (
                        str(existing.get("project") or "") != project
                        or (expected_pid and expected_pid != pid)
                        or (
                            terminal_tty
                            and str(existing.get("terminal_tty") or "")
                            not in {"", terminal_tty}
                            and terminal_tty != existing_provider_tty
                        )
                        or str(existing.get("claude_uuid") or "") not in {"", claude_uuid}
                    ):
                        return {"state": "conflict", "reason": "canonical_identity_changed"}
                    merged_metadata = dict(existing_metadata)
                    merged_metadata.update({
                        "send_scope_id": existing_send_scope_id,
                        "canonical_native_id": canonical_native_id,
                        "registered_by": "internal_session_register",
                    })
                    stored_terminal_tty = str(existing.get("terminal_tty") or "")
                    next_terminal_tty = (
                        stored_terminal_tty
                        if existing_provider_tty
                        and terminal_tty == existing_provider_tty
                        else terminal_tty
                    )
                    conn.execute(
                        "UPDATE agent_sessions SET project=?, pid=?, "
                        "terminal_tty=COALESCE(NULLIF(?, ''), terminal_tty), "
                        "state='running', last_heartbeat=?, closed_at=NULL, "
                        "metadata_json=?, claude_uuid=?, working_on=? "
                        "WHERE provider='claude' AND native_id=?",
                        (
                            project,
                            pid,
                            next_terminal_tty,
                            now,
                            json.dumps(merged_metadata, sort_keys=True),
                            claude_uuid,
                            working_on,
                            canonical_native_id,
                        ),
                    )
                    result = {
                        "state": "already_linked",
                        "canonical_native_id": canonical_native_id,
                        "pending_native_id": str(
                            existing_metadata.get("pending_native_id")
                            or existing_metadata.get("broker_native_id")
                            or ""
                        ),
                        "broker_native_id": str(existing_metadata.get("broker_native_id") or ""),
                        "broker_id": str(existing_metadata.get("broker_id") or ""),
                        "send_scope_id": existing_send_scope_id,
                    }
                else:
                    pending_rows = [
                        dict(row)
                        for row in conn.execute(
                            "SELECT * FROM agent_sessions WHERE provider='claude' "
                            "AND native_id LIKE 'pending-%' AND project=? AND pid=? "
                            "AND closed_at IS NULL ORDER BY started_at DESC LIMIT 3",
                            (project, pid),
                        ).fetchall()
                    ]
                    valid_pending = []
                    for row in pending_rows:
                        pending_native_id = str(row.get("native_id") or "")
                        metadata = _registry_metadata_from_row(row)
                        send_scope_id = _durable_send_scope_id_from_registry_row(
                            row,
                            provider="claude",
                            native_id=pending_native_id,
                        )
                        expected_scope = _qualified_session_id(
                            "claude", pending_native_id
                        )
                        broker_id = _normalized_send_scope_id(
                            "claude", metadata.get("broker_id")
                        )
                        capture_backend = str(metadata.get("capture_backend") or "")
                        script_binding = bool(
                            capture_backend == "script"
                            and str(metadata.get("provider_tty") or "")
                            == terminal_tty
                            and _direct_terminal_binding_is_verified(
                                row,
                                "claude",
                                pid,
                                provider_tty=terminal_tty,
                            )
                        )
                        exact_tty = (
                            not terminal_tty
                            or str(row.get("terminal_tty") or "") == terminal_tty
                            or script_binding
                        )
                        if (
                            send_scope_id == expected_scope
                            and exact_tty
                            and (
                                (
                                    capture_backend == "pty_broker"
                                    and broker_id == expected_scope
                                )
                                or (
                                    capture_backend == "script"
                                    and not broker_id
                                )
                            )
                        ):
                            valid_pending.append(
                                (row, metadata, send_scope_id, broker_id)
                            )
                    if len(pending_rows) > 1 or len(valid_pending) != 1:
                        if pending_rows:
                            return {
                                "state": "ambiguous",
                                "reason": "pending_launch_identity_unverified",
                            }
                        return {"state": "not_found"}

                    pending, pending_metadata, send_scope_id, broker_id = valid_pending[0]
                    pending_native_id = str(pending.get("native_id") or "")
                    if existing is not None:
                        if (
                            str(existing.get("project") or "") != project
                            or int(existing.get("pid") or 0) not in {0, pid}
                            or str(existing.get("claude_uuid") or "") not in {"", claude_uuid}
                        ):
                            return {"state": "conflict", "reason": "canonical_identity_changed"}
                    merged_metadata = dict(_registry_metadata_from_row(existing))
                    merged_metadata.update(pending_metadata)
                    merged_metadata.update({
                        "send_scope_id": send_scope_id,
                        "pending_native_id": pending_native_id,
                        "canonical_native_id": canonical_native_id,
                        "identity_link": "exact_pid_project",
                        "registered_by": "internal_session_register",
                    })
                    if broker_id:
                        merged_metadata.update({
                            "broker_id": broker_id,
                            "broker_native_id": pending_native_id,
                        })
                    pending_tty = str(pending.get("terminal_tty") or "")
                    capture_backend = str(
                        pending_metadata.get("capture_backend") or ""
                    )
                    chosen_tty = (
                        pending_tty
                        if capture_backend == "script"
                        else terminal_tty or pending_tty
                    ) or str((existing or {}).get("terminal_tty") or "")
                    started_at = float(
                        (existing or {}).get("started_at")
                        or pending.get("started_at")
                        or now
                    )
                    conn.execute(
                        """
                        INSERT INTO agent_sessions
                            (provider, native_id, project, pid, terminal_tty, state,
                             started_at, last_heartbeat, closed_at, metadata_json,
                             claude_uuid, working_on)
                        VALUES ('claude', ?, ?, ?, ?, 'running', ?, ?, NULL, ?, ?, ?)
                        ON CONFLICT(provider, native_id) DO UPDATE SET
                            project=excluded.project,
                            pid=excluded.pid,
                            terminal_tty=excluded.terminal_tty,
                            state='running',
                            last_heartbeat=excluded.last_heartbeat,
                            closed_at=NULL,
                            metadata_json=excluded.metadata_json,
                            claude_uuid=excluded.claude_uuid,
                            working_on=excluded.working_on
                        """,
                        (
                            canonical_native_id,
                            project,
                            pid,
                            chosen_tty,
                            started_at,
                            now,
                            json.dumps(merged_metadata, sort_keys=True),
                            claude_uuid,
                            working_on,
                        ),
                    )
                    deleted = conn.execute(
                        "DELETE FROM agent_sessions WHERE provider='claude' "
                        "AND native_id=? AND project=? AND pid=? "
                        "AND terminal_tty=? AND metadata_json=? "
                        "AND closed_at IS NULL",
                        (
                            pending_native_id,
                            project,
                            int(pending.get("pid") or 0),
                            str(pending.get("terminal_tty") or ""),
                            str(pending.get("metadata_json") or ""),
                        ),
                    )
                    if deleted.rowcount != 1:
                        raise RuntimeError("pending broker identity changed during registration")
                    result = {
                        "state": "linked",
                        "canonical_native_id": canonical_native_id,
                        "pending_native_id": pending_native_id,
                        "broker_native_id": pending_native_id if broker_id else "",
                        "broker_id": broker_id,
                        "send_scope_id": send_scope_id,
                    }
                # Keep the registry promotion uncommitted until the durable
                # removal receipt is cleared. A tombstone store failure must
                # roll back the canonical insert and pending-row delete rather
                # than report failure after the identity already changed.
                _clear_session_tombstone_for_reopen("claude", canonical_native_id)
    except Exception as exc:
        return {"state": "error", "reason": type(exc).__name__}

    _invalidate_sessions_provider_inventory("claude")
    _invalidate_session_list_caches()
    identity_event = {
        "type": "session_identity_linked",
        "provider": "claude",
        "native_id": canonical_native_id,
        "send_scope_id": result.get("send_scope_id"),
        "broker_id": result.get("broker_id"),
        "project": project,
        "heartbeat_at": now,
    }
    _publish_session_event(SESSION_SUMMARIES_TOPIC, identity_event)
    send_scope_id = str(result.get("send_scope_id") or "")
    if send_scope_id:
        # Viewers opened against the temporary identity do not listen to the
        # summaries topic. Wake their exact terminal topic immediately.
        _publish_session_event(f"terminal:{send_scope_id}", dict(identity_event))
    return result


def _session_launch_context_from_metadata(metadata: dict | None) -> dict | None:
    if not isinstance(metadata, dict):
        return None
    strategy = str(metadata.get("launch_strategy") or "").strip()
    if strategy == "aperture_cli":
        redacted_env = metadata.get("generated_env_redacted")
        if not isinstance(redacted_env, dict):
            redacted_env = {}
        config_writes = metadata.get("config_writes")
        if not isinstance(config_writes, list):
            config_writes = []
        return {
            "strategy": "aperture_cli",
            "summary": "Launched through Aperture CLI",
            "client_id": metadata.get("client_id"),
            "endpoint_url": metadata.get("aperture_endpoint_url"),
            "endpoint_mode": metadata.get("aperture_endpoint_mode"),
            "aperture_provider_id": metadata.get("aperture_provider_id"),
            "backend_id": metadata.get("aperture_backend_id"),
            "model": metadata.get("aperture_model"),
            "danger_mode": bool(metadata.get("danger_mode")),
            "generated_config_home": redacted_env.get("CODEX_HOME"),
            "config_writes": [str(item) for item in config_writes if item],
            "aperture_cli_version": metadata.get("aperture_cli_version"),
        }
    if strategy == "direct_pairling":
        return {
            "strategy": "direct_pairling",
            "summary": "Launched directly by Pairling",
            "danger_mode": bool(metadata.get("danger_mode")),
        }
    return None


def _session_launch_context_for_identity(provider: str, native_id: str) -> dict | None:
    """Resolve launch metadata only through an exact durable session identity."""
    provider = str(provider or "").strip().lower()
    native_id = str(native_id or "").strip()
    if provider not in {"claude", "codex"} or not native_id:
        return None

    canonical_native_id = _agent_registry_resolve_native_alias(provider, native_id)
    registry_row = _agent_registry_get(provider, canonical_native_id)
    if registry_row is None and provider == "claude":
        # Export callers may hold the transcript UUID instead of the durable
        # session row id. This lookup is exact and rejects recency guesses.
        registry_row = _agent_registry_get_by_claude_uuid(provider, native_id)
    return _session_launch_context_from_metadata(
        _registry_metadata_from_row(registry_row)
    )


def _append_launch_frontmatter(front: list[str], launch_context: dict | None) -> None:
    if not isinstance(launch_context, dict):
        return
    strategy = str(launch_context.get("strategy") or "").strip()
    if not strategy:
        return
    front.append(f"launch_strategy: {strategy}")
    if strategy != "aperture_cli":
        return
    for key, value in [
        ("aperture_endpoint", launch_context.get("endpoint_url")),
        ("aperture_provider", launch_context.get("aperture_provider_id")),
        ("aperture_backend", launch_context.get("backend_id")),
        ("model", launch_context.get("model")),
        ("danger_mode", "true" if launch_context.get("danger_mode") is True else "false"),
    ]:
        if value is None:
            continue
        text = str(value).replace("\n", " ").strip()
        if text:
            front.append(f"{key}: {text}")


def _apply_launch_context_to_session_row(row: dict, metadata: dict | None) -> dict:
    launch_context = _session_launch_context_from_metadata(metadata)
    if launch_context is None:
        return row
    row["launch_context"] = launch_context
    if launch_context.get("strategy") == "aperture_cli" and launch_context.get("model") and not row.get("model"):
        row["model"] = launch_context.get("model")
    return row


def _agent_registry_live(provider: str, *, limit: int = 100) -> list[dict]:
    limit = max(1, min(int(limit or 100), 1000))
    snapshot = _current_agent_registry_read_snapshot(provider)
    if snapshot is not None:
        return snapshot.live(limit)
    try:
        with _agent_registry_conn() as conn:
            rows = conn.execute(
                "SELECT * FROM agent_sessions "
                "WHERE provider = ? AND closed_at IS NULL "
                "ORDER BY last_heartbeat DESC LIMIT ?",
                (provider, limit),
            ).fetchall()
            return [dict(r) for r in rows]
    except Exception:
        return []


def _agent_registry_recent(
    provider: str,
    since_min: int = 60 * 24,
    limit: int = 300,
    *,
    strict: bool = False,
) -> list[dict]:
    cutoff = _time.time() - max(1, int(since_min or 1)) * 60
    limit = max(1, min(int(limit or 300), 1000))
    snapshot = _current_agent_registry_read_snapshot(provider)
    if snapshot is not None:
        return snapshot.recent(since_min, limit)
    try:
        with _agent_registry_conn() as conn:
            rows = conn.execute(
                "SELECT * FROM agent_sessions "
                "WHERE provider = ? AND last_heartbeat >= ? "
                "ORDER BY last_heartbeat DESC LIMIT ?",
                (provider, cutoff, limit),
            ).fetchall()
            return [dict(r) for r in rows]
    except Exception:
        if strict:
            raise
        return []


def _codex_spawn_pending_registry_rows(
    project: str,
    observed_started_at: float,
    *,
    registry_rows: list[dict] | None = None,
) -> list[dict]:
    observed_started_at = float(observed_started_at or 0)
    return [
        row for row in (
            registry_rows
            if registry_rows is not None
            else _agent_registry_live("codex", limit=1000)
        )
        if row.get("native_id", "").startswith("pending-")
        and row.get("project") == project
        and (
            observed_started_at <= 0
            or float(row.get("started_at") or 0) - 5 <= observed_started_at <= float(row.get("started_at") or 0) + 300
        )
    ]


def _agent_registry_mark_closed(provider: str, native_id: str) -> None:
    changed = False
    try:
        with _agent_registry_conn() as conn:
            cursor = conn.execute(
                "UPDATE agent_sessions SET closed_at = ?, state = 'terminated' "
                "WHERE provider = ? AND native_id = ? AND closed_at IS NULL",
                (_time.time(), provider, native_id),
            )
            changed = bool(cursor.rowcount)
    except Exception:
        pass
    if changed:
        _invalidate_sessions_provider_inventory(provider)
        _invalidate_session_list_caches()


def _agent_registry_update_control(provider: str, native_id: str, *,
                                   pid: int | None = None,
                                   terminal_tty: str | None = None,
                                   state: str | None = None,
                                   claude_uuid: str | None = None,
                                   working_on: str | None = None,
                                   reopen: bool = False) -> None:
    assignments = ["last_heartbeat = ?"]
    params: list[object] = [_time.time()]
    if pid is not None:
        assignments.append("pid = ?")
        params.append(int(pid or 0))
    if terminal_tty is not None:
        assignments.append("terminal_tty = ?")
        params.append(terminal_tty)
    if state is not None:
        assignments.append("state = ?")
        params.append(state)
    if claude_uuid is not None:
        assignments.append("claude_uuid = ?")
        params.append(claude_uuid)
    if working_on is not None:
        assignments.append("working_on = ?")
        params.append(working_on)
    if reopen:
        assignments.append("closed_at = NULL")
    params.extend([provider, native_id])
    membership_changed = False
    try:
        with _session_tombstone_reopen_guard() as track_reopen:
            if reopen:
                track_reopen(provider, native_id)
            with _agent_registry_conn() as conn:
                previous = conn.execute(
                    "SELECT pid, terminal_tty, closed_at FROM agent_sessions "
                    "WHERE provider = ? AND native_id = ?",
                    (provider, native_id),
                ).fetchone()
                cursor = conn.execute(
                    f"UPDATE agent_sessions SET {', '.join(assignments)} "
                    "WHERE provider = ? AND native_id = ?",
                    tuple(params),
                )
                changed = cursor.rowcount > 0
                if reopen and changed:
                    _clear_session_tombstone_for_reopen(provider, native_id)
                membership_changed = bool(
                    changed
                    and previous is not None
                    and (
                        (reopen and previous["closed_at"] is not None)
                        or (
                            pid is not None
                            and int(previous["pid"] or 0) != int(pid or 0)
                        )
                        or (
                            terminal_tty is not None
                            and str(previous["terminal_tty"] or "")
                            != terminal_tty
                        )
                    )
                )
    except Exception:
        return
    if membership_changed:
        _invalidate_sessions_provider_inventory(provider)
        _invalidate_session_list_caches()


def _close_codex_terminal_placeholders(tty: str, canonical_native_id: str) -> None:
    if not tty:
        return
    for row in _agent_registry_live("codex"):
        native_id = str(row.get("native_id") or "")
        if (
            native_id != canonical_native_id
            and native_id.startswith("terminal-")
            and row.get("terminal_tty") == tty
        ):
            _agent_registry_mark_closed("codex", native_id)


def _bind_codex_registry_to_terminal(
    native_id: str,
    project: str,
    discovered: dict,
    *,
    discovered_by: str,
) -> dict | None:
    """Atomically bind one discovered Codex process to its canonical rollout.

    A pending launch row is consumed only when PID, TTY, project, and its
    durable send identity all match. The canonical write and pending delete
    share one SQLite transaction, so neither identity can be lost or doubled
    by a partial failure.
    """
    native_id = str(native_id or "").strip()
    provider_tty = str(
        discovered.get("provider_tty") or discovered.get("tty") or ""
    )
    observed_terminal_tty = str(
        discovered.get("terminal_tty") or provider_tty
    )
    try:
        pid = int(discovered.get("pid") or 0)
        observed_terminal_owner_pid = int(
            discovered.get("terminal_owner_pid") or 0
        )
        observed_terminal_owner_started_at = float(
            discovered.get("terminal_owner_process_started_at") or 0
        )
        observed_process_started_at = float(
            discovered.get("started_at") or 0
        )
    except (TypeError, ValueError):
        return _agent_registry_get("codex", native_id)
    canonical_project = str(discovered.get("project") or project or "")
    output_path = str(discovered.get("output_path") or "")
    has_inventory_topology = bool(
        str(discovered.get("identity_probe_state") or "") == "exact"
        and discovered.get("terminal_tty")
        and observed_process_started_at > 0
    )
    if (
        not _safe_agent_native_id(native_id)
        or not canonical_project
        or pid <= 0
        or re.fullmatch(r"/dev/ttys[0-9]{3,}", provider_tty) is None
        or re.fullmatch(r"/dev/ttys[0-9]{3,}", observed_terminal_tty) is None
        or (
            observed_terminal_tty != provider_tty
            and (
                observed_terminal_owner_pid <= 0
                or observed_terminal_owner_started_at <= 0
            )
        )
    ):
        return _agent_registry_get("codex", native_id)
    approved_output_path = (
        _approved_codex_transcript_path(Path(output_path), native_id)
        if output_path
        else None
    )
    if approved_output_path is None:
        return _agent_registry_get("codex", native_id)
    output_path = str(approved_output_path)

    def terminal_topology_matches(registry_row: dict) -> bool:
        if has_inventory_topology:
            return _codex_inventory_registry_process_matches(
                registry_row, [discovered]
            )
        return _direct_terminal_binding_is_verified(
            registry_row,
            "codex",
            pid,
            provider_tty=provider_tty,
        )

    now = _time.time()
    linked_send_scope_id = ""
    linked_broker_id = ""
    registry_changed = False
    tombstone_cleared = False
    try:
        with _session_tombstone_reopen_guard() as track_reopen:
            track_reopen("codex", native_id)
            with _agent_registry_conn() as conn:
                conn.execute("BEGIN IMMEDIATE")
                exact_raw = conn.execute(
                    "SELECT * FROM agent_sessions WHERE provider='codex' "
                    "AND native_id=? LIMIT 1",
                    (native_id,),
                ).fetchone()
                exact = dict(exact_raw) if exact_raw else None
                exact_metadata = _registry_metadata_from_row(exact)
                exact_send_scope_id = _durable_send_scope_id_from_registry_row(
                    exact,
                    provider="codex",
                    native_id=native_id,
                )
                closed_exact_rebind = bool(
                    exact is not None
                    and exact.get("closed_at") is not None
                    and approved_output_path is not None
                )
                if exact is not None:
                    exact_project = str(exact.get("project") or "")
                    exact_pid = int(exact.get("pid") or 0)
                    exact_tty = str(exact.get("terminal_tty") or "")
                    exact_provider_tty = str(
                        exact_metadata.get("provider_tty") or ""
                    )
                    exact_script_binding = bool(
                        exact.get("closed_at") is None
                        and exact_provider_tty == provider_tty
                        and terminal_topology_matches(exact)
                    )
                    identity_conflict = (
                        bool(exact_project and exact_project != canonical_project)
                        or bool(
                            exact_tty
                            and exact_tty != provider_tty
                            and not exact_script_binding
                        )
                        or bool(
                            not exact_tty
                            and exact_pid not in {0, pid}
                            and _process_alive(exact_pid)
                        )
                    )
                    if exact.get("closed_at") is not None and not closed_exact_rebind:
                        return exact
                    if identity_conflict and not closed_exact_rebind:
                        return exact

                pending_rows = [
                    dict(row)
                    for row in conn.execute(
                        "SELECT * FROM agent_sessions WHERE provider='codex' "
                        "AND native_id LIKE 'pending-%' AND project=? AND pid=? "
                        "AND closed_at IS NULL "
                        "ORDER BY started_at DESC LIMIT 3",
                        (canonical_project, pid),
                    ).fetchall()
                ]
                pending_owner = None
                pending_metadata: dict = {}
                valid_pending_rows: list[tuple[dict, dict]] = []
                for candidate in pending_rows:
                    candidate_native_id = str(candidate.get("native_id") or "")
                    candidate_metadata = _registry_metadata_from_row(candidate)
                    candidate_scope = _durable_send_scope_id_from_registry_row(
                        candidate,
                        provider="codex",
                        native_id=candidate_native_id,
                    )
                    expected_scope = _qualified_session_id(
                        "codex", candidate_native_id
                    )
                    capture_backend = str(
                        candidate_metadata.get("capture_backend") or ""
                    )
                    candidate_broker_id = _normalized_send_scope_id(
                        "codex", candidate_metadata.get("broker_id")
                    )
                    valid_capture = capture_backend in {"pty_broker", "script"}
                    valid_broker = (
                        capture_backend != "pty_broker"
                        or candidate_broker_id == expected_scope
                    )
                    candidate_terminal_tty = str(
                        candidate.get("terminal_tty") or ""
                    )
                    exact_terminal_topology = bool(
                        (
                            capture_backend == "pty_broker"
                            and candidate_terminal_tty == provider_tty
                        )
                        or (
                            capture_backend == "script"
                            and str(candidate_metadata.get("provider_tty") or "")
                            == provider_tty
                            and terminal_topology_matches(candidate)
                        )
                    )
                    if (
                        candidate_scope == expected_scope
                        and valid_capture
                        and valid_broker
                        and exact_terminal_topology
                    ):
                        valid_pending_rows.append((candidate, candidate_metadata))
                if pending_rows and len(valid_pending_rows) != 1:
                    return exact
                if len(valid_pending_rows) == 1:
                    pending_owner, pending_metadata = valid_pending_rows[0]

                pending_send_scope_id = _durable_send_scope_id_from_registry_row(
                    pending_owner,
                    provider="codex",
                    native_id=str((pending_owner or {}).get("native_id") or ""),
                )
                if (
                    pending_send_scope_id
                    and exact_send_scope_id
                    and pending_send_scope_id != exact_send_scope_id
                    and not closed_exact_rebind
                ):
                    return exact

                metadata = dict(exact_metadata)
                if closed_exact_rebind:
                    for stale_key in (
                        "broker_id",
                        "broker_native_id",
                        "capture_backend",
                        "terminal_source",
                        "terminal_capture_log",
                        "send_scope_id",
                        "pending_native_id",
                        "provider_tty",
                        "terminal_owner_pid",
                        "terminal_owner_process_started_at",
                        "process_started_at",
                    ):
                        metadata.pop(stale_key, None)
                metadata.update(pending_metadata)
                metadata.pop("terminal_only", None)
                if pending_owner is not None:
                    pending_native_id = str(pending_owner.get("native_id") or "")
                    linked_send_scope_id = pending_send_scope_id
                    linked_broker_id = _normalized_send_scope_id(
                        "codex", pending_metadata.get("broker_id")
                    )
                    identity_link = (
                        "exact_delivered_first_prompt_pid_project_terminal_topology"
                        if discovered_by == "delivered_first_prompt"
                        else "exact_pid_project_terminal_topology"
                    )
                    metadata.update({
                        "send_scope_id": linked_send_scope_id,
                        "pending_native_id": pending_native_id,
                        "canonical_native_id": native_id,
                        "identity_link": identity_link,
                    })
                    if linked_broker_id:
                        metadata.update({
                            "broker_id": linked_broker_id,
                            "broker_native_id": pending_native_id,
                            "capture_backend": "pty_broker",
                            "terminal_source": str(
                                pending_metadata.get("terminal_source")
                                or "broker_vt"
                            ),
                        })
                metadata.update({
                    "discovered_by": discovered_by,
                    "provider_tty": provider_tty,
                    "command": str(
                        discovered.get("command") or metadata.get("command") or ""
                    )[:500],
                })
                if observed_terminal_tty != provider_tty:
                    metadata.update({
                        "terminal_owner_pid": observed_terminal_owner_pid,
                        "terminal_owner_process_started_at": (
                            observed_terminal_owner_started_at
                        ),
                    })
                process_started_at = float(
                    observed_process_started_at or _process_start_epoch(pid) or 0
                )
                if process_started_at > 0:
                    metadata["process_started_at"] = process_started_at
                if output_path:
                    metadata["output_path"] = output_path
                elif exact_metadata.get("output_path"):
                    metadata["output_path"] = exact_metadata["output_path"]
                process_project = str(discovered.get("process_project") or "")
                if process_project and process_project != canonical_project:
                    metadata["process_project"] = process_project

                canonical_tty = observed_terminal_tty
                if pending_owner is not None:
                    canonical_tty = str(
                        pending_owner.get("terminal_tty") or provider_tty
                    )
                elif exact is not None and not closed_exact_rebind:
                    exact_provider_tty = str(
                        exact_metadata.get("provider_tty") or ""
                    )
                    if exact_provider_tty == provider_tty:
                        exact_terminal_tty = str(
                            exact.get("terminal_tty") or provider_tty
                        )
                        if exact_terminal_tty != provider_tty:
                            canonical_tty = exact_terminal_tty

                if canonical_tty == provider_tty:
                    metadata.pop("terminal_owner_pid", None)
                    metadata.pop(
                        "terminal_owner_process_started_at", None
                    )

                started_at = float(
                    (exact or {}).get("started_at")
                    or (pending_owner or {}).get("started_at")
                    or now
                )
                next_state = (
                    "running"
                    if closed_exact_rebind
                    else str((exact or {}).get("state") or "running")
                )
                next_working_on = str((exact or {}).get("working_on") or "")
                registry_changed = bool(
                    exact is None
                    or pending_owner is not None
                    or str(exact.get("project") or "") != canonical_project
                    or int(exact.get("pid") or 0) != pid
                    or str(exact.get("terminal_tty") or "") != canonical_tty
                    or str(exact.get("state") or "") != next_state
                    or exact.get("closed_at") is not None
                    or exact_metadata != metadata
                )
                if registry_changed:
                    conn.execute(
                        """
                        INSERT INTO agent_sessions
                            (provider, native_id, project, pid, terminal_tty, state,
                             started_at, last_heartbeat, closed_at, metadata_json,
                             claude_uuid, working_on)
                        VALUES ('codex', ?, ?, ?, ?, ?, ?, ?, NULL, ?, '', ?)
                        ON CONFLICT(provider, native_id) DO UPDATE SET
                            project=excluded.project,
                            pid=excluded.pid,
                            terminal_tty=excluded.terminal_tty,
                            state=excluded.state,
                            last_heartbeat=excluded.last_heartbeat,
                            closed_at=NULL,
                            metadata_json=excluded.metadata_json,
                            working_on=excluded.working_on
                        """,
                        (
                            native_id,
                            canonical_project,
                            pid,
                            canonical_tty,
                            next_state,
                            started_at,
                            now,
                            json.dumps(metadata, sort_keys=True),
                            next_working_on,
                        ),
                    )
                if pending_owner is not None:
                    deleted = conn.execute(
                        "DELETE FROM agent_sessions WHERE provider='codex' "
                        "AND native_id=? AND project=? AND pid=? "
                        "AND terminal_tty=? AND metadata_json=? "
                        "AND closed_at IS NULL",
                        (
                            str(pending_owner.get("native_id") or ""),
                            canonical_project,
                            pid,
                            str(pending_owner.get("terminal_tty") or ""),
                            str(pending_owner.get("metadata_json") or ""),
                        ),
                    )
                    if deleted.rowcount != 1:
                        raise RuntimeError(
                            "pending Codex identity changed during promotion"
                        )
                tombstone_cleared = _clear_session_tombstone_for_reopen(
                    "codex", native_id
                )
    except Exception:
        return _agent_registry_get("codex", native_id)

    promoted = _agent_registry_get("codex", native_id)
    if promoted is None:
        return None
    if not registry_changed and not tombstone_cleared:
        return promoted
    _close_codex_terminal_placeholders(canonical_tty, native_id)
    _invalidate_sessions_provider_inventory("codex")
    _invalidate_session_list_caches()
    if linked_send_scope_id:
        identity_event = {
            "type": "session_identity_linked",
            "provider": "codex",
            "native_id": native_id,
            "send_scope_id": linked_send_scope_id,
            "broker_id": linked_broker_id or None,
            "project": canonical_project,
            "heartbeat_at": now,
        }
        _publish_session_event(SESSION_SUMMARIES_TOPIC, identity_event)
        _publish_session_event(
            f"terminal:{linked_send_scope_id}",
            dict(identity_event),
        )
    else:
        _publish_session_event(SESSION_SUMMARIES_TOPIC, {
            "type": "session_registered",
            "provider": "codex",
            "native_id": native_id,
            "project": canonical_project,
            "state": str(promoted.get("state") or "running"),
            "working_on": str(promoted.get("working_on") or ""),
            "heartbeat_at": now,
        })
    return promoted


def _codex_user_message_hashes_in_window(
    path: Path,
    native_id: str,
    earliest_at: float,
    latest_at: float,
) -> set[str] | None:
    """Hash timestamped user records in one delivery window."""
    approved = _approved_codex_transcript_path(path, native_id)
    if approved is None:
        return None
    hashes: set[str] = set()
    try:
        with approved.open(encoding="utf-8", errors="replace") as transcript:
            for _, line in zip(range(512), transcript):
                try:
                    obj = json.loads(line)
                except (ValueError, json.JSONDecodeError):
                    continue
                if not isinstance(obj, dict):
                    continue
                if obj.get("type") != "response_item":
                    continue
                payload = (
                    obj.get("payload")
                    if isinstance(obj.get("payload"), dict)
                    else {}
                )
                if (
                    payload.get("type") != "message"
                    or payload.get("role") != "user"
                ):
                    continue
                message_at = _iso_to_epoch(
                    obj.get("timestamp") or payload.get("timestamp")
                )
                if message_at < earliest_at or message_at > latest_at:
                    continue
                content = payload.get("content")
                if isinstance(content, str):
                    text = content
                elif isinstance(content, list):
                    parts: list[str] = []
                    for item in content:
                        if isinstance(item, str):
                            parts.append(item)
                            continue
                        if not isinstance(item, dict):
                            continue
                        value = item.get("text")
                        if not isinstance(value, str):
                            value = item.get("content")
                        if isinstance(value, str):
                            parts.append(value)
                    text = "\n".join(parts)
                else:
                    continue
                if not text:
                    continue
                hashes.add(hashlib.sha256(text.encode("utf-8")).hexdigest())
    except OSError:
        return None
    return hashes


def _codex_unique_attested_rollout_path(
    native_id: str,
    project: str,
    observed_output_path: str,
) -> tuple[Path, dict] | None:
    """Require one exact CLI rollout for the observed canonical identity."""
    if not observed_output_path:
        return None
    approved_observed = _approved_codex_transcript_path(
        Path(observed_output_path), native_id
    )
    if approved_observed is None:
        return None
    observed_meta = _codex_rollout_meta(approved_observed)
    if (
        not isinstance(observed_meta, dict)
        or observed_meta.get("id") != native_id
        or observed_meta.get("cwd") != project
        or observed_meta.get("source") != "cli"
    ):
        return None
    try:
        candidates = list(
            CODEX_SESSIONS_DIR.rglob(f"rollout-*{native_id}.jsonl")
        )
    except OSError:
        return None
    exact_paths: set[Path] = set()
    for candidate in candidates:
        approved = _approved_codex_transcript_path(candidate, native_id)
        if approved is None:
            continue
        meta = _codex_rollout_meta(approved)
        if (
            isinstance(meta, dict)
            and meta.get("id") == native_id
            and meta.get("cwd") == project
            and meta.get("source") == "cli"
        ):
            exact_paths.add(approved)
    if exact_paths != {approved_observed}:
        return None
    return approved_observed, observed_meta


def _codex_attested_prompt_rollout_is_unique(
    native_id: str,
    project: str,
    output_path: Path,
    prompt_hash: str,
    earliest_rollout_at: float,
    latest_rollout_at: float,
    earliest_message_at: float,
    latest_message_at: float,
) -> bool:
    """Reject a prompt proof that could name another new CLI rollout."""
    try:
        candidates = list(CODEX_SESSIONS_DIR.rglob("rollout-*.jsonl"))
    except OSError:
        return False
    matches: set[tuple[str, Path]] = set()
    for candidate in candidates:
        meta = _codex_rollout_meta(candidate)
        if not isinstance(meta, dict):
            continue
        candidate_native_id = str(meta.get("id") or "")
        candidate_started_at = _iso_to_epoch(meta.get("timestamp"))
        if (
            not _safe_agent_native_id(candidate_native_id)
            or meta.get("cwd") != project
            or meta.get("source") != "cli"
            or candidate_started_at < earliest_rollout_at
            or candidate_started_at > latest_rollout_at
        ):
            continue
        approved = _approved_codex_transcript_path(
            candidate, candidate_native_id
        )
        if approved is None:
            return False
        candidate_hashes = _codex_user_message_hashes_in_window(
            approved,
            candidate_native_id,
            earliest_message_at,
            latest_message_at,
        )
        if candidate_hashes is None:
            return False
        if prompt_hash in candidate_hashes:
            matches.add((candidate_native_id, approved))
    return matches == {(native_id, output_path)}


def _codex_delivered_first_prompt_identity_proof(
    native_id: str,
    project: str,
    observed_started_at: float,
    observed_output_path: str,
    process_rows: list[dict],
) -> dict | None:
    """Bind a Pairling spawn when its delivered prompt proves the rollout.

    Codex does not keep its rollout open, so lsof can miss the otherwise exact
    process-to-transcript link. This proof is intentionally narrow: one
    Pairling-owned broker process, one durable delivered prompt, and one CLI
    rollout must all agree on action, prompt hash, project, terminal, and time.
    """
    rollout = _codex_unique_attested_rollout_path(
        native_id, project, observed_output_path
    )
    if rollout is None:
        return None
    output_path, rollout_meta = rollout
    rollout_started_at = _iso_to_epoch(rollout_meta.get("timestamp"))
    if (
        rollout_started_at <= 0
        or abs(rollout_started_at - float(observed_started_at or 0)) > 2
    ):
        return None

    proofs: list[tuple[dict, dict, dict]] = []
    for candidate in _codex_spawn_pending_registry_rows(
        project, observed_started_at
    ):
        pending_native_id = str(candidate.get("native_id") or "")
        candidate_pid = int(candidate.get("pid") or 0)
        candidate_tty = str(candidate.get("terminal_tty") or "")
        metadata = _registry_metadata_from_row(candidate)
        expected_scope = _qualified_session_id("codex", pending_native_id)
        action_id = str(metadata.get("spawn_action_id") or "")
        if (
            str(candidate.get("provider") or "") != "codex"
            or candidate.get("closed_at") is not None
            or not pending_native_id.startswith("pending-")
            or metadata.get("spawned_by") != "pairling"
            or metadata.get("capture_backend") != "pty_broker"
            or _normalized_send_scope_id(
                "codex", metadata.get("broker_id")
            ) != expected_scope
            or _durable_send_scope_id_from_registry_row(
                candidate,
                provider="codex",
                native_id=pending_native_id,
            ) != expected_scope
            or not str(metadata.get("capture_id") or "")
            or not str(metadata.get("terminal_log") or "")
            or not _valid_client_action_id(action_id)
            or re.fullmatch(
                r"[0-9a-f]{64}", str(metadata.get("spawn_body_hash") or "")
            ) is None
            or candidate_pid <= 0
            or re.fullmatch(r"/dev/ttys[0-9]{3,}", candidate_tty) is None
            or not _process_alive(candidate_pid)
            or not _codex_registry_process_birth_matches(
                candidate, candidate_pid
            )
            or not _direct_terminal_binding_is_verified(
                candidate,
                "codex",
                candidate_pid,
                provider_tty=candidate_tty,
            )
        ):
            continue

        delivery = _read_first_prompt_delivery("codex", pending_native_id)
        if not isinstance(delivery, dict):
            continue
        delivery_hash = str(delivery.get("text_hash") or "")
        delivery_state = str(delivery.get("state") or "")
        retained_text = str(delivery.get("text") or "")
        provider_submit_attested = (
            delivery_state in {"awaiting_provider", "indeterminate"}
            and delivery.get("pty_written") is True
            and delivery.get("write_outcome") == "complete"
            and delivery.get("paste_render_confirmed") is True
            and delivery.get("submit_key_written") is True
            and bool(retained_text)
            and hashlib.sha256(retained_text.encode("utf-8")).hexdigest()
            == delivery_hash
        )
        if (
            delivery.get("schema_version") != 1
            or delivery.get("provider") != "codex"
            or delivery.get("native_id") != pending_native_id
            or (
                delivery_state != "delivered"
                and not provider_submit_attested
            )
            or str(delivery.get("client_action_id") or "") != action_id
            or not str(delivery.get("device_id") or "")
            or re.fullmatch(r"[0-9a-f]{64}", delivery_hash) is None
        ):
            continue

        try:
            candidate_started_at = float(candidate.get("started_at") or 0)
            process_started_at = float(
                metadata.get("process_started_at") or 0
            )
            created_at = float(delivery.get("created_at") or 0)
            dispatch_started_at = float(
                delivery.get("dispatch_started_at") or 0
            )
            proof_at = float(
                delivery.get("finished_at")
                or delivery.get("provider_wait_started_at")
                or 0
            )
        except (TypeError, ValueError):
            continue
        proof_window_end = proof_at
        if not (
            candidate_started_at > 0
            and process_started_at > 0
            and abs(candidate_started_at - process_started_at) <= 60
            and candidate_started_at - 1 <= created_at <= candidate_started_at + 10
            and created_at <= dispatch_started_at <= proof_at
            and proof_at <= (
                candidate_started_at
                + FIRST_PROMPT_DELIVERY_TIMEOUT_SECONDS
                + 15
            )
            and process_started_at - 2
            <= rollout_started_at
            <= proof_window_end + 15
        ):
            continue
        if not _codex_attested_prompt_rollout_is_unique(
            native_id,
            project,
            output_path,
            delivery_hash,
            process_started_at - 2,
            proof_window_end + 15,
            dispatch_started_at,
            proof_window_end + 120,
        ):
            continue

        competing_process = False
        for process_row in process_rows:
            if str(process_row.get("project") or "") != project:
                continue
            process_tty = str(process_row.get("tty") or "")
            if not process_tty or process_tty == candidate_tty:
                continue
            try:
                competing_started_at = float(
                    process_row.get("started_at") or 0
                )
            except (TypeError, ValueError):
                competing_started_at = 0
            if (
                competing_started_at <= 0
                or process_started_at - 2
                <= competing_started_at
                <= proof_window_end + 15
            ):
                competing_process = True
                break
        if competing_process:
            continue

        control_rows = [
            row
            for row in process_rows
            if int(row.get("pid") or 0) == candidate_pid
            and str(row.get("tty") or "") == candidate_tty
            and str(row.get("project") or "") == project
        ]
        if len(control_rows) != 1:
            continue
        proofs.append((candidate, metadata, control_rows[0]))

    if len(proofs) != 1:
        return None
    candidate, metadata, control_row = proofs[0]
    return {
        "pid": int(candidate.get("pid") or 0),
        "tty": str(candidate.get("terminal_tty") or ""),
        "project": project,
        "started_at": float(
            control_row.get("started_at")
            or candidate.get("started_at")
            or observed_started_at
        ),
        "command": str(
            control_row.get("command") or metadata.get("command") or ""
        ),
        "native_id": native_id,
        "output_path": str(output_path),
    }


def _agent_registry_promote_codex(
    native_id: str,
    project: str,
    observed_started_at: float,
    observed_output_path: str = "",
) -> dict | None:
    exact = _agent_registry_get("codex", native_id)
    observed_started_at = float(observed_started_at or 0)
    exact_terminal = _codex_discover_terminal_control_for_session(native_id)
    if exact_terminal:
        exact = _bind_codex_registry_to_terminal(
            native_id,
            project,
            exact_terminal,
            discovered_by="open_rollout",
        )
        return exact
    if observed_started_at <= 0:
        return exact
    if exact:
        return exact
    process_probe_ok, process_rows = _scan_provider_process_rows("codex")
    if not process_probe_ok:
        return None
    pending_proofs: list[tuple[dict, str, dict]] = []
    open_rollout_probe_failed = False
    for candidate in _codex_spawn_pending_registry_rows(project, 0):
        if (
            str(candidate.get("provider") or "") != "codex"
            or str(candidate.get("project") or "") != project
            or candidate.get("closed_at") is not None
        ):
            continue
        candidate_pid = int(candidate.get("pid") or 0)
        candidate_tty = str(candidate.get("terminal_tty") or "")
        candidate_metadata = _registry_metadata_from_row(candidate)
        provider_tty = str(
            candidate_metadata.get("provider_tty") or candidate_tty
        )
        if (
            candidate_pid <= 0
            or re.fullmatch(r"/dev/ttys[0-9]{3,}", candidate_tty) is None
            or re.fullmatch(r"/dev/ttys[0-9]{3,}", provider_tty) is None
            or not _process_alive(candidate_pid)
        ):
            continue
        candidate_started_at = float(candidate.get("started_at") or 0)
        process_started_at = _process_start_epoch(candidate_pid)
        if (
            candidate_started_at <= 0
            or process_started_at <= 0
            or process_started_at > candidate_started_at + 5
            or candidate_started_at - process_started_at > 60
        ):
            continue
        if (
            not _codex_registry_process_birth_matches(candidate, candidate_pid)
            or not _direct_terminal_binding_is_verified(
                candidate,
                "codex",
                candidate_pid,
                provider_tty=provider_tty,
            )
        ):
            continue
        family_rows = [
            process
            for process in process_rows
            if str(process.get("tty") or "") == provider_tty
            and str(process.get("project") or "") == project
            and _process_is_descendant_of(
                int(process.get("pid") or 0), candidate_pid
            )
        ]
        verified_family_pids = sorted({
            int(process.get("pid") or 0)
            for process in family_rows
            if int(process.get("pid") or 0) > 0
        })
        control_row = next(
            (
                process
                for process in family_rows
                if int(process.get("pid") or 0) == candidate_pid
            ),
            None,
        )
        if control_row is None or not verified_family_pids:
            continue
        rollout_probe = _codex_open_rollouts_by_pid(
            verified_family_pids,
            include_probe_status=True,
        )
        if isinstance(rollout_probe, tuple):
            rollout_probe_ok, open_rollouts_by_pid = rollout_probe
        else:
            # Keep compatibility with injected test scanners while the real
            # implementation always returns the status tuple requested above.
            rollout_probe_ok, open_rollouts_by_pid = True, rollout_probe
        if not rollout_probe_ok:
            open_rollout_probe_failed = True
            continue
        family_rollouts = {
            (
                str(rollout.get("native_id") or ""),
                str(rollout.get("project") or ""),
                str(rollout.get("output_path") or ""),
            )
            for provider_pid in verified_family_pids
            for rollout in (open_rollouts_by_pid.get(provider_pid) or [])
            if str(rollout.get("project") or "") == project
            and rollout.get("output_path")
        }
        if len(family_rollouts) != 1:
            continue
        rollout_native_id, _, exact_output_path = next(iter(family_rollouts))
        if rollout_native_id != native_id:
            continue
        pending_proofs.append((candidate, exact_output_path, control_row))
    if open_rollout_probe_failed:
        return None
    if len(pending_proofs) == 1:
        row, exact_output_path, control_row = pending_proofs[0]
        pid = int(row.get("pid") or 0)
        pending_metadata = _registry_metadata_from_row(row)
        provider_tty = str(
            pending_metadata.get("provider_tty")
            or control_row.get("tty")
            or ""
        )
        return _bind_codex_registry_to_terminal(
            native_id,
            project,
            {
                "pid": pid,
                "tty": provider_tty,
                "project": project,
                "started_at": float(
                    control_row.get("started_at")
                    or row.get("started_at")
                    or observed_started_at
                ),
                "command": str(
                    control_row.get("command")
                    or pending_metadata.get("command")
                    or ""
                ),
                "native_id": native_id,
                "output_path": exact_output_path,
            },
            discovered_by="registry_open_rollout",
        )
    if pending_proofs:
        return None
    attested = _codex_delivered_first_prompt_identity_proof(
        native_id,
        project,
        observed_started_at,
        observed_output_path,
        process_rows,
    )
    if attested is None:
        return None
    return _bind_codex_registry_to_terminal(
        native_id,
        project,
        attested,
        discovered_by="delivered_first_prompt",
    )


def _process_alive(pid: int) -> bool:
    if not pid:
        return False
    try:
        os.kill(int(pid), 0)
        return True
    except OSError:
        return False


SESSION_TERMINATE_GRACE_SECONDS = 2.0
SESSION_TERMINATE_KILL_SECONDS = 1.0
SESSION_TERMINATE_POLL_SECONDS = 0.05


def _wait_for_process_exit(pid: int, timeout: float) -> bool:
    """Return true only after the exact PID no longer exists."""
    deadline = _time.monotonic() + max(0.0, float(timeout or 0))
    while True:
        if not _process_alive(pid):
            return True
        remaining = deadline - _time.monotonic()
        if remaining <= 0:
            return False
        _time.sleep(min(SESSION_TERMINATE_POLL_SECONDS, remaining))


def _signal_process_group(pid: int, sig: int) -> None:
    try:
        os.killpg(os.getpgid(pid), sig)
    except ProcessLookupError:
        raise
    except Exception:
        os.kill(pid, sig)


def _terminate_direct_session_process(row: dict, provider: str, pid: int) -> dict:
    """Terminate a non-broker provider process and prove that it exited."""
    def post_signal_result(error: str, error_code: str) -> dict:
        if not _process_alive(pid):
            return {
                "ok": True,
                "error": None,
                "error_code": None,
                "outcome_indeterminate": False,
            }
        if _session_signal_target_is_verified(row, provider, pid):
            return {
                "ok": False,
                "error": error,
                "error_code": error_code,
                "outcome_indeterminate": False,
            }
        return {
            "ok": False,
            "error": (
                f"{provider.title()} termination started, but the process identity "
                "changed before Pairling could confirm the final outcome"
            ),
            "error_code": "termination_outcome_unknown",
            "outcome_indeterminate": True,
        }

    try:
        _signal_process_group(pid, signal.SIGTERM)
    except ProcessLookupError:
        return {
            "ok": True,
            "error": None,
            "error_code": None,
            "outcome_indeterminate": False,
        }
    except (PermissionError, OSError) as error:
        return {
            "ok": False,
            "error": f"{type(error).__name__}: {error}",
            "error_code": "signal_failed",
            "outcome_indeterminate": False,
        }

    try:
        exited = _wait_for_process_exit(pid, SESSION_TERMINATE_GRACE_SECONDS)
    except Exception as error:
        return post_signal_result(
            f"{type(error).__name__}: {error}",
            "termination_wait_failed",
        )
    if exited:
        return {
            "ok": True,
            "error": None,
            "error_code": None,
            "outcome_indeterminate": False,
        }

    # Do not escalate if the PID no longer proves as this session. It may have
    # been reused, and killing a replacement process would cross identities.
    if not _session_signal_target_is_verified(row, provider, pid):
        return post_signal_result(
            f"{provider.title()} process identity changed while termination was pending",
            "process_identity_unverified",
        )

    try:
        _signal_process_group(pid, signal.SIGKILL)
    except ProcessLookupError:
        return {
            "ok": True,
            "error": None,
            "error_code": None,
            "outcome_indeterminate": False,
        }
    except (PermissionError, OSError) as error:
        return post_signal_result(
            f"{type(error).__name__}: {error}",
            "signal_failed",
        )

    try:
        exited = _wait_for_process_exit(pid, SESSION_TERMINATE_KILL_SECONDS)
    except Exception as error:
        return post_signal_result(
            f"{type(error).__name__}: {error}",
            "termination_wait_failed",
        )
    if exited:
        return {
            "ok": True,
            "error": None,
            "error_code": None,
            "outcome_indeterminate": False,
        }
    return post_signal_result(
        f"{provider.title()} process exit could not be confirmed",
        "process_exit_unconfirmed",
    )


# --- Fleet Live Activity: independent-freshness row cache ----------------
# The fleet publisher needs the fleet's tier composition even while the phone
# is locked and polling nothing. Every /sessions read passes its fully enriched
# rows through _record_sessions_scan, so we stash a bounded, tier-relevant
# projection here (with recent_anomaly, which only the client enrichment
# computes). When that projection is fresh the publisher reuses it; when it has
# aged out — the locked-phone case — the publisher recomputes the active tiers
# directly from the broker snapshot and turn-state files.
_fleet_scan_lock = threading.Lock()
_fleet_scan_rows: list[dict] = []
_fleet_scan_at: float = 0.0
_FLEET_SCAN_FRESH_SECONDS = 15.0


def _record_fleet_scan_rows(rows: list[dict]) -> None:
    global _fleet_scan_rows, _fleet_scan_at
    projected: list[dict] = []
    for row in rows[:200]:
        attention = row.get("terminal_attention")
        projected.append({
            "id": row.get("id"),
            "readable_state": row.get("readable_state"),
            "closed_at": row.get("closed_at"),
            "last_heartbeat": row.get("last_heartbeat"),
            "state": row.get("state"),
            "terminal_attention": attention if isinstance(attention, dict) else None,
            "recent_anomaly": row.get("recent_anomaly"),
        })
    with _fleet_scan_lock:
        _fleet_scan_rows = projected
        _fleet_scan_at = _time.time()


def _fleet_scan_rows_if_fresh(now: float) -> list[dict] | None:
    with _fleet_scan_lock:
        if _fleet_scan_rows and (now - _fleet_scan_at) < _FLEET_SCAN_FRESH_SECONDS:
            return [dict(row) for row in _fleet_scan_rows]
    return None


def _record_sessions_scan(rows: list[dict]) -> None:
    with _sessions_health_lock:
        _sessions_health["last_scan_at"] = _time.time()
        _sessions_health["last_snapshot_count"] = len(rows)
    _record_fleet_scan_rows(rows)


def _sessions_health_snapshot() -> dict:
    with _sessions_health_lock:
        return dict(_sessions_health)


def _copy_cache_value(value):
    return copy.deepcopy(value)


def _runtime_admission_for_path(path: str) -> _RuntimeAdmission:
    if path in _FAST_ENDPOINTS:
        if _FAST_ADMISSION_SEMAPHORE.acquire(blocking=False):
            return _RuntimeAdmission(_FAST_ADMISSION_SEMAPHORE, True)
        return _RuntimeAdmission(None, False, "fast_capacity_exceeded")
    if path in _DASHBOARD_STREAM_ENDPOINTS:
        if _DASHBOARD_STREAM_ADMISSION_SEMAPHORE.acquire(blocking=False):
            return _RuntimeAdmission(_DASHBOARD_STREAM_ADMISSION_SEMAPHORE, True)
        return _RuntimeAdmission(None, False, "dashboard_stream_capacity_exceeded")
    if path in _AUX_STREAM_ENDPOINTS:
        if _AUX_STREAM_ADMISSION_SEMAPHORE.acquire(blocking=False):
            return _RuntimeAdmission(_AUX_STREAM_ADMISSION_SEMAPHORE, True)
        return _RuntimeAdmission(None, False, "aux_stream_capacity_exceeded")
    if path in _STREAM_ENDPOINTS or _is_orchestration_stream_path(path):
        if _STREAM_ADMISSION_SEMAPHORE.acquire(blocking=False):
            return _RuntimeAdmission(_STREAM_ADMISSION_SEMAPHORE, True)
        return _RuntimeAdmission(None, False, "stream_capacity_exceeded")
    if path == "/upload":
        if _UPLOAD_ADMISSION_SEMAPHORE.acquire(blocking=False):
            return _RuntimeAdmission(_UPLOAD_ADMISSION_SEMAPHORE, True)
        return _RuntimeAdmission(None, False, "upload_capacity_exceeded")
    if _REQUEST_ADMISSION_SEMAPHORE.acquire(blocking=False):
        return _RuntimeAdmission(_REQUEST_ADMISSION_SEMAPHORE, True)
    return _RuntimeAdmission(None, False, "request_capacity_exceeded")


def _cached_runtime_snapshot(
    key: tuple,
    ttl_seconds: float,
    loader,
    *,
    force_refresh: bool = False,
    store_after_loader_invalidation: bool = False,
):
    now = _time.time()
    with _runtime_snapshot_cache_lock:
        cached = _runtime_snapshot_cache.get(key)
        if (
            not force_refresh
            and cached is not None
            and now - cached[0] < ttl_seconds
        ):
            return _copy_cache_value(cached[1])
        key_lock_entry = _runtime_snapshot_key_locks.get(key)
        if key_lock_entry is None:
            key_lock_entry = _RuntimeSnapshotKeyLock()
            _runtime_snapshot_key_locks[key] = key_lock_entry
        key_lock_entry.users += 1
    try:
        with key_lock_entry.lock:
            now = _time.time()
            with _runtime_snapshot_cache_lock:
                cached = _runtime_snapshot_cache.get(key)
                if (
                    not force_refresh
                    and cached is not None
                    and now - cached[0] < ttl_seconds
                ):
                    return _copy_cache_value(cached[1])
                load_generation = _runtime_snapshot_cache_generation
                loader_invalidation_count = (
                    _runtime_snapshot_invalidation_count_for_current_thread()
                )
            value = loader()
            stored_at = _time.time()
            with _runtime_snapshot_cache_lock:
                generation_delta = (
                    _runtime_snapshot_cache_generation - load_generation
                )
                loader_invalidation_delta = (
                    _runtime_snapshot_invalidation_count_for_current_thread()
                    - loader_invalidation_count
                )
                loader_caused_every_invalidation = (
                    store_after_loader_invalidation
                    and generation_delta > 0
                    and generation_delta == loader_invalidation_delta
                )
                if generation_delta == 0 or loader_caused_every_invalidation:
                    _runtime_snapshot_cache[key] = (
                        stored_at,
                        _copy_cache_value(value),
                    )
                    if len(_runtime_snapshot_cache) > 256:
                        for old_key in list(_runtime_snapshot_cache.keys())[:64]:
                            _runtime_snapshot_cache.pop(old_key, None)
            return _copy_cache_value(value)
    finally:
        with _runtime_snapshot_cache_lock:
            current_entry = _runtime_snapshot_key_locks.get(key)
            if current_entry is key_lock_entry:
                key_lock_entry.users -= 1
                if key_lock_entry.users == 0:
                    _runtime_snapshot_key_locks.pop(key, None)


def _clear_runtime_load_caches_for_tests() -> None:
    global _runtime_snapshot_cache_generation
    with _runtime_snapshot_cache_lock:
        _runtime_snapshot_cache_generation += 1
        _runtime_snapshot_cache.clear()
    _clear_auth_result_cache()
    _SESSION_TRANSCRIPT_STATS_CACHE.clear()
    _clear_codex_rollout_caches()


def _cached_probe(key: str, ttl_seconds: float, loader):
    now = _time.time()
    with _health_probe_cache_lock:
        cached = _health_probe_cache.get(key)
        if cached is not None and now - cached[0] < ttl_seconds:
            return _copy_cache_value(cached[1])
    value = loader()
    with _health_probe_cache_lock:
        _health_probe_cache[key] = (now, _copy_cache_value(value))
    return _copy_cache_value(value)


def _clear_health_probe_caches_for_tests() -> None:
    with _health_probe_cache_lock:
        _health_probe_cache.clear()
    with _health_payload_cache_lock:
        _health_payload_cache.clear()


def _run_text(
    cmd: list[str],
    timeout: float = 3.0,
    env: dict[str, str] | None = None,
) -> tuple[bool, str, str]:
    try:
        run_kwargs = {"env": env} if env is not None else {}
        proc = subprocess.run(
            cmd,
            capture_output=True,
            text=True,
            timeout=timeout,
            **run_kwargs,
        )
        return proc.returncode == 0, proc.stdout or "", proc.stderr or ""
    except Exception as exc:
        return False, "", f"{type(exc).__name__}: {exc}"


def _process_parent_pid(pid: int) -> int:
    if not pid:
        return 0
    ok, out, _ = _run_text(["/bin/ps", "-o", "ppid=", "-p", str(int(pid))], timeout=2)
    if not ok:
        return 0
    try:
        return int((out.strip().splitlines() or ["0"])[0].strip() or "0")
    except ValueError:
        return 0


def _process_start_epoch(pid: int) -> float:
    if not pid:
        return 0.0
    ok, out, _ = _run_text(
        ["/bin/ps", "-o", "lstart=", "-p", str(int(pid))],
        timeout=2,
        env={**os.environ, "LC_ALL": "C"},
    )
    if not ok:
        return 0.0
    started = " ".join((out.strip().splitlines() or [""])[0].split())
    try:
        return datetime.strptime(started, "%a %b %d %H:%M:%S %Y").timestamp()
    except (TypeError, ValueError):
        return 0.0


def _registry_process_birth_matches(reg: dict | None, pid: int) -> bool:
    if not reg or int(pid or 0) <= 0:
        return False
    metadata = _registry_metadata_from_row(reg)
    try:
        expected = float(metadata.get("process_started_at") or 0)
    except (TypeError, ValueError):
        return False
    actual = _process_start_epoch(int(pid))
    return expected > 0 and actual > 0 and abs(expected - actual) <= 2


def _codex_registry_process_birth_matches(reg: dict | None, pid: int) -> bool:
    return _registry_process_birth_matches(reg, pid)


def _process_is_descendant_of(pid: int, ancestor_pid: int) -> bool:
    current = int(pid or 0)
    ancestor_pid = int(ancestor_pid or 0)
    if current <= 0 or ancestor_pid <= 0:
        return False
    seen: set[int] = set()
    for _ in range(8):
        if current == ancestor_pid:
            return True
        if current in seen:
            return False
        seen.add(current)
        current = _process_parent_pid(current)
        if current <= 0:
            return False
    return False


def _process_tty(pid: int) -> str:
    if not pid:
        return ""
    ok, out, _ = _run_text(["/bin/ps", "-o", "tty=", "-p", str(int(pid))], timeout=2)
    if not ok:
        return ""
    tty = (out.strip().splitlines() or [""])[0].strip()
    if not tty or tty == "??":
        return ""
    return tty if tty.startswith("/dev/") else f"/dev/{tty}"


def _process_command(pid: int) -> str:
    if not pid:
        return ""
    ok, out, _ = _run_text(["/bin/ps", "-o", "command=", "-p", str(int(pid))], timeout=2)
    if not ok:
        return ""
    return (out.strip().splitlines() or [""])[0].strip()


def _terminal_script_owner_pid(provider_pid: int, terminal_tty: str) -> int:
    """Return the exact script ancestor that owns one visible Terminal tab."""
    provider_pid = int(provider_pid or 0)
    if (
        provider_pid <= 0
        or re.fullmatch(r"/dev/ttys[0-9]{3,}", terminal_tty or "") is None
    ):
        return 0
    current = _process_parent_pid(provider_pid)
    seen: set[int] = set()
    for _ in range(8):
        if current <= 0 or current in seen:
            return 0
        seen.add(current)
        command = _process_command(current)
        if (
            "/usr/bin/script" in command
            and _process_tty(current) == terminal_tty
        ):
            return current
        current = _process_parent_pid(current)
    return 0


def _direct_terminal_binding_is_verified(
    row: dict | None,
    provider: str,
    pid: int,
    *,
    provider_tty: str | None = None,
) -> bool:
    """Prove how one provider PID maps to its visible Terminal tab."""
    if not isinstance(row, dict) or int(pid or 0) <= 0:
        return False
    terminal_tty = str(row.get("terminal_tty") or "")
    if re.fullmatch(r"/dev/ttys[0-9]{3,}", terminal_tty) is None:
        return False
    metadata = _registry_metadata_from_row(row)
    expected_provider_tty = str(metadata.get("provider_tty") or "")
    actual_provider_tty = str(provider_tty or _process_tty(pid) or "")
    if expected_provider_tty and actual_provider_tty != expected_provider_tty:
        return False
    if actual_provider_tty == terminal_tty:
        return True
    owner_pid = _terminal_script_owner_pid(pid, terminal_tty)
    if owner_pid <= 0:
        return False
    try:
        stored_owner_pid = int(metadata.get("terminal_owner_pid") or 0)
        stored_owner_started_at = float(
            metadata.get("terminal_owner_process_started_at") or 0
        )
    except (TypeError, ValueError):
        return False
    if stored_owner_pid <= 0 or stored_owner_started_at <= 0:
        return False
    if stored_owner_pid != owner_pid:
        return False
    actual_owner_started_at = _process_start_epoch(owner_pid)
    if (
        actual_owner_started_at <= 0
        or abs(actual_owner_started_at - stored_owner_started_at) > 2
    ):
        return False
    return True


def _codex_terminal_tty_candidates(reg: dict | None) -> list[str]:
    if not reg:
        return []
    pid = int(reg.get("pid") or 0)
    if (
        reg.get("closed_at") is not None
        or pid <= 0
        or not _process_alive(pid)
        or not _registry_process_birth_matches(reg, pid)
        or not _session_signal_target_is_verified(reg, "codex", pid)
    ):
        return []
    candidates: list[str] = []

    def add(tty: str | None) -> None:
        if tty and re.match(r"^/dev/ttys[0-9]{3,}$", tty) and tty not in candidates:
            candidates.append(tty)

    chain: list[tuple[int, str, str]] = []
    seen: set[int] = set()
    current = pid
    for _ in range(6):
        if not current or current in seen:
            break
        seen.add(current)
        chain.append((current, _process_tty(current), _process_command(current)))
        current = _process_parent_pid(current)

    # The provider's own tty is not always the tty that Terminal.app exposes.
    # A visible Pairling launch runs below /usr/bin/script. Only the current,
    # re-proved script ancestry may add the outer Terminal tab as a target.
    metadata = _registry_metadata_from_row(reg)
    provider_tty = str(metadata.get("provider_tty") or (chain[0][1] if chain else ""))
    terminal_tty = str(reg.get("terminal_tty") or "")
    if _direct_terminal_binding_is_verified(
        reg, "codex", pid, provider_tty=provider_tty
    ):
        add(terminal_tty)
    if terminal_tty == provider_tty:
        add(provider_tty)
    return candidates


def _probe_tailnet_ip() -> str | None:
    ok, out, _ = _run_text(["tailscale", "ip", "-4"], timeout=3)
    if not ok:
        return None
    for line in out.splitlines():
        ip = line.strip()
        if ip.startswith("100."):
            return ip
    return None


def _tailnet_ip() -> str | None:
    return _cached_probe("tailnet_ip", _HEALTH_PROBE_CACHE_SECONDS, _probe_tailnet_ip)


def _probe_lan_ips() -> list[str]:
    ok, out, _ = _run_text(["/sbin/ifconfig"], timeout=3)
    if not ok:
        return []
    ips: list[str] = []
    for match in re.finditer(r"\binet\s+(\d+\.\d+\.\d+\.\d+)\b", out):
        ip = match.group(1)
        if ip.startswith(("127.", "169.254.", "100.")):
            continue
        if ip not in ips:
            ips.append(ip)
    return ips


def _lan_ips() -> list[str]:
    return _cached_probe("lan_ips", _HEALTH_PROBE_CACHE_SECONDS, _probe_lan_ips)


def _bonjour_hostname(raw_hostname: str | None) -> str | None:
    hostname = str(raw_hostname or "").strip().rstrip(".")
    if not hostname:
        return None
    try:
        ipaddress.ip_address(hostname.strip("[]"))
        return None
    except ValueError:
        pass
    label = hostname.removesuffix(".local").split(".", 1)[0]
    if (
        not re.fullmatch(r"[A-Za-z0-9](?:[A-Za-z0-9-]{0,61}[A-Za-z0-9])?", label)
        or label.isdigit()
        or label.lower() == "localhost"
    ):
        return None
    return f"{label}.local"


def _probe_listener_entries() -> list[str]:
    host = BOUND_HOST or os.environ.get("PAIRLING_BOUND_HOST", "")
    entries: list[str] = []
    ok, out, _ = _run_text(["/usr/sbin/lsof", "-nP", f"-iTCP:{PORT}", "-sTCP:LISTEN"], timeout=3)
    if ok:
        for line in out.splitlines()[1:]:
            if " TCP " not in line:
                continue
            entry = line.split(" TCP ", 1)[1].replace(" (LISTEN)", "").strip()
            if entry and entry not in entries:
                entries.append(entry)
    if not entries and host:
        entries.append(f"{host}:{PORT}")
    return entries


def _listener_entries() -> list[str]:
    return _cached_probe("listener_entries", _HEALTH_PROBE_CACHE_SECONDS, _probe_listener_entries)


def _pairling_connect_health() -> dict:
    """Cached snapshot of the Pairling Connect (connectd) axis for health
    surfaces: {"ready": bool, "summary": dict | None, "routes": list}.

    connectd is the embedded-tailnet gateway on 127.0.0.1:7774. A ready
    connect route serves phones regardless of the standalone Tailscale app,
    so /health, route advertisement, and posture must treat it as a
    first-class tailnet axis instead of reporting critical whenever the
    standalone CLI has no 100.x IP.
    """
    def probe() -> dict:
        if fetch_connectd_status is None or advertised_pairling_connect_routes is None:
            return {"ready": False, "summary": None, "routes": []}
        try:
            status = fetch_connectd_status(timeout_seconds=0.7)
        except Exception:
            status = {}
        if not status:
            with _health_probe_cache_lock:
                last_ready = _health_probe_cache.get("pairling_connect_health_last_ready")
            if (
                last_ready is not None
                and _time.time() - last_ready[0] <= _PAIRLING_CONNECT_STATUS_MISS_GRACE_SECONDS
            ):
                return _copy_cache_value(last_ready[1])
            return {"ready": False, "summary": None, "routes": []}
        try:
            routes = advertised_pairling_connect_routes(status)
        except Exception:
            routes = []
        summary = None
        if redacted_connectd_summary is not None:
            try:
                paired_recently = None
                if DEVICE_REGISTRY is not None:
                    try:
                        paired_recently = DEVICE_REGISTRY.any_device_seen_within(7 * 86400)
                    except Exception:
                        paired_recently = None
                summary = redacted_connectd_summary(status, paired_recently=paired_recently)
            except Exception:
                summary = None
        ready = any(
            route.get("source") == "pairling_connectd" and route.get("status") == "ready"
            for route in routes
        )
        result = {"ready": ready, "summary": summary, "routes": routes}
        if ready:
            with _health_probe_cache_lock:
                _health_probe_cache["pairling_connect_health_last_ready"] = (
                    _time.time(),
                    _copy_cache_value(result),
                )
        return result

    return _cached_probe("pairling_connect_health", _HEALTH_PROBE_CACHE_SECONDS, probe)


def _coordinator_from_pairling_connect(connect: dict) -> dict:
    ready = bool(connect.get("ready"))
    return {
        "role": "primary_coordinator",
        "host": DEFAULT_COORDINATOR_HOST,
        "posture": "ready" if ready else "unknown",
        "severity": "ok" if ready else "unknown",
        "summary": (
            "Pairling Connect route is ready."
            if ready
            else "Pairling Connect route is not ready."
        ),
        "stale": False,
        "tailnet_axis": "pairling_connect",
    }


def _health_routes(coordinator: dict) -> list[dict]:
    now = _time.time()
    routes: list[dict] = []
    connect = _pairling_connect_health()
    for route in connect.get("routes") or []:
        base_url = route.get("base_url")
        if not isinstance(base_url, str) or not base_url:
            continue
        ready = route.get("status") == "ready"
        kind = str(route.get("kind") or "tailnet")
        is_funnel = kind == "funnel"
        routes.append({
            "kind": kind,
            "base_url": base_url,
            "status": "ok" if ready else "degraded",
            "score": (10 if ready else 5) if is_funnel else (110 if ready else 30),
            "last_ok_at": now if ready else None,
            "source": str(route.get("source") or "pairling_connectd"),
            "id": route.get("id") or ("pairling-connect-funnel" if is_funnel else "pairling-connect-tailnet"),
        })
    tailnet = _tailnet_ip()
    if tailnet:
        tailnet_base_url = f"http://{tailnet}:{PORT}"
        if not any(route["base_url"] == tailnet_base_url for route in routes):
            routes.append({
                "kind": "tailnet",
                "base_url": tailnet_base_url,
                "status": "candidate",
                "score": 40,
                "last_ok_at": None,
                "source": "standalone_tailnet",
                "id": "standalone-tailnet",
            })
    for ip in _lan_ips()[:2]:
        routes.append({
            "kind": "lan",
            "base_url": f"http://{ip}:{PORT}",
            "status": "candidate",
            "score": 20,
            "last_ok_at": None,
            "source": "lan",
            "id": f"lan-{ip}",
        })
    if not routes:
        host = os.environ.get("PAIRLING_BOUND_HOST", f"0.0.0.0")
        base_url = host if host.startswith("http") else f"http://{host}:{PORT}"
        routes.append({
            "kind": "manual",
            "base_url": base_url,
            "status": "unknown",
            "score": 0,
            "last_ok_at": None,
            "source": "manual",
            "id": "manual-bound-host",
        })
    routes.sort(key=lambda route: int(route["score"]), reverse=True)
    return routes


def _daemon_snapshot() -> dict:
    entries = _listener_entries()
    return {
        "name": "pairlingd",
        "pid": os.getpid(),
        "uptime_seconds": int(_time.time() - DAEMON_STARTED_AT),
        "version": DAEMON_VERSION,
        "bind": entries,
        "threaded": True,
    }


def _request_proof_health_snapshot() -> dict:
    unavailable = {
        "contract_version": "pairling-request-proof-health-v1",
        "ok": False,
        "durable": False,
        "writable": False,
        "entry_count": None,
        "max_entries": REQUEST_PROOF_CACHE_MAX_ENTRIES,
        "full": False,
        "reason": "verifier_unavailable",
    }
    if verify_request_proof is None or _proof_replay_cache is None:
        return unavailable
    try:
        status = _proof_replay_cache.status()
    except Exception:
        return unavailable
    if not isinstance(status, dict):
        return unavailable
    return status


def _session_control_health_snapshot() -> dict:
    unavailable = {
        "schema_version": 1,
        "available": False,
        "authority": None,
        "negotiate_route": "/session-control/v1/negotiate",
        "snapshot_route": "/session-control/v1/snapshot",
        "execute_route": "/session-control/v1/execute",
        "recover_route": "/session-control/v1/recover",
        "events_route": "/session-control/v1/events",
    }
    try:
        gateway = _ensure_session_control_gateway()
        authority = getattr(gateway, "authority", None)
        public_key = getattr(authority, "public_key", None)
        if gateway is None or public_key is None:
            return unavailable
        descriptor = public_key.to_payload()
        if not isinstance(descriptor, dict):
            return unavailable
    except Exception:
        return unavailable
    return {
        **unavailable,
        "available": True,
        "authority": descriptor,
    }


def _readyz_payload() -> dict:
    request_proof = _request_proof_health_snapshot()
    return {
        "ok": request_proof.get("ok") is True,
        "schema_version": 1,
        "contract_version": RUNTIME_CONTRACT_VERSION,
    }


def _health_source_identity(auth_result=None, runtime_info: dict | None = None) -> dict:
    runtime_info = runtime_info or _runtime_info_snapshot()
    install_id = getattr(PAIRING_STORE, "install_id", "") if PAIRING_STORE else ""
    hostname = os.environ.get("PAIRLING_HOSTNAME") or os.uname().nodename.split(".")[0]
    return {
        "schema_version": 1,
        "install_id": str(install_id or getattr(auth_result, "install_id", "") or ""),
        "device_id": str(getattr(auth_result, "device_id", "") or ""),
        "runtime_port": PORT,
        "runtime_version": runtime_info.get("runtime_version"),
        "hostname": hostname,
    }

def _authorization_health_snapshot(auth_result, *, now: float | None = None) -> dict:
    generated_at = _time.time() if now is None else float(now)
    device_id = str(getattr(auth_result, "device_id", "") or "").strip()
    install_id = str(getattr(auth_result, "install_id", "") or "").strip()
    scopes = frozenset(getattr(auth_result, "scopes", ()) or ())
    role = str(getattr(auth_result, "role", "") or "").strip().lower() or None
    expires_at = generated_at + AUTHORIZATION_ADVERTISEMENT_TTL_SECONDS
    credential_expires_at = getattr(auth_result, "credential_expires_at", None)
    if credential_expires_at is not None:
        try:
            expires_at = min(expires_at, float(credential_expires_at))
        except (TypeError, ValueError, OverflowError):
            expires_at = generated_at
    controls = (
        _authorization_controls_for_scopes(scopes)
        if (
            getattr(auth_result, "ok", False)
            and device_id
            and install_id
            and expires_at > generated_at
        )
        else []
    )
    return {
        "contract_version": AUTHORIZATION_ADVERTISEMENT_CONTRACT,
        "generated_at": generated_at,
        "expires_at": expires_at,
        "device_id": device_id,
        "install_id": install_id,
        "role": role,
        "scopes": sorted(str(scope) for scope in scopes),
        "controls": controls,
    }



def _routez_payload(auth_result=None) -> dict:
    runtime_info = _runtime_info_snapshot()
    runtime_contract = runtime_info.get("contract_version") or RUNTIME_CONTRACT_VERSION
    verified = bool(runtime_info.get("verified"))
    ok = verified and runtime_contract == RUNTIME_CONTRACT_VERSION
    install_id = getattr(PAIRING_STORE, "install_id", "") if PAIRING_STORE else ""
    route_runtime = {
        "runtime_version": runtime_info.get("runtime_version"),
        "contract_version": runtime_contract,
        "source_revision": runtime_info.get("source_revision"),
        "source_branch": runtime_info.get("source_branch"),
        "source_dirty": runtime_info.get("source_dirty"),
        "verified": verified,
        "manifest_path": runtime_info.get("manifest_path"),
        "manifest_error": runtime_info.get("manifest_error"),
        "port": runtime_info.get("port") or PORT,
    }
    source = {
        "schema_version": 1,
        "install_id": str(install_id or getattr(auth_result, "install_id", "") or ""),
        "device_id": str(getattr(auth_result, "device_id", "") or ""),
        "runtime_port": PORT,
    }
    return {
        "ok": ok,
        "schema_version": 1,
        "contract_version": RUNTIME_CONTRACT_VERSION,
        "runtime": route_runtime,
        "source": source,
    }


def _public_health_payload(*, ok: bool, runtime_info: dict) -> dict:
    """Return the exact unauthenticated health contract, not a redacted private snapshot."""
    runtime = {
        "contract_version": runtime_info.get("contract_version") or RUNTIME_CONTRACT_VERSION,
        "compat_mode": runtime_info.get("compat_mode") or "pairling-v1",
        "verified": runtime_info.get("verified") is True,
    }
    return {
        "ok": bool(ok),
        "schema_version": 1,
        "contract_version": RUNTIME_CONTRACT_VERSION,
        "pairing_contracts": dict(PAIRING_CONTRACTS),
        "pairing_activation_contracts": [PAIRING_ACTIVATION_CONTRACT],
        "runtime": runtime,
        "auth": {
            "mode": RUNTIME_AUTH_MODE,
            "required": True,
            "legacy_global_token": False,
        },
    }


def _health_payload(authenticated: bool = False, auth_result=None) -> dict:
    connect = _pairling_connect_health()
    coordinator = _coordinator_from_pairling_connect(connect)
    if connect.get("summary") is not None:
        coordinator = dict(coordinator)
        coordinator["pairling_connect"] = connect["summary"]
    routes = _health_routes(coordinator)
    request_proof = _request_proof_health_snapshot()
    ok = (
        coordinator.get("posture") in ("ready", "warning")
        and request_proof.get("ok") is True
    )
    runtime_info = _runtime_info_snapshot()
    if not authenticated:
        return _public_health_payload(ok=ok, runtime_info=runtime_info)
    payload = {
        "ok": ok,
        "schema_version": 1,
        "contract_version": RUNTIME_CONTRACT_VERSION,
        "pairing_contracts": dict(PAIRING_CONTRACTS),
        "pairing_activation_contracts": [PAIRING_ACTIVATION_CONTRACT],
        "ts": _time.time(),
        "runtime": runtime_info,
        "auth": {
            "mode": RUNTIME_AUTH_MODE,
            "required": True,
            "legacy_global_token": False,
        },
        "daemon": _daemon_snapshot(),
        "coordinator": coordinator,
        "request_proof": request_proof,
        "provider_controls": {
            "schema_version": PROVIDER_CONTROL_SCHEMA_VERSION,
            "available": all((
                _PROVIDER_CONTROL_SERVICE is not None,
                _provider_operation_manifest_payload is not None,
            )),
            "catalog_source": "companiond",
            "snapshot_route": "/provider-controls/snapshot",
            "stream_route": "/provider-controls/stream",
            "execute_route": "/provider-controls/execute",
            "snapshot_scope": "sessions:read",
            "execute_scope": "provider:control",
        },
        "session_control": _session_control_health_snapshot(),
    }
    if authenticated:
        payload["source"] = _health_source_identity(auth_result, runtime_info=runtime_info)
        payload["authorization"] = _authorization_health_snapshot(auth_result)
        payload["routes"] = routes
        payload["sessions"] = _sessions_health_snapshot()
        payload["streams"] = _stream_stats_snapshot()
        # The push-plane dead-man's switch: the phone banners on degraded so
        # a silently dead APNs provider is visible at the next health read.
        if PUSH_DISPATCHER is not None:
            try:
                push_device_id = str(getattr(auth_result, "device_id", "") or "") or None
                payload["push"] = PUSH_DISPATCHER.health_axis(device_id=push_device_id)
            except Exception:
                payload["push"] = {
                    "contract_version": "pairling-push-health-v1",
                    "provider_configured": False,
                    "provider_mode": "unknown",
                    "degraded": True,
                    "reason": "health_axis_failed",
                    "last_delivery_outcome": None,
                    "last_delivery_at": None,
                    "registered_devices": 0,
                }
        payload["mirror"] = _mirror_cached_summary()
        payload["safety"] = SAFETY_MONITOR.status() if SAFETY_MONITOR else {
            "contract_version": "pairling-safety-v0",
            "mode": "absent",
            "installed": False,
            "approved": False,
            "running": False,
            "full_disk_access": "unknown",
            "visibility": "unavailable",
            "summary": "Pairling Safety Monitor bridge is unavailable.",
            "event_count": 0,
            "high_risk_count": 0,
            "updated_at": _time.time(),
        }
    return payload


def _cached_health_payload(authenticated: bool = False, auth_result=None) -> dict:
    device_id = str(getattr(auth_result, "device_id", "") or "")
    install_id = str(getattr(auth_result, "install_id", "") or "")
    scopes = tuple(sorted(getattr(auth_result, "scopes", ()) or ()))
    role = str(getattr(auth_result, "role", "") or "")
    key = (bool(authenticated), device_id, install_id, role, scopes)
    now = _time.time()
    with _health_payload_cache_lock:
        cached = _health_payload_cache.get(key)
        if cached is not None and now - cached[0] < _HEALTH_PAYLOAD_CACHE_SECONDS:
            return _copy_cache_value(cached[1])
    payload = _health_payload(authenticated=authenticated, auth_result=auth_result)
    with _health_payload_cache_lock:
        _health_payload_cache[key] = (now, _copy_cache_value(payload))
    return _copy_cache_value(payload)


def _mac_health_alert_snapshot() -> dict:
    connect = _pairling_connect_health()
    coordinator = _coordinator_from_pairling_connect(connect)
    if connect.get("summary") is not None:
        coordinator = dict(coordinator)
        coordinator["pairling_connect"] = connect["summary"]
    return {
        "ok": coordinator.get("posture") in ("ready", "warning"),
        "schema_version": 1,
        "contract_version": RUNTIME_CONTRACT_VERSION,
        "ts": _time.time(),
        "coordinator": coordinator,
    }


def _health_diff_digest(payload: dict) -> str:
    stable = json.loads(json.dumps(payload))
    stable.pop("ts", None)
    daemon = stable.get("daemon")
    if isinstance(daemon, dict):
        daemon.pop("uptime_seconds", None)
    coordinator = stable.get("coordinator")
    if isinstance(coordinator, dict):
        coordinator.pop("sample_age_seconds", None)
    for route in stable.get("routes") or []:
        if isinstance(route, dict):
            route.pop("last_ok_at", None)
    mirror = stable.get("mirror")
    if isinstance(mirror, dict):
        mirror.pop("updated_at", None)
    return hashlib.sha256(json.dumps(stable, sort_keys=True).encode()).hexdigest()


def _orchestration_preflight_from_health(health: dict) -> tuple[dict, dict]:
    coordinator = health.get("coordinator") or {}
    route = (health.get("routes") or [{}])[0]
    runtime_info = health.get("runtime") if isinstance(health.get("runtime"), dict) else {}
    preflight = {
        "posture": coordinator.get("posture") or "unknown",
        "warnings": [],
        "route": route.get("kind") or "unknown",
        "route_base": route.get("base_url"),
        "checked_at": health.get("ts"),
        "tailscale_ip": None,
        "lid_closed": None,
        "ac_power": None,
        "low_power_mode": None,
        "thermal": "unknown",
        "runtime_version": runtime_info.get("runtime_version"),
        "runtime_source_revision": runtime_info.get("source_revision"),
        "runtime_contract_version": runtime_info.get("contract_version") or RUNTIME_CONTRACT_VERSION,
        "summary": coordinator.get("summary"),
    }
    mirror = health.get("mirror")
    if isinstance(mirror, dict):
        preflight["mirror"] = mirror
    coordinator_meta = {
        "host": coordinator.get("host") or DEFAULT_COORDINATOR_HOST,
        "role": coordinator.get("role") or "primary_coordinator",
        "daemon_version": DAEMON_VERSION,
        "runtime_version": runtime_info.get("runtime_version"),
        "source_revision": runtime_info.get("source_revision"),
        "contract_version": runtime_info.get("contract_version") or RUNTIME_CONTRACT_VERSION,
    }
    return coordinator_meta, preflight


def _mirror_cli_path() -> Path:
    return Path(__file__).resolve().parent.parent / "mirror" / "companion-mirror"


def _mirror_cached_summary() -> dict:
    try:
        data = json.loads(PROJECT_MIRROR_STATE.read_text())
        summary = data.get("summary")
        if isinstance(summary, dict):
            return summary
    except Exception:
        pass
    return {
        "contract_version": PROJECT_MIRROR_CONTRACT,
        "status": "misconfigured",
        "ready": 0,
        "syncing": 0,
        "offline": 0,
        "conflicted": 0,
        "total": 0,
        "updated_at": None,
        "summary": "Project mirror state has not been initialized.",
    }


def _mirror_cli_json(args: list[str], timeout: int = 45) -> tuple[int, dict]:
    cli = _mirror_cli_path()
    if not cli.exists():
        return 127, {
            "ok": False,
            "contract_version": PROJECT_MIRROR_CONTRACT,
            "error": f"mirror CLI missing: {cli}",
        }
    try:
        proc = subprocess.run(
            [sys.executable, str(cli), *args],
            capture_output=True,
            text=True,
            timeout=timeout,
        )
    except Exception as exc:
        return 1, {
            "ok": False,
            "contract_version": PROJECT_MIRROR_CONTRACT,
            "error": f"{type(exc).__name__}: {exc}",
        }
    try:
        payload = json.loads(proc.stdout or "{}")
    except json.JSONDecodeError:
        payload = {
            "ok": False,
            "contract_version": PROJECT_MIRROR_CONTRACT,
            "error": (proc.stderr or proc.stdout or "mirror command produced invalid JSON")[:2000],
        }
    if proc.returncode != 0 and "ok" not in payload:
        payload["ok"] = False
    if proc.stderr and "stderr" not in payload:
        payload["stderr"] = proc.stderr.strip()[:2000]
    return proc.returncode, payload


def _pids_for_tty_command(tty: str, command_name: str) -> list[int]:
    tty_name = os.path.basename(tty or "")
    if not tty_name:
        return []
    try:
        proc = subprocess.run(
            ["ps", "-t", tty_name, "-o", "pid=,comm=,args="],
            capture_output=True,
            text=True,
            timeout=2,
        )
    except Exception:
        return []
    if proc.returncode != 0:
        return []
    matching_pids: list[int] = []
    for line in proc.stdout.splitlines():
        parts = line.strip().split(None, 2)
        if len(parts) < 2 or not parts[0].isdigit():
            continue
        # ``comm`` and ``args`` both begin with the executable on macOS. Use
        # the full argv column when present so the command matcher sees one
        # real process command instead of a duplicated executable token.
        haystack = (parts[2] if len(parts) == 3 else parts[1]).lower()
        normalized_name = command_name.lower()
        if normalized_name == "codex":
            command_matches = _is_codex_cli_command(haystack)
        elif normalized_name == "claude":
            command_matches = _is_claude_cli_command(haystack)
        else:
            command_matches = normalized_name in haystack
        if command_matches:
            matching_pids.append(int(parts[0]))
    return matching_pids


def _pid_for_tty_command(tty: str, command_name: str) -> int:
    matches = _pids_for_tty_command(tty, command_name)
    return matches[0] if matches else 0


def _parse_kern_procargs2(payload: bytes) -> list[str] | None:
    """Decode one macOS KERN_PROCARGS2 payload into its exact argv."""
    int_size = ctypes.sizeof(ctypes.c_int)
    if len(payload) < int_size:
        return None
    argc = ctypes.c_int.from_buffer_copy(payload[:int_size]).value
    if argc <= 0 or argc > 65536:
        return None

    # The executable path precedes argv and is followed by NUL padding.
    offset = payload.find(b"\0", int_size)
    if offset < 0:
        return None
    offset += 1
    while offset < len(payload) and payload[offset] == 0:
        offset += 1

    argv: list[str] = []
    for _ in range(argc):
        end = payload.find(b"\0", offset)
        if end < 0:
            return None
        raw_argument = payload[offset:end]
        if not argv and not raw_argument:
            return None
        argv.append(os.fsdecode(raw_argument))
        offset = end + 1
    return argv if argv and argv[0] else None


def _process_argv(pid: int) -> tuple[bool, list[str]]:
    """Read one process's exact argv through macOS KERN_PROCARGS2."""
    pid = int(pid or 0)
    if pid <= 0 or sys.platform != "darwin":
        return False, []
    try:
        libc = ctypes.CDLL(None, use_errno=True)
        sysctl = libc.sysctl
        mib = (ctypes.c_int * 3)(1, 49, pid)  # CTL_KERN, KERN_PROCARGS2
        payload_size = ctypes.c_size_t(0)
        if sysctl(mib, 3, None, ctypes.byref(payload_size), None, 0) != 0:
            return False, []
        if payload_size.value <= 0 or payload_size.value > 16 * 1024 * 1024:
            return False, []
        payload = ctypes.create_string_buffer(payload_size.value)
        if (
            sysctl(
                mib,
                3,
                payload,
                ctypes.byref(payload_size),
                None,
                0,
            )
            != 0
        ):
            return False, []
        argv = _parse_kern_procargs2(
            bytes(payload.raw[:payload_size.value])
        )
    except (AttributeError, OSError, OverflowError, ValueError):
        return False, []
    return (True, argv) if argv is not None else (False, [])


def _parse_process_snapshot_line(line: str) -> dict | None:
    """Parse current process rows and the older focused-test row shape."""
    stripped = line.strip()
    if not stripped:
        return None

    current_parts = stripped.split(None, 11)
    current_format = (
        len(current_parts) == 12
        and current_parts[0].isdigit()
        and current_parts[1].isdigit()
        and re.fullmatch(r"-?\d+", current_parts[3]) is not None
        and re.fullmatch(r"-?\d+", current_parts[4]) is not None
    )
    if current_format:
        pid = int(current_parts[0])
        ppid = int(current_parts[1])
        state = current_parts[2]
        process_group_id = int(current_parts[3])
        foreground_process_group_id = int(current_parts[4])
        tty_name = current_parts[5]
        started_text = " ".join(current_parts[6:11])
        command = current_parts[11]
        legacy_fixture_format = False
        fixture_argv = None
    else:
        legacy_parts = stripped.split(None, 8)
        if (
            len(legacy_parts) < 9
            or not legacy_parts[0].isdigit()
            or not legacy_parts[1].isdigit()
        ):
            raise ValueError("process snapshot lacks exact parent identity")
        pid = int(legacy_parts[0])
        ppid = int(legacy_parts[1])
        state = ""
        process_group_id = 0
        foreground_process_group_id = 0
        tty_name = legacy_parts[2]
        started_text = " ".join(legacy_parts[3:8])
        command = legacy_parts[8]
        legacy_fixture_format = True
        try:
            fixture_argv = shlex.split(command)
        except ValueError:
            fixture_argv = None

    started_at = datetime.strptime(
        started_text, "%a %b %d %H:%M:%S %Y"
    ).timestamp()
    tty = "" if tty_name == "??" else (
        tty_name if tty_name.startswith("/dev/") else f"/dev/{tty_name}"
    )
    return {
        "pid": pid,
        "ppid": ppid,
        "state": state,
        "process_group_id": process_group_id,
        "foreground_process_group_id": foreground_process_group_id,
        "job_control_observed": not legacy_fixture_format,
        "tty": tty,
        "started_at": started_at,
        "command": command,
        "fixture_argv": fixture_argv,
        "legacy_fixture_format": legacy_fixture_format,
        "ppid_observed": True,
    }


def _scan_process_snapshot() -> tuple[bool, dict[int, dict]]:
    """Read the process table once for one inventory scan."""
    try:
        proc = subprocess.run(
            [
                "/bin/ps",
                "-axo",
                "pid=,ppid=,state=,pgid=,tpgid=,tty=,lstart=,command=",
            ],
            capture_output=True,
            text=True,
            timeout=2,
            env={**os.environ, "LC_ALL": "C"},
        )
    except Exception:
        return False, {}
    if proc.returncode != 0:
        return False, {}

    snapshot: dict[int, dict] = {}
    try:
        for line in proc.stdout.splitlines():
            process = _parse_process_snapshot_line(line)
            if process is None:
                continue
            snapshot[int(process["pid"])] = process
    except (TypeError, ValueError):
        # Partial process metadata cannot prove ancestry, birth, or foreground
        # ownership. Fail the inventory instead of publishing a subset.
        return False, {}
    return True, snapshot


def _snapshot_process_is_descendant_of(
    snapshot: dict[int, dict], pid: int, ancestor_pid: int
) -> bool:
    current = int(pid or 0)
    ancestor_pid = int(ancestor_pid or 0)
    if current <= 0 or ancestor_pid <= 0:
        return False
    seen: set[int] = set()
    for _ in range(8):
        if current == ancestor_pid:
            return True
        if current in seen:
            return False
        seen.add(current)
        row = snapshot.get(current)
        if row is None or not bool(row.get("ppid_observed")):
            return False
        current = int(row.get("ppid") or 0)
        if current <= 0:
            return False
    return False


def _snapshot_terminal_script_owner(
    snapshot: dict[int, dict], provider_pid: int, terminal_tty: str = ""
) -> dict | None:
    current_row = snapshot.get(int(provider_pid or 0))
    if current_row is None or not bool(current_row.get("ppid_observed")):
        return None
    current = int(current_row.get("ppid") or 0)
    seen: set[int] = set()
    for _ in range(8):
        if current <= 0 or current in seen:
            return None
        seen.add(current)
        row = snapshot.get(current)
        if row is None:
            return None
        row_tty = str(row.get("tty") or "")
        if (
            "/usr/bin/script" in str(row.get("command") or "")
            and re.fullmatch(r"/dev/ttys[0-9]{3,}", row_tty) is not None
            and (not terminal_tty or row_tty == terminal_tty)
        ):
            return row
        if not bool(row.get("ppid_observed")):
            return None
        current = int(row.get("ppid") or 0)
    return None


def _is_codex_cli_entrypoint(value: str) -> bool:
    normalized = value.strip().lower()
    basename = os.path.basename(normalized)
    if basename == "codex":
        return True
    return (
        "/@openai/codex/" in normalized
        and basename in {"codex.js", "index.js"}
    )


def _is_omp_cli_entrypoint(value: str) -> bool:
    return os.path.basename(value.strip().lower()) == "omp"


def _is_claude_cli_entrypoint(value: str) -> bool:
    normalized = value.strip().lower()
    basename = os.path.basename(normalized)
    if basename == "claude":
        return True
    if (
        "/@anthropic-ai/claude-code/" in normalized
        and basename in {"claude.js", "cli.js", "index.js"}
    ):
        return True
    return (
        "/.local/share/claude/versions/" in normalized
        and re.fullmatch(
            r"\d+(?:\.\d+)+(?:[-+][a-z0-9._-]+)?",
            basename,
        )
        is not None
    )


def _lossy_command_may_be_provider_entrypoint(
    command: str, provider: str
) -> bool:
    """Use flattened ps text only to bound which PIDs need exact argv."""
    tokens = (command or "").strip().split()
    if not tokens:
        return False
    entrypoints = {
        "claude": _is_claude_cli_entrypoint,
        "codex": _is_codex_cli_entrypoint,
        "omp": _is_omp_cli_entrypoint,
    }
    is_entrypoint = entrypoints.get(provider)
    if is_entrypoint is None:
        return False
    if is_entrypoint(tokens[0]):
        return True
    if os.path.basename(tokens[0]).lower() not in {"node", "nodejs", "bun"}:
        return False
    return any(is_entrypoint(token) for token in tokens[1:])


def _snapshot_process_is_foreground(process: dict) -> bool:
    state = str(process.get("state") or "").upper()
    if state[:1] in {"T", "X", "Z"}:
        return False
    if not bool(process.get("job_control_observed")):
        return True
    if not str(process.get("tty") or ""):
        return True
    process_group_id = int(process.get("process_group_id") or 0)
    foreground_process_group_id = int(
        process.get("foreground_process_group_id") or 0
    )
    return (
        process_group_id > 0
        and foreground_process_group_id > 0
        and process_group_id == foreground_process_group_id
    )


def _scan_provider_process_rows(
    provider: str,
    *,
    include_snapshot: bool = False,
):
    """Read provider processes from one all-process inventory snapshot."""
    empty = (False, [], {}) if include_snapshot else (False, [])
    if provider not in {"claude", "codex", "omp"}:
        return empty
    snapshot_ok, snapshot = _scan_process_snapshot()
    if not snapshot_ok:
        return empty

    raw_candidates: list[dict] = []
    for process in snapshot.values():
        command = str(process.get("command") or "")
        if not _lossy_command_may_be_provider_entrypoint(command, provider):
            continue
        fixture_argv = process.get("fixture_argv")
        if bool(process.get("legacy_fixture_format")):
            if not isinstance(fixture_argv, list) or not fixture_argv:
                return empty
            argv = [str(argument) for argument in fixture_argv]
        else:
            argv_ok, argv = _process_argv(int(process["pid"]))
            if not argv_ok:
                # Flattened ps text cannot prove the provider command. A PID
                # exit or denied argv read invalidates this exact inventory.
                return empty
        classifiers = {
            "claude": _is_claude_cli_argv,
            "codex": _is_codex_cli_argv,
            "omp": _is_omp_cli_argv,
        }
        command_matches = classifiers[provider](argv)
        if not command_matches:
            continue
        raw_candidates.append({
            "pid": int(process["pid"]),
            "ppid": int(process.get("ppid") or 0),
            "state": str(process.get("state") or ""),
            "process_group_id": int(process.get("process_group_id") or 0),
            "foreground_process_group_id": int(
                process.get("foreground_process_group_id") or 0
            ),
            "job_control_observed": bool(
                process.get("job_control_observed")
            ),
            "tty": str(process.get("tty") or ""),
            "started_at": float(process.get("started_at") or 0),
            "command": shlex.join(argv),
            "argv": argv,
            "legacy_fixture_format": bool(
                process.get("legacy_fixture_format")
            ),
            "ppid_observed": bool(process.get("ppid_observed")),
        })

    stdio_probe_pids = [
        int(candidate["pid"])
        for candidate in raw_candidates
        if (
            not candidate["tty"]
            or (
                provider == "claude"
                and not bool(candidate.get("legacy_fixture_format"))
            )
        )
    ]
    stdio_probe_ok, stdio_evidence_by_pid = _process_stdio_tty_evidence(
        stdio_probe_pids
    )
    if not stdio_probe_ok:
        return empty

    candidates: list[dict] = []
    for raw_candidate in raw_candidates:
        pid = int(raw_candidate["pid"])
        tty = str(raw_candidate["tty"])
        foreground_eligible = _snapshot_process_is_foreground(raw_candidate)
        if (
            provider == "claude"
            and not bool(raw_candidate.get("legacy_fixture_format"))
        ):
            # Claude becomes a one-shot command whenever stdout is not a TTY,
            # even without --print. Require exact PTY input/output evidence
            # for every candidate so redirected jobs cannot become sessions.
            stdio_evidence = stdio_evidence_by_pid.get(pid)
            if stdio_evidence is None:
                continue
            evidence_tty = str(stdio_evidence["tty"])
            if tty and tty != evidence_tty:
                continue
            tty = evidence_tty
            control_eligible = (
                bool(stdio_evidence["control_eligible"])
                and foreground_eligible
            )
        elif not tty:
            stdio_evidence = stdio_evidence_by_pid.get(pid)
            if stdio_evidence is None:
                # A provider command without one trustworthy PTY binding is
                # not part of an interactive TUI process family.
                continue
            tty = str(stdio_evidence["tty"])
            control_eligible = (
                bool(stdio_evidence["control_eligible"])
                and foreground_eligible
            )
        else:
            control_eligible = foreground_eligible
        candidates.append({
            "pid": pid,
            "ppid": int(raw_candidate.get("ppid") or 0),
            "state": str(raw_candidate.get("state") or ""),
            "process_group_id": int(
                raw_candidate.get("process_group_id") or 0
            ),
            "foreground_process_group_id": int(
                raw_candidate.get("foreground_process_group_id") or 0
            ),
            "job_control_observed": bool(
                raw_candidate.get("job_control_observed")
            ),
            "tty": tty,
            "started_at": float(raw_candidate["started_at"]),
            "command": str(raw_candidate["command"]),
            "argv": list(raw_candidate.get("argv") or []),
            "control_eligible": control_eligible,
            "ppid_observed": bool(raw_candidate.get("ppid_observed")),
        })
    cwd_probe_ok, cwd_by_pid = _process_cwds([
        int(candidate["pid"]) for candidate in candidates
    ])
    if not cwd_probe_ok:
        # A partial process scan is not exact identity evidence. Returning a
        # successful partial list would make a real session disappear or let
        # the registry act on a subset while lsof is temporarily unavailable.
        return empty
    executable_by_pid: dict[int, str] = {}
    if provider == "omp":
        executable_probe_ok, executable_by_pid = _process_executable_paths([
            int(candidate["pid"]) for candidate in candidates
        ])
        if not executable_probe_ok:
            return empty
    rows = [
        {
            **candidate,
            "project": cwd_by_pid[int(candidate["pid"])],
            **(
                {"executable_path": executable_by_pid[int(candidate["pid"])]}
                if provider == "omp"
                else {}
            ),
        }
        for candidate in candidates
    ]
    if include_snapshot:
        return True, rows, snapshot
    return True, rows


def _provider_terminal_identity_for_tab(
    terminal_tty: str, provider: str
) -> dict | None:
    """Resolve one provider process below one exact visible Terminal tab."""
    if re.fullmatch(r"/dev/ttys[0-9]{3,}", terminal_tty or "") is None:
        return None
    probe_ok, processes, process_snapshot = _scan_provider_process_rows(
        provider, include_snapshot=True
    )
    if not probe_ok:
        return None
    groups: dict[tuple[str, int], list[dict]] = {}
    for process in processes:
        pid = int(process.get("pid") or 0)
        provider_tty = str(process.get("tty") or "")
        owner_pid = 0
        if provider_tty != terminal_tty:
            owner = _snapshot_terminal_script_owner(
                process_snapshot, pid, terminal_tty
            )
            if owner is not None:
                owner_pid = int(owner.get("pid") or 0)
            if owner_pid <= 0:
                continue
        groups.setdefault((provider_tty, owner_pid), []).append(process)
    if len(groups) != 1:
        return None
    (provider_tty, owner_pid), candidates = next(iter(groups.items()))
    control_candidates = [
        item for item in candidates
        if bool(item.get("control_eligible", True))
    ]
    if not control_candidates:
        return None
    control = min(
        control_candidates,
        key=lambda item: int(item.get("pid") or 0),
    )
    control_pid = int(control.get("pid") or 0)
    family_pids = [
        int(item.get("pid") or 0)
        for item in candidates
        if _snapshot_process_is_descendant_of(
            process_snapshot,
            int(item.get("pid") or 0),
            control_pid,
        )
    ]
    if not family_pids:
        return None
    owner_started_at = float(
        (process_snapshot.get(owner_pid) or {}).get("started_at") or 0
    )
    return {
        **control,
        "pid": control_pid,
        "tty": terminal_tty,
        "provider_tty": provider_tty,
        "provider_pids": family_pids,
        "terminal_owner_pid": owner_pid,
        "terminal_owner_process_started_at": owner_started_at,
    }


def _wait_for_provider_terminal_identity(
    terminal_tty: str,
    provider: str,
    timeout_seconds: float = 3.0,
) -> dict | None:
    deadline = _time.monotonic() + max(0.0, timeout_seconds)
    while True:
        identity = _provider_terminal_identity_for_tab(terminal_tty, provider)
        if identity:
            return identity
        remaining = deadline - _time.monotonic()
        if remaining <= 0:
            return None
        _time.sleep(min(0.1, remaining))


def _provider_terminal_identity_metadata(identity: dict | None) -> dict:
    if not isinstance(identity, dict):
        return {}
    return {
        "provider_tty": str(identity.get("provider_tty") or "") or None,
        "terminal_owner_pid": int(identity.get("terminal_owner_pid") or 0) or None,
        "terminal_owner_process_started_at": (
            float(identity.get("terminal_owner_process_started_at") or 0)
            or None
        ),
    }


_CODEX_TERMINAL_VISIBILITY_GRACE_SECONDS = 15.0
_codex_terminal_scan_cache: dict[str, object] = {
    "ts": 0.0,
    "rows": [],
    "last_exact_ts": 0.0,
    "last_exact_rows": [],
    "probe_state": "unknown",
    "probe_reason": None,
    "membership_complete": False,
}
_codex_terminal_scan_lock = threading.Lock()
_claude_terminal_scan_cache: dict[str, object] = {
    "ts": 0.0,
    "rows": [],
    "probe_state": "unknown",
    "probe_reason": None,
    "membership_complete": False,
}
_claude_terminal_scan_lock = threading.Lock()
_sessions_membership_snapshot_lock = threading.Lock()
_AMBIENT_SESSION_MEMBERSHIP_PROVIDERS = frozenset({"claude", "codex"})


def _session_membership_provider_ids() -> set[str]:
    """Providers whose complete live membership Pairling can materialize."""
    return set(_agent_provider_ids())


def _provider_supports(provider: str, capability: str) -> bool:
    if _provider_get is None:
        return False
    try:
        adapter = _provider_get(provider)
        return bool(adapter and adapter.supports(capability))
    except Exception:
        return False
_SESSION_INVENTORY_FRESH_SECONDS = 5.0
_SESSION_INVENTORY_REFRESH_WAIT_SECONDS = 4.0
_sessions_inventory_bundle_lock = threading.Lock()
_sessions_inventory_bundle: dict[str, object] = {
    "generation": 0,
    "membership_generation": 0,
    "inventories": {},
    "completed_at": 0.0,
    "refreshing": False,
    "error": None,
}
_sessions_inventory_scan_context = threading.local()
_codex_task_boundary_cache: dict[str, dict[str, object]] = {}


def _sessions_inventory_scan_active() -> bool:
    return bool(getattr(_sessions_inventory_scan_context, "active", False))


def _sessions_inventory_membership_generation() -> int:
    with _sessions_inventory_bundle_lock:
        return int(
            _sessions_inventory_bundle.get("membership_generation") or 0
        )


def _invalidate_sessions_provider_inventory(provider: str | None = None) -> None:
    """Expire exact membership before publishing a real registry mutation."""
    if _sessions_inventory_scan_active():
        return
    provider = str(provider or "").strip().lower()
    with _sessions_inventory_bundle_lock:
        stored = _sessions_inventory_bundle.get("inventories") or {}
        membership_providers = _session_membership_provider_ids()
        targets = (
            {provider}
            if provider in membership_providers
            else membership_providers
        )
        for target in targets:
            inventory = stored.get(target)
            if isinstance(inventory, dict):
                inventory["checked_at"] = 0.0
                inventory["membership_complete"] = False
        _sessions_inventory_bundle["generation"] = int(
            _sessions_inventory_bundle.get("generation") or 0
        ) + 1
        _sessions_inventory_bundle["membership_generation"] = int(
            _sessions_inventory_bundle.get("membership_generation") or 0
        ) + 1
        refreshing = bool(_sessions_inventory_bundle.get("refreshing"))
    with _sessions_health_lock:
        _sessions_health["inventory_state"] = (
            "refreshing" if refreshing else "cold"
        )
        _sessions_health["inventory_checked_at"] = 0.0


def _process_executable_paths(pids: list[int]) -> tuple[bool, dict[int, str]]:
    unique_pids = sorted({int(pid) for pid in pids if int(pid or 0) > 0})
    if not unique_pids:
        return True, {}

    paths: dict[int, str] = {}
    try:
        libproc = ctypes.CDLL("/usr/lib/libproc.dylib", use_errno=True)
        proc_pidpath = libproc.proc_pidpath
        proc_pidpath.argtypes = [ctypes.c_int, ctypes.c_void_p, ctypes.c_uint32]
        proc_pidpath.restype = ctypes.c_int
    except (AttributeError, OSError):
        proc_pidpath = None

    if proc_pidpath is not None:
        for pid in unique_pids:
            buffer = ctypes.create_string_buffer(4096)
            length = int(proc_pidpath(pid, buffer, len(buffer)))
            if length <= 0:
                continue
            try:
                path = buffer.raw[:length].rstrip(b"\0").decode("utf-8")
            except UnicodeError:
                continue
            if path:
                paths[pid] = path

    unresolved = [pid for pid in unique_pids if pid not in paths]
    if unresolved:
        try:
            proc = subprocess.run(
                [
                    "lsof", "-a", "-p", ",".join(str(pid) for pid in unresolved),
                    "-d", "txt", "-Fpn",
                ],
                capture_output=True,
                text=True,
                timeout=2,
            )
        except Exception:
            return False, {}
        if proc.returncode != 0:
            return False, {}
        current_pid = 0
        for line in proc.stdout.splitlines():
            if line.startswith("p") and line[1:].isdigit():
                current_pid = int(line[1:])
                continue
            if current_pid in unresolved and line.startswith("n") and current_pid not in paths:
                path = line[1:].strip()
                if path:
                    paths[current_pid] = path

    if any(pid not in paths for pid in unique_pids):
        return False, {}
    return True, paths


def _omp_executable_path_matches(observed: str, resolved_binary: Path) -> bool:
    try:
        return (
            Path(observed).expanduser().resolve(strict=True)
            == resolved_binary.expanduser().resolve(strict=True)
        )
    except OSError:
        return False


def _omp_expected_executable_path(*, home: Path | None = None) -> Path | None:
    if _provider_get is None or _provider_resolve_executable is None:
        return None
    adapter = _provider_get("omp", home=home or HOME)
    if adapter is None:
        return None
    resolved = _provider_resolve_executable(
        "omp",
        adapter.candidates,
        env_var="PAIRLING_OMP_BIN",
    )
    if resolved is None:
        return None
    try:
        return resolved.path.resolve(strict=True)
    except OSError:
        return None


def _omp_resume_terminal_identity_matches(
    identity: dict | None,
    *,
    terminal_tty: str,
    canonical_project: str,
    resolved_binary: Path,
    record_mtime: float,
) -> bool:
    """Prove a resumed OMP UUID is bound to the expected live process."""
    if not isinstance(identity, dict):
        return False
    try:
        pid = int(identity.get("pid") or 0)
        process_started_at = float(identity.get("started_at") or 0)
    except (TypeError, ValueError):
        return False
    if (
        pid <= 0
        or process_started_at <= 0
        or str(identity.get("tty") or "") != terminal_tty
        or record_mtime < process_started_at
        or not _omp_executable_path_matches(
            str(identity.get("executable_path") or ""),
            resolved_binary,
        )
    ):
        return False
    try:
        return os.path.realpath(
            str(identity.get("project") or "")
        ) == os.path.realpath(canonical_project)
    except OSError:
        return str(identity.get("project") or "") == canonical_project


def _wait_for_omp_resume_terminal_identity(
    native_id: str,
    *,
    terminal_tty: str,
    canonical_project: str,
    resolved_binary: Path,
    timeout_seconds: float = 5.0,
) -> dict | None:
    """Wait briefly for OMP's terminal record and process identity to agree."""
    deadline = _time.monotonic() + max(0.1, timeout_seconds)
    while True:
        scan_ok, process_rows = _scan_provider_process_rows("omp")
        if scan_ok:
            inventory = _omp_provider_inventory_from_process_rows(process_rows, home=HOME)
            matches = [
                terminal
                for terminal in inventory.get("terminals") or []
                if str(terminal.get("native_id") or "") == native_id
                and str(terminal.get("terminal_tty") or "") == terminal_tty
                and str(terminal.get("identity_probe_state") or "") == "exact"
            ]
            if len(matches) == 1:
                terminal = matches[0]
                if _omp_resume_terminal_identity_matches(
                    terminal,
                    terminal_tty=terminal_tty,
                    canonical_project=canonical_project,
                    resolved_binary=resolved_binary,
                    record_mtime=float(terminal.get("record_mtime") or 0),
                ):
                    return terminal
        if _time.monotonic() >= deadline:
            return None
        _time.sleep(0.25)


def _wait_for_omp_spawn_terminal_identity(
    provider_identity: dict | None,
    *,
    canonical_project: str,
    timeout_seconds: float = 5.0,
) -> dict | None:
    """Return OMP's exact transcript ID or its exact Pairling-owned process."""
    if not isinstance(provider_identity, dict):
        return None
    try:
        pid = int(provider_identity.get("pid") or 0)
        started_at = float(provider_identity.get("started_at") or 0)
    except (TypeError, ValueError):
        return None
    provider_tty = str(
        provider_identity.get("provider_tty")
        or provider_identity.get("tty")
        or ""
    )
    if pid <= 0 or started_at <= 0 or not provider_tty:
        return None
    resolved_binary = _omp_expected_executable_path()
    expected_executable = str(provider_identity.get("executable_path") or "")
    if (
        resolved_binary is None
        or not _omp_executable_path_matches(
            expected_executable,
            resolved_binary,
        )
    ):
        return None
    try:
        if os.path.realpath(
            str(provider_identity.get("project") or "")
        ) != os.path.realpath(canonical_project):
            return None
    except OSError:
        return None

    deadline = _time.monotonic() + max(0.0, timeout_seconds)
    while True:
        scan_ok, process_rows = _scan_provider_process_rows("omp")
        if scan_ok:
            inventory = _omp_provider_inventory_from_process_rows(
                process_rows,
                home=HOME,
            )
            matches = []
            for terminal in inventory.get("terminals") or []:
                if (
                    str(terminal.get("identity_probe_state") or "") != "exact"
                    or int(terminal.get("pid") or 0) != pid
                    or str(terminal.get("terminal_tty") or "") != provider_tty
                ):
                    continue
                try:
                    candidate_started_at = float(
                        terminal.get("process_started_at") or 0
                    )
                    projects_match = os.path.realpath(
                        str(terminal.get("project") or "")
                    ) == os.path.realpath(canonical_project)
                except (OSError, TypeError, ValueError):
                    continue
                if (
                    candidate_started_at > 0
                    and abs(candidate_started_at - started_at) <= 2
                    and projects_match
                ):
                    matches.append(terminal)
            if len(matches) == 1:
                return matches[0]
            pending_matches = []
            for process in process_rows:
                try:
                    projects_match = os.path.realpath(
                        str(process.get("project") or "")
                    ) == os.path.realpath(canonical_project)
                    process_started_at = float(process.get("started_at") or 0)
                except (OSError, TypeError, ValueError):
                    continue
                if (
                    int(process.get("pid") or 0) == pid
                    and str(process.get("tty") or "") == provider_tty
                    and process_started_at > 0
                    and abs(process_started_at - started_at) <= 2
                    and projects_match
                    and expected_executable
                    and os.path.realpath(
                        str(process.get("executable_path") or "")
                    ) == os.path.realpath(expected_executable)
                ):
                    pending_matches.append(process)
            if len(pending_matches) == 1:
                process = pending_matches[0]
                return {
                    "provider": "omp",
                    "project": os.path.realpath(canonical_project),
                    "pid": pid,
                    "provider_tty": provider_tty,
                    "process_started_at": started_at,
                    "executable_path": str(
                        process.get("executable_path") or ""
                    ),
                    "identity_probe_state": "pairling_pending_process",
                    "can_control": True,
                    "source": "pairling_owned_process",
                }
        elif (
            _process_alive(pid)
            and abs(_process_start_epoch(pid) - started_at) <= 2
        ):
            return {
                "provider": "omp",
                "project": os.path.realpath(canonical_project),
                "pid": pid,
                "provider_tty": provider_tty,
                "process_started_at": started_at,
                "executable_path": expected_executable,
                "identity_probe_state": "pairling_pending_process",
                "can_control": True,
                "source": "pairling_owned_process",
            }
        if _time.monotonic() >= deadline:
            return None
        _time.sleep(0.1)


def _process_cwds(pids: list[int]) -> tuple[bool, dict[int, str]]:
    unique_pids = sorted({int(pid) for pid in pids if int(pid or 0) > 0})
    if not unique_pids:
        return True, {}
    try:
        proc = subprocess.run(
            [
                "lsof", "-a", "-p", ",".join(str(pid) for pid in unique_pids),
                "-d", "cwd", "-Fpn",
            ],
            capture_output=True,
            text=True,
            timeout=2,
        )
    except Exception:
        return False, {}
    if proc.returncode != 0:
        return False, {}
    current_pid = 0
    cwd_by_pid: dict[int, str] = {}
    for line in proc.stdout.splitlines():
        if line.startswith("p") and line[1:].isdigit():
            current_pid = int(line[1:])
            continue
        if current_pid > 0 and line.startswith("n/"):
            cwd_by_pid[current_pid] = line[1:]
    if any(pid not in cwd_by_pid for pid in unique_pids):
        return False, {}
    return True, cwd_by_pid


def _process_stdio_tty_evidence(
    pids: list[int],
) -> tuple[bool, dict[int, dict[str, object]]]:
    """Return control or identity PTY evidence for processes without a tty."""
    unique_pids = sorted({int(pid) for pid in pids if int(pid or 0) > 0})
    if not unique_pids:
        return True, {}
    try:
        proc = subprocess.run(
            [
                "lsof", "-a", "-p", ",".join(str(pid) for pid in unique_pids),
                "-d", "0,1,2", "-Ffpn",
            ],
            capture_output=True,
            text=True,
            timeout=2,
        )
    except Exception:
        return False, {}
    if proc.returncode != 0:
        return False, {}

    current_pid = 0
    current_fd = -1
    seen_pids: set[int] = set()
    stdio_by_pid: dict[int, dict[int, str]] = {}
    for line in proc.stdout.splitlines():
        if line.startswith("p") and line[1:].isdigit():
            current_pid = int(line[1:])
            current_fd = -1
            seen_pids.add(current_pid)
            continue
        if line.startswith("f"):
            current_fd = int(line[1:]) if line[1:] in {"0", "1", "2"} else -1
            continue
        if current_pid > 0 and current_fd >= 0 and line.startswith("n"):
            stdio_by_pid.setdefault(current_pid, {})[current_fd] = line[1:]

    if any(pid not in seen_pids for pid in unique_pids):
        return False, {}

    evidence_by_pid: dict[int, dict[str, object]] = {}
    for pid in unique_pids:
        fd_paths = stdio_by_pid.get(pid, {})
        if set(fd_paths) != {0, 1, 2}:
            return False, {}
        stdin_path = fd_paths[0]
        stdout_path = fd_paths[1]
        stderr_path = fd_paths[2]
        if (
            stdin_path == stdout_path
            and re.fullmatch(r"/dev/ttys[0-9]{3,}", stdin_path)
        ):
            if stderr_path == stdin_path:
                evidence_by_pid[pid] = {
                    "tty": stdin_path,
                    "control_eligible": True,
                }
                continue
            if not stderr_path.startswith("/dev/ttys"):
                # Codex's native child can inherit the wrapper's stdin/stdout
                # PTY while sending stderr to /dev/null. Keep it in the
                # wrapper's identity family so its open rollout can identify
                # the session, but never select it as a control process.
                evidence_by_pid[pid] = {
                    "tty": stdin_path,
                    "control_eligible": False,
                }
    return True, evidence_by_pid


def _is_codex_cli_argv(argv: list[str]) -> bool:
    if not argv:
        return False
    lower = " ".join(argv).lower()
    if "codex-code-mode-host" in lower:
        return False

    if _is_codex_cli_entrypoint(argv[0]):
        entrypoint_index = 0
    else:
        launcher = os.path.basename(argv[0]).lower()
        if launcher not in {"node", "nodejs", "bun"}:
            return False
        entrypoint_index = next(
            (
                index
                for index, arg in enumerate(argv[1:], start=1)
                if _is_codex_cli_entrypoint(arg)
            ),
            -1,
        )
        if entrypoint_index < 0:
            return False

    non_session_commands = {
        "app",
        "app-server",
        "apply",
        "archive",
        "cloud",
        "completion",
        "debug",
        "delete",
        "doctor",
        "e",
        "exec",
        "exec-server",
        "features",
        "help",
        "login",
        "logout",
        "mcp",
        "mcp-server",
        "plugin",
        "remote-control",
        "review",
        "sandbox",
        "unarchive",
        "update",
    }
    options_with_values = {
        "-a",
        "--add-dir",
        "--ask-for-approval",
        "-c",
        "-C",
        "--cd",
        "--config",
        "--disable",
        "--enable",
        "-i",
        "--image",
        "-m",
        "--model",
        "-p",
        "--profile",
        "-s",
        "--sandbox",
    }
    trailing = argv[entrypoint_index + 1:]
    index = 0
    while index < len(trailing):
        argument = trailing[index]
        lowered = argument.lower()
        if argument == "--":
            return True
        if argument.startswith("-"):
            if "=" not in argument and argument in options_with_values:
                index += 2
            else:
                index += 1
            continue
        return lowered not in non_session_commands
    return not any(
        argument.lower() in {"-h", "--help", "-v", "--version"}
        for argument in trailing
    )


def _is_codex_cli_command(command: str) -> bool:
    try:
        argv = shlex.split(command or "")
    except ValueError:
        return False
    return _is_codex_cli_argv(argv)


def _is_claude_cli_argv(argv: list[str]) -> bool:
    if not argv:
        return False

    if _is_claude_cli_entrypoint(argv[0]):
        entrypoint_index = 0
    else:
        launcher = os.path.basename(argv[0]).lower()
        if launcher not in {"node", "nodejs", "bun"}:
            return False
        entrypoint_index = next(
            (
                index
                for index, argument in enumerate(argv[1:], start=1)
                if _is_claude_cli_entrypoint(argument)
            ),
            -1,
        )
        if entrypoint_index < 0:
            return False

    trailing = argv[entrypoint_index + 1:]
    option_tokens = trailing[:trailing.index("--")] if "--" in trailing else trailing
    if any(
        argument in {
            "-p",
            "--print",
            "-v",
            "--version",
            "-h",
            "--help",
            "--bg",
            "--background",
        }
        or argument.startswith("--print=")
        for argument in option_tokens
    ):
        return False

    non_session_commands = {
        "agents",
        "auth",
        "auto-mode",
        "doctor",
        "gateway",
        "install",
        "mcp",
        "plugin",
        "plugins",
        "project",
        "setup-token",
        "ultrareview",
        "update",
        "upgrade",
    }
    options_with_values = {
        "--agent",
        "--agents",
        "--append-system-prompt",
        "--debug-file",
        "--effort",
        "--fallback-model",
        "--input-format",
        "--json-schema",
        "--max-budget-usd",
        "--model",
        "-m",
        "--name",
        "-n",
        "--output-format",
        "--permission-mode",
        "--plugin-dir",
        "--plugin-url",
        "--remote-control-session-name-prefix",
        "--session-id",
        "--setting-sources",
        "--settings",
        "--system-prompt",
    }
    variadic_options = {
        "--add-dir",
        "--allowedTools",
        "--allowed-tools",
        "--betas",
        "--disallowedTools",
        "--disallowed-tools",
        "--file",
        "--mcp-config",
        "--tools",
    }
    optional_value_options = {
        "--debug",
        "-d",
        "--from-pr",
        "--prompt-suggestions",
        "--remote-control",
        "--resume",
        "-r",
        "--worktree",
        "-w",
    }
    index = 0
    while index < len(trailing):
        argument = trailing[index]
        if argument == "--":
            return True
        if argument.startswith("-"):
            option = argument.split("=", 1)[0]
            if "=" in argument:
                index += 1
                continue
            if option in variadic_options:
                index += 1
                while index < len(trailing) and not trailing[index].startswith("-"):
                    index += 1
                continue
            if option in options_with_values:
                index += 2
                continue
            if option in optional_value_options:
                index += 1
                if index < len(trailing) and not trailing[index].startswith("-"):
                    index += 1
                continue
            index += 1
            continue
        return argument.lower() not in non_session_commands
    return True


def _is_omp_cli_argv(argv: list[str]) -> bool:
    if not argv or not _is_omp_cli_entrypoint(argv[0]):
        return False
    trailing = argv[1:]
    non_session_commands = {
        "agents",
        "browser-relay",
        "compact",
        "config",
        "doctor",
        "export",
        "gateway",
        "help",
        "hub",
        "init",
        "install",
        "join",
        "mcp",
        "models",
        "plugins",
        "remote",
        "stats",
        "update",
        "upgrade",
        "versions",
        "whoami",
    }
    options_with_values = {
        "--config-dir",
        "--cwd",
        "--extension",
        "--mode",
        "--model",
        "--plan",
        "--plan-yolo-into",
        "--plugin-dir",
        "--prewalk-into",
        "--provider",
        "--resume",
        "--smol",
    }
    index = 0
    while index < len(trailing):
        argument = trailing[index]
        lowered = argument.lower()
        if lowered.startswith("--mode="):
            if lowered.split("=", 1)[1] == "rpc":
                return False
            index += 1
            continue
        if argument == "--mode":
            if index + 1 >= len(trailing):
                return False
            if trailing[index + 1].lower() == "rpc":
                return False
            index += 2
            continue
        if argument == "--":
            return True
        if argument.startswith("-"):
            option = argument.split("=", 1)[0]
            if "=" not in argument and option in options_with_values:
                index += 2
            else:
                index += 1
            continue
        if lowered.startswith("__omp_"):
            return False
        return lowered not in non_session_commands
    return not any(
        argument.lower() in {"-h", "--help", "-v", "--version"}
        for argument in trailing
    )


def _is_claude_cli_command(command: str) -> bool:
    try:
        argv = shlex.split(command or "")
    except ValueError:
        return False
    return _is_claude_cli_argv(argv)


def _codex_open_rollouts_by_pid(
    pids: list[int],
    *,
    include_probe_status: bool = False,
) -> dict[int, list[dict]] | tuple[bool, dict[int, list[dict]]]:
    unique_pids = sorted({int(pid) for pid in pids if int(pid or 0) > 0})
    if not unique_pids:
        result: dict[int, list[dict]] = {}
        return (True, result) if include_probe_status else result
    try:
        proc = subprocess.run(
            ["lsof", "-a", "-p", ",".join(str(pid) for pid in unique_pids), "-Fpn"],
            capture_output=True,
            text=True,
            timeout=2,
        )
    except Exception:
        result = {}
        return (False, result) if include_probe_status else result
    if proc.returncode != 0:
        result = {}
        return (False, result) if include_probe_status else result

    root_text = str(CODEX_SESSIONS_DIR)
    current_pid = 0
    by_pid: dict[int, list[dict]] = {}
    for line in proc.stdout.splitlines():
        if line.startswith("p") and line[1:].isdigit():
            current_pid = int(line[1:])
            continue
        if current_pid <= 0 or not line.startswith("n"):
            continue
        raw_path = line[1:]
        if not raw_path.startswith(root_text + os.sep):
            continue
        path = Path(raw_path)
        if path.suffix != ".jsonl" or not path.name.startswith("rollout-"):
            continue
        meta = _codex_rollout_meta(path)
        if meta is None or meta.get("source") != "cli":
            continue
        approved = _approved_codex_transcript_path(path, str(meta.get("id") or ""))
        if approved is None:
            continue
        by_pid.setdefault(current_pid, []).append({
            "native_id": meta["id"],
            "output_path": str(approved),
            "project": meta["cwd"],
        })
    return (True, by_pid) if include_probe_status else by_pid


def _codex_live_terminal_rows(*, force_refresh: bool = False) -> list[dict]:
    with _codex_terminal_scan_lock:
        return _codex_live_terminal_rows_locked(force_refresh=force_refresh)


def _codex_live_terminal_rows_locked(
    *, force_refresh: bool = False
) -> list[dict]:
    now = _time.time()
    cached_ts = float(_codex_terminal_scan_cache.get("ts") or 0)
    if not force_refresh and now - cached_ts < 2:
        return copy.deepcopy(_codex_terminal_scan_cache.get("rows") or [])

    def degraded_rows(reason: str) -> list[dict]:
        exact_ts = float(_codex_terminal_scan_cache.get("last_exact_ts") or 0)
        last_exact_rows = copy.deepcopy(
            _codex_terminal_scan_cache.get("last_exact_rows") or []
        )
        within_visibility_grace = (
            now - exact_ts <= _CODEX_TERMINAL_VISIBILITY_GRACE_SECONDS
        )
        if within_visibility_grace:
            rows = last_exact_rows
        else:
            rows = []
            for row in last_exact_rows:
                pid = int(row.get("pid") or 0)
                expected_started_at = float(row.get("started_at") or 0)
                actual_started_at = _process_start_epoch(pid)
                if (
                    pid > 0
                    and expected_started_at > 0
                    and _process_alive(pid)
                    and actual_started_at > 0
                    and abs(actual_started_at - expected_started_at) <= 2
                ):
                    rows.append(row)
        for row in rows:
            row["identity_probe_state"] = "failed"
            row["identity_probe_reason"] = reason
        _codex_terminal_scan_cache["ts"] = now
        _codex_terminal_scan_cache["rows"] = copy.deepcopy(rows)
        _codex_terminal_scan_cache["probe_state"] = "failed"
        _codex_terminal_scan_cache["probe_reason"] = reason
        _codex_terminal_scan_cache["membership_complete"] = (
            within_visibility_grace
            and len(rows) == len(last_exact_rows)
            and bool(last_exact_rows)
        )
        return rows

    ps_ok, process_rows, process_snapshot = _scan_provider_process_rows(
        "codex", include_snapshot=True
    )
    if not ps_ok:
        return degraded_rows("process_scan_failed")

    process_groups: dict[str, list[dict]] = {}
    for process in process_rows:
        tty = str(process.get("tty") or "")
        process_groups.setdefault(tty, []).append(process)

    by_tty: dict[str, dict] = {}
    for tty, processes in process_groups.items():
        control_candidates = [
            process for process in processes
            if bool(process.get("control_eligible", True))
        ]
        if not control_candidates:
            continue
        # Only a fully attached process may receive signals. A mixed-stdio
        # native child stays in provider_pids solely so its open rollout can
        # identify the wrapper's canonical session.
        control = min(
            control_candidates,
            key=lambda item: int(item.get("pid") or 0),
        )
        control_pid = int(control.get("pid") or 0)
        owner = _snapshot_terminal_script_owner(
            process_snapshot, control_pid
        )
        terminal_tty = str((owner or {}).get("tty") or tty)
        by_tty[tty] = {
            "pid": control_pid,
            "tty": tty,
            "provider_tty": tty,
            "terminal_tty": terminal_tty,
            "terminal_owner_pid": int((owner or {}).get("pid") or 0),
            "terminal_owner_process_started_at": float(
                (owner or {}).get("started_at") or 0
            ),
            "project": control.get("project"),
            "started_at": control.get("started_at"),
            "command": control.get("command"),
            "provider_pids": sorted(
                int(process.get("pid") or 0) for process in processes
            ),
        }

    rollout_probe_ok, rollout_map = _codex_open_rollouts_by_pid(
        [
            pid
            for row in by_tty.values()
            for pid in row.get("provider_pids") or []
        ],
        include_probe_status=True,
    )
    if not rollout_probe_ok:
        return degraded_rows("rollout_identity_probe_failed")
    for row in by_tty.values():
        candidates: dict[tuple[str, str, str], dict] = {}
        control_pid = int(row.get("pid") or 0)
        verified_provider_pids = [
            pid
            for pid in (row.get("provider_pids") or [])
            if _snapshot_process_is_descendant_of(
                process_snapshot, int(pid), control_pid
            )
        ]
        for pid in verified_provider_pids:
            for candidate in rollout_map.get(int(pid), []):
                identity = (
                    str(candidate.get("native_id") or ""),
                    str(candidate.get("project") or ""),
                    str(candidate.get("output_path") or ""),
                )
                if all(identity):
                    candidates[identity] = candidate
        if len(candidates) != 1:
            continue
        transcript = next(iter(candidates.values()))
        row["native_id"] = transcript["native_id"]
        row["output_path"] = transcript["output_path"]
        row["process_project"] = row.get("project") or ""
        row["project"] = transcript["project"]
    rows = list(by_tty.values())
    for row in rows:
        row["identity_probe_state"] = "exact"
    _codex_terminal_scan_cache["ts"] = now
    _codex_terminal_scan_cache["rows"] = copy.deepcopy(rows)
    _codex_terminal_scan_cache["last_exact_ts"] = now
    _codex_terminal_scan_cache["last_exact_rows"] = copy.deepcopy(rows)
    _codex_terminal_scan_cache["probe_state"] = "exact"
    _codex_terminal_scan_cache["probe_reason"] = None
    _codex_terminal_scan_cache["membership_complete"] = True
    return copy.deepcopy(rows)


def _claude_live_terminal_rows(*, force_refresh: bool = False) -> list[dict]:
    with _claude_terminal_scan_lock:
        return _claude_live_terminal_rows_locked(force_refresh=force_refresh)


def _claude_live_terminal_rows_locked(
    *, force_refresh: bool = False
) -> list[dict]:
    now = _time.time()
    cached_ts = float(_claude_terminal_scan_cache.get("ts") or 0)
    if not force_refresh and now - cached_ts < 2:
        return copy.deepcopy(_claude_terminal_scan_cache.get("rows") or [])
    ps_ok, process_rows = _scan_provider_process_rows("claude")
    if not ps_ok:
        _claude_terminal_scan_cache["ts"] = now
        _claude_terminal_scan_cache["rows"] = []
        _claude_terminal_scan_cache["probe_state"] = "failed"
        _claude_terminal_scan_cache["probe_reason"] = "process_scan_failed"
        _claude_terminal_scan_cache["membership_complete"] = False
        return []

    by_tty: dict[str, dict] = {}
    for process in process_rows:
        if not bool(process.get("control_eligible", True)):
            continue
        pid = int(process.get("pid") or 0)
        tty = str(process.get("tty") or "")
        current = by_tty.get(tty)
        if current is None or pid < int(current.get("pid") or 0):
            by_tty[tty] = {
                "pid": pid,
                "tty": tty,
                "project": process.get("project"),
                "started_at": process.get("started_at"),
                "command": process.get("command"),
                "identity_probe_state": "exact",
            }
    rows = list(by_tty.values())
    _claude_terminal_scan_cache["ts"] = now
    _claude_terminal_scan_cache["rows"] = copy.deepcopy(rows)
    _claude_terminal_scan_cache["probe_state"] = "exact"
    _claude_terminal_scan_cache["probe_reason"] = None
    _claude_terminal_scan_cache["membership_complete"] = True
    return copy.deepcopy(rows)


def _omp_provider_inventory_from_process_rows(
    process_rows: list[dict],
    *,
    home: Path | None = None,
) -> dict:
    checked_at = _time.time()
    if (
        _provider_get is None
        or _provider_resolve_executable is None
        or _omp_terminal_session_records is None
        or _omp_session_runtime_metadata is None
    ):
        return {
            "provider": "omp",
            "terminals": [],
            "rows": [],
            "checked_at": checked_at,
            "probe_state": "failed",
            "probe_reason": "omp_adapter_unavailable",
            "membership_complete": False,
        }
    home = home or Path.home()
    adapter = _provider_get("omp", home=home)
    if adapter is None:
        return {
            "provider": "omp",
            "terminals": [],
            "rows": [],
            "checked_at": checked_at,
            "probe_state": "failed",
            "probe_reason": "omp_adapter_unavailable",
            "membership_complete": False,
        }
    resolved = _provider_resolve_executable(
        "omp",
        adapter.candidates,
        env_var="PAIRLING_OMP_BIN",
    )
    if resolved is None:
        return {
            "provider": "omp",
            "terminals": [],
            "rows": [],
            "checked_at": checked_at,
            "probe_state": "exact",
            "probe_reason": "omp_not_installed",
            "membership_complete": True,
        }
    try:
        resolved_binary = resolved.path.resolve(strict=True)
    except OSError:
        return {
            "provider": "omp",
            "terminals": [],
            "rows": [],
            "checked_at": checked_at,
            "probe_state": "failed",
            "probe_reason": "omp_binary_unavailable",
            "membership_complete": False,
        }

    candidates_by_tty: dict[str, list[dict]] = {}
    for process in process_rows:
        argv = process.get("argv")
        if not isinstance(argv, list):
            try:
                argv = shlex.split(str(process.get("command") or ""))
            except ValueError:
                continue
        argv = [str(argument) for argument in argv]
        if not _is_omp_cli_argv(argv):
            continue
        executable_path = str(process.get("executable_path") or "")
        if not executable_path or not _omp_executable_path_matches(
            executable_path, resolved_binary
        ):
            continue
        tty = str(process.get("tty") or "")
        pid = int(process.get("pid") or 0)
        started_at = float(process.get("started_at") or 0)
        project = str(process.get("project") or "")
        if not tty or pid <= 0 or started_at <= 0 or not project:
            continue
        candidates_by_tty.setdefault(tty, []).append(process)

    terminals: list[dict] = []
    for record in _omp_terminal_session_records(home=home):
        candidates = candidates_by_tty.get(record.terminal_tty) or []
        if len(candidates) != 1:
            continue
        process = candidates[0]
        process_started_at = float(process.get("started_at") or 0)
        if process_started_at <= 0 or record.record_mtime < process_started_at:
            continue
        try:
            process_project = os.path.realpath(str(process.get("project") or ""))
        except OSError:
            continue
        if process_project != record.project:
            continue
        can_control = True
        runtime_metadata = _omp_session_runtime_metadata(Path(record.session_path))
        terminals.append({
            "provider": "omp",
            "session_id": record.session_id,
            "native_id": record.native_id,
            "project": record.project,
            "title": record.title,
            "output_path": record.session_path,
            "session_path": record.session_path,
            "terminal_tty": record.terminal_tty,
            "tty": record.terminal_tty,
            "executable_path": str(process.get("executable_path") or ""),
            "pid": int(process.get("pid") or 0),
            "provider_pid": int(process.get("pid") or 0),
            "process_started_at": process_started_at,
            "started_at": process_started_at,
            "command": str(
                process.get("command") or shlex.join(process.get("argv") or [])
            ),
            "identity_probe_state": "exact",
            "can_control": can_control,
            "record_mtime": record.record_mtime,
            "record_fresh": record.fresh,
            "identity_probe_reason": None,
            "source": "omp_terminal_record",
            "model": runtime_metadata.get("model"),
            "effort": runtime_metadata.get("effort"),
        })

    counts: dict[str, int] = {}
    for terminal in terminals:
        native_id = str(terminal.get("native_id") or "")
        counts[native_id] = counts.get(native_id, 0) + 1
    for terminal in terminals:
        if counts.get(str(terminal.get("native_id") or ""), 0) > 1:
            terminal["identity_probe_state"] = "ambiguous"
            terminal["can_control"] = False

    return {
        "provider": "omp",
        "terminals": terminals,
        "rows": terminals,
        "checked_at": checked_at,
        "probe_state": "exact",
        "probe_reason": None,
        "membership_complete": True,
    }


def _omp_pairling_pending_terminal(
    registry_row: dict | None,
    process_rows: list[dict] | None = None,
) -> dict | None:
    """Bind one Pairling pending id to one exact live OMP process."""
    if (
        not isinstance(registry_row, dict)
        or registry_row.get("closed_at") is not None
        or str(registry_row.get("provider") or "").strip().lower() != "omp"
    ):
        return None
    native_id = str(registry_row.get("native_id") or "")
    project = str(registry_row.get("project") or "")
    pid = int(registry_row.get("pid") or 0)
    stored_terminal_tty = str(registry_row.get("terminal_tty") or "")
    metadata = _registry_metadata_from_row(registry_row)
    try:
        expected_started_at = float(metadata.get("process_started_at") or 0)
    except (TypeError, ValueError):
        return None
    expected_provider_tty = str(
        metadata.get("provider_tty") or stored_terminal_tty
    )
    executable_path = str(metadata.get("executable_path") or "")
    resolved_binary = _omp_expected_executable_path()
    send_scope_id = _normalized_send_scope_id(
        "omp", metadata.get("send_scope_id")
    )
    if (
        not native_id.startswith("pending-")
        or not _safe_agent_native_id(native_id)
        or not project
        or pid <= 0
        or expected_started_at <= 0
        or re.fullmatch(r"/dev/ttys[0-9]{3,}", expected_provider_tty) is None
        or (
            stored_terminal_tty
            and re.fullmatch(r"/dev/ttys[0-9]{3,}", stored_terminal_tty) is None
        )
        or not executable_path
        or resolved_binary is None
        or not _omp_executable_path_matches(executable_path, resolved_binary)
        or metadata.get("spawned_by") != "pairling"
        or metadata.get("identity_probe_state") != "pairling_pending_process"
        or str(metadata.get("pending_native_id") or "") != native_id
        or send_scope_id != _qualified_session_id("omp", native_id)
    ):
        return None

    candidates = process_rows
    if candidates is None:
        process_scan_ok, candidates = _scan_provider_process_rows("omp")
        if not process_scan_ok:
            return None
    matches: list[dict] = []
    for candidate in candidates:
        if int(candidate.get("pid") or 0) != pid:
            continue
        candidate_provider_tty = str(
            candidate.get("provider_tty")
            or candidate.get("tty")
            or candidate.get("terminal_tty")
            or ""
        )
        if candidate_provider_tty != expected_provider_tty:
            continue
        if not bool(
            candidate.get(
                "control_eligible",
                candidate.get("can_control", True),
            )
        ):
            continue
        try:
            candidate_started_at = float(
                candidate.get("process_started_at")
                or candidate.get("started_at")
                or 0
            )
            projects_match = os.path.realpath(
                str(candidate.get("project") or "")
            ) == os.path.realpath(project)
        except (OSError, TypeError, ValueError):
            continue
        if (
            candidate_started_at <= 0
            or abs(candidate_started_at - expected_started_at) > 2
            or not projects_match
            or not _omp_executable_path_matches(
                str(candidate.get("executable_path") or ""),
                resolved_binary,
            )
        ):
            continue
        if (
            stored_terminal_tty
            and stored_terminal_tty != expected_provider_tty
            and not _direct_terminal_binding_is_verified(
                registry_row,
                "omp",
                pid,
                provider_tty=expected_provider_tty,
            )
        ):
            continue
        matches.append(candidate)
    if len(matches) != 1:
        return None

    candidate = matches[0]
    broker_id = _normalized_send_scope_id("omp", metadata.get("broker_id"))
    broker_session = (
        _registry_owned_broker_session("omp", native_id, registry_row)
        if broker_id
        else None
    )
    broker_relation = _broker_runtime_relation() if broker_session is not None else ""
    broker_controllable = bool(
        broker_session is not None
        and _broker_pid(broker_session) == pid
        and _broker_slave_tty(broker_session) == expected_provider_tty
        and broker_relation == "current"
        and _broker_supports_current_atomic_control(broker_relation)
    )
    return {
        "provider": "omp",
        "session_id": native_id,
        "native_id": native_id,
        "project": os.path.realpath(project),
        "title": str(
            metadata.get("terminal_title")
            or registry_row.get("working_on")
            or "OMP session"
        ),
        "terminal_tty": stored_terminal_tty or expected_provider_tty,
        "tty": expected_provider_tty,
        "executable_path": executable_path,
        "pid": pid,
        "provider_pid": pid,
        "process_started_at": expected_started_at,
        "started_at": expected_started_at,
        "command": str(candidate.get("command") or ""),
        "identity_probe_state": "pairling_pending_process",
        "identity_probe_reason": "awaiting_omp_transcript",
        "can_control": broker_controllable if broker_id else True,
        "control_profile": (
            "current_atomic_v2"
            if broker_controllable
            else ("read_only" if broker_id else "direct_terminal_receipted")
        ),
        "source": "pairling_owned_process",
        "send_scope_id": send_scope_id,
        **({"broker_id": broker_id} if broker_id else {}),
    }


def _omp_sessions_from_inventory(inventory: dict) -> list[dict]:
    checked_at = float(inventory.get("checked_at") or _time.time())
    rows: list[dict] = []
    for terminal in inventory.get("terminals") or []:
        if not isinstance(terminal, dict):
            continue
        native_id = str(terminal.get("native_id") or terminal.get("session_id") or "")
        project = str(terminal.get("project") or "")
        if not native_id or not project:
            continue
        identity_state = str(terminal.get("identity_probe_state") or "")
        resumable = identity_state == "exact"
        direct_steerable = bool(
            identity_state in {"exact", "pairling_pending_process"}
            and terminal.get("can_control")
        )
        broker_controllable = bool(
            terminal.get("broker_id")
            and terminal.get("control_profile") == "current_atomic_v2"
        )
        capabilities = ["terminal_output", "terminal_surface"]
        if resumable:
            capabilities.insert(0, "resume")
        if direct_steerable:
            capabilities.extend(["send_text", "interrupt", "terminate"])
        if broker_controllable:
            capabilities.extend([
                "terminal_control",
            ])
        reason = (
            None
            if direct_steerable
            else (
                str(
                    terminal.get("identity_probe_reason")
                    or "process_identity_unverified"
                )
            )
        )
        started_at = float(terminal.get("process_started_at") or checked_at)
        rows.append({
            "id": _qualified_session_id("omp", native_id),
            "provider": "omp",
            "native_id": native_id,
            "send_scope_id": terminal.get("send_scope_id") or None,
            "broker_id": terminal.get("broker_id") or None,
            "project": project,
            "working_on": str(terminal.get("title") or "OMP session"),
            "started_at": int(started_at),
            "last_heartbeat": int(checked_at),
            "stale_seconds": max(0, int(_time.time() - checked_at)),
            "source_freshness": "inventory_live",
            "terminal_tty": str(terminal.get("terminal_tty") or ""),
            "pid": int(terminal.get("pid") or 0),
            "terminal_title": terminal.get("title"),
            "first_prompt": None,
            "state": "running",
            "tool": None,
            "turn_started_at": None,
            "effort": terminal.get("effort"),
            "model": terminal.get("model"),
            "context_pct": None,
            "capabilities": capabilities,
            "controllability": {
                "can_send_text": direct_steerable,
                "can_interrupt": direct_steerable,
                "can_terminate": direct_steerable,
                "can_control": broker_controllable,
                "reason": reason,
            },
        })
    return rows


def _omp_reconcile_provider_inventory(
    inventory: dict,
    *,
    registry_rows: list[dict] | None = None,
) -> None:
    if (
        inventory.get("probe_state") != "exact"
        or not bool(inventory.get("membership_complete"))
    ):
        return
    registry_rows = (
        list(registry_rows)
        if registry_rows is not None
        else _agent_registry_live("omp", limit=1000)
    )
    live_ids: set[str] = set()
    for terminal in inventory.get("terminals") or []:
        if str(terminal.get("identity_probe_state") or "") != "pairling_pending_process":
            continue
        native_id = str(terminal.get("native_id") or "")
        pending_row = next(
            (
                row
                for row in registry_rows
                if str(row.get("native_id") or "") == native_id
            ),
            None,
        )
        if _omp_pairling_pending_terminal(pending_row, [terminal]) is not None:
            live_ids.add(native_id)
    for terminal in inventory.get("terminals") or []:
        if str(terminal.get("identity_probe_state") or "") != "exact":
            continue
        native_id = str(terminal.get("native_id") or "")
        project = str(terminal.get("project") or "")
        pid = int(terminal.get("pid") or 0)
        terminal_tty = str(terminal.get("terminal_tty") or "")
        process_started_at = float(terminal.get("process_started_at") or 0)
        if (
            not native_id
            or not project
            or pid <= 0
            or not terminal_tty
            or process_started_at <= 0
        ):
            continue
        metadata = {
            "provider_tty": str(terminal.get("tty") or terminal_tty),
            "process_started_at": process_started_at,
            "output_path": str(terminal.get("output_path") or ""),
            "session_path": str(terminal.get("session_path") or ""),
            "command": str(terminal.get("command") or ""),
            "identity_probe_state": "exact",
            "can_control": bool(terminal.get("can_control")),
            "record_mtime": float(terminal.get("record_mtime") or 0),
            "source": "omp_terminal_record",
        }
        existing = _agent_registry_get("omp", native_id)
        pending_owner = None
        if existing is None or not _omp_inventory_registry_process_matches(
            existing,
            [terminal],
        ):
            pending_matches = [
                row
                for row in registry_rows
                if _omp_pairling_pending_terminal(row, [terminal]) is not None
            ]
            if len(pending_matches) > 1:
                continue
            if len(pending_matches) == 1:
                pending_owner = pending_matches[0]
                existing = pending_owner
        registry_terminal_tty = terminal_tty
        existing_matches_canonical = (
            existing is not None
            and _omp_inventory_registry_process_matches(existing, [terminal])
        )
        if pending_owner is not None or existing_matches_canonical:
            durable_metadata = _registry_metadata_from_row(existing)
            metadata = {**durable_metadata, **metadata}
            existing_terminal_tty = str(existing.get("terminal_tty") or "")
            if re.fullmatch(r"/dev/ttys[0-9]{3,}", existing_terminal_tty):
                registry_terminal_tty = existing_terminal_tty
                terminal["terminal_tty"] = existing_terminal_tty
        existing_native_id = str(
            (existing or {}).get("native_id") or native_id
        )
        broker_session = _registry_owned_broker_session(
            "omp", existing_native_id, existing
        )
        if (
            broker_session is not None
            and os.path.realpath(str((existing or {}).get("project") or ""))
            == os.path.realpath(project)
            and _broker_pid(broker_session) == pid
            and _broker_slave_tty(broker_session) == terminal_tty
        ):
            broker_relation = _broker_runtime_relation()
            current_atomic_control = (
                broker_relation == "current"
                and _broker_supports_current_atomic_control(broker_relation)
            )
            durable_metadata = _registry_metadata_from_row(existing)
            metadata = {**durable_metadata, **metadata}
            metadata["terminal_source"] = "broker_vt"
            terminal.update({
                "broker_id": _broker_session_id(broker_session),
                "terminal_source": "broker_vt",
                "can_control": current_atomic_control,
                "control_profile": (
                    "current_atomic_v2"
                    if current_atomic_control
                    else "read_only"
                ),
            })
        durable_send_scope_id = _durable_send_scope_id_from_registry_row(
            existing,
            provider="omp",
            native_id=native_id,
        )
        if durable_send_scope_id:
            terminal["send_scope_id"] = durable_send_scope_id
        if _agent_registry_upsert(
            "omp",
            native_id,
            project,
            pid=pid,
            terminal_tty=registry_terminal_tty,
            state="running",
            metadata=metadata,
            working_on=str(terminal.get("title") or ""),
        ):
            live_ids.add(native_id)
            if pending_owner is not None:
                pending_native_id = str(pending_owner.get("native_id") or "")
                if pending_native_id and pending_native_id != native_id:
                    _agent_registry_mark_closed("omp", pending_native_id)
                    live_ids.add(pending_native_id)

    for row in registry_rows:
        native_id = str(row.get("native_id") or "")
        if not native_id or native_id in live_ids:
            continue
        if _registry_owned_broker_session("omp", native_id, row) is not None:
            continue
        _agent_registry_mark_closed("omp", native_id)


def _capture_sessions_provider_inventory(provider: str) -> dict:
    """Capture one exact ambient and/or Pairling-owned provider generation."""
    omp_inventory: dict | None = None
    if provider == "omp":
        if provider not in _session_membership_provider_ids():
            return {
                "provider": provider,
                "rows": [],
                "probe_state": "unsupported",
                "membership_complete": False,
                "checked_at": _time.time(),
            }
        process_scan_ok, process_rows = _scan_provider_process_rows("omp")
        if not process_scan_ok:
            return {
                "provider": "omp",
                "rows": [],
                "terminals": [],
                "checked_at": _time.time(),
                "probe_state": "failed",
                "probe_reason": "process_scan_failed",
                "membership_complete": False,
            }
        inventory = _omp_provider_inventory_from_process_rows(process_rows)
        registry_rows = _agent_registry_live("omp", limit=1000)
        canonical_terminals = list(inventory.get("terminals") or [])
        pending_terminals = []
        for row in registry_rows:
            pending_terminal = _omp_pairling_pending_terminal(row, process_rows)
            if pending_terminal is None:
                continue
            if any(
                int(terminal.get("pid") or 0)
                == int(pending_terminal.get("pid") or 0)
                and str(terminal.get("tty") or "")
                == str(pending_terminal.get("tty") or "")
                and abs(
                    float(terminal.get("process_started_at") or 0)
                    - float(pending_terminal.get("process_started_at") or 0)
                )
                <= 2
                for terminal in canonical_terminals
            ):
                continue
            pending_terminals.append(pending_terminal)
        inventory["terminals"] = canonical_terminals + pending_terminals
        inventory["rows"] = list(inventory["terminals"])
        _omp_reconcile_provider_inventory(
            inventory,
            registry_rows=registry_rows,
        )
        if (
            inventory.get("probe_state") != "exact"
            or not bool(inventory.get("membership_complete"))
        ):
            return inventory
        omp_inventory = inventory
    if provider not in _session_membership_provider_ids():
        return {
            "provider": provider,
            "rows": [],
            "probe_state": "unsupported",
            "membership_complete": False,
            "checked_at": _time.time(),
        }

    managed_rows: list[dict] = []
    manager = _ensure_managed_provider_session_manager()
    if manager is None:
        return {
            "provider": provider,
            "rows": [],
            "probe_state": "failed",
            "probe_reason": "managed_session_inventory_unavailable",
            "membership_complete": False,
            "checked_at": _time.time(),
        }
    try:
        managed_rows = manager.list_rows(
            provider=provider,
            live_only=True,
            active_within_min=None,
            limit=201,
            poll_live=True,
        )
    except Exception as error:
        return {
            "provider": provider,
            "rows": [],
            "probe_state": "failed",
            "probe_reason": (
                "managed_session_inventory_failed:"
                f"{type(error).__name__}"
            ),
            "membership_complete": False,
            "checked_at": _time.time(),
        }
    if len(managed_rows) >= 201:
        return {
            "provider": provider,
            "rows": copy.deepcopy(managed_rows),
            "probe_state": "incomplete",
            "probe_reason": "managed_session_inventory_truncated",
            "membership_complete": False,
            "checked_at": _time.time(),
        }
    if any(
        not isinstance(row, dict)
        or not bool(row.get("managed"))
        or str(row.get("provider") or "").strip().lower() != provider
        or row.get("closed_at") is not None
        or str(row.get("lifecycle") or "")
        not in {"launching", "running", "waiting", "blocked", "closing"}
        for row in managed_rows
    ):
        return {
            "provider": provider,
            "rows": [],
            "probe_state": "failed",
            "probe_reason": "managed_session_inventory_invalid",
            "membership_complete": False,
            "checked_at": _time.time(),
        }

    if omp_inventory is not None:
        return {
            **omp_inventory,
            "rows": (
                copy.deepcopy(omp_inventory.get("rows") or [])
                + copy.deepcopy(managed_rows)
            ),
            "checked_at": _time.time(),
        }

    if provider not in _AMBIENT_SESSION_MEMBERSHIP_PROVIDERS:
        return {
            "provider": provider,
            "rows": copy.deepcopy(managed_rows),
            "probe_state": "exact",
            "membership_complete": True,
            "checked_at": _time.time(),
        }

    if provider == "codex":
        lock = _codex_terminal_scan_lock
        cache = _codex_terminal_scan_cache
        loader = _codex_live_terminal_rows_locked
    else:
        lock = _claude_terminal_scan_lock
        cache = _claude_terminal_scan_cache
        loader = _claude_live_terminal_rows_locked

    with lock:
        ambient_rows = loader(force_refresh=True)
        return {
            "provider": provider,
            "rows": copy.deepcopy(ambient_rows) + copy.deepcopy(managed_rows),
            "probe_state": str(cache.get("probe_state") or "unknown"),
            "membership_complete": bool(cache.get("membership_complete")),
            # The scanner records its cache timestamp before slower process
            # probes. This timestamp is taken after all probes and row capture.
            "checked_at": _time.time(),
        }


def _sessions_inventory_placeholder(
    provider: str,
    state: str,
    error: str | None = None,
) -> dict:
    payload = {
        "provider": provider,
        "rows": [],
        "probe_state": state,
        "membership_complete": False,
        "checked_at": 0.0,
    }
    if error:
        payload["probe_reason"] = error
    return payload


def _sessions_inventory_degradation(state: str) -> dict | None:
    if state == "ready":
        return None
    return {
        "reason": f"session_inventory_{state}",
        "detail": (
            "Pairling is refreshing the Mac session inventory. "
            "The last trusted session list is being kept until it is exact."
        ),
    }


def _refresh_sessions_inventory_bundle(
    providers: tuple[str, ...],
    expected_generation: int | None = None,
    expected_membership_generation: int | None = None,
) -> None:
    try:
        if expected_generation is None or expected_membership_generation is None:
            with _sessions_inventory_bundle_lock:
                if expected_generation is None:
                    expected_generation = int(
                        _sessions_inventory_bundle.get("generation") or 0
                    )
                expected_membership_generation = int(
                    _sessions_inventory_bundle.get("membership_generation")
                    or 0
                )
        previous_scan_state = _sessions_inventory_scan_active()
        _sessions_inventory_scan_context.active = True
        try:
            with _sessions_membership_snapshot_lock:
                inventories = {
                    provider: _capture_sessions_provider_inventory(provider)
                    for provider in providers
                }
        finally:
            _sessions_inventory_scan_context.active = previous_scan_state
        completed_at = _time.time()
        # A multi-provider generation is committed only after every serial
        # probe succeeds. Keep each exact probe's checked_at for evidence, but
        # start cache freshness at this generation's commit so an early probe
        # cannot expire before the generation is publishable.
        for inventory in inventories.values():
            inventory["refreshed_at"] = completed_at
        with _sessions_inventory_bundle_lock:
            if (
                int(_sessions_inventory_bundle.get("generation") or 0)
                != int(expected_generation)
                or int(
                    _sessions_inventory_bundle.get("membership_generation")
                    or 0
                )
                != int(expected_membership_generation)
            ):
                _sessions_inventory_bundle["refreshing"] = False
                discarded = True
                stored = copy.deepcopy(
                    _sessions_inventory_bundle.get("inventories") or {}
                )
            else:
                discarded = False
                stored = copy.deepcopy(
                    _sessions_inventory_bundle.get("inventories") or {}
                )
                stored.update(copy.deepcopy(inventories))
                _sessions_inventory_bundle["inventories"] = stored
                _sessions_inventory_bundle["completed_at"] = completed_at
                _sessions_inventory_bundle["refreshing"] = False
                _sessions_inventory_bundle["error"] = None
                _sessions_inventory_bundle["generation"] = int(
                    _sessions_inventory_bundle.get("generation") or 0
                ) + 1
        if discarded:
            with _sessions_health_lock:
                _sessions_health["inventory_state"] = "cold"
                _sessions_health["inventory_checked_at"] = 0.0
            _publish_session_event(
                SESSION_SUMMARIES_TOPIC,
                {"type": "session_inventory_invalidated"},
            )
            return
        now = _time.time()
        state = "ready" if all(
            isinstance(inventory, dict)
            and inventory.get("probe_state") == "exact"
            and bool(inventory.get("membership_complete"))
            and float(inventory.get("checked_at") or 0) > 0
            and _sessions_inventory_is_fresh(inventory, now)
            for inventory in stored.values()
        ) else "incomplete"
        with _sessions_health_lock:
            _sessions_health["inventory_state"] = state
            _sessions_health["inventory_checked_at"] = completed_at
        _publish_session_event(
            SESSION_SUMMARIES_TOPIC,
            {"type": "session_inventory_refreshed", "checked_at": completed_at},
        )
    except Exception as error:
        detail = f"{type(error).__name__}: {str(error)[:160]}"
        with _sessions_inventory_bundle_lock:
            _sessions_inventory_bundle["refreshing"] = False
            _sessions_inventory_bundle["error"] = detail
            _sessions_inventory_bundle["generation"] = int(
                _sessions_inventory_bundle.get("generation") or 0
            ) + 1
        with _sessions_health_lock:
            _sessions_health["inventory_state"] = "failed"
        _publish_session_event(
            SESSION_SUMMARIES_TOPIC,
            {"type": "session_inventory_failed"},
        )


def _sessions_inventory_is_fresh(inventory: object, now: float) -> bool:
    if not isinstance(inventory, dict):
        return False
    refreshed_at = float(
        inventory.get("refreshed_at") or inventory.get("checked_at") or 0
    )
    return (
        refreshed_at > 0
        and now - refreshed_at < _SESSION_INVENTORY_FRESH_SECONDS
    )


def _sessions_provider_inventory_bundle(
    requested: set[str],
    *,
    wait_timeout: float = 0.0,
) -> tuple[dict[str, dict], str, int, int]:
    requested = set(requested) & _session_membership_provider_ids()
    if not requested:
        with _sessions_inventory_bundle_lock:
            generation = int(_sessions_inventory_bundle.get("generation") or 0)
            membership_generation = int(
                _sessions_inventory_bundle.get("membership_generation") or 0
            )
        return {}, "ready", generation, membership_generation
    now = _time.time()
    start_refresh = False
    refresh_timed_out = False
    refresh_generation = 0
    membership_generation = 0
    refresh_providers: set[str] = set()
    with _sessions_inventory_bundle_lock:
        refreshing = bool(_sessions_inventory_bundle.get("refreshing"))
        stored = copy.deepcopy(_sessions_inventory_bundle.get("inventories") or {})
        provider_fresh = {
            provider: _sessions_inventory_is_fresh(stored.get(provider), now)
            for provider in requested
        }
        refresh_providers = {
            provider for provider, fresh in provider_fresh.items() if not fresh
        }
        stale = bool(refresh_providers)
        if stale and not refreshing:
            _sessions_inventory_bundle["refreshing"] = True
            _sessions_inventory_bundle["generation"] = int(
                _sessions_inventory_bundle.get("generation") or 0
            ) + 1
            refresh_generation = int(
                _sessions_inventory_bundle["generation"]
            )
            refreshing = True
            start_refresh = True
        error = str(_sessions_inventory_bundle.get("error") or "") or None
        generation = int(_sessions_inventory_bundle.get("generation") or 0)
        membership_generation = int(
            _sessions_inventory_bundle.get("membership_generation") or 0
        )

    if start_refresh:
        try:
            threading.Thread(
                target=_refresh_sessions_inventory_bundle,
                args=(
                    tuple(sorted(refresh_providers)),
                    refresh_generation,
                    membership_generation,
                ),
                name="pairling-session-inventory",
                daemon=True,
            ).start()
        except Exception as thread_error:
            error = f"{type(thread_error).__name__}: {str(thread_error)[:160]}"
            with _sessions_inventory_bundle_lock:
                _sessions_inventory_bundle["refreshing"] = False
                _sessions_inventory_bundle["error"] = error
                _sessions_inventory_bundle["generation"] = int(
                    _sessions_inventory_bundle.get("generation") or 0
                ) + 1
                generation = int(_sessions_inventory_bundle["generation"])
            refreshing = False

    if wait_timeout > 0 and stale and refreshing:
        deadline = _time.monotonic() + wait_timeout
        # ponytail: Poll the existing state; add a condition only if this
        # bounded request wait becomes measurable lock contention.
        while True:
            with _sessions_inventory_bundle_lock:
                refreshing = bool(_sessions_inventory_bundle.get("refreshing"))
                if not refreshing:
                    stored = copy.deepcopy(
                        _sessions_inventory_bundle.get("inventories") or {}
                    )
                    error = (
                        str(_sessions_inventory_bundle.get("error") or "")
                        or None
                    )
                    generation = int(
                        _sessions_inventory_bundle.get("generation") or 0
                    )
                    membership_generation = int(
                        _sessions_inventory_bundle.get(
                            "membership_generation"
                        ) or 0
                    )
                    break
            remaining = deadline - _time.monotonic()
            if remaining <= 0:
                refresh_timed_out = True
                break
            _time.sleep(min(0.01, remaining))
        if not refresh_timed_out:
            now = _time.time()
            provider_fresh = {
                provider: _sessions_inventory_is_fresh(stored.get(provider), now)
                for provider in requested
            }
            stale = any(not fresh for fresh in provider_fresh.values())

    fresh = not stale
    exact = fresh and all(
        isinstance(stored.get(provider), dict)
        and stored[provider].get("probe_state") == "exact"
        and bool(stored[provider].get("membership_complete"))
        for provider in requested
    )
    if refresh_timed_out:
        state = "timeout"
    elif fresh:
        state = "ready" if exact else "incomplete"
    elif refreshing:
        state = "refreshing" if any(provider_fresh.values()) else "warming"
    else:
        state = "failed" if error else "cold"

    inventories: dict[str, dict] = {}
    for provider in sorted(requested):
        inventory = copy.deepcopy(stored.get(provider))
        if not isinstance(inventory, dict):
            inventories[provider] = _sessions_inventory_placeholder(
                provider,
                "failed" if error and not refreshing else state,
                error,
            )
            continue
        if not provider_fresh.get(provider, False):
            inventory["probe_state"] = state
            inventory["membership_complete"] = False
        inventories[provider] = inventory

    if state != "ready":
        with _sessions_health_lock:
            _sessions_health["inventory_state"] = state
    return inventories, state, generation, membership_generation


def _session_inventory_terminal_matches_row(
    provider: str,
    terminal: dict,
    row: dict,
) -> bool:
    if str(row.get("provider") or "").strip().lower() != provider:
        return False
    if row.get("closed_at") is not None:
        return False
    if bool(terminal.get("managed")):
        terminal_id = str(
            terminal.get("id") or terminal.get("session_id") or ""
        )
        row_id = str(row.get("id") or row.get("session_id") or "")
        return (
            bool(row.get("managed"))
            and bool(terminal_id)
            and row_id == terminal_id
            and str(row.get("native_id") or "")
            == str(terminal.get("native_id") or "")
        )
    try:
        terminal_pid = int(terminal.get("pid") or 0)
        row_pid = int(row.get("pid") or row.get("claude_pid") or 0)
    except (TypeError, ValueError):
        return False
    terminal_tty = str(
        terminal.get("terminal_tty")
        or terminal.get("provider_tty")
        or terminal.get("tty")
        or ""
    )
    row_tty = str(row.get("terminal_tty") or "")
    if terminal_pid <= 0 or row_pid != terminal_pid or row_tty != terminal_tty:
        return False

    terminal_project = str(terminal.get("project") or "")
    row_project = str(row.get("project") or "")
    if not terminal_project or not row_project:
        return False
    try:
        if os.path.realpath(terminal_project) != os.path.realpath(row_project):
            return False
    except OSError:
        if terminal_project != row_project:
            return False

    if provider == "claude":
        native_id = str(row.get("native_id") or "")
        registry_row = _agent_registry_get("claude", native_id)
        return _claude_inventory_registry_process_matches(
            registry_row,
            [terminal],
        )

    terminal_native_id = str(terminal.get("native_id") or "")
    if provider in {"codex", "omp"} and terminal_native_id:
        return str(row.get("native_id") or "") == terminal_native_id
    return True


def _codex_discover_terminal_control_for_session(native_id: str) -> dict | None:
    if not native_id:
        return None
    matches = [
        row for row in _codex_live_terminal_rows()
        if row.get("native_id") == native_id
        and str(row.get("identity_probe_state") or "exact") == "exact"
    ]
    return matches[0] if len(matches) == 1 else None


def _codex_terminal_native_id(row: dict) -> str:
    tty = str(row.get("tty") or "")
    project = str(row.get("project") or "")
    started = int(float(row.get("started_at") or 0))
    seed = f"{tty}|{project}|{started}"
    return "terminal-" + hashlib.sha256(seed.encode("utf-8")).hexdigest()[:16]


def _claude_terminal_native_id(row: dict) -> str:
    tty = str(row.get("tty") or "")
    project = str(row.get("project") or "")
    started = int(float(row.get("started_at") or 0))
    seed = f"{tty}|{project}|{started}"
    return "terminal-" + hashlib.sha256(seed.encode("utf-8")).hexdigest()[:16]


def _codex_register_terminal_only_rows(
    seen: set[str],
    live_terminal_rows: list[dict] | None = None,
) -> None:
    terminals = (
        live_terminal_rows
        if live_terminal_rows is not None
        else _codex_live_terminal_rows()
    )
    for terminal in terminals:
        if str(terminal.get("identity_probe_state") or "exact") != "exact":
            continue
        provider_tty = str(
            terminal.get("provider_tty") or terminal.get("tty") or ""
        )
        terminal_tty = str(terminal.get("terminal_tty") or provider_tty)
        project = str(terminal.get("project") or "")
        pid = int(terminal.get("pid") or 0)
        try:
            terminal_owner_pid = int(terminal.get("terminal_owner_pid") or 0)
            terminal_owner_started_at = float(
                terminal.get("terminal_owner_process_started_at") or 0
            )
            process_started_at = float(terminal.get("started_at") or 0)
        except (TypeError, ValueError):
            continue
        if (
            not project
            or pid <= 0
            or process_started_at <= 0
            or re.fullmatch(r"/dev/ttys[0-9]{3,}", provider_tty) is None
            or re.fullmatch(r"/dev/ttys[0-9]{3,}", terminal_tty) is None
        ):
            continue
        if (
            provider_tty != terminal_tty
            and (terminal_owner_pid <= 0 or terminal_owner_started_at <= 0)
        ):
            continue
        discovery_metadata = {
            "discovered_by": "terminal_scan",
            "terminal_only": True,
            "command": str(terminal.get("command") or "")[:500],
            "process_started_at": process_started_at,
            "provider_tty": provider_tty,
        }
        if terminal_owner_pid > 0 and terminal_owner_started_at > 0:
            discovery_metadata.update({
                "terminal_owner_pid": terminal_owner_pid,
                "terminal_owner_process_started_at": terminal_owner_started_at,
            })
        exact_native_id = str(terminal.get("native_id") or "")
        if exact_native_id:
            _agent_registry_promote_codex(exact_native_id, project, 0)
            continue
        existing = _agent_registry_get_by_tty("codex", terminal_tty)
        if existing and not existing.get("closed_at"):
            native_id = str(existing.get("native_id") or "")
            existing_pid = int(existing.get("pid") or 0)
            expected_terminal_native_id = _codex_terminal_native_id(terminal)
            if (
                native_id == expected_terminal_native_id
                and str(existing.get("project") or "") == project
            ):
                if (
                    existing_pid == pid
                    and str(existing.get("terminal_tty") or "") == terminal_tty
                    and _codex_inventory_registry_process_matches(
                        existing, [terminal]
                    )
                ):
                    # A safety scan is observation, not new session activity.
                    # Refresh the stale-sweep lease without publishing a
                    # summary event that would wake every sessions stream and
                    # immediately trigger another scan.
                    _agent_registry_update_control(
                        "codex",
                        native_id,
                        pid=pid,
                        terminal_tty=terminal_tty,
                        state="running",
                    )
                else:
                    existing_metadata = _registry_metadata_from_row(existing)
                    existing_metadata.update(discovery_metadata)
                    _agent_registry_upsert(
                        "codex",
                        native_id,
                        project,
                        pid=pid,
                        terminal_tty=terminal_tty,
                        state="running",
                        metadata=existing_metadata,
                        working_on=str(existing.get("working_on") or "Live Codex terminal"),
                    )
                continue
            if (
                native_id.startswith("pending-")
                and existing_pid == pid
                and str(existing.get("project") or "") == project
                and _codex_inventory_registry_process_matches(
                    existing, [terminal]
                )
            ):
                continue
            if native_id.startswith("terminal-") or existing_pid <= 0 or not _process_alive(existing_pid):
                _agent_registry_mark_closed("codex", native_id)
        native_id = _codex_terminal_native_id(terminal)
        if native_id in seen:
            continue
        _agent_registry_upsert(
            "codex",
            native_id,
            project,
            pid=pid,
            terminal_tty=terminal_tty,
            state="running",
            metadata=discovery_metadata,
            working_on="Live Codex terminal",
        )


def _registry_row_has_live_terminal(row: dict, command_name: str) -> bool:
    tty = str(row.get("terminal_tty") or "")
    if not re.match(r"^/dev/ttys[0-9]{3,}$", tty):
        return False
    return bool(_pid_for_tty_command(tty, command_name))


def _session_has_verified_provider_process(
    row: dict,
    provider: str | None = None,
    inventory_rows: list[dict] | None = None,
) -> bool:
    provider = str(provider or row.get("provider") or "").strip().lower()
    if provider not in {"claude", "codex", "omp"}:
        return False
    pid = int(row.get("pid") or row.get("claude_pid") or 0)
    tty = str(row.get("terminal_tty") or "")
    project = str(row.get("project") or "")
    native_id = str(row.get("native_id") or "")
    if provider in {"claude", "codex", "omp"} and not _registry_process_birth_matches(row, pid):
        return False

    if provider == "omp" and native_id.startswith("pending-"):
        pending_rows = inventory_rows
        if pending_rows is None:
            process_scan_ok, pending_rows = _scan_provider_process_rows("omp")
            if not process_scan_ok:
                return False
        return _omp_pairling_pending_terminal(row, pending_rows) is not None

    candidates = inventory_rows
    if candidates is None:
        if provider == "omp":
            inventory = _capture_sessions_provider_inventory("omp")
            if (
                inventory.get("probe_state") != "exact"
                or not bool(inventory.get("membership_complete"))
            ):
                return False
            candidates = list(inventory.get("terminals") or [])
        else:
            candidates = (
                _codex_live_terminal_rows()
                if provider == "codex"
                else _claude_live_terminal_rows()
            )

    def project_matches(candidate_project: str) -> bool:
        if not project:
            return True
        if not candidate_project:
            return False
        try:
            return os.path.realpath(candidate_project) == os.path.realpath(project)
        except OSError:
            return candidate_project == project

    if pid <= 0 or not _process_alive(pid):
        return False
    for candidate in candidates:
        if str(candidate.get("identity_probe_state") or "exact") != "exact":
            continue
        if int(candidate.get("pid") or 0) != pid:
            continue
        if (
            provider in {"codex", "omp"}
            and native_id
            and not native_id.startswith(("pending-", "terminal-"))
            and str(candidate.get("native_id") or "") != native_id
        ):
            continue
        if not project_matches(str(candidate.get("project") or "")):
            continue
        if tty and not _direct_terminal_binding_is_verified(
            row,
            provider,
            pid,
            provider_tty=str(candidate.get("tty") or ""),
        ):
            continue
        return True
    return False


def _codex_inventory_registry_process_matches(
    reg: dict | None,
    live_terminal_rows: list[dict] | None = None,
) -> bool:
    """Verify read-only inventory membership against one exact scan.

    This deliberately does not replace the mutation verifier below. Inventory
    may use the scan's process birth and terminal topology. A signal or stale
    close must still re-read the target process immediately before mutation.
    """
    if not isinstance(reg, dict) or reg.get("closed_at") is not None:
        return False
    if str(reg.get("provider") or "codex").strip().lower() != "codex":
        return False
    pid = int(reg.get("pid") or 0)
    native_id = str(reg.get("native_id") or "")
    project = str(reg.get("project") or "")
    terminal_tty = str(reg.get("terminal_tty") or "")
    metadata = _registry_metadata_from_row(reg)
    try:
        expected_started_at = float(metadata.get("process_started_at") or 0)
        stored_owner_pid = int(metadata.get("terminal_owner_pid") or 0)
        stored_owner_started_at = float(
            metadata.get("terminal_owner_process_started_at") or 0
        )
    except (TypeError, ValueError):
        return False
    expected_provider_tty = str(metadata.get("provider_tty") or terminal_tty)
    if (
        pid <= 0
        or expected_started_at <= 0
        or re.fullmatch(r"/dev/ttys[0-9]{3,}", terminal_tty) is None
        or re.fullmatch(r"/dev/ttys[0-9]{3,}", expected_provider_tty) is None
    ):
        return False

    candidates = (
        live_terminal_rows
        if live_terminal_rows is not None
        else _codex_live_terminal_rows()
    )
    for candidate in candidates:
        if str(candidate.get("identity_probe_state") or "exact") != "exact":
            continue
        if int(candidate.get("pid") or 0) != pid:
            continue
        try:
            actual_started_at = float(candidate.get("started_at") or 0)
        except (TypeError, ValueError):
            continue
        if (
            actual_started_at <= 0
            or abs(actual_started_at - expected_started_at) > 2
        ):
            continue
        candidate_native_id = str(candidate.get("native_id") or "")
        if (
            native_id
            and not native_id.startswith(("pending-", "terminal-"))
            and candidate_native_id != native_id
        ):
            continue
        candidate_project = str(candidate.get("project") or "")
        if project:
            if not candidate_project:
                continue
            try:
                projects_match = os.path.realpath(candidate_project) == os.path.realpath(project)
            except OSError:
                projects_match = candidate_project == project
            if not projects_match:
                continue

        candidate_provider_tty = str(
            candidate.get("provider_tty") or candidate.get("tty") or ""
        )
        candidate_terminal_tty = str(
            candidate.get("terminal_tty") or candidate_provider_tty
        )
        if (
            candidate_provider_tty != expected_provider_tty
            or candidate_terminal_tty != terminal_tty
        ):
            continue
        if terminal_tty != expected_provider_tty:
            try:
                candidate_owner_pid = int(
                    candidate.get("terminal_owner_pid") or 0
                )
                candidate_owner_started_at = float(
                    candidate.get("terminal_owner_process_started_at") or 0
                )
            except (TypeError, ValueError):
                continue
            if (
                stored_owner_pid <= 0
                or stored_owner_started_at <= 0
                or candidate_owner_pid != stored_owner_pid
                or candidate_owner_started_at <= 0
                or abs(
                    candidate_owner_started_at - stored_owner_started_at
                ) > 2
            ):
                continue
        return True
    return False


def _omp_inventory_registry_process_matches(
    reg: dict | None,
    live_terminal_rows: list[dict] | None = None,
    *,
    require_direct_control: bool = True,
) -> bool:
    """Bind one OMP UUID to one exact terminal record and process birth."""
    if not isinstance(reg, dict) or reg.get("closed_at") is not None:
        return False
    if str(reg.get("provider") or "omp").strip().lower() != "omp":
        return False
    native_id = str(reg.get("native_id") or "")
    project = str(reg.get("project") or "")
    terminal_tty = str(reg.get("terminal_tty") or "")
    pid = int(reg.get("pid") or 0)
    metadata = _registry_metadata_from_row(reg)
    try:
        expected_started_at = float(metadata.get("process_started_at") or 0)
    except (TypeError, ValueError):
        return False
    expected_provider_tty = str(metadata.get("provider_tty") or terminal_tty)
    if (
        not native_id
        or not project
        or pid <= 0
        or expected_started_at <= 0
        or re.fullmatch(r"/dev/ttys[0-9]{3,}", terminal_tty) is None
        or re.fullmatch(r"/dev/ttys[0-9]{3,}", expected_provider_tty) is None
    ):
        return False
    candidates = live_terminal_rows
    if candidates is None:
        inventory = _capture_sessions_provider_inventory("omp")
        if (
            inventory.get("probe_state") != "exact"
            or not bool(inventory.get("membership_complete"))
        ):
            return False
        candidates = list(inventory.get("terminals") or [])
    for candidate in candidates:
        if str(candidate.get("identity_probe_state") or "") != "exact":
            continue
        if require_direct_control and not bool(candidate.get("can_control")):
            continue
        if str(candidate.get("native_id") or "") != native_id:
            continue
        if int(candidate.get("pid") or 0) != pid:
            continue
        candidate_provider_tty = str(
            candidate.get("tty") or candidate.get("terminal_tty") or ""
        )
        if candidate_provider_tty != expected_provider_tty:
            continue
        try:
            actual_started_at = float(
                candidate.get("process_started_at") or candidate.get("started_at") or 0
            )
        except (TypeError, ValueError):
            continue
        if actual_started_at <= 0 or abs(actual_started_at - expected_started_at) > 2:
            continue
        try:
            projects_match = os.path.realpath(
                str(candidate.get("project") or "")
            ) == os.path.realpath(project)
        except OSError:
            projects_match = str(candidate.get("project") or "") == project
        if not projects_match:
            continue
        if terminal_tty != expected_provider_tty and not _direct_terminal_binding_is_verified(
            reg,
            "omp",
            pid,
            provider_tty=expected_provider_tty,
        ):
            continue
        return True
    return False


def _claude_registry_process_identity_matches(
    reg: dict | None,
    candidate: dict | None,
) -> bool:
    """Match one registry row to one exact Claude process observation."""
    if not isinstance(reg, dict) or not isinstance(candidate, dict):
        return False
    if str(reg.get("provider") or "claude").strip().lower() != "claude":
        return False
    if str(candidate.get("identity_probe_state") or "exact") != "exact":
        return False
    pid = int(reg.get("pid") or 0)
    terminal_tty = str(reg.get("terminal_tty") or "")
    project = str(reg.get("project") or "")
    metadata = _registry_metadata_from_row(reg)
    try:
        expected_started_at = float(metadata.get("process_started_at") or 0)
        actual_started_at = float(candidate.get("started_at") or 0)
    except (TypeError, ValueError):
        return False
    if (
        pid <= 0
        or int(candidate.get("pid") or 0) != pid
        or expected_started_at <= 0
        or actual_started_at <= 0
        or abs(actual_started_at - expected_started_at) > 2
        or not project
        or re.fullmatch(r"/dev/ttys[0-9]{3,}", terminal_tty) is None
        or str(candidate.get("tty") or "") != terminal_tty
    ):
        return False
    candidate_project = str(candidate.get("project") or "")
    try:
        return os.path.realpath(candidate_project) == os.path.realpath(project)
    except OSError:
        return candidate_project == project


def _claude_inventory_registry_process_matches(
    reg: dict | None,
    live_terminal_rows: list[dict] | None = None,
) -> bool:
    """Bind one open Claude registry identity to one exact process observation."""
    if not isinstance(reg, dict) or reg.get("closed_at") is not None:
        return False
    candidates = (
        live_terminal_rows
        if live_terminal_rows is not None
        else _claude_live_terminal_rows()
    )
    return any(
        _claude_registry_process_identity_matches(reg, candidate)
        for candidate in candidates
    )


def _codex_registry_row_for_strict_live_display(row: dict) -> dict | None:
    """Resolve private process proof for one public Codex session row.

    API rows deliberately omit registry metadata such as process birth time.
    Strict membership must therefore verify the owning registry row instead of
    re-running the birth check against the redacted response object.
    """
    native_id = str(row.get("native_id") or "").strip()
    if not native_id:
        return None
    canonical_id = _agent_registry_resolve_native_alias("codex", native_id)
    reg = _agent_registry_get("codex", canonical_id)
    if not reg or reg.get("closed_at") is not None:
        return None

    display_pid = int(row.get("pid") or row.get("claude_pid") or 0)
    registry_pid = int(reg.get("pid") or 0)
    if display_pid <= 0 or registry_pid != display_pid:
        return None

    display_tty = str(row.get("terminal_tty") or "")
    registry_tty = str(reg.get("terminal_tty") or "")
    if display_tty and registry_tty != display_tty:
        return None

    display_project = str(row.get("project") or "")
    registry_project = str(reg.get("project") or "")
    if display_project:
        if not registry_project:
            return None
        try:
            projects_match = os.path.realpath(display_project) == os.path.realpath(registry_project)
        except OSError:
            projects_match = display_project == registry_project
        if not projects_match:
            return None
    return reg


def _session_signal_target_is_verified(row: dict, provider: str, pid: int) -> bool:
    """Re-prove the exact PID before a direct signal leaves the daemon.

    Clearing the TTY is deliberate. The general session verifier may accept a
    matching live TTY even when a stale registry PID has since been reused.
    Process mutation must bind the provider and project to the exact PID that
    will receive the signal.
    """
    if not isinstance(row, dict) or int(pid or 0) <= 0:
        return False
    candidate = dict(row)
    candidate["provider"] = provider
    candidate["pid"] = int(pid)
    candidate["claude_pid"] = int(pid)
    candidate["terminal_tty"] = ""
    return _session_has_verified_provider_process(candidate, provider)


class ProcessIdentityDriftError(RuntimeError):
    pass


def _verified_session_signal_target(
    provider: str,
    native_id: str,
    *,
    expected_pid: int = 0,
) -> tuple[dict | None, int, str | None]:
    """Resolve and verify the exact live process that may receive a signal."""
    if provider == "codex":
        native_id = _agent_registry_resolve_native_alias("codex", native_id)
        row = _agent_registry_get("codex", native_id)
    elif provider == "claude":
        row = _claude_sessions_backend().session_record(native_id)
    elif provider == "omp":
        row = _agent_registry_get("omp", native_id)
    else:
        return None, 0, "unsupported_provider"
    if not row or row.get("closed_at") is not None:
        return row, 0, "process_not_found"
    pid = int(row.get("pid") or row.get("claude_pid") or 0)
    if expected_pid and pid != int(expected_pid):
        return row, pid, "process_identity_unverified"
    if pid <= 0 or not _process_alive(pid):
        return row, pid, "process_not_found"
    if not _session_signal_target_is_verified(row, provider, pid):
        return row, pid, "process_identity_unverified"
    return row, pid, None


def _claude_reconcile_terminated_registry_rows(
    live_terminal_rows: list[dict],
) -> None:
    """Close exact Claude identities after their owning process exits."""
    observed_pids = {
        int(row.get("pid") or 0)
        for row in live_terminal_rows
        if isinstance(row, dict)
        and str(row.get("identity_probe_state") or "exact") == "exact"
        and int(row.get("pid") or 0) > 0
    }
    for row in _agent_registry_live("claude", limit=1000):
        native_id = str(row.get("native_id") or "")
        pid = int(row.get("pid") or 0)
        if not native_id or pid <= 0 or pid in observed_pids:
            continue
        if not _process_alive(pid):
            _agent_registry_mark_closed("claude", native_id)
            continue
        metadata = _registry_metadata_from_row(row)
        try:
            expected_started_at = float(metadata.get("process_started_at") or 0)
            actual_started_at = float(_process_start_epoch(pid) or 0)
        except (TypeError, ValueError, OSError):
            continue
        if (
            expected_started_at > 0
            and actual_started_at > 0
            and abs(actual_started_at - expected_started_at) > 2
        ):
            _agent_registry_mark_closed("claude", native_id)


def _claude_register_terminal_only_rows(
    seen: set[str],
    live_terminal_rows: list[dict] | None = None,
) -> None:
    terminals = (
        live_terminal_rows
        if live_terminal_rows is not None
        else _claude_live_terminal_rows()
    )
    _claude_reconcile_terminated_registry_rows(terminals)
    for terminal in terminals:
        tty = str(terminal.get("tty") or "")
        project = str(terminal.get("project") or "")
        pid = int(terminal.get("pid") or 0)
        try:
            process_started_at = float(terminal.get("started_at") or 0)
        except (TypeError, ValueError):
            process_started_at = 0.0
        if (
            not project
            or pid <= 0
            or process_started_at <= 0
            or re.fullmatch(r"/dev/ttys[0-9]{3,}", tty) is None
        ):
            continue
        existing = _agent_registry_get_by_tty("claude", tty)
        if existing and _claude_registry_process_identity_matches(
            existing,
            terminal,
        ):
            native_id = str(existing.get("native_id") or "")
            if existing.get("closed_at") is not None or native_id in seen:
                # SessionEnd is authoritative for this exact process. A
                # trailing terminal scan must not create a second identity.
                continue
            # Observation renews the stale-sweep lease only. It must never
            # transplant a prior Claude UUID onto a replacement process.
            _agent_registry_update_control(
                "claude",
                native_id,
                pid=pid,
                terminal_tty=tty,
                state="running",
            )
            continue
        if existing and not existing.get("closed_at"):
            _agent_registry_mark_closed(
                "claude",
                str(existing.get("native_id") or ""),
            )
        native_id = _claude_terminal_native_id(terminal)
        if native_id in seen:
            continue
        _agent_registry_upsert(
            "claude",
            native_id,
            project,
            pid=pid,
            terminal_tty=tty,
            state="running",
            metadata={
                "discovered_by": "terminal_scan",
                "terminal_only": True,
                "command": str(terminal.get("command") or "")[:500],
                "process_started_at": process_started_at,
                "provider_tty": tty,
            },
            working_on="Live Claude terminal",
        )


# Phase 4 B.3: warm claude --continue pool. Maintains up to one long-running
# `claude` session per model. After 5 min idle, the worker exits.
# This turns 18-25s cold start into ~2s for repeat /llm-route calls.

class _WarmWorker:
    """A long-lived `claude` subprocess that we feed prompts via stdin."""

    def __init__(self, model: str):
        self.model = model
        self.proc: subprocess.Popen | None = None
        self.last_used: float = 0.0
        self.lock = threading.Lock()
        self.session_dir = HOME / ".claude" / "warm-workers" / model
        self.session_dir.mkdir(parents=True, exist_ok=True)

    def _spawn(self) -> bool:
        claude_bin = HOME / ".local" / "bin" / "claude"
        if not claude_bin.exists():
            return False
        # We use stream-json input so we can feed multiple prompts to one session.
        # Each input line is a UserMessage object; output is a stream of JSON events.
        cmd = [
            str(claude_bin), "-p",
            "--input-format", "stream-json",
            "--output-format", "stream-json",
            "--include-partial-messages",
            "--model", self.model,
            "--tools", "",
            "--no-session-persistence",
        ]
        try:
            self.proc = subprocess.Popen(
                cmd,
                stdin=subprocess.PIPE,
                stdout=subprocess.PIPE,
                stderr=subprocess.PIPE,
                text=True,
                bufsize=1,
                cwd=str(self.session_dir),
                env=_provider_child_environment(),
            )
            return True
        except Exception:
            return False

    def alive(self) -> bool:
        return self.proc is not None and self.proc.poll() is None

    def shutdown(self):
        with self.lock:
            if self.proc and self.proc.stdin is not None:
                try:
                    self.proc.stdin.close()
                except Exception:
                    pass
                try:
                    self.proc.terminate()
                    self.proc.wait(timeout=2)
                except Exception:
                    try:
                        self.proc.kill()
                    except Exception:
                        pass
                self.proc = None


class _WarmPool:
    def __init__(self, idle_timeout: float = 300.0):
        self.workers: dict[str, _WarmWorker] = {}
        self.idle_timeout = idle_timeout
        self.global_lock = threading.Lock()
        # Background reaper for idle workers
        threading.Thread(target=self._reaper, daemon=True).start()

    def get(self, model: str) -> _WarmWorker:
        with self.global_lock:
            w = self.workers.get(model)
            if w is None:
                w = _WarmWorker(model)
                self.workers[model] = w
        return w

    def _reaper(self):
        while True:
            _time.sleep(60)
            now = _time.time()
            with self.global_lock:
                stale = [m for m, w in self.workers.items()
                         if w.alive() and (now - w.last_used) > self.idle_timeout]
            for m in stale:
                self.workers[m].shutdown()


_warm_pool = _WarmPool()


def _inject_rate_check(session_id: str, max_per_min: int = 30) -> tuple[bool, int]:
    """Return one bounded per-session mutation rate decision."""
    now = _time.time()
    with _inject_rate_lock:
        for key in list(_inject_rate_state):
            recent = [
                timestamp
                for timestamp in _inject_rate_state[key]
                if now - timestamp < 60
            ]
            if recent:
                _inject_rate_state[key] = recent
            else:
                _inject_rate_state.pop(key, None)
        if (
            session_id not in _inject_rate_state
            and len(_inject_rate_state) >= _INJECT_RATE_MAX_KEYS
        ):
            oldest_key = min(
                _inject_rate_state,
                key=lambda key: max(_inject_rate_state[key]),
            )
            _inject_rate_state.pop(oldest_key, None)
        timestamps = _inject_rate_state.get(session_id, [])
        if len(timestamps) >= max_per_min:
            oldest = min(timestamps)
            retry = max(1, int(60 - (now - oldest)))
            return False, retry
        if timestamps and now - max(timestamps) < 1.0:
            return False, 1
        timestamps.append(now)
        _inject_rate_state[session_id] = timestamps
    return True, 0

# Project paths matching any of these glob-ish substrings are filtered out of
# /corpus, /sessions, and bucket rollups. Users can accumulate many one-shot
# research scratch dirs that drown out signal — exclude by default.
PROJECT_EXCLUDE_PATTERNS = [
    "biotech-labs/synth-synth-",        # ephemeral synth-* worktrees
    "biotech-labs/crohns-research/scripts",   # bench-research scratch
    "biotech-research-",                # legacy biotech-research-<hash> dirs
    "/sentinel-orchestration-",                  # ephemeral Sentinel orchestration worktrees
]


def _is_excluded_project(project_path: str) -> bool:
    if not project_path:
        return False
    return any(p in project_path for p in PROJECT_EXCLUDE_PATTERNS)


def _is_recent_project_candidate(project_path: str) -> bool:
    """Recent-project picker should prefer user workspaces, not daemon/smoke dirs."""
    if not project_path or _is_excluded_project(project_path):
        return False
    normalized = project_path.rstrip("/")
    home_prefix = str(HOME) + os.sep
    if not (normalized == str(HOME) or normalized.startswith(home_prefix) or normalized.startswith(("/tmp/", "/private/tmp/"))):
        return False
    if normalized in (str(HOME), str(HOME / "projects"), "/tmp", "/private/tmp"):
        return False
    name = os.path.basename(normalized)
    if name in {"runs", "build", "dist", "DerivedData", "__pycache__", "node_modules"}:
        return False
    if normalized.startswith(("/tmp/", "/private/tmp/")):
        return False
    if normalized.endswith((".xcodeproj", ".xcworkspace", ".xcarchive", ".app", ".dSYM", ".bundle")):
        return False
    if normalized.startswith(str(HOME / ".claude")) or normalized.startswith(str(HOME / ".codex")):
        return False
    return True


def _looks_like_project_root(path: Path) -> bool:
    markers = {
        ".git", "project.yml", "Package.swift", "pyproject.toml", "package.json",
        "Cargo.toml", "go.mod", "Gemfile", "Makefile", "Justfile", "Podfile",
    }
    try:
        return any((path / marker).exists() for marker in markers) or any(path.glob("*.xcodeproj"))
    except OSError:
        return False


def _filesystem_project_candidates(limit: int = 80) -> list[tuple[str, int]]:
    """Return real local project folders for spawn-sheet autocomplete.

    This is intentionally shallow and cheap. It covers the user's normal
    workspace roots so a path can be suggested before it has ever appeared in
    Pairling's session history.
    """
    roots = [
        HOME / "projects",
        HOME / "Developer",
        HOME / "dev",
        HOME / "work",
        Path("/tmp"),
    ]
    skip_names = {
        ".git", ".venv", "__pycache__", "node_modules", "DerivedData",
        "Library", "Applications", "Downloads", "Movies", "Music", "Pictures",
    }
    candidates: dict[str, int] = {}

    def add(path: Path, *, require_marker: bool = False) -> None:
        try:
            resolved = str(path.resolve())
            if not path.is_dir() or not _is_recent_project_candidate(resolved):
                return
            if require_marker and not _looks_like_project_root(path):
                return
            st = path.stat()
        except OSError:
            return
        candidates[resolved] = max(candidates.get(resolved, 0), int(st.st_mtime))

    for root in roots:
        if not root.is_dir():
            continue
        try:
            children = list(root.iterdir())
        except OSError:
            continue
        for child in children[:400]:
            if child.name.startswith(".") or child.name in skip_names:
                continue
            add(child)
            try:
                grandchildren = list(child.iterdir())
            except OSError:
                continue
            for grandchild in grandchildren[:120]:
                if grandchild.name.startswith(".") or grandchild.name in skip_names:
                    continue
                add(grandchild, require_marker=True)

    return sorted(candidates.items(), key=lambda kv: kv[1], reverse=True)[:limit]


def _encode_project_dir(project_path: str) -> str:
    """Convert a project filesystem path to Claude Code's encoded transcript
    directory name under ~/.claude/projects/.

    Claude Code encodes ALL of `/`, `.`, and `_` as `-`. This means a path
    like /Users/example/.claude/state/sentinel/projects/onestream-378da5/terminals/orange_team
    becomes -Users-example--claude-state-sentinel-projects-onestream-378da5-terminals-orange-team
    (note: `.claude` → `-claude` so two consecutive `-`; `orange_team` → `orange-team`).

    The previous implementation only handled `/` and broke for sentinel
    sessions and any project path containing dots or underscores.
    """
    if not project_path:
        return ""
    return re.sub(r"[/._]", "-", project_path)


# Sentinel session paths look like:
#   /Users/example/.claude/state/sentinel/projects/<bucket>-<6hex>/terminals/<mode>
# We strip the sentinel prefix + the 6-hex suffix to recover the underlying
# project bucket name (e.g. "proofforge"). Regular projects use their basename.
_SENTINEL_PROJECTS_RE = re.compile(
    r"/\.claude/state/sentinel/projects/([^/]+?)-[0-9a-f]{6}(?:/|$)"
)
_HEX_SUFFIX_RE = re.compile(r"-[0-9a-f]{6}$")


# =============================================================================
# Slash command catalog (P15)
# =============================================================================

# Best-effort list of Claude Code's built-in commands. There's no JSON manifest
# for these — they're rendered text in the binary — so we hardcode a known set.
# When new built-ins ship, refresh this list.
# ----- Session-scoped keep-awake (SPEC-p7) -----
# The manager holds one caffeinate -i -w <pid> child while supervised work
# runs. The daemon owns the activity predicate: A = a phone attached to a
# live stream (counter below), B = registered sessions state=running with a
# fresh heartbeat, C = orchestration workers. Warm-pool rows are excluded —
# idle warm workers must not hold the machine awake. A paired-but-idle Mac
# asserts nothing (Law 3: the Mac sleeps exactly as the user configured it
# whenever Pairling has no active work).
_KEEP_AWAKE = None
_KEEP_AWAKE_HEARTBEAT_FRESH_SECONDS = 120
_LIVE_STREAM_ATTACHMENTS = 0
_LIVE_STREAM_LOCK = threading.Lock()
_KEEP_AWAKE_WORKER_KINDS = {"worker", "orchestration_worker"}


@contextmanager
def _track_live_stream():
    global _LIVE_STREAM_ATTACHMENTS
    with _LIVE_STREAM_LOCK:
        _LIVE_STREAM_ATTACHMENTS += 1
    _keep_awake_poke()
    try:
        yield
    finally:
        with _LIVE_STREAM_LOCK:
            _LIVE_STREAM_ATTACHMENTS = max(0, _LIVE_STREAM_ATTACHMENTS - 1)
        _keep_awake_poke()


def _keep_awake_reasons() -> dict:
    with _LIVE_STREAM_LOCK:
        streams = _LIVE_STREAM_ATTACHMENTS
    sessions = 0
    workers = 0
    cutoff = _time.time() - _KEEP_AWAKE_HEARTBEAT_FRESH_SECONDS
    try:
        with _agent_registry_conn() as conn:
            rows = conn.execute(
                "SELECT state, metadata_json FROM agent_sessions "
                "WHERE closed_at IS NULL AND last_heartbeat >= ?",
                (cutoff,),
            ).fetchall()
        for row in rows:
            if str(row["state"] or "") != "running":
                continue
            kind = None
            raw = row["metadata_json"]
            if raw:
                try:
                    kind = (json.loads(raw) or {}).get("kind")
                except Exception:
                    kind = None
            if kind in _KEEP_AWAKE_WORKER_KINDS:
                workers += 1
            elif kind is None or kind not in {"warm_pool", "warm"}:
                sessions += 1
    except Exception:
        pass
    return {"streams": streams, "sessions": sessions, "workers": workers}


def _keep_awake_poke() -> None:
    manager = _KEEP_AWAKE
    if manager is None:
        return
    try:
        manager.evaluate(_keep_awake_reasons())
    except Exception:
        pass


def _start_keep_awake() -> None:
    """Boot the keep-awake manager plus its 30s reconcile tick. Event pokes
    (stream attach/detach) keep transitions immediate; the tick catches
    session/worker state changes that arrive via hooks."""
    global _KEEP_AWAKE
    if _KeepAwakeManager is None:
        return
    manager = _KeepAwakeManager()
    _KEEP_AWAKE = manager
    if not manager.enabled:
        return

    def run():
        while True:
            _time.sleep(30)
            _keep_awake_poke()

    threading.Thread(target=run, name="pairling-keep-awake-reconcile", daemon=True).start()
    atexit.register(manager.shutdown)
    _keep_awake_poke()


# Type mode (SPEC-p4): per-session interactive input state. Entry is the
# receipted mutation; the mode expires after 10 idle minutes.
_TYPE_MODE_SESSIONS: dict[str, dict] = {}
_TYPE_MODE_LOCK = threading.Lock()
TYPE_MODE_IDLE_SECONDS = 600


# Catalog epoch: bumped on spawn and on provider-visibility changes so the
# stream's next 5s signature check re-emits even when no source file moved —
# a just-installed plugin is present in the very first composer open of a new
# session (SPEC-p2 §2.4).
_CATALOG_EPOCH = 0
_CATALOG_EPOCH_LOCK = threading.Lock()


def _bump_catalog_epoch() -> None:
    global _CATALOG_EPOCH
    with _CATALOG_EPOCH_LOCK:
        _CATALOG_EPOCH += 1


# Builtin slash commands come from providers/builtin-commands.json — a
# version-verified data file with a memoized --version probe (SPEC-p2 §2.1).
# No literal list lives here anymore; a version drift is served labeled
# stale_for_version instead of silently lying.
def _builtin_commands_for(provider: str) -> list[dict]:
    try:
        if _builtin_catalog_entries is not None:
            items = _builtin_catalog_entries(provider)
            if provider == "codex":
                return [{**item, "source": "builtin"} for item in items]
            return items
    except Exception:
        pass
    return []


def _builtin_catalog_meta_for(provider: str) -> dict:
    try:
        if _builtin_catalog_meta is not None:
            return _builtin_catalog_meta(provider, home=HOME)
    except Exception:
        pass
    return {"provider": provider, "verified_version": None, "installed_version": None, "stale_for_version": None, "source": "unavailable"}


def _catalog_payload_extras(provider: str, items: list, signature: str) -> tuple[list, dict]:
    """Freshness + honesty fields shared by /commands, /invocations, and both
    streams (SPEC-p2): first_seen-annotated items plus catalog_version, the
    builtin_catalog meta, and pending_review."""
    annotated = items
    try:
        if _catalog_annotate_first_seen is not None:
            annotated = _catalog_annotate_first_seen(provider, items, home=HOME)
    except Exception:
        annotated = items
    pending: list = []
    try:
        if _pending_review_collect is not None:
            pending = _pending_review_collect(home=HOME)
    except Exception:
        pending = []
    extras = {
        "catalog_version": signature,
        "builtin_catalog": _builtin_catalog_meta_for(provider),
        "pending_review": pending,
    }
    return annotated, extras

_INVOCATION_SCHEMA_VERSION = 1
_INVOCATION_MAX_SKILL_FILE_SIZE = 256 * 1024
_INVOCATION_MAX_SKILL_FILES = 2500
_INVOCATION_MAX_TOTAL_BYTES = 32 * 1024 * 1024
_INVOCATION_MAX_TRAVERSAL_DEPTH = 8


_INVOCATION_MAX_SCAN_ENTRIES = 10_000


def _bounded_invocation_scan(
    root: Path,
    *,
    file_name: str | None = None,
    suffix: str | None = None,
    directory_name: str | None = None,
    max_depth: int = _INVOCATION_MAX_TRAVERSAL_DEPTH,
    max_results: int = _INVOCATION_MAX_SKILL_FILES,
) -> list[Path]:
    """Enumerate invocation metadata without following links or unbounded trees."""
    try:
        root_resolved = root.resolve(strict=True)
    except (OSError, RuntimeError):
        return []
    results: list[Path] = []
    pending: list[tuple[Path, int]] = [(root_resolved, 0)]
    entries_seen = 0
    while pending and entries_seen < _INVOCATION_MAX_SCAN_ENTRIES:
        directory, depth = pending.pop()
        try:
            with os.scandir(directory) as entries:
                for entry in entries:
                    entries_seen += 1
                    if entries_seen > _INVOCATION_MAX_SCAN_ENTRIES:
                        break
                    try:
                        if entry.is_symlink():
                            continue
                        if entry.is_dir(follow_symlinks=False):
                            if directory_name is not None and entry.name == directory_name:
                                results.append(Path(entry.path))
                                if len(results) >= max_results:
                                    return sorted(results, key=lambda path: str(path))
                            if depth < max_depth:
                                pending.append((Path(entry.path), depth + 1))
                            continue
                        if not entry.is_file(follow_symlinks=False):
                            continue
                    except OSError:
                        continue
                    if file_name is not None and entry.name != file_name:
                        continue
                    if suffix is not None and not entry.name.endswith(suffix):
                        continue
                    results.append(Path(entry.path))
                    if len(results) >= max_results:
                        return sorted(results, key=lambda path: str(path))
        except OSError:
            continue
    return sorted(results, key=lambda path: str(path))


def _read_invocation_file_nofollow(
    root: Path,
    path: Path,
) -> tuple[str, os.stat_result]:
    """Read one scanner result through no-follow directory descriptors."""
    root_resolved = root.resolve(strict=True)
    try:
        relative = path.relative_to(root)
    except ValueError:
        relative = path.relative_to(root_resolved)
    if not relative.parts:
        raise OSError(errno.EINVAL, "invocation path is empty")
    directory_flags = os.O_RDONLY | getattr(os, "O_DIRECTORY", 0) | getattr(os, "O_NOFOLLOW", 0)
    file_flags = os.O_RDONLY | getattr(os, "O_NOFOLLOW", 0)
    directory_fd = os.open(root_resolved, directory_flags)
    try:
        for component in relative.parts[:-1]:
            next_fd = os.open(component, directory_flags, dir_fd=directory_fd)
            os.close(directory_fd)
            directory_fd = next_fd
        file_fd = os.open(relative.parts[-1], file_flags, dir_fd=directory_fd)
        try:
            stat_result = os.fstat(file_fd)
            if not stat.S_ISREG(stat_result.st_mode):
                raise OSError(errno.EINVAL, "invocation path is not a regular file")
            with os.fdopen(file_fd, "r", errors="replace", closefd=False) as stream:
                text = stream.read(_INVOCATION_MAX_SKILL_FILE_SIZE + 1)
            if len(text.encode("utf-8", errors="replace")) > _INVOCATION_MAX_SKILL_FILE_SIZE:
                raise OSError(errno.EFBIG, "invocation file exceeds size limit")
            return text, stat_result
        finally:
            os.close(file_fd)
    finally:
        os.close(directory_fd)


def _title_from_invocation_name(name: str) -> str:
    parts = re.split(r"[-_\s]+", name.strip())
    return " ".join(p[:1].upper() + p[1:] for p in parts if p) or name


def _bool_frontmatter(value: str | None, default: bool = True) -> bool:
    if value is None:
        return default
    return str(value).strip().lower() not in {"false", "0", "no", "off"}


def _invocation_id(provider: str, trigger: str, kind: str, namespace: str, name: str) -> str:
    return f"{provider}:{trigger}:{kind}:{namespace}:{name}"


def _make_invocation(*, provider: str, trigger: str, name: str, description: str,
                     source: str, kind: str, namespace: str, args=None,
                     insert_text: str | None = None, display_name: str | None = None,
                     source_path: Path | str | None = None, trust: dict | None = None,
                     visibility: dict | None = None) -> dict:
    clean_name = name.lstrip("/$")
    return {
        "id": _invocation_id(provider, trigger, kind, namespace, clean_name),
        "provider": provider,
        "trigger": trigger,
        "name": clean_name,
        "display_name": display_name or _title_from_invocation_name(clean_name),
        "insert_text": insert_text or f"{trigger}{clean_name}",
        "kind": kind,
        "namespace": namespace,
        "source": source,
        "source_path": str(Path(source_path).resolve()) if source_path else None,
        "description": description or "",
        "args": args,
        "trust": trust,
        "visibility": visibility or {"user_invocable": True, "hidden": False},
    }


def _invocation_sort_key(item: dict) -> tuple:
    source = item.get("source", "")
    kind = item.get("kind", "")
    trigger = item.get("trigger", "")
    return (
        0 if trigger == "/" else 1,
        0 if kind == "builtin" else 1 if kind == "command" else 2 if kind == "skill" else 3,
        0 if source == "builtin" else 1 if source == "user" else 2 if source == "project" else 3 if source.startswith("plugin:") else 4,
        str(item.get("display_name") or item.get("name") or "").lower(),
        str(item.get("id") or ""),
    )


def _dedupe_invocations(items: list[dict]) -> list[dict]:
    seen: set[str] = set()
    out: list[dict] = []
    for item in sorted(items, key=_invocation_sort_key):
        item_id = str(item.get("id") or "")
        if not item_id or item_id in seen:
            continue
        seen.add(item_id)
        out.append(item)
    return out


def _legacy_command_from_invocation(item: dict) -> dict:
    insert_text = str(item.get("insert_text") or "")
    name = insert_text if insert_text.startswith("/") else f"/{item.get('name', '')}"
    return {
        "name": name,
        "description": item.get("description") or "",
        "source": item.get("source") or "",
        "args": item.get("args"),
    }


def _builtin_invocations(provider: str) -> list[dict]:
    raw = _builtin_commands_for(provider)
    return [
        _make_invocation(
            provider=provider,
            trigger="/",
            name=str(cmd.get("name") or "").lstrip("/"),
            description=str(cmd.get("description") or ""),
            source="builtin",
            kind="builtin",
            namespace="builtin",
            args=cmd.get("args"),
            insert_text=str(cmd.get("name") or ""),
            source_path=None,
            trust={"local": True, "allowlisted_root": True, "signed": False},
        )
        for cmd in raw
    ]


def _parse_md_frontmatter(text: str) -> dict:
    """Pull simple key: value pairs from a YAML frontmatter block at the
    top of a markdown file. Doesn't handle nested YAML; that's fine — slash
    command frontmatter is flat (description, name, args, user-invocable)."""
    if not text.startswith("---"):
        return {}
    end = text.find("\n---", 3)
    if end < 0:
        return {}
    out: dict = {}
    for line in text[3:end].split("\n"):
        line = line.rstrip()
        if not line or line.startswith("#"):
            continue
        if ":" not in line:
            continue
        k, _, v = line.partition(":")
        out[k.strip()] = v.strip().strip('"').strip("'")
    return out


def _first_prose_line(text: str) -> str:
    """Fallback description: first non-empty, non-header line of the body."""
    in_frontmatter = text.startswith("---")
    body = text
    if in_frontmatter:
        end = text.find("\n---", 3)
        if end >= 0:
            body = text[end + 4:]
    for line in body.split("\n"):
        line = line.strip()
        if not line or line.startswith("#") or line.startswith("---"):
            continue
        return line[:200]
    return ""


def _scan_md_dir_invocations(dir_path: Path, *, source_label: str, namespace: str,
                             provider: str, trigger: str = "/", kind: str = "command") -> list:
    items: list = []
    total_bytes = 0
    for path in _bounded_invocation_scan(
        dir_path,
        suffix=".md",
        max_depth=0,
    ):
        try:
            text, stat_result = _read_invocation_file_nofollow(dir_path, path)
            if stat_result.st_size > _INVOCATION_MAX_SKILL_FILE_SIZE:
                continue
            if total_bytes + stat_result.st_size > _INVOCATION_MAX_TOTAL_BYTES:
                break
        except OSError:
            continue
        total_bytes += stat_result.st_size
        fm = _parse_md_frontmatter(text)
        if not _bool_frontmatter(fm.get("user-invocable"), True):
            continue
        desc = fm.get("description") or _first_prose_line(text)
        name = fm.get("name") or path.stem
        items.append(_make_invocation(
            provider=provider,
            trigger=trigger,
            name=name,
            description=desc,
            source=source_label,
            kind=kind,
            namespace=namespace,
            args=fm.get("args"),
            insert_text=f"{trigger}{name.lstrip('/$')}",
            source_path=path,
            trust={"local": True, "allowlisted_root": True, "signed": False},
            visibility={"user_invocable": True, "hidden": False},
        ))
    return items


def _scan_omp_skill_root(
    skills_dir: Path,
    *,
    source: str,
    namespace: str,
) -> list:
    items: list = []
    total_bytes = 0
    for skill_md in _bounded_invocation_scan(
        skills_dir,
        file_name="SKILL.md",
        max_depth=1,
    ):
        try:
            if skill_md.parent.parent != skills_dir.resolve():
                continue
            text, stat_result = _read_invocation_file_nofollow(skills_dir, skill_md)
            if stat_result.st_size > _INVOCATION_MAX_SKILL_FILE_SIZE:
                continue
            if total_bytes + stat_result.st_size > _INVOCATION_MAX_TOTAL_BYTES:
                break
        except OSError:
            continue
        total_bytes += stat_result.st_size
        frontmatter = _parse_md_frontmatter(text)
        if not _bool_frontmatter(frontmatter.get("user-invocable"), True):
            continue
        name = frontmatter.get("name") or skill_md.parent.name
        items.append(_make_invocation(
            provider="omp",
            trigger="/",
            name=name,
            description=frontmatter.get("description") or _first_prose_line(text),
            source=source,
            kind="skill",
            namespace=namespace,
            args=frontmatter.get("args"),
            insert_text=f"/{name.lstrip('/')}",
            source_path=skill_md,
            trust={"local": True, "allowlisted_root": True, "signed": False},
            visibility={"user_invocable": True, "hidden": False},
        ))
    return items


def _scan_claude_skill_invocations() -> list:
    items: list = []
    total_bytes = 0
    skills_dir = HOME / ".claude" / "skills"
    for skill_md in _bounded_invocation_scan(
        skills_dir,
        file_name="SKILL.md",
        max_depth=1,
    ):
        if skill_md.parent.parent != skills_dir.resolve():
            continue
        try:
            text, stat_result = _read_invocation_file_nofollow(skills_dir, skill_md)
            if stat_result.st_size > _INVOCATION_MAX_SKILL_FILE_SIZE:
                continue
            if total_bytes + stat_result.st_size > _INVOCATION_MAX_TOTAL_BYTES:
                break
        except OSError:
            continue
        total_bytes += stat_result.st_size
        fm = _parse_md_frontmatter(text)
        if not _bool_frontmatter(fm.get("user-invocable"), True):
            continue
        name = fm.get("name") or skill_md.parent.name
        items.append(_make_invocation(
            provider="claude",
            trigger="/",
            name=name,
            description=fm.get("description") or _first_prose_line(text),
            source="skill",
            kind="skill",
            namespace="skill",
            args=fm.get("args"),
            insert_text=f"/{name.lstrip('/')}",
            source_path=skill_md,
            trust={"local": True, "allowlisted_root": True, "signed": False},
            visibility={"user_invocable": True, "hidden": False},
        ))
    return items


def _scan_claude_plugin_invocations() -> list:
    items: list = []
    total_bytes = 0
    plugins_dir = HOME / ".claude" / "plugins"
    for path in _bounded_invocation_scan(plugins_dir, suffix=".md"):
        if path.parent.name != "commands":
            continue
        try:
            relative_parts = path.relative_to(plugins_dir.resolve()).parts
            plugin_name = relative_parts[0]
        except (ValueError, IndexError):
            continue
        if plugin_name == "cache":
            continue
        if plugin_name == "marketplaces":
            if len(relative_parts) < 3:
                continue
            plugin_name = relative_parts[1]
        try:
            text, stat_result = _read_invocation_file_nofollow(plugins_dir, path)
            if stat_result.st_size > _INVOCATION_MAX_SKILL_FILE_SIZE:
                continue
            if total_bytes + stat_result.st_size > _INVOCATION_MAX_TOTAL_BYTES:
                break
        except OSError:
            continue
        total_bytes += stat_result.st_size
        fm = _parse_md_frontmatter(text)
        if not _bool_frontmatter(fm.get("user-invocable"), True):
            continue
        name = fm.get("name") or path.stem
        items.append(_make_invocation(
            provider="claude",
            trigger="/",
            name=name,
            description=fm.get("description") or _first_prose_line(text),
            source=f"plugin:{plugin_name}",
            kind="plugin",
            namespace=plugin_name,
            args=fm.get("args"),
            insert_text=f"/{name.lstrip('/')}",
            source_path=path,
            trust={"local": True, "allowlisted_root": True, "signed": False},
            visibility={"user_invocable": True, "hidden": False},
        ))
    return items


def _path_is_relative_to(path: Path, root: Path) -> bool:
    try:
        path.relative_to(root)
        return True
    except ValueError:
        return False

def _authorized_user_path(raw_path: str, *, allow_tmp: bool):
    roots = [HOME]
    if allow_tmp:
        roots.append(Path("/tmp"))
    return authorize_path(raw_path, roots=roots)


def _canonical_user_directory(raw_path: str, *, allow_tmp: bool) -> str:
    """Validate one existing non-symlink directory under canonical user roots."""
    raw_path = (raw_path or "").strip()
    if not raw_path:
        raise ValueError("directory path is required")
    authorized = _authorized_user_path(raw_path, allow_tmp=allow_tmp)
    descriptor = open_directory_fd(authorized.path, root=authorized.root)
    os.close(descriptor)
    return str(authorized.path)


def _canonical_user_path(raw_path: str, *, allow_tmp: bool) -> str:
    """Validate a regular file or directory without following any symlink."""
    raw_path = (raw_path or "").strip()
    if not raw_path:
        raise ValueError("path is required")
    authorized = _authorized_user_path(raw_path, allow_tmp=allow_tmp)
    try:
        descriptor = open_directory_fd(authorized.path, root=authorized.root)
    except (NotADirectoryError, ValueError):
        descriptor = open_regular_file_fd(authorized.path, root=authorized.root)
    os.close(descriptor)
    return str(authorized.path)


def _revalidate_canonical_user_directory(path: str, *, allow_tmp: bool) -> str:
    resolved = _canonical_user_directory(path, allow_tmp=allow_tmp)
    if resolved != path:
        raise PermissionError(f"directory path changed after validation: {path}")
    return resolved




def _codex_skill_roots() -> list[Path]:
    roots = [
        HOME / ".codex" / "skills" / ".system",
        HOME / ".agents" / "skills",
    ]
    cache_root = HOME / ".codex" / "plugins" / "cache"
    roots.extend(
        _bounded_invocation_scan(
            cache_root,
            directory_name="skills",
        )
    )
    out: list[Path] = []
    seen: set[str] = set()
    for root in roots:
        try:
            resolved = root.resolve()
        except OSError:
            continue
        key = str(resolved)
        if key not in seen:
            seen.add(key)
            out.append(root)
    return out


def _codex_skill_namespace(skill_md: Path, root: Path) -> tuple[str, str]:
    try:
        root_resolved = root.resolve()
        skill_resolved = skill_md.resolve()
    except OSError:
        return ("unknown", "unknown")
    if root_resolved == (HOME / ".codex" / "skills" / ".system").resolve():
        return (".system", "system")
    if root_resolved == (HOME / ".agents" / "skills").resolve():
        return ("agents", "agents")
    parts = skill_resolved.parts
    namespace = "plugin"
    try:
        cache_idx = parts.index("cache")
        skills_idx = parts.index("skills")
        if skills_idx > cache_idx + 1:
            namespace = parts[cache_idx + 2] if len(parts) > cache_idx + 2 else parts[cache_idx + 1]
    except (ValueError, IndexError):
        namespace = root_resolved.name
    return (namespace, f"plugin:{namespace}")


def _scan_codex_dollar_skill_invocations() -> list:
    items: list = []
    total_bytes = 0
    files_seen = 0
    for root in _codex_skill_roots():
        if not root.is_dir():
            continue
        try:
            root_resolved = root.resolve()
            candidates = _bounded_invocation_scan(root, file_name="SKILL.md")
        except OSError:
            continue
        for skill_md in candidates:
            if files_seen >= _INVOCATION_MAX_SKILL_FILES:
                return items
            try:
                resolved = skill_md.resolve()
                if not _path_is_relative_to(resolved, root_resolved):
                    continue
                rel_depth = len(resolved.relative_to(root_resolved).parts)
                if rel_depth > _INVOCATION_MAX_TRAVERSAL_DEPTH:
                    continue
                text, st = _read_invocation_file_nofollow(root_resolved, skill_md)
                if st.st_size > _INVOCATION_MAX_SKILL_FILE_SIZE:
                    continue
                if total_bytes + st.st_size > _INVOCATION_MAX_TOTAL_BYTES:
                    return items
            except OSError:
                continue
            files_seen += 1
            total_bytes += st.st_size
            fm = _parse_md_frontmatter(text)
            if not _bool_frontmatter(fm.get("user-invocable"), True):
                continue
            name = fm.get("name") or resolved.parent.name
            namespace, source = _codex_skill_namespace(resolved, root)
            hidden = str(fm.get("visibility") or "").strip().lower() == "hidden"
            items.append(_make_invocation(
                provider="codex",
                trigger="$",
                name=name,
                display_name=_title_from_invocation_name(name),
                description=fm.get("description") or fm.get("metadata.short-description") or _first_prose_line(text),
                source=source,
                kind="skill",
                namespace=namespace,
                args=fm.get("args"),
                insert_text=f"${name.lstrip('$')}",
                source_path=resolved,
                trust={"local": True, "allowlisted_root": True, "signed": False},
                visibility={"user_invocable": True, "hidden": hidden},
            ))
    return items


def _build_invocation_catalog(cwd: str = "", provider: str = "claude",
                              trigger: str | None = None) -> list:
    provider = (provider or "claude").strip().lower()
    if not _provider_supports(provider, "commands"):
        return []
    items: list = []
    if trigger in (None, "/"):
        items.extend(_builtin_invocations(provider))
        if provider == "omp":
            user_root = HOME / ".omp" / "agent" / "commands"
        else:
            user_root = HOME / (".codex" if provider == "codex" else ".claude") / "commands"
        items.extend(_scan_md_dir_invocations(
            user_root,
            source_label="user",
            namespace="user",
            provider=provider,
            trigger="/",
            kind="command",
        ))
        if cwd and os.path.isdir(cwd):
            if provider == "omp":
                project_root = Path(cwd) / ".omp" / "commands"
            else:
                project_root = Path(cwd) / (".codex" if provider == "codex" else ".claude") / "commands"
            items.extend(_scan_md_dir_invocations(
                project_root,
                source_label="project",
                namespace="project",
                provider=provider,
                trigger="/",
                kind="command",
            ))
        if provider == "claude":
            items.extend(_scan_claude_plugin_invocations())
            items.extend(_scan_claude_skill_invocations())
        elif provider == "omp":
            items.extend(_scan_omp_skill_root(
                HOME / ".omp" / "agent" / "skills",
                source="skill",
                namespace="skill",
            ))
            items.extend(_scan_omp_skill_root(
                HOME / ".omp" / "agent" / "managed-skills",
                source="managed-skill",
                namespace="managed-skill",
            ))
            if cwd and os.path.isdir(cwd):
                items.extend(_scan_omp_skill_root(
                    Path(cwd) / ".omp" / "skills",
                    source="project-skill",
                    namespace="project-skill",
                ))
    if provider == "codex" and trigger in (None, "$"):
        items.extend(_scan_codex_dollar_skill_invocations())
    return _dedupe_invocations(items)


def _invocations_signature(cwd: str = "", provider: str = "claude",
                           trigger: str | None = None) -> str:
    provider = (provider or "claude").strip().lower()
    if not _provider_supports(provider, "commands"):
        return f"unsupported:{provider}:{trigger or ''}"
    h = hashlib.sha256()
    h.update(f"epoch:{_CATALOG_EPOCH}\n".encode())
    h.update(json.dumps(_builtin_catalog_meta_for(provider), sort_keys=True).encode())
    roots: list[Path] = []
    if trigger in (None, "/"):
        if provider == "omp":
            roots.append(HOME / ".omp" / "agent" / "commands")
        else:
            roots.append(HOME / (".codex" if provider == "codex" else ".claude") / "commands")
        if provider == "claude":
            roots.extend([HOME / ".claude" / "skills", HOME / ".claude" / "plugins"])
        elif provider == "omp":
            roots.extend([
                HOME / ".omp" / "agent" / "skills",
                HOME / ".omp" / "agent" / "managed-skills",
            ])
        if cwd and os.path.isdir(cwd):
            if provider == "omp":
                roots.extend([
                    Path(cwd) / ".omp" / "commands",
                    Path(cwd) / ".omp" / "skills",
                ])
            else:
                roots.append(Path(cwd) / (".codex" if provider == "codex" else ".claude") / "commands")
    if provider == "codex" and trigger in (None, "$"):
        roots.extend(_codex_skill_roots())
    for root in roots:
        try:
            resolved_root = root.resolve()
        except OSError:
            resolved_root = root
        if not root.is_dir():
            h.update(b"M:" + str(resolved_root).encode() + b"\n")
            continue
        try:
            entries: list[tuple[str, float, int]] = []
            for pattern in ("*.md", "SKILL.md"):
                for p in root.rglob(pattern):
                    try:
                        resolved = p.resolve()
                        if not _path_is_relative_to(resolved, resolved_root):
                            continue
                        st = resolved.stat()
                        entries.append((str(resolved), st.st_mtime, st.st_size))
                    except OSError:
                        continue
            entries.sort(key=lambda t: t[0])
            for path, mtime, size in entries:
                h.update(f"{path}|{mtime}|{size}\n".encode())
        except OSError:
            continue
    return h.hexdigest()


def _scan_md_dir(dir_path: Path, source_label: str, name_prefix: str = "/") -> list:
    """Generic scanner for `.md` slash command files in a directory.
    Each file becomes one command; name is the file stem (basename without
    extension), description from frontmatter `description:` or first body line."""
    items: list = []
    if not dir_path.is_dir():
        return items
    try:
        files = sorted(dir_path.glob("*.md"))
    except OSError:
        return items
    for p in files:
        try:
            text = p.read_text(errors="replace")
        except OSError:
            continue
        fm = _parse_md_frontmatter(text)
        desc = fm.get("description") or _first_prose_line(text)
        items.append({
            "name": f"{name_prefix}{p.stem}",
            "description": desc,
            "source": source_label,
            "args": fm.get("args"),
        })
    return items


def _scan_skills() -> list:
    """Skills live at ~/.claude/skills/<name>/SKILL.md with YAML frontmatter
    (name, description, user-invocable). Filter out skills explicitly marked
    user-invocable: false."""
    items: list = []
    skills_dir = HOME / ".claude" / "skills"
    if not skills_dir.is_dir():
        return items
    try:
        skill_dirs = sorted(d for d in skills_dir.iterdir() if d.is_dir() and not d.name.startswith("."))
    except OSError:
        return items
    for d in skill_dirs:
        skill_md = d / "SKILL.md"
        if not skill_md.is_file():
            continue
        try:
            text = skill_md.read_text(errors="replace")
        except OSError:
            continue
        fm = _parse_md_frontmatter(text)
        if fm.get("user-invocable", "true").lower() == "false":
            continue
        name = fm.get("name", d.name)
        items.append({
            "name": f"/{name}",
            "description": fm.get("description") or _first_prose_line(text),
            "source": "skill",
            "args": fm.get("args"),
        })
    return items


def _scan_plugins() -> list:
    """Plugin slash commands live under ~/.claude/plugins/<plugin>/commands/*.md
    or ~/.claude/plugins/marketplaces/<market>/.claude/commands/*.md.
    We walk the entire plugins tree shallowly and pick anything that ends in
    /commands/*.md, tagging by the highest-level plugin segment."""
    items: list = []
    plugins_dir = HOME / ".claude" / "plugins"
    if not plugins_dir.is_dir():
        return items
    try:
        all_md = list(plugins_dir.glob("**/commands/*.md"))
    except OSError:
        return items
    for p in all_md:
        # Identify plugin segment — the directory immediately under "plugins/".
        try:
            parts = p.parts
            idx = parts.index("plugins")
            plugin_name = parts[idx + 1]
        except (ValueError, IndexError):
            continue
        # Skip the plugin cache + marketplaces metadata files.
        if plugin_name in ("cache",):
            continue
        if plugin_name == "marketplaces":
            # Use the marketplace name as the source tag.
            try:
                plugin_name = parts[idx + 2]
            except IndexError:
                continue
        try:
            text = p.read_text(errors="replace")
        except OSError:
            continue
        fm = _parse_md_frontmatter(text)
        items.append({
            "name": f"/{p.stem}",
            "description": fm.get("description") or _first_prose_line(text),
            "source": f"plugin:{plugin_name}",
            "args": fm.get("args"),
        })
    return items


def _scan_user_commands() -> list:
    return _scan_md_dir(HOME / ".claude" / "commands", "user")


def _scan_project_commands(cwd: str) -> list:
    if not cwd or not os.path.isdir(cwd):
        return []
    return _scan_md_dir(Path(cwd) / ".claude" / "commands", "project")


def _commands_signature(cwd: str = "", provider: str = "claude") -> str:
    """Stable hash representing the current state of all command source dirs.
    Changes whenever a file is added, removed, or modified across any source.
    Used by /commands-stream to decide whether to re-emit the catalog.

    Cheap: ~1000 stat calls on local fs across 5 dirs is sub-millisecond.
    """
    provider = (provider or "claude").strip().lower()
    if not _provider_supports(provider, "mcp"):
        return f"unsupported:{provider}"
    h = hashlib.sha256()
    h.update(f"epoch:{_CATALOG_EPOCH}\n".encode())
    # The builtin meta (verified/installed/stale) is part of the catalog
    # truth: a binary upgrade re-emits without any command file moving.
    h.update(json.dumps(_builtin_catalog_meta_for(provider), sort_keys=True).encode())
    sources: list[Path] = [
        HOME / ".claude" / "commands",
        HOME / ".claude" / "skills",
        HOME / ".claude" / "plugins",
    ]
    if provider == "codex":
        sources = [
            HOME / ".codex" / "commands",
            HOME / ".codex" / "plugins",
            HOME / ".codex" / "skills",
        ]
    if cwd and os.path.isdir(cwd):
        sources.append(Path(cwd) / (".codex" if provider == "codex" else ".claude") / "commands")

    for root in sources:
        if not root.is_dir():
            h.update(b"M:" + str(root).encode() + b"\n")
            continue
        # Walk shallowly: directories matter for path; files we hash by
        # name + mtime + size. Sorted for determinism.
        try:
            entries: list[tuple[str, float, int]] = []
            for p in root.rglob("*.md"):
                try:
                    st = p.stat()
                    entries.append((str(p), st.st_mtime, st.st_size))
                except OSError:
                    continue
            entries.sort(key=lambda t: t[0])
            for path, mtime, size in entries:
                h.update(f"{path}|{mtime}|{size}\n".encode())
        except OSError:
            continue
    return h.hexdigest()


def _scan_codex_user_commands() -> list:
    return _scan_md_dir(HOME / ".codex" / "commands", "user")


def _scan_codex_project_commands(cwd: str) -> list:
    if not cwd or not os.path.isdir(cwd):
        return []
    return _scan_md_dir(Path(cwd) / ".codex" / "commands", "project")


def _build_codex_command_catalog(cwd: str = "") -> list:
    items = list(_builtin_commands_for("codex"))
    items.extend(_scan_codex_user_commands())
    items.extend(_scan_codex_project_commands(cwd))
    return sorted(items, key=lambda c: (
        0 if c["source"] == "builtin"
        else 1 if c["source"] == "user"
        else 2 if c["source"] == "project"
        else 3,
        c["name"].lower(),
    ))


def _build_command_catalog(cwd: str = "", provider: str = "claude") -> list:
    """Scan all five sources and return a deduplicated list of commands.
    Built-ins always first, then user, project, plugin, skill — matches Claude
    Code's resolution order for shadowing (later sources override earlier ones)."""
    return [
        _legacy_command_from_invocation(item)
        for item in _build_invocation_catalog(cwd=cwd, provider=provider, trigger="/")
    ]


def _derive_bucket_folder(project_path: str) -> str:
    """Derive the upload-folder bucket name from a session's project path.
    Sentinel sessions get unwrapped to their underlying project name; regular
    projects use their basename. Sanitized to filesystem-safe chars."""
    if not project_path:
        return "misc"
    m = _SENTINEL_PROJECTS_RE.search(project_path)
    if m:
        raw = m.group(1)
    else:
        raw = os.path.basename(project_path.rstrip("/")) or "misc"
        # Belt-and-suspenders: also strip a -<6hex> suffix from a non-sentinel
        # path if the user manually nests projects that pattern. Cheap.
        raw = _HEX_SUFFIX_RE.sub("", raw)
    return re.sub(r"[^a-zA-Z0-9_.-]", "_", raw) or "misc"


def _is_excluded_project_dir_name(encoded: str) -> bool:
    """For walking ~/.claude/projects/<encoded-dir>, check exclusion against the
    encoded directory name (which has '-' instead of '/')."""
    if not encoded:
        return False
    for pattern in PROJECT_EXCLUDE_PATTERNS:
        encoded_pattern = "-" + pattern.replace("/", "-")
        if encoded_pattern in encoded:
            return True
    return False


def _safe_session_id(s: str) -> bool:
    """Whitelist the characters we expect in session ids (UUIDs or continuous-claude
    `s-...` ids) before passing into a SQL query."""
    if not s or len(s) > 64:
        return False
    return all(c.isalnum() or c in "-_" for c in s)


def _safe_agent_native_id(s: str) -> bool:
    """Whitelist provider-native ids before process/registry operations."""
    if not s or len(s) > 160:
        return False
    return all(c.isalnum() or c in "-_" for c in s)


# Import-failure fallback ONLY. Live membership checks go through
# _agent_provider_ids(), which derives session-capable providers from the
# registry (depth deep|standard) so the set is data, not a literal
# (SPEC-p2 §2.1).
AGENT_PROVIDERS = {"claude", "codex"}


def _agent_provider_ids() -> set[str]:
    try:
        if _provider_session_capable_ids:
            ids = set(_provider_session_capable_ids())
            if ids:
                return ids
    except Exception:
        pass
    return set(AGENT_PROVIDERS)


def _registered_agent_provider_ids() -> set[str]:
    try:
        if _provider_registry_ids:
            return set(_provider_registry_ids())
    except Exception:
        pass
    return set(AGENT_PROVIDERS)


def _known_agent_provider_ids() -> set[str]:
    try:
        if _provider_known_ids:
            return set(_provider_known_ids())
    except Exception:
        pass
    return set(AGENT_PROVIDERS)


def _excluded_provider_ids() -> set[str]:
    """The user's visibility choice from ~/.pairling/providers.json.
    Missing/corrupt file (or an unavailable providers package) reads as
    "hide nothing" — default is everything detected is included."""
    try:
        if _provider_visibility_read_excluded:
            return set(_provider_visibility_read_excluded(home=HOME))
    except Exception:
        pass
    return set()


def _visible_agent_provider_ids() -> set[str]:
    """Session-capable providers the user has not excluded (SPEC-p1 §2.3).
    Exclusion hides a provider from session, command, and spawn surfaces; it
    never touches the provider's own config or processes (Law 3)."""
    visible = _registered_agent_provider_ids() & _agent_provider_ids()
    return visible - _excluded_provider_ids()


def _provider_visible(provider_id: str) -> bool:
    return (provider_id or "").strip().lower() not in _excluded_provider_ids()


def _provider_hidden_payload(provider: str) -> dict:
    return {
        "ok": False,
        "error": {
            "code": "provider_hidden",
            "message": f"Provider {provider} is hidden by visibility settings. Include it in Settings → Providers to use it.",
            "provider": provider,
        },
    }


def _send_provider_hidden(handler, provider: str) -> None:
    handler._send_json(_provider_hidden_payload(provider), status=409)


def _valid_provider_filter(provider: str, *, allow_all: bool = True) -> bool:
    provider = (provider or "").strip().lower()
    if allow_all and provider == "all":
        return True
    return provider in _registered_agent_provider_ids()


def _unknown_provider_payload(provider: str) -> dict:
    known = sorted(_registered_agent_provider_ids())
    future = sorted(_known_agent_provider_ids() - set(known))
    return {
        "ok": False,
        "error": {
            "code": "unknown_provider",
            "message": f"Unknown provider: {provider}",
            "known_providers": known,
            "known_future_providers": future,
        },
    }


def _send_unknown_provider(handler, provider: str):
    handler._send_json(_unknown_provider_payload(provider), status=400)


def _unsupported_provider_payload(provider: str, capability: str) -> dict:
    return {
        "ok": False,
        "error": {
            "code": "unsupported_provider",
            "message": f"Provider {provider} does not support {capability} in this Pairling runtime.",
            "provider": provider,
            "capability": capability,
        },
    }


def _send_unsupported_provider(handler, provider: str, capability: str, status: int = 400):
    handler._send_json(_unsupported_provider_payload(provider, capability), status=status)


CLAUDE_SESSION_CAPABILITIES = [
    "transcript",
    "live_state",
    "send_text",
    "interrupt",
    "terminate",
    "upload",
    "commands",
    "export",
    "resume",
]
CODEX_READ_ONLY_CAPABILITIES = [
    "transcript",
    "export",
]
CODEX_CONTROL_CAPABILITIES = [
    "transcript",
    "live_state",
    "send_text",
    "interrupt",
    "terminate",
    "upload",
    "commands",
    "terminal_output",
    "terminal_surface",
    "terminal_control",
    "export",
]

_SESSION_TRANSCRIPT_STATS_CACHE: dict[tuple[str, str, str, int, int], dict] = {}
_SESSION_TRANSCRIPT_STATS_CACHE_MAX_ENTRIES = 2048
_SESSION_TRANSCRIPT_STATS_CACHE_TRIM_ENTRIES = 256
_codex_rollout_paths_lock = threading.Lock()
_codex_rollout_paths_cache: dict[str, object] = {"ts": 0.0, "paths": []}
_codex_rollout_index_lock = threading.Lock()
_codex_rollout_index_cache: dict[str, object] = {
    "signature": (),
    "meta_by_file": {},
    "entries": [],
    "by_id": {},
}


def _clear_codex_rollout_caches() -> None:
    with _codex_rollout_paths_lock:
        _codex_rollout_paths_cache["ts"] = 0.0
        _codex_rollout_paths_cache["paths"] = []
    with _codex_rollout_index_lock:
        _codex_rollout_index_cache["signature"] = ()
        _codex_rollout_index_cache["meta_by_file"] = {}
        _codex_rollout_index_cache["entries"] = []
        _codex_rollout_index_cache["by_id"] = {}
_MEANINGFUL_LINE_PARSE_MAX_BYTES = 1024 * 1024
_MEANINGFUL_LINE_PREFIX_BYTES = 128 * 1024
_REVERSE_JSONL_CHUNK_BYTES = 64 * 1024


def _transcript_timestamp_epoch(value) -> float | None:
    if isinstance(value, (int, float)):
        return float(value) if value > 0 else None
    if not isinstance(value, str) or not value.strip():
        return None
    try:
        return datetime.fromisoformat(value.strip().replace("Z", "+00:00")).timestamp()
    except (TypeError, ValueError):
        return None


def _meaningful_transcript_turn_at(row: dict) -> float | None:
    """Return the timestamp for provider-authored conversational text.

    Tool traffic, reasoning, lifecycle rows, and injected harness blocks do
    not count. This value is allowed to move a dashboard row, so it must be
    tied to assistant text from the provider transcript. A user prompt does
    not masquerade as provider output; new sessions use start time until the
    provider answers.
    """
    message = row.get("message") if isinstance(row.get("message"), dict) else {}
    role = str(message.get("role") or row.get("type") or "").lower()
    if role != "assistant":
        return None
    content = message.get("content")
    texts: list[str] = []
    if isinstance(content, str):
        texts.append(content)
    elif isinstance(content, list):
        for block in content:
            if not isinstance(block, dict):
                continue
            block_type = str(block.get("type") or "text")
            if block_type not in {"text", "input_text", "output_text"}:
                continue
            text = block.get("text") or block.get("content")
            if isinstance(text, str):
                texts.append(text)
    for text in texts:
        cleaned = _strip_transcript_harness_blocks(text).strip()
        if cleaned and cleaned != ".":
            return _transcript_timestamp_epoch(row.get("timestamp"))
    return None


def _reverse_jsonl_line_spans(handle):
    """Yield non-empty JSONL byte ranges from newest to oldest."""
    handle.seek(0, os.SEEK_END)
    size = handle.tell()
    cursor = size
    line_end = size
    while cursor > 0:
        start = max(0, cursor - _REVERSE_JSONL_CHUNK_BYTES)
        handle.seek(start)
        chunk = handle.read(cursor - start)
        for index in range(len(chunk) - 1, -1, -1):
            if chunk[index] != 0x0A:
                continue
            newline = start + index
            if newline + 1 < line_end:
                yield newline + 1, line_end
            line_end = newline
        cursor = start
    if line_end > 0:
        yield 0, line_end


def _timestamp_from_json_prefix(prefix: str) -> float | None:
    match = re.search(
        r'"timestamp"\s*:\s*(?:"([^"\\]*(?:\\.[^"\\]*)*)"|([0-9]+(?:\.[0-9]+)?))',
        prefix,
    )
    if match is None:
        return None
    value = match.group(1) if match.group(1) is not None else match.group(2)
    if match.group(1) is not None:
        try:
            value = json.loads(f'"{value}"')
        except (ValueError, json.JSONDecodeError):
            return None
    return _transcript_timestamp_epoch(value)


def _large_transcript_line_block_types(
    handle,
    start: int,
    length: int,
    provider: str,
) -> set[str]:
    """Read only JSON structure while skipping arbitrarily large values.

    The scanner retains short field names and type values, never transcript
    text. It follows the provider message/payload content array so nested tool
    input objects cannot masquerade as provider-authored text blocks.
    """
    provider = str(provider or "").strip().lower()
    if provider == "codex":
        target_container = "payload"
    elif provider == "claude":
        target_container = "message"
    else:
        raise _UnsupportedTranscriptProviderError(provider)
    frames: list[dict] = []
    block_types: set[str] = set()
    candidate_key: str | None = None
    token = bytearray()
    token_truncated = False
    in_string = False
    escaped = False
    remaining = max(0, int(length))
    handle.seek(start)

    def finish_string() -> None:
        nonlocal candidate_key
        value = None if token_truncated else token.decode("ascii", errors="ignore")
        if frames and frames[-1]["kind"] == "object" and frames[-1].get("pending_key") is not None:
            key = frames[-1].pop("pending_key")
            if frames[-1].get("target_block") and key == "type" and value:
                block_types.add(value)
            candidate_key = None
        else:
            candidate_key = value

    while remaining > 0:
        chunk = handle.read(min(_REVERSE_JSONL_CHUNK_BYTES, remaining))
        if not chunk:
            break
        remaining -= len(chunk)
        for byte in chunk:
            if in_string:
                if escaped:
                    escaped = False
                    if len(token) < 128:
                        token.append(byte)
                    else:
                        token_truncated = True
                    continue
                if byte == 0x5C:
                    escaped = True
                    continue
                if byte == 0x22:
                    in_string = False
                    finish_string()
                    continue
                if len(token) < 128:
                    token.append(byte)
                else:
                    token_truncated = True
                continue

            if byte in b" \t\r\n":
                continue
            if byte == 0x22:
                in_string = True
                escaped = False
                token.clear()
                token_truncated = False
                continue
            if byte == 0x3A:  # :
                if frames and frames[-1]["kind"] == "object" and candidate_key is not None:
                    frames[-1]["pending_key"] = candidate_key
                candidate_key = None
                continue
            if byte in (0x7B, 0x5B):  # { [
                opened_by = None
                if frames and frames[-1]["kind"] == "object":
                    opened_by = frames[-1].pop("pending_key", None)
                parent = frames[-1] if frames else None
                kind = "object" if byte == 0x7B else "array"
                target_content = bool(
                    kind == "array"
                    and opened_by == "content"
                    and parent
                    and parent.get("opened_by") == target_container
                )
                target_block = bool(
                    kind == "object" and parent and parent.get("target_content")
                )
                frames.append({
                    "kind": kind,
                    "opened_by": opened_by,
                    "target_content": target_content,
                    "target_block": target_block,
                })
                candidate_key = None
                continue
            if byte in (0x7D, 0x5D):  # } ]
                if frames:
                    frames.pop()
                candidate_key = None
                continue
            if byte == 0x2C:  # ,
                if frames and frames[-1]["kind"] == "object":
                    frames[-1].pop("pending_key", None)
                candidate_key = None
                continue
            candidate_key = None
    return block_types


def _large_transcript_line_meaningful_at(
    prefix: str,
    provider: str,
    block_types: set[str] | None = None,
) -> float | None:
    """Classify a large provider row from bounded structural metadata.

    Provider JSONL writes the record type, role, timestamp, and content block
    type before the potentially huge text or tool result. This lets reverse
    lookup skip giant tool rows without loading them into memory.
    """
    compact = re.sub(r"\s+", "", prefix)
    timestamp = _timestamp_from_json_prefix(prefix)
    if timestamp is None:
        return None
    provider = str(provider or "").strip().lower()
    if provider == "codex":
        if '"type":"response_item"' not in compact:
            return None
        payload_at = compact.find('"payload":')
        payload = compact[payload_at:] if payload_at >= 0 else ""
        if '"type":"message"' not in payload:
            return None
        if '"role":"assistant"' not in payload:
            return None
        block_types = block_types or set(re.findall(
            r'(?:\[\{|},\{)"type":"([^"]+)"', payload
        ))
        if not block_types.intersection({"text", "input_text", "output_text"}):
            return None
    elif provider == "claude":
        if '"type":"assistant"' not in compact:
            return None
        message_at = compact.find('"message":')
        message = compact[message_at:] if message_at >= 0 else ""
        if '"role":"assistant"' not in message:
            return None
        content_at = message.find('"content":')
        content = message[content_at:] if content_at >= 0 else ""
        block_types = block_types or set(re.findall(
            r'(?:\[\{|},\{)"type":"([^"]+)"', content
        ))
        if not content.startswith('"content":"') and (
            not block_types.intersection({"text", "input_text", "output_text"})
        ):
            return None
    else:
        raise _UnsupportedTranscriptProviderError(provider)
    lowered = prefix.lower()
    if any(f"<{tag}>" in lowered for tag in TRANSCRIPT_HARNESS_BLOCK_TAGS):
        return None
    return timestamp


def _large_transcript_line_is_provider_text_candidate(
    prefix: str,
    provider: str,
) -> bool:
    """Return whether a large row can contain provider-authored text.

    Giant tool results and state snapshots can be hundreds of megabytes. Their
    envelope identifies them before the large value begins, so reading every
    byte cannot improve the answer and makes the sessions list scale with tool
    output size.
    """
    compact = re.sub(r"\s+", "", prefix)
    lowered = prefix.lower()
    if any(f"<{tag}>" in lowered for tag in TRANSCRIPT_HARNESS_BLOCK_TAGS):
        return False
    provider = str(provider or "").strip().lower()
    if provider == "codex":
        if '"type":"response_item"' not in compact:
            return False
        payload_at = compact.find('"payload":')
        payload = compact[payload_at:] if payload_at >= 0 else ""
        return (
            '"type":"message"' in payload
            and '"role":"assistant"' in payload
        )
    if provider == "claude":
        if '"type":"assistant"' not in compact:
            return False
        message_at = compact.find('"message":')
        message = compact[message_at:] if message_at >= 0 else ""
        return '"role":"assistant"' in message
    raise _UnsupportedTranscriptProviderError(provider)


def _last_meaningful_transcript_turn_at(
    path: Path,
    provider: str,
    native_id: str,
) -> float | None:
    provider = str(provider or "").strip().lower()
    if provider not in _SUPPORTED_TRANSCRIPT_PROVIDERS:
        raise _UnsupportedTranscriptProviderError(provider)
    try:
        with _open_session_transcript_file(path) as handle:
            for start, end in _reverse_jsonl_line_spans(handle):
                length = max(0, end - start)
                if length <= 0:
                    continue
                handle.seek(start)
                if length > _MEANINGFUL_LINE_PARSE_MAX_BYTES:
                    prefix = handle.read(min(length, _MEANINGFUL_LINE_PREFIX_BYTES)).decode(
                        "utf-8", errors="replace"
                    )
                    meaningful = _large_transcript_line_meaningful_at(
                        prefix, provider
                    )
                    if meaningful is not None:
                        return meaningful
                    if not _large_transcript_line_is_provider_text_candidate(
                        prefix, provider
                    ):
                        continue
                    block_types = _large_transcript_line_block_types(
                        handle, start, length, provider
                    )
                    meaningful = _large_transcript_line_meaningful_at(
                        prefix, provider, block_types
                    )
                    if meaningful is not None:
                        return meaningful
                    continue
                raw = handle.read(length).decode("utf-8", errors="replace")
                if provider == "codex":
                    for row in _normalize_codex_line(raw, native_id):
                        meaningful = _meaningful_transcript_turn_at(row)
                        if meaningful is not None:
                            return meaningful
                elif provider == "claude":
                    try:
                        row = json.loads(raw)
                    except (ValueError, json.JSONDecodeError):
                        continue
                    meaningful = _meaningful_transcript_turn_at(row)
                    if meaningful is not None:
                        return meaningful
                else:
                    raise _UnsupportedTranscriptProviderError(provider)
    except OSError:
        return None
    return None


def _session_workspace_identity(project: str | None) -> dict:
    project = str(project or "").strip()
    if not project or not Path(project).is_dir():
        return {"branch": None, "worktree": None}

    def load() -> dict:
        ok, root_out, _ = _run_text(
            ["git", "-C", project, "rev-parse", "--show-toplevel"], timeout=2.0
        )
        if not ok:
            return {"branch": None, "worktree": None}
        root = root_out.strip()
        branch_ok, branch_out, _ = _run_text(
            ["git", "-C", project, "branch", "--show-current"], timeout=2.0
        )
        branch = branch_out.strip() if branch_ok else ""
        git_marker = Path(root) / ".git"
        return {
            "branch": branch or None,
            "worktree": root if git_marker.is_file() else None,
        }

    return _cached_runtime_snapshot(
        ("session-workspace-identity", project), 30.0, load
    )


def _transcript_root_for_path(path: Path | str) -> tuple[Path, Path]:
    authorized = authorize_path(
        path,
        roots=(CLAUDE_PROJECTS_DIR, CODEX_SESSIONS_DIR, OMP_SESSIONS_DIR),
    )
    return authorized.root, authorized.path


def _session_transcript_handle(path: Path | str):
    root, target = _transcript_root_for_path(path)
    descriptor = open_regular_file_fd(target, root=root)
    try:
        return os.fdopen(descriptor, "rb", closefd=True)
    except Exception:
        os.close(descriptor)
        raise


@contextmanager
def _open_session_transcript_file(path: Path | str):
    handle = _session_transcript_handle(path)
    with handle:
        yield handle


def _tail_lines(path: Path | str, *, max_lines: int = 240, max_bytes: int = TRANSCRIPT_TAIL_SCAN_BYTES) -> list[bytes]:
    max_lines = max(1, int(max_lines or 1))
    max_bytes = max(1, int(max_bytes or 1))
    try:
        with _open_session_transcript_file(path) as f:
            size = os.fstat(f.fileno()).st_size
            start = max(0, size - max_bytes)
            f.seek(start)
            data = f.read(min(size, max_bytes))
    except OSError:
        return []
    if start > 0:
        first_newline = data.find(b"\n")
        if first_newline >= 0:
            data = data[first_newline + 1:]
        else:
            data = b""
    lines = data.splitlines()
    return lines[-max_lines:]


def _bounded_transcript_stream_start(*, since: int, size: int) -> int:
    since = max(0, int(since or 0))
    size = max(0, int(size or 0))
    if since == 0 and size > TRANSCRIPT_INITIAL_STREAM_BYTES:
        return max(0, size - TRANSCRIPT_INITIAL_STREAM_BYTES)
    return min(since, size)


def _session_transcript_stats(path: Path | str | None, provider: str, native_id: str) -> dict:
    provider = str(provider or "").strip().lower()
    if provider not in _SUPPORTED_TRANSCRIPT_PROVIDERS:
        return {
            "turn_count": None,
            "bytes": None,
            "mtime": None,
            "last_meaningful_turn_at": None,
            "reason": "unsupported_provider",
            "provider": provider or "unknown",
        }
    if path is None:
        return {
            "turn_count": None,
            "bytes": None,
            "mtime": None,
            "last_meaningful_turn_at": None,
        }
    target = Path(path)
    try:
        with _open_session_transcript_file(target) as handle:
            stat = os.fstat(handle.fileno())
    except OSError:
        return {
            "turn_count": None,
            "bytes": None,
            "mtime": None,
            "last_meaningful_turn_at": None,
        }

    key = (
        str(target),
        provider,
        native_id,
        int(stat.st_mtime_ns),
        int(stat.st_size),
    )
    cached = _SESSION_TRANSCRIPT_STATS_CACHE.get(key)
    if cached is not None:
        return dict(cached)

    turns = 0
    last_meaningful_turn_at: float | None = None
    partial = stat.st_size > TRANSCRIPT_STATS_MAX_SCAN_BYTES
    try:
        if partial:
            iterable = [raw.decode("utf-8", errors="replace") for raw in _tail_lines(
                target,
                max_lines=2500,
                max_bytes=TRANSCRIPT_STATS_MAX_SCAN_BYTES,
            )]
        elif provider in {"codex", "claude"}:
            with _open_session_transcript_file(target) as f:
                if provider == "codex":
                    iterable = [
                        raw.decode("utf-8", errors="replace")
                        for raw in f
                    ]
                else:
                    iterable = list(f)
        else:
            raise _UnsupportedTranscriptProviderError(provider)
        if provider == "codex":
            for raw in iterable:
                if not raw.strip():
                    continue
                for row in _normalize_codex_line(raw, native_id):
                    msg = row.get("message") or {}
                    if msg.get("role") == "user":
                        turns += 1
                    meaningful_at = _meaningful_transcript_turn_at(row)
                    if meaningful_at is not None:
                        last_meaningful_turn_at = max(
                            last_meaningful_turn_at or meaningful_at,
                            meaningful_at,
                        )
        elif provider == "claude":
            for raw in iterable:
                if not raw.strip():
                    continue
                try:
                    obj = json.loads(raw)
                except (ValueError, json.JSONDecodeError):
                    continue
                msg = obj.get("message") or {}
                if obj.get("type") == "user" and msg.get("role") == "user":
                    turns += 1
                meaningful_at = _meaningful_transcript_turn_at(obj)
                if meaningful_at is not None:
                    last_meaningful_turn_at = max(
                        last_meaningful_turn_at or meaningful_at,
                        meaningful_at,
                    )
        else:
            raise _UnsupportedTranscriptProviderError(provider)
    except OSError:
        return {
            "turn_count": None,
            "bytes": stat.st_size,
            "mtime": int(stat.st_mtime),
            "partial": partial,
            "last_meaningful_turn_at": None,
        }

    if partial:
        last_meaningful_turn_at = _last_meaningful_transcript_turn_at(
            target, provider, native_id
        )
    stats = {
        "turn_count": turns,
        "bytes": stat.st_size,
        "mtime": int(stat.st_mtime),
        "partial": partial,
        "last_meaningful_turn_at": last_meaningful_turn_at,
    }
    _SESSION_TRANSCRIPT_STATS_CACHE[key] = stats
    if len(_SESSION_TRANSCRIPT_STATS_CACHE) > _SESSION_TRANSCRIPT_STATS_CACHE_MAX_ENTRIES:
        for old_key in list(_SESSION_TRANSCRIPT_STATS_CACHE.keys())[
            :_SESSION_TRANSCRIPT_STATS_CACHE_TRIM_ENTRIES
        ]:
            _SESSION_TRANSCRIPT_STATS_CACHE.pop(old_key, None)
    return dict(stats)


def _parse_agent_session_ref(raw: str) -> tuple[str, str]:
    """Return (provider, native_id), treating unqualified hook ids as Claude.

    Unknown provider prefixes are preserved so operation boundaries can return
    explicit unsupported-provider errors instead of silently relabeling future
    provider sessions as Claude.
    """
    raw = (raw or "").strip()
    if ":" in raw:
        provider, native_id = raw.split(":", 1)
        provider = provider.strip().lower()
        if provider and len(provider) <= 48 and re.fullmatch(r"[a-z0-9_]+", provider):
            return provider, native_id
    return "claude", raw


class ClaudeSessionsPgBackend:
    """Claude session reads from the Continuous-Claude Postgres via
    docker-exec psql. The legacy product path; retained behind
    PAIRLING_SESSION_BACKEND=pg as the rollback backend."""

    name = "pg"

    @staticmethod
    def _psql(sql: str, timeout: int = 3, tabbed: bool = False):
        args = ["docker", "exec", "continuous-claude-postgres",
                "psql", "-U", "claude", "-d", "continuous_claude"]
        if tabbed:
            args += ["-A", "-F", "\t", "-t"]
        else:
            args += ["-A", "-t"]
        args += ["-c", sql]
        return subprocess.run(args, capture_output=True, text=True, timeout=timeout)

    def uuid_for_session(self, session_id: str) -> str:
        sql = f"SELECT claude_uuid FROM sessions WHERE id = '{session_id}' LIMIT 1"
        try:
            proc = self._psql(sql)
            if proc.returncode != 0:
                return ""
            return (proc.stdout or "").strip()
        except Exception:
            return ""

    def session_for_uuid(self, claude_uuid: str) -> str:
        sql = f"SELECT id FROM sessions WHERE claude_uuid = '{claude_uuid}' ORDER BY last_heartbeat DESC LIMIT 1"
        try:
            proc = self._psql(sql)
            if proc.returncode != 0:
                return ""
            return (proc.stdout or "").strip()
        except Exception:
            return ""

    def session_record(self, session_id: str) -> dict | None:
        if not _safe_session_id(session_id):
            return None
        sql = (
            "SELECT id, project, working_on, "
            "EXTRACT(EPOCH FROM started_at)::bigint AS started_at, "
            "EXTRACT(EPOCH FROM last_heartbeat)::bigint AS last_heartbeat, "
            "claude_pid, claude_uuid, terminal_tty, "
            "EXTRACT(EPOCH FROM closed_at)::bigint AS closed_at "
            f"FROM sessions WHERE id = '{session_id}' LIMIT 1;"
        )
        try:
            proc = self._psql(sql, timeout=5, tabbed=True)
        except Exception:
            return None
        if proc.returncode != 0:
            return None
        line = (proc.stdout or "").strip("\r\n ")
        if not line:
            return None
        parts = line.split("\t")
        if len(parts) < 8:
            return None
        return {
            "provider": "claude",
            "native_id": parts[0],
            "project": parts[1],
            "working_on": parts[2] or None,
            "started_at": int(parts[3]) if parts[3].isdigit() else 0,
            "last_heartbeat": int(parts[4]) if parts[4].isdigit() else 0,
            "pid": int(parts[5]) if parts[5].isdigit() else 0,
            "claude_uuid": parts[6] if len(parts) > 6 else "",
            "terminal_tty": parts[7] if len(parts) > 7 else "",
            "closed_at": int(parts[8]) if len(parts) > 8 and parts[8].isdigit() else None,
        }

    def session_ids_for_uuid(self, claude_uuid: str) -> list[str]:
        if not re.fullmatch(r"[A-Za-z0-9_.:-]{1,180}", str(claude_uuid or "")):
            return []
        try:
            proc = self._psql(
                "SELECT id FROM sessions "
                f"WHERE claude_uuid = '{claude_uuid}' ORDER BY last_heartbeat DESC;",
                timeout=5,
            )
        except Exception:
            return []
        if proc.returncode != 0:
            return []
        return [value.strip() for value in (proc.stdout or "").splitlines() if value.strip()]

    def delete_registry_record(self, session_id: str) -> bool:
        if not _safe_session_id(session_id):
            return False
        try:
            proc = self._psql(
                "WITH changed AS ("
                "UPDATE sessions SET closed_at = NOW() "
                f"WHERE id = '{session_id}' AND closed_at IS NULL RETURNING 1"
                ") SELECT COUNT(*) FROM changed;",
                timeout=5,
            )
        except Exception:
            return False
        changed = any(
            line.strip().isdigit() and int(line.strip()) > 0
            for line in (proc.stdout or "").splitlines()
        )
        if proc.returncode == 0 and changed:
            _invalidate_sessions_provider_inventory("claude")
            _invalidate_session_list_caches()
        return proc.returncode == 0

    def worker_stats_rows(self, since_min: int) -> list[tuple[str, str, int]]:
        sql = (
            "SELECT id, project, "
            "EXTRACT(EPOCH FROM last_heartbeat)::bigint AS heartbeat "
            "FROM sessions "
            f"WHERE last_heartbeat > NOW() - INTERVAL '{since_min} minutes' "
            "ORDER BY last_heartbeat DESC;"
        )
        proc = self._psql(sql, timeout=5, tabbed=True)
        if proc.returncode != 0:
            raise RuntimeError(f"psql failed: {proc.stderr.strip()[:200]}")
        rows: list[tuple[str, str, int]] = []
        for line in proc.stdout.strip().split("\n"):
            if not line.strip():
                continue
            parts = line.split("\t")
            if len(parts) < 3:
                continue
            rows.append((parts[0], parts[1], int(parts[2] or 0)))
        return rows

    def recent_project_rows(self, within_min: int, limit: int) -> list[tuple[str, int]]:
        sql = (
            "SELECT project, MAX(EXTRACT(EPOCH FROM last_heartbeat)::bigint) AS last_heartbeat "
            "FROM sessions "
            f"WHERE last_heartbeat > NOW() - INTERVAL '{within_min} minutes' "
            "AND project IS NOT NULL AND project <> '' "
            "GROUP BY project "
            "ORDER BY last_heartbeat DESC "
            f"LIMIT {limit};"
        )
        try:
            proc = self._psql(sql, timeout=5, tabbed=True)
        except (OSError, subprocess.SubprocessError):
            return []
        if proc.returncode != 0:
            return []
        rows: list[tuple[str, int]] = []
        for line in proc.stdout.strip().split("\n"):
            if not line.strip():
                continue
            parts = line.split("\t")
            if len(parts) < 2:
                continue
            rows.append((parts[0], int(parts[1]) if parts[1].isdigit() else 0))
        return rows

    def sessions_rows(self, live_only: bool, within_min: int) -> list[dict]:
        if live_only:
            where_clause = (
                "WHERE closed_at IS NULL "
                "AND claude_uuid IS NOT NULL "
                f"AND last_heartbeat > NOW() - INTERVAL '{within_min} minutes' "
            )
        else:
            where_clause = (
                f"WHERE last_heartbeat > NOW() - INTERVAL '{within_min} minutes' "
            )
        sql = (
            "SELECT id, project, working_on, "
            "EXTRACT(EPOCH FROM started_at)::bigint AS started_at, "
            "EXTRACT(EPOCH FROM last_heartbeat)::bigint AS last_heartbeat, "
            "claude_pid, claude_uuid, terminal_tty "
            "FROM sessions "
            + where_clause +
            "ORDER BY started_at DESC;"
        )
        proc = self._psql(sql, timeout=5, tabbed=True)
        if proc.returncode != 0:
            raise RuntimeError(f"psql failed: {proc.stderr.strip()[:200]}")
        rows: list[dict] = []
        for line in proc.stdout.strip().split("\n"):
            if not line.strip():
                continue
            parts = line.split("\t")
            if len(parts) < 5:
                continue
            claude_pid_str = parts[5] if len(parts) > 5 else ""
            rows.append({
                "id": parts[0],
                "project": parts[1],
                "working_on": parts[2] if parts[2] else None,
                "started_at": int(parts[3]) if parts[3] else 0,
                "last_heartbeat": int(parts[4]) if parts[4] else 0,
                "claude_pid": int(claude_pid_str) if claude_pid_str.isdigit() else 0,
                "claude_uuid": parts[6] if len(parts) > 6 else "",
                "terminal_tty": parts[7] if len(parts) > 7 else "",
            })
        return rows

    def tombstone_sessions(self, session_ids: list[str]) -> None:
        ids_sql = ",".join(f"'{i}'" for i in session_ids if _safe_session_id(i))
        if not ids_sql:
            return
        gc_sql = (
            "WITH changed AS (UPDATE sessions SET closed_at = NOW() "
            f"WHERE id IN ({ids_sql}) AND closed_at IS NULL RETURNING 1) "
            "SELECT COUNT(*) FROM changed;"
        )
        try:
            proc = self._psql(gc_sql, timeout=3)
        except Exception:
            return  # GC is best-effort
        changed = any(
            line.strip().isdigit() and int(line.strip()) > 0
            for line in (proc.stdout or "").splitlines()
        )
        if proc.returncode == 0 and changed:
            _invalidate_sessions_provider_inventory("claude")
            _invalidate_session_list_caches()

    def collect_rows(
        self,
        since_min: int,
        live_only: bool,
        limit: int,
        *,
        strict: bool = False,
    ) -> list[dict]:
        where = [
            f"last_heartbeat > NOW() - INTERVAL '{since_min} minutes'",
            "claude_uuid IS NOT NULL",
        ]
        if live_only:
            where.insert(0, "closed_at IS NULL")
        sql = (
            "SELECT id, project, working_on, "
            "EXTRACT(EPOCH FROM started_at)::bigint AS started_at, "
            "EXTRACT(EPOCH FROM last_heartbeat)::bigint AS last_heartbeat, "
            "claude_pid, claude_uuid, terminal_tty, "
            "EXTRACT(EPOCH FROM closed_at)::bigint AS closed_at "
            "FROM sessions WHERE " + " AND ".join(where) +
            f" ORDER BY last_heartbeat DESC LIMIT {limit};"
        )
        try:
            proc = self._psql(sql, timeout=5, tabbed=True)
        except Exception:
            if strict:
                raise
            return []
        if proc.returncode != 0:
            if strict:
                raise RuntimeError(
                    f"psql failed: {proc.stderr.strip()[:200]}"
                )
            return []
        rows: list[dict] = []
        for line in proc.stdout.strip().split("\n"):
            if not line.strip():
                continue
            parts = line.split("\t")
            if len(parts) < 8:
                if strict:
                    raise RuntimeError("psql returned a malformed session row")
                continue
            rows.append({
                "id": parts[0],
                "project": parts[1],
                "working_on": parts[2] if parts[2] else None,
                "started_at": int(parts[3] or 0),
                "last_heartbeat": int(parts[4] or 0),
                "claude_pid": int(parts[5]) if parts[5].isdigit() else None,
                "claude_uuid": parts[6] or None,
                "terminal_tty": parts[7] if len(parts) > 7 else "",
                "closed_at": int(parts[8]) if len(parts) > 8 and parts[8].isdigit() else None,
            })
        return rows

    def lookup_field(self, session_id: str, field: str):
        try:
            proc = self._psql(
                f"SELECT {field} FROM sessions WHERE id='{session_id}'",
                timeout=4,
            )
        except Exception:
            return None
        if proc.returncode != 0:
            return None
        return proc.stdout.strip() or None

    def terminal_tty(self, session_id: str) -> str:
        sql = f"SELECT terminal_tty FROM sessions WHERE id = '{session_id}' LIMIT 1"
        try:
            proc = self._psql(sql)
            if proc.returncode != 0:
                return ""
            return proc.stdout.strip() or ""
        except Exception:
            return ""

    def claude_pid(self, session_id: str) -> int:
        sql = f"SELECT claude_pid FROM sessions WHERE id = '{session_id}' LIMIT 1"
        try:
            proc = self._psql(sql)
            if proc.returncode != 0:
                return 0
            out = (proc.stdout or "").strip()
            return int(out) if out.isdigit() else 0
        except Exception:
            return 0

    def session_age_seconds(self, session_id: str):
        sql = (
            f"SELECT EXTRACT(EPOCH FROM (NOW() - started_at)) "
            f"FROM sessions WHERE id = '{session_id}' LIMIT 1"
        )
        try:
            proc = self._psql(sql)
            if proc.returncode != 0:
                return None
            s = (proc.stdout or "").strip()
            return float(s) if s else None
        except Exception:
            return None

    def stale_session_ids(self) -> list[str]:
        sql = (
            "SELECT id FROM sessions "
            "WHERE last_heartbeat < NOW() - INTERVAL '60 minutes' "
            "AND last_heartbeat > NOW() - INTERVAL '24 hours';"
        )
        try:
            proc = self._psql(sql, timeout=5)
        except Exception:
            return []
        if proc.returncode != 0:
            return []
        return [sid.strip() for sid in proc.stdout.strip().split("\n") if sid.strip()]

    def idle_seconds(self, session_id: str) -> int:
        sql = f"SELECT EXTRACT(EPOCH FROM (NOW() - last_heartbeat))::int FROM sessions WHERE id='{session_id}';"
        try:
            proc = self._psql(sql)
        except Exception:
            return 0
        try:
            return int(proc.stdout.strip()) if proc.returncode == 0 else 0
        except ValueError:
            return 0


class ClaudeSessionsSqliteBackend:
    """Claude session reads from the daemon-owned SQLite agent registry —
    the product path. Row shapes are byte-compatible with the Pg backend
    (same dict keys, epoch ints, ''/None conventions) so /sessions payloads
    do not change when the backend flips."""

    name = "sqlite"

    def uuid_for_session(self, session_id: str) -> str:
        row = _agent_registry_get("claude", session_id)
        return str(row.get("claude_uuid") or "") if row else ""

    def session_for_uuid(self, claude_uuid: str) -> str:
        row = _agent_registry_get_by_claude_uuid("claude", claude_uuid)
        return str(row.get("native_id") or "") if row else ""

    def session_record(self, session_id: str) -> dict | None:
        row = _agent_registry_get("claude", session_id)
        if not row:
            return None
        result = dict(row)
        result["provider"] = "claude"
        result["pid"] = int(result.get("pid") or 0)
        return result

    def session_ids_for_uuid(self, claude_uuid: str) -> list[str]:
        if not claude_uuid:
            return []
        try:
            with _agent_registry_conn() as conn:
                rows = conn.execute(
                    "SELECT native_id FROM agent_sessions "
                    "WHERE provider = 'claude' AND claude_uuid = ? "
                    "ORDER BY last_heartbeat DESC",
                    (claude_uuid,),
                ).fetchall()
            return [str(row["native_id"] or "") for row in rows if row["native_id"]]
        except Exception:
            return []

    def delete_registry_record(self, session_id: str) -> bool:
        if not _safe_session_id(session_id):
            return False
        try:
            with _agent_registry_conn() as conn:
                conn.execute(
                    "DELETE FROM agent_sessions WHERE provider = 'claude' AND native_id = ?",
                    (session_id,),
                )
            return True
        except Exception:
            return False

    def worker_stats_rows(self, since_min: int) -> list[tuple[str, str, int]]:
        return [
            (str(row.get("native_id") or ""), str(row.get("project") or ""),
             int(row.get("last_heartbeat") or 0))
            for row in _agent_registry_recent("claude", since_min=since_min, limit=1000)
        ]

    def recent_project_rows(self, within_min: int, limit: int) -> list[tuple[str, int]]:
        projects: dict[str, int] = {}
        for row in _agent_registry_recent("claude", since_min=within_min, limit=1000):
            project = str(row.get("project") or "").strip()
            if not project:
                continue
            hb = int(row.get("last_heartbeat") or 0)
            projects[project] = max(projects.get(project, 0), hb)
        ranked = sorted(projects.items(), key=lambda kv: kv[1], reverse=True)
        return ranked[:max(1, limit)]

    def sessions_rows(self, live_only: bool, within_min: int) -> list[dict]:
        cutoff = _time.time() - max(1, int(within_min)) * 60
        try:
            with _agent_registry_conn() as conn:
                if live_only:
                    source = [
                        dict(row)
                        for row in conn.execute(
                            "SELECT * FROM agent_sessions "
                            "WHERE provider = 'claude' AND closed_at IS NULL "
                            "ORDER BY started_at DESC"
                        ).fetchall()
                    ]
                else:
                    source = [
                        dict(row)
                        for row in conn.execute(
                            "SELECT * FROM agent_sessions "
                            "WHERE provider = 'claude' AND last_heartbeat >= ? "
                            "ORDER BY started_at DESC",
                            (cutoff,),
                        ).fetchall()
                    ]
        except Exception:
            source = []
        if live_only:
            source = [
                row for row in source
                if (
                    row.get("claude_uuid")
                    and float(row.get("last_heartbeat") or 0) > cutoff
                ) or _registry_row_has_live_terminal(row, "claude")
            ]
        rows: list[dict] = []
        for row in source:
            rows.append({
                "id": str(row.get("native_id") or ""),
                "project": str(row.get("project") or ""),
                "working_on": (row.get("working_on") or None),
                "started_at": int(row.get("started_at") or 0),
                "last_heartbeat": int(row.get("last_heartbeat") or 0),
                "claude_pid": int(row.get("pid") or 0),
                "claude_uuid": str(row.get("claude_uuid") or ""),
                "terminal_tty": str(row.get("terminal_tty") or ""),
            })
        return rows

    def tombstone_sessions(self, session_ids: list[str]) -> None:
        for sid in session_ids:
            if _safe_session_id(sid):
                _agent_registry_mark_closed("claude", sid)

    def collect_rows(
        self,
        since_min: int,
        live_only: bool,
        limit: int,
        *,
        strict: bool = False,
    ) -> list[dict]:
        rows: list[dict] = []
        for row in _agent_registry_recent(
            "claude",
            since_min=since_min,
            limit=1000,
            strict=strict,
        ):
            if not row.get("claude_uuid") and not _registry_row_has_live_terminal(row, "claude"):
                continue
            if live_only and row.get("closed_at") is not None:
                continue
            closed_at = row.get("closed_at")
            rows.append({
                "id": str(row.get("native_id") or ""),
                "project": str(row.get("project") or ""),
                "working_on": (row.get("working_on") or None),
                "started_at": int(row.get("started_at") or 0),
                "last_heartbeat": int(row.get("last_heartbeat") or 0),
                "claude_pid": int(row.get("pid")) if row.get("pid") else None,
                "claude_uuid": str(row.get("claude_uuid")) or None,
                "terminal_tty": str(row.get("terminal_tty") or ""),
                "closed_at": int(closed_at) if closed_at else None,
            })
            if len(rows) >= limit:
                break
        return rows

    def lookup_field(self, session_id: str, field: str):
        row = _agent_registry_get("claude", session_id)
        if not row:
            return None
        column = "pid" if field == "claude_pid" else field
        value = row.get(column)
        if value is None:
            return None
        text = str(value).strip()
        return text or None

    def terminal_tty(self, session_id: str) -> str:
        row = _agent_registry_get("claude", session_id)
        return str(row.get("terminal_tty") or "") if row else ""

    def claude_pid(self, session_id: str) -> int:
        row = _agent_registry_get("claude", session_id)
        if not row:
            return 0
        try:
            return int(row.get("pid") or 0)
        except (TypeError, ValueError):
            return 0

    def session_age_seconds(self, session_id: str):
        row = _agent_registry_get("claude", session_id)
        if not row or not row.get("started_at"):
            return None
        return max(0.0, _time.time() - float(row["started_at"]))

    def stale_session_ids(self) -> list[str]:
        now = _time.time()
        return [
            str(row.get("native_id") or "")
            for row in _agent_registry_recent("claude", since_min=60 * 24, limit=1000)
            if now - float(row.get("last_heartbeat") or 0) >= 3600
        ]

    def idle_seconds(self, session_id: str) -> int:
        row = _agent_registry_get("claude", session_id)
        if not row or not row.get("last_heartbeat"):
            return 0
        return int(max(0, _time.time() - float(row["last_heartbeat"])))


_CLAUDE_SESSIONS_PG_BACKEND = ClaudeSessionsPgBackend()
_CLAUDE_SESSIONS_SQLITE_BACKEND = ClaudeSessionsSqliteBackend()


def _claude_sessions_backend():
    if _session_backend() == "sqlite":
        return _CLAUDE_SESSIONS_SQLITE_BACKEND
    return _CLAUDE_SESSIONS_PG_BACKEND


def _lookup_claude_uuid_for_session(session_id: str) -> str:
    session_id = _claude_native_session_id(session_id)
    if not session_id:
        return ""
    canonical_id = _agent_registry_resolve_native_alias("claude", session_id)
    registry_row = _agent_registry_get("claude", canonical_id)
    registry_uuid = str((registry_row or {}).get("claude_uuid") or "")
    return registry_uuid or _claude_sessions_backend().uuid_for_session(canonical_id)


def _lookup_claude_session_for_uuid(claude_uuid: str) -> str:
    claude_uuid = str(claude_uuid or "").strip()
    if not re.fullmatch(r"[A-Za-z0-9_.:-]{1,180}", claude_uuid):
        return ""
    registry_row = _agent_registry_get_by_claude_uuid("claude", claude_uuid)
    if registry_row:
        return str(registry_row.get("native_id") or "")
    return _claude_sessions_backend().session_for_uuid(claude_uuid)


def _start_live_activity_publisher():
    if LiveActivityTurnStatePublisher is None or PUSH_DISPATCHER is None:
        return None
    publisher = LiveActivityTurnStatePublisher(
        turn_state_dir=TURN_STATE_DIR,
        push_dispatcher=PUSH_DISPATCHER,
        claude_uuid_resolver=_lookup_claude_uuid_for_session,
        logger=lambda msg: print(f"[live-activity-publisher] {msg}", file=sys.stderr, flush=True),
    )
    publisher.start()
    return publisher


def _start_push_delivery_retry_worker(
    *,
    dispatcher=None,
    stop_event: threading.Event | None = None,
    interval_seconds: float = PUSH_DELIVERY_RETRY_INTERVAL_SECONDS,
):
    """Own the one process-wide startup and due-time push retry drain."""
    dispatcher = PUSH_DISPATCHER if dispatcher is None else dispatcher
    if dispatcher is None:
        return None
    stop = stop_event or threading.Event()
    wait_seconds = max(0.1, float(interval_seconds))

    def run():
        while not stop.is_set():
            try:
                dispatcher.drain_due_deliveries()
            except Exception as exc:
                print(
                    f"[push-delivery-retry] drain failed: {type(exc).__name__}: {str(exc)[:120]}",
                    file=sys.stderr,
                    flush=True,
                )
            stop.wait(wait_seconds)

    thread = threading.Thread(
        target=run,
        name="pairling-push-delivery-retry",
        daemon=True,
    )
    thread.stop_event = stop
    thread.start()
    return thread


def _start_standard_turn_push_publisher():
    if TurnStateAlertPublisher is None or PUSH_DISPATCHER is None:
        return None
    publisher = TurnStateAlertPublisher(
        turn_state_dir=TURN_STATE_DIR,
        push_dispatcher=PUSH_DISPATCHER,
        claude_session_resolver=_lookup_claude_session_for_uuid,
        device_authorization_fn=(
            DEVICE_REGISTRY.authorization_for_device if DEVICE_REGISTRY is not None else None
        ),
        mac_install_id=getattr(PAIRING_STORE, "install_id", "") if PAIRING_STORE else "",
        logger=lambda msg: print(f"[standard-turn-publisher] {msg}", file=sys.stderr, flush=True),
    )
    publisher.start()
    return publisher


def _start_mac_health_push_publisher():
    if MacHealthAlertPublisher is None or PUSH_DISPATCHER is None:
        return None
    publisher = MacHealthAlertPublisher(
        push_dispatcher=PUSH_DISPATCHER,
        health_snapshot_fn=_mac_health_alert_snapshot,
        logger=lambda msg: print(f"[mac-health-publisher] {msg}", file=sys.stderr, flush=True),
    )
    publisher.start()
    return publisher


def _start_sentinel_push_publisher():
    if SentinelBackgroundEvaluator is None or SENTINEL_NOTIFICATIONS is None or PUSH_DISPATCHER is None:
        return None
    publisher = SentinelBackgroundEvaluator(
        sentinel_center=SENTINEL_NOTIFICATIONS,
        push_dispatcher=PUSH_DISPATCHER,
        worker_stats_fn=lambda: _worker_stats_payload(60),
        human_idle_minutes_fn=_human_idle_minutes,
        token_sessions_fn=lambda: [],
        logger=lambda msg: print(f"[sentinel-publisher] {msg}", file=sys.stderr, flush=True),
    )
    publisher.start()
    return publisher


def _fleet_rows_recompute(now: float) -> list[dict]:
    """Recompute live sessions' active-tier signals without a client poll.

    Faithful to _collect_visible_session_rows for the needs-you and running
    tiers: terminal_attention comes from the same broker snapshot, state from
    the same turn-state file. The attention tier's recent_anomaly is only
    derived during a client read, so a pure-anomaly session with no block and
    no in-flight turn reads as idle here until the next foreground poll — the
    active tiers a glance cares about stay correct."""
    rows: list[dict] = []
    try:
        visible = _visible_agent_provider_ids()
    except Exception:
        visible = {"claude", "codex"}
    if "claude" in visible:
        try:
            base = _claude_sessions_backend().collect_rows(since_min=10, live_only=True, limit=200)
        except Exception:
            base = []
        for raw in base:
            native_id = raw.get("id") or ""
            claude_uuid = raw.get("claude_uuid") or ""
            row: dict = {
                "id": _qualified_session_id("claude", native_id),
                "last_heartbeat": raw.get("last_heartbeat"),
                "closed_at": raw.get("closed_at"),
                "readable_state": raw.get("readable_state"),
            }
            if claude_uuid:
                try:
                    payload = json.loads((TURN_STATE_DIR / f"{claude_uuid}.json").read_text())
                    row["state"] = payload.get("state")
                except Exception:
                    pass
            try:
                caps = _terminal_surface_capabilities(row["id"])
                broker_id = caps.get("broker_id")
                if caps.get("source") == "broker_vt" and broker_id and PTY_BROKER is not None:
                    row["terminal_attention"] = _terminal_attention_from_snapshot(PTY_BROKER.snapshot(broker_id))
            except Exception:
                pass
            rows.append(row)
    if "codex" in visible:
        try:
            for row in _list_codex_sessions(live_only=True, active_within_min=10):
                rows.append(row)
        except Exception:
            pass
    return rows


def _fleet_session_rows() -> list[dict]:
    """Rows for the fleet publisher: the client-enriched scan when it is fresh,
    else an independent recompute so the fleet stays correct while the phone is
    locked and polling nothing."""
    now = _time.time()
    fresh = _fleet_scan_rows_if_fresh(now)
    if fresh is not None:
        return fresh
    return _fleet_rows_recompute(now)


def _fleet_activity_target_signature() -> tuple[str, ...]:
    """Cheap identity of fleet activities that can receive an APNs update."""
    dispatcher = PUSH_DISPATCHER
    if dispatcher is None:
        return ()
    try:
        status = dispatcher.status()
    except Exception as exc:
        raise RuntimeError("fleet push status unavailable") from exc
    if not isinstance(status, dict):
        raise RuntimeError("fleet push status is malformed")
    provider = status.get("provider")
    if isinstance(provider, dict) and not provider.get("configured"):
        return ()
    devices = status.get("devices") if isinstance(status, dict) else []
    targets: set[str] = set()
    for device in devices if isinstance(devices, list) else []:
        if not isinstance(device, dict) or not device.get("live_activity_enabled"):
            continue
        device_id = str(device.get("device_id") or "").strip()
        if not device_id:
            continue
        for activity in device.get("live_activities") or []:
            if (
                not isinstance(activity, dict)
                or activity.get("invalidated_at")
                or str(activity.get("session_id") or "").strip() != FLEET_ACTIVITY_SESSION_ID
            ):
                continue
            registration_id = str(
                activity.get("token_hash") or activity.get("activity_id") or "legacy"
            ).strip()
            targets.add(f"{device_id}:{registration_id}")
    return tuple(sorted(targets))


def _emit_fleet_activity(payload: dict) -> None:
    """Deliver one fleet-summary Live Activity event to every device that has a
    live 'fleet' activity registered. Mirrors the per-session publisher's device
    iteration but pins the session id to the fleet key so the dispatcher resolves
    the fleet push token. active_total == 0 ends the activity; otherwise updates."""
    dispatcher = PUSH_DISPATCHER
    if dispatcher is None:
        raise RuntimeError("fleet push dispatcher unavailable")
    try:
        status = dispatcher.status()
    except Exception as exc:
        raise RuntimeError("fleet push status unavailable during delivery") from exc
    if not isinstance(status, dict):
        raise RuntimeError("fleet push status is malformed during delivery")
    devices = status.get("devices")
    content_state = payload.get("content_state") or {}
    event = "end" if int(payload.get("active_total") or 0) <= 0 else "update"
    attempted = 0
    failures: list[str] = []
    for device in devices if isinstance(devices, list) else []:
        if not isinstance(device, dict) or not device.get("live_activity_enabled"):
            continue
        device_id = str(device.get("device_id") or "").strip()
        if not device_id:
            continue
        has_fleet = any(
            isinstance(a, dict) and not a.get("invalidated_at")
            and str(a.get("session_id") or "").strip() == FLEET_ACTIVITY_SESSION_ID
            for a in (device.get("live_activities") or [])
        )
        if not has_fleet:
            continue
        event_payload = {
            "session_id": FLEET_ACTIVITY_SESSION_ID,
            "event": event,
            "content_state": content_state,
            "event_id": content_state.get("eventId"),
            "stale_seconds": payload.get("stale_seconds"),
        }
        attempted += 1
        try:
            result = dispatcher.record_live_activity_event(device_id=device_id, payload=event_payload)
            if not isinstance(result, dict) or not result.get("ok"):
                outcome = ((result or {}).get("delivery") or {}).get("outcome") if isinstance(result, dict) else None
                failures.append(f"{device_id[:8]}:{outcome or 'delivery_failed'}")
        except Exception as exc:
            failures.append(f"{device_id[:8]}:{type(exc).__name__}")
    if attempted == 0:
        raise RuntimeError("fleet targets changed before delivery")
    if failures:
        raise RuntimeError("fleet delivery failed: " + ",".join(failures))


def _start_fd_watchdog():
    if fd_watchdog is None:
        return None
    return fd_watchdog.start(
        logger=lambda msg: print(f"[fd-watchdog] {msg}", file=sys.stderr, flush=True),
    )


def _start_fleet_activity_publisher():
    if FleetActivityPublisher is None or PUSH_DISPATCHER is None:
        return None
    try:
        interval = max(1.0, float(os.environ.get("PAIRLING_FLEET_ACTIVITY_POLL_S", "4.0")))
    except Exception:
        interval = 4.0
    publisher = FleetActivityPublisher(
        targets_provider=_fleet_activity_target_signature,
        rows_provider=_fleet_session_rows,
        emit=_emit_fleet_activity,
        logger=lambda msg: print(f"[fleet-activity-publisher] {msg}", file=sys.stderr, flush=True),
    )

    def run() -> None:
        while True:
            try:
                publisher.tick()
            except Exception as exc:
                print(f"[fleet-activity-publisher] tick failed: {type(exc).__name__}: {str(exc)[:120]}", file=sys.stderr, flush=True)
            _time.sleep(interval)

    thread = threading.Thread(target=run, name="pairling-fleet-activity", daemon=True)
    thread.start()
    print(f"[fleet-activity-publisher] started (interval {interval:.1f}s)", file=sys.stderr, flush=True)
    return thread


def _tty_key(tty: str) -> str:
    """Return a filesystem-safe key for a Terminal tty path."""
    name = os.path.basename((tty or "").strip())
    if re.match(r"^ttys[0-9]{3,}$", name):
        return name
    return ""


def _terminal_capture_map_path(tty: str) -> Path | None:
    key = _tty_key(tty)
    if not key:
        return None
    return TERMINAL_CAPTURE_MAP_DIR / f"{key}.json"


def _is_terminal_capture_path(path: Path) -> bool:
    try:
        path.resolve().relative_to(TERMINAL_CAPTURE_DIR.resolve())
        return True
    except Exception:
        return False


def _write_terminal_capture_mapping(tty: str, log_path: Path, *, provider: str,
                                    project: str, capture_id: str) -> None:
    map_path = _terminal_capture_map_path(tty)
    if map_path is None or not _is_terminal_capture_path(log_path):
        return
    payload = {
        "tty": tty,
        "provider": provider,
        "project": project,
        "capture_id": capture_id,
        "terminal_log": str(log_path),
        "created_at": _time.time(),
        "backend": "script",
    }
    try:
        TERMINAL_CAPTURE_MAP_DIR.mkdir(parents=True, exist_ok=True)
        tmp = map_path.with_name(f"{map_path.name}.tmp.{os.getpid()}")
        tmp.write_text(json.dumps(payload, sort_keys=True))
        tmp.replace(map_path)
    except Exception:
        pass


def _terminal_capture_for_tty(tty: str, project: str | None = None) -> Path | None:
    map_path = _terminal_capture_map_path(tty)
    if map_path is None or not map_path.is_file():
        return None
    try:
        payload = json.loads(map_path.read_text())
        if project and payload.get("project") != project:
            return None
        raw_path = str(payload.get("terminal_log") or "")
        if not raw_path:
            return None
        path = Path(raw_path)
        if not _is_terminal_capture_path(path):
            return None
        if not path.is_file():
            return None
        return path
    except Exception:
        return None


def _terminal_capture_from_metadata(metadata: dict) -> Path | None:
    raw_path = str(metadata.get("terminal_log") or "")
    if not raw_path:
        return None
    path = Path(raw_path)
    if not _is_terminal_capture_path(path):
        return None
    if not path.is_file():
        return None
    return path


def _terminal_surface_pending_input(rows: list[str]) -> dict | None:
    from terminal_screen_backend import detect_terminal_pending_input

    return detect_terminal_pending_input(rows)


def _terminal_surface_snapshot_from_text(
    *,
    session_id: str,
    source: str,
    text: str,
    columns: int,
    rows: int,
    cursor: dict | None = None,
) -> dict:
    safe_columns = max(1, min(int(columns or 80), 500))
    safe_rows = max(1, min(int(rows or 24), 200))
    text_rows = text.replace("\r\n", "\n").replace("\r", "\n").split("\n")
    if len(text_rows) > safe_rows:
        text_rows = text_rows[-safe_rows:]
    cursor_payload = cursor or {"row": None, "column": None, "visible": False}
    dimensions = {"columns": safe_columns, "rows": safe_rows}
    hash_material = {
        "session_id": session_id,
        "source": source,
        "dimensions": dimensions,
        "rows": text_rows,
        "cursor": cursor_payload,
    }
    screen_hash = hashlib.sha256(json.dumps(hash_material, sort_keys=True).encode()).hexdigest()
    pending = _terminal_surface_pending_input(text_rows)
    payload = {
        "session_id": session_id,
        "source": source,
        "screen_hash": screen_hash,
        "nonce": screen_hash,
        "dimensions": dimensions,
        "rows": text_rows,
        "cursor": cursor_payload,
        "changed_at": _time.time(),
    }
    if pending is not None:
        payload["pending_input"] = pending
    return payload


def _sha256_prefixed(material: dict) -> str:
    return "sha256:" + hashlib.sha256(
        json.dumps(material, sort_keys=True, separators=(",", ":")).encode("utf-8")
    ).hexdigest()


def _terminal_surface_v2_cell_payload(cell) -> dict:
    payload = {"text": str(getattr(cell, "text", ""))}
    width = int(getattr(cell, "width", 1) or 1)
    fg = str(getattr(cell, "fg", "default") or "default")
    bg = str(getattr(cell, "bg", "default") or "default")
    bold = bool(getattr(cell, "bold", False))
    italic = bool(getattr(cell, "italic", False))
    underline = bool(getattr(cell, "underline", False))
    inverse = bool(getattr(cell, "inverse", False))
    link_id = getattr(cell, "link_id", None)
    if width != 1:
        payload["width"] = width
    if fg != "default":
        payload["fg"] = fg
    if bg != "default":
        payload["bg"] = bg
    if bold:
        payload["bold"] = True
    if italic:
        payload["italic"] = True
    if underline:
        payload["underline"] = True
    if inverse:
        payload["inverse"] = True
    if link_id is not None:
        payload["link_id"] = link_id
    return payload


def _terminal_surface_v2_payload_from_state(session_id: str, state) -> dict:
    provider, native_id = _parse_agent_session_ref(session_id)
    row_payloads: list[dict] = []
    links_payload: dict[str, dict] = {}
    for link_id, link_value in (getattr(state, "links", None) or {}).items():
        if isinstance(link_value, dict):
            url = link_value.get("url")
            label = link_value.get("label")
        else:
            url = str(link_value)
            label = None
        links_payload[str(link_id)] = {
            "url": str(url) if url is not None else None,
            "label": str(label) if label is not None else None,
        }
    for row in getattr(state, "visible_rows", ()):
        cells = [_terminal_surface_v2_cell_payload(cell) for cell in getattr(row, "cells", ())]
        row_material = {
            "index": int(getattr(row, "index", 0)),
            "wrapped": bool(getattr(row, "wrapped", False)),
            "cells": cells,
        }
        row_payloads.append({
            "index": row_material["index"],
            "wrapped": row_material["wrapped"],
            "dirty_generation": int(getattr(row, "dirty_generation", 0) or 0),
            "cells_hash": _sha256_prefixed(row_material),
            "cells": cells,
        })
    cursor = getattr(state, "cursor", None)
    cursor_payload = {
        "row": getattr(cursor, "row", None),
        "column": getattr(cursor, "column", None),
        "visible": bool(getattr(cursor, "visible", True)),
        "style": str(getattr(cursor, "style", "block") or "block"),
    }
    dimensions = {
        "rows": int(getattr(state, "rows", 0) or 0),
        "columns": int(getattr(state, "columns", 0) or 0),
    }
    capabilities = list(getattr(state, "capabilities", ()) or ())
    scrollback = {
        "window_start": 0,
        "window_size": len(row_payloads),
        "total_rows": len(row_payloads),
        "truncated_before": False,
    }
    pending_input = getattr(state, "pending_input", None)
    pending_input_detection = getattr(state, "pending_input_detection", None)
    if pending_input_detection is None:
        pending_input_detection = {
            "status": "unknown",
            "parser_version": None,
            "surface": "v2",
            "confidence": None,
            "reason": "detection_metadata_missing",
        }
    pending_input_state = "present" if isinstance(pending_input, dict) else (
        "none" if pending_input_detection.get("status") == "ran" else "unknown"
    )
    hash_material = {
        "schema_version": 2,
        "session_id": session_id,
        "provider": provider,
        "native_id": native_id,
        "source": getattr(state, "source", "broker_vt"),
        "backend": getattr(state, "backend", "pty_broker"),
        "capabilities": capabilities,
        "degraded_reason": getattr(state, "degraded_reason", None),
        "generation": int(getattr(state, "generation", 0) or 0),
        "raw_offset": int(getattr(state, "raw_offset", 0) or 0),
        "dimensions": dimensions,
        "title": getattr(state, "title", None),
        "alternate_screen": bool(getattr(state, "alternate_screen", False)),
        "cursor": cursor_payload,
        "scrollback": scrollback,
        "rows": row_payloads,
        "links": links_payload,
        "pending_input": pending_input,
        "pending_input_state": pending_input_state,
        "pending_input_detection": pending_input_detection,
    }
    screen_hash = _sha256_prefixed(hash_material)
    nonce = _sha256_prefixed({
        "screen_hash": screen_hash,
        "generation": hash_material["generation"],
        "raw_offset": hash_material["raw_offset"],
        "server_salt": TERMINAL_SURFACE_V2_NONCE_SALT,
    })
    return {
        **hash_material,
        "screen_hash": screen_hash,
        "nonce": nonce,
        "changed_at": _time.time(),
        "event_limits": {
            "max_event_bytes": SSE_MAX_EVENT_BYTES,
            "truncated": False,
            "truncation_reason": None,
        },
    }


def _terminal_surface_v2_from_text_snapshot(
    v1: dict,
    *,
    provider: str,
    native_id: str,
    degraded_reason: str | None = None,
) -> dict:
    from terminal_screen_backend import TerminalCell, TerminalCursor, TerminalRow, TerminalScreenState

    rows = tuple(
        TerminalRow(
            index=index,
            cells=tuple(TerminalCell(text=ch) for ch in str(row)),
            wrapped=False,
            dirty_generation=int(v1.get("generation") or 0),
        )
        for index, row in enumerate(v1.get("rows") or [])
    )
    dims = v1.get("dimensions") or {}
    source = str(v1.get("source") or "terminal_app_contents")
    reason = degraded_reason or (
        "terminal_app_contents_is_text_only"
        if source == "terminal_app_contents"
        else "text_snapshot_is_not_cell_grid"
    )
    state = TerminalScreenState(
        rows=int(dims.get("rows") or len(rows) or 0),
        columns=int(dims.get("columns") or 0),
        generation=int(v1.get("generation") or 0),
        raw_offset=0,
        source=source,
        backend="terminal_app" if source == "terminal_app_contents" else "pty_broker_text_snapshot",
        title=None,
        alternate_screen=False,
        cursor=TerminalCursor(row=None, column=None, visible=False),
        visible_rows=rows,
        dirty_row_indexes=tuple(row.index for row in rows),
        capabilities=("text_snapshot",),
        pending_input=v1.get("pending_input"),
        pending_input_detection={
            "status": "ran",
            "parser_version": "terminal_pending_input_text_snapshot_v1",
            "surface": "text_snapshot",
            "confidence": (v1.get("pending_input") or {}).get("confidence") if isinstance(v1.get("pending_input"), dict) else None,
            "reason": reason,
        },
        degraded_reason=reason,
        links=None,
    )
    return _terminal_surface_v2_payload_from_state(_qualified_session_id(provider, native_id), state)


def _terminal_surface_v2_unavailable(*, provider: str, native_id: str, reason: str) -> dict:
    from terminal_screen_backend import TerminalCell, TerminalCursor, TerminalRow, TerminalScreenState

    safe_reason = str(reason or "terminal surface unavailable")[:160]
    message = f"Terminal surface unavailable: {safe_reason}"
    state = TerminalScreenState(
        rows=1,
        columns=max(40, min(len(message), 120)),
        generation=0,
        raw_offset=0,
        source="unavailable",
        backend="unavailable",
        title=None,
        alternate_screen=False,
        cursor=TerminalCursor(row=None, column=None, visible=False),
        visible_rows=(
            TerminalRow(
                index=0,
                cells=(TerminalCell(text=message),),
                wrapped=False,
                dirty_generation=0,
            ),
        ),
        dirty_row_indexes=(0,),
        capabilities=(),
        pending_input=None,
        pending_input_detection={
            "status": "not_applicable",
            "parser_version": None,
            "surface": "v2",
            "confidence": None,
            "reason": safe_reason,
        },
        degraded_reason=safe_reason,
        links=None,
    )
    return _terminal_surface_v2_payload_from_state(_qualified_session_id(provider, native_id), state)


def _direct_terminal_action_profile(
    provider: str,
    registry_row: dict,
    tty: str,
    *,
    allowed: bool = True,
    inventory_live_terminal_rows: list[dict] | None = None,
) -> dict:
    """Expose only the direct Terminal actions whose identity is still proven."""
    read_only = {
        "can_control": False,
        "can_send_text": False,
        "can_interrupt": False,
        "can_terminate": False,
        "control_profile": "read_only",
    }
    if not allowed or provider not in {"claude", "codex", "omp"} or not isinstance(registry_row, dict):
        return read_only
    if registry_row.get("closed_at") is not None:
        return read_only
    if not re.match(r"^/dev/ttys[0-9]{3,}$", tty or ""):
        return read_only
    pid = int(registry_row.get("pid") or registry_row.get("claude_pid") or 0)
    if pid <= 0:
        return read_only
    if inventory_live_terminal_rows is not None and provider in {"codex", "omp"}:
        matches_inventory = (
            _codex_inventory_registry_process_matches(
                registry_row, inventory_live_terminal_rows
            )
            if provider == "codex"
            else (
                _omp_pairling_pending_terminal(
                    registry_row, inventory_live_terminal_rows
                )
                is not None
                if str(registry_row.get("native_id") or "").startswith("pending-")
                else _omp_inventory_registry_process_matches(
                    registry_row, inventory_live_terminal_rows
                )
            )
        )
        if not matches_inventory:
            return read_only
        return {
            "can_control": False,
            "can_send_text": True,
            "can_interrupt": True,
            "can_terminate": True,
            "control_profile": "direct_terminal_receipted",
        }
    if not _process_alive(pid):
        return read_only
    # Bind the recorded provider process to the exact Terminal tab before
    # advertising any action. A script-backed launch has separate provider and
    # visible-tab ttys, so this proves their current ancestry instead of
    # assuming they are the same device.
    if not _direct_terminal_binding_is_verified(
        registry_row, provider, pid
    ):
        return read_only
    if not _session_signal_target_is_verified(registry_row, provider, pid):
        return read_only
    return {
        "can_control": False,
        "can_send_text": True,
        "can_interrupt": True,
        "can_terminate": True,
        "control_profile": "direct_terminal_receipted",
    }


def _terminal_surface_source(
    raw_session: str,
    *,
    inventory_live_terminal_rows: list[dict] | None = None,
) -> dict:
    provider, native_id = _parse_agent_session_ref(raw_session)
    qualified = _qualified_session_id(provider, native_id) if native_id else ""
    if not native_id:
        return {"available": False, "source": "unavailable", "reason": "bad_session"}
    if not re.fullmatch(r"[a-z0-9_]{1,48}", provider or ""):
        return {"available": False, "source": "unavailable", "reason": "bad_session"}
    if not _provider_supports(provider, "terminal_surface"):
        return {"available": False, "source": "unavailable", "reason": "unsupported_provider"}

    broker_error = ""

    if provider == "codex":
        registry_native_id = _agent_registry_resolve_native_alias("codex", native_id)
        reg = _agent_registry_get("codex", registry_native_id) or {}
        metadata = {}
        try:
            metadata = json.loads(reg.get("metadata_json") or "{}")
            if not isinstance(metadata, dict):
                metadata = {}
        except Exception:
            metadata = {}
        broker_id = str(metadata.get("broker_id") or "").strip()
        if broker_id and PTY_BROKER is not None:
            try:
                session = PTY_BROKER.get(broker_id)
            except Exception as e:
                session = None
                broker_error = str(e)[:160]
            if session is not None and _broker_session_owns_identity(
                session, "codex", native_id
            ):
                try:
                    PTY_BROKER.register_alias(qualified, _broker_session_id(session))
                except Exception:
                    pass
                broker_relation = _broker_runtime_relation()
                current_atomic_control = (
                    broker_relation == "current"
                    and _broker_supports_current_atomic_control(broker_relation)
                )
                draining_interrupt = broker_relation == "stale_deferred"
                return {
                    "available": True,
                    "source": "broker_vt",
                    "reason": "broker_vt",
                    "broker_id": _broker_session_id(session),
                    "tty": _broker_slave_tty(session),
                    "pid": _broker_pid(session),
                    "can_control": current_atomic_control,
                    "can_send_text": current_atomic_control,
                    "can_interrupt": current_atomic_control or draining_interrupt,
                    "can_terminate": current_atomic_control,
                    "control_profile": (
                        "current_atomic_v2"
                        if current_atomic_control
                        else (
                            "draining_broker_interrupt_only"
                            if draining_interrupt
                            else "read_only"
                        )
                    ),
                }
        capture_path = _terminal_capture_from_metadata(metadata)
        if capture_path and capture_path.exists():
            tty = reg.get("terminal_tty") or ""
            if not tty:
                candidates = _codex_terminal_tty_candidates(reg)
                tty = candidates[0] if candidates else ""
            direct_actions = _direct_terminal_action_profile(
                "codex",
                reg,
                tty,
                allowed=not broker_id,
                inventory_live_terminal_rows=inventory_live_terminal_rows,
            )
            return {
                "available": True,
                "source": "script_capture",
                "reason": "script_capture",
                "terminal_log": str(capture_path),
                "tty": tty,
                "pid": int(reg.get("pid") or 0),
                **direct_actions,
            }
        tty = reg.get("terminal_tty") or ""
        if not tty:
            candidates = _codex_terminal_tty_candidates(reg)
            tty = candidates[0] if candidates else ""
        if not tty:
            return {"available": False, "source": "unavailable", "reason": "no_terminal_tty"}
        if not re.match(r"^/dev/ttys[0-9]{3,}$", tty):
            return {"available": False, "source": "unavailable", "reason": "invalid_tty", "tty": tty}
        direct_actions = _direct_terminal_action_profile(
            "codex",
            reg,
            tty,
            allowed=not broker_id,
            inventory_live_terminal_rows=inventory_live_terminal_rows,
        )
        if direct_actions.get("control_profile") == "read_only":
            return {
                "available": False,
                "source": "unavailable",
                "reason": "process_identity_unverified",
                "tty": tty,
                "pid": int(reg.get("pid") or 0),
                **direct_actions,
            }
        return {
            "available": True,
            "source": "terminal_app_contents",
            "reason": "terminal_app_contents",
            "tty": tty,
            "pid": int(reg.get("pid") or 0),
            **direct_actions,
        }

    if provider == "omp":
        reg = _agent_registry_get("omp", native_id) or {}
        metadata = _registry_metadata_from_row(reg)
        broker_id = str(metadata.get("broker_id") or "").strip()
        broker_session = _registry_owned_broker_session(
            "omp", native_id, reg
        )
        if broker_session is not None:
            try:
                PTY_BROKER.register_alias(
                    qualified, _broker_session_id(broker_session)
                )
            except Exception:
                pass
            broker_relation = _broker_runtime_relation()
            current_atomic_control = (
                broker_relation == "current"
                and _broker_supports_current_atomic_control(broker_relation)
            )
            return {
                "available": True,
                "source": "broker_vt",
                "reason": "broker_vt",
                "broker_id": _broker_session_id(broker_session),
                "tty": _broker_slave_tty(broker_session),
                "pid": _broker_pid(broker_session),
                "can_control": current_atomic_control,
                "can_send_text": current_atomic_control,
                "can_interrupt": current_atomic_control,
                "can_terminate": current_atomic_control,
                "control_profile": (
                    "current_atomic_v2"
                    if current_atomic_control
                    else "read_only"
                ),
            }
        tty = str(reg.get("terminal_tty") or "")
        if not re.match(r"^/dev/ttys[0-9]{3,}$", tty):
            return {
                "available": False,
                "source": "unavailable",
                "reason": "invalid_tty" if tty else "no_terminal_tty",
                "tty": tty,
            }
        live_terminal_rows = inventory_live_terminal_rows
        if live_terminal_rows is None:
            inventory = _capture_sessions_provider_inventory("omp")
            if (
                inventory.get("probe_state") == "exact"
                and bool(inventory.get("membership_complete"))
            ):
                live_terminal_rows = list(inventory.get("terminals") or [])
            else:
                live_terminal_rows = []
        identity_matches = (
            _omp_pairling_pending_terminal(reg, live_terminal_rows) is not None
            if native_id.startswith("pending-")
            else _omp_inventory_registry_process_matches(
                reg,
                live_terminal_rows,
                require_direct_control=False,
            )
        )
        if not identity_matches:
            return {
                "available": False,
                "source": "unavailable",
                "reason": "process_identity_unverified",
                "tty": tty,
                "pid": int(reg.get("pid") or 0),
                "can_control": False,
                "can_send_text": False,
                "can_interrupt": False,
                "can_terminate": False,
                "control_profile": "read_only",
            }
        direct_actions = _direct_terminal_action_profile(
            "omp",
            reg,
            tty,
            allowed=not broker_id,
            inventory_live_terminal_rows=live_terminal_rows,
        )
        if direct_actions.get("control_profile") == "read_only":
            return {
                "available": False,
                "source": "unavailable",
                "reason": "process_identity_unverified",
                "tty": tty,
                "pid": int(reg.get("pid") or 0),
                **direct_actions,
            }
        return {
            "available": True,
            "source": "terminal_app_contents",
            "reason": "terminal_app_contents",
            "tty": tty,
            "pid": int(reg.get("pid") or 0),
            **direct_actions,
        }

    if provider == "claude":
        registry_native_id = _agent_registry_resolve_native_alias("claude", native_id)
        reg = _agent_registry_get("claude", registry_native_id) or {}
        metadata = {}
        try:
            metadata = json.loads(reg.get("metadata_json") or "{}")
            if not isinstance(metadata, dict):
                metadata = {}
        except Exception:
            metadata = {}
        broker_id = str(metadata.get("broker_id") or "").strip()
        if broker_id and PTY_BROKER is not None:
            try:
                session = PTY_BROKER.get(broker_id)
            except Exception as e:
                session = None
                broker_error = str(e)[:160]
            if session is not None and _broker_session_owns_identity(
                session, "claude", native_id
            ):
                try:
                    PTY_BROKER.register_alias(qualified, _broker_session_id(session))
                except Exception:
                    pass
                broker_relation = _broker_runtime_relation()
                current_atomic_control = (
                    broker_relation == "current"
                    and _broker_supports_current_atomic_control(broker_relation)
                )
                draining_interrupt = broker_relation == "stale_deferred"
                return {
                    "available": True,
                    "source": "broker_vt",
                    "reason": "broker_vt",
                    "broker_id": _broker_session_id(session),
                    "tty": _broker_slave_tty(session),
                    "pid": _broker_pid(session),
                    "can_control": current_atomic_control,
                    "can_send_text": current_atomic_control,
                    "can_interrupt": current_atomic_control or draining_interrupt,
                    "can_terminate": current_atomic_control,
                    "control_profile": (
                        "current_atomic_v2"
                        if current_atomic_control
                        else (
                            "draining_broker_interrupt_only"
                            if draining_interrupt
                            else "read_only"
                        )
                    ),
                }
        tty = str(reg.get("terminal_tty") or "")
        if not tty:
            return {"available": False, "source": "unavailable", "reason": broker_error or "no_terminal_tty"}
        if not re.match(r"^/dev/ttys[0-9]{3,}$", tty):
            return {"available": False, "source": "unavailable", "reason": "invalid_tty", "tty": tty}
        capture_path = _terminal_capture_for_tty(tty, reg.get("project"))
        if capture_path and capture_path.exists():
            direct_actions = _direct_terminal_action_profile(
                "claude", reg, tty, allowed=not broker_id
            )
            return {
                "available": True,
                "source": "script_capture",
                "reason": "script_capture",
                "terminal_log": str(capture_path),
                "tty": tty,
                "pid": int(reg.get("pid") or 0),
                **direct_actions,
            }
        direct_actions = _direct_terminal_action_profile(
            "claude", reg, tty, allowed=not broker_id
        )
        if direct_actions.get("control_profile") == "read_only":
            return {
                "available": False,
                "source": "unavailable",
                "reason": "process_identity_unverified",
                "tty": tty,
                "pid": int(reg.get("pid") or 0),
                **direct_actions,
            }
        return {
            "available": True,
            "source": "terminal_app_contents",
            "reason": "terminal_app_contents",
            "tty": tty,
            "pid": int(reg.get("pid") or 0),
            **direct_actions,
        }

    return {"available": False, "source": "unavailable", "reason": broker_error or "no_terminal_tty"}


def _terminal_surface_capabilities(
    raw_session: str,
    *,
    inventory_live_terminal_rows: list[dict] | None = None,
) -> dict:
    source = _terminal_surface_source(
        raw_session,
        inventory_live_terminal_rows=inventory_live_terminal_rows,
    )
    capabilities = []
    if source.get("available"):
        capabilities.extend(["terminal_output", "terminal_surface"])
        if source.get("can_control"):
            capabilities.append("terminal_control")
    return {
        **source,
        "capabilities": capabilities,
        "can_surface": bool(source.get("available")),
        "can_control": bool(source.get("can_control") and source.get("available")),
        "can_send_text": bool(source.get("can_send_text") and source.get("available")),
        "can_interrupt": bool(source.get("can_interrupt") and source.get("available")),
        "can_terminate": bool(source.get("can_terminate") and source.get("available")),
    }


def _broker_snapshot_or_none(broker_id: object) -> dict | None:
    if PTY_BROKER is None or not broker_id:
        return None
    try:
        snapshot = PTY_BROKER.snapshot(str(broker_id))
    except Exception:
        return None
    return snapshot if isinstance(snapshot, dict) else None


def _terminal_attention_from_snapshot(snapshot: dict | None) -> dict | None:
    if not snapshot:
        return None
    pending = snapshot.get("pending_input")
    if not isinstance(pending, dict):
        return None

    def cleaned(value: object, max_characters: int) -> str | None:
        if not isinstance(value, str):
            return None
        text = " ".join(_clean_terminal_display_text(value).split()).strip()
        return text[:max_characters] or None

    return {
        "needs_input": True,
        "state": cleaned(pending.get("state"), 64),
        "source": snapshot.get("source"),
        "changed_at": snapshot.get("changed_at"),
        "prompt": cleaned(pending.get("prompt"), 512),
        "confidence": cleaned(pending.get("confidence"), 32),
        "kind": cleaned(pending.get("kind"), 64),
    }


def _session_terminal_title(row: dict) -> str | None:
    def cleaned(value) -> str | None:
        title = re.sub(r"[\x00-\x1f\x7f]+", " ", str(value or ""))
        title = " ".join(title.split()).strip()
        return title[:240] or None

    existing = cleaned(row.get("terminal_title"))
    if existing:
        return existing
    row_metadata_title = cleaned(
        _registry_metadata_from_row(row).get("terminal_title")
    )
    if row_metadata_title:
        return row_metadata_title
    session_id = str(row.get("id") or "").strip()
    provider = str(row.get("provider") or "").strip().lower()
    native_id = str(row.get("native_id") or "").strip()
    if session_id and (not provider or not native_id):
        parsed_provider, parsed_native_id = _parse_agent_session_ref(session_id)
        provider = provider or parsed_provider
        native_id = native_id or parsed_native_id
    registry_row = (
        _agent_registry_get(provider, native_id)
        if provider in {"claude", "codex"} and native_id
        else None
    )
    if registry_row is None:
        tty = str(row.get("terminal_tty") or "").strip()
        if provider in {"claude", "codex"} and tty:
            registry_row = _agent_registry_get_by_tty(provider, tty)
    metadata_title = cleaned(
        _registry_metadata_from_row(registry_row).get("terminal_title")
    )
    if metadata_title:
        return metadata_title
    terminal_capabilities = {
        "terminal_output",
        "terminal_surface",
        "terminal_control",
    }
    if (
        registry_row is None
        and not str(row.get("terminal_tty") or "").strip()
        and not terminal_capabilities.intersection(row.get("capabilities") or [])
    ):
        return None
    if not session_id or PTY_BROKER is None:
        return None
    registry_metadata = _registry_metadata_from_row(registry_row)
    broker_id = str(
        row.get("broker_id") or registry_metadata.get("broker_id") or ""
    ).strip()
    if not broker_id:
        return None
    try:
        broker_session = PTY_BROKER.get(broker_id)
    except Exception:
        return None
    if broker_session is None or not _broker_session_owns_identity(
        broker_session, provider, native_id
    ):
        return None
    snapshot = _broker_snapshot_or_none(broker_id)
    return cleaned((snapshot or {}).get("title"))


def _truth_issue(code: str, severity: str, user_message: str, *, detail: str | None = None,
                 sources: list[str] | None = None, blocks_control: bool = False) -> dict:
    payload = {
        "code": code,
        "severity": severity,
        "user_message": user_message,
        "blocks_control": bool(blocks_control),
    }
    if detail:
        payload["detail"] = detail
    if sources:
        payload["sources"] = sources
    return payload


def _surface_pending_input_state(surface: dict | None, *, version: str) -> str:
    if not isinstance(surface, dict):
        return "unknown"
    if isinstance(surface.get("pending_input"), dict):
        return "present"
    if version == "v2":
        state = str(surface.get("pending_input_state") or "").strip()
        if state in {"present", "none", "unknown", "omitted"}:
            return state
        detection = surface.get("pending_input_detection") if isinstance(surface.get("pending_input_detection"), dict) else {}
        return "none" if detection.get("status") == "ran" else "unknown"
    return "none"


def _surface_detection(surface: dict | None, *, version: str) -> dict:
    if isinstance(surface, dict) and isinstance(surface.get("pending_input_detection"), dict):
        return dict(surface["pending_input_detection"])
    if version == "v1":
        parser_ran = isinstance(surface, dict)
        return {
            "status": "ran" if parser_ran else "unknown",
            "parser_version": "terminal_pending_input_v1" if parser_ran else None,
            "surface": "v1",
            "confidence": ((surface or {}).get("pending_input") or {}).get("confidence") if isinstance((surface or {}).get("pending_input"), dict) else None,
            "reason": None if parser_ran else "surface_missing",
        }
    return {
        "status": "unknown",
        "parser_version": None,
        "surface": "v2",
        "confidence": None,
        "reason": "detection_metadata_missing",
    }


def _runtime_freshness_truth(expected_source_revision: str | None = None) -> dict:
    info = _runtime_info_snapshot()
    expected = (
        expected_source_revision
        or os.environ.get("PAIRLING_EXPECTED_SOURCE_REVISION")
        or os.environ.get("PAIRLING_APP_SOURCE_REVISION")
        or ""
    ).strip()
    source_revision = str(info.get("source_revision") or "unknown")
    source_dirty = info.get("source_dirty")
    revision_matches = (
        source_revision == expected
        or (len(source_revision) >= 7 and expected.startswith(source_revision))
        or (len(expected) >= 7 and source_revision.startswith(expected))
    ) if expected and source_revision and source_revision != "unknown" else False
    if expected:
        if not revision_matches:
            if source_dirty is False:
                # A clean tree on a different revision is diagnostic drift,
                # not a hard mismatch. It remains visible in technical truth
                # without making a healthy session look degraded. Dirty trees
                # stay hard mismatches.
                matches = None
                confidence = "revision_drift"
                mismatch_reason = "runtime_revision_drift"
            else:
                matches = False
                confidence = "mismatch"
                mismatch_reason = "runtime_source_mismatch"
        elif source_dirty is True:
            matches = False
            confidence = "mismatch"
            mismatch_reason = "runtime_source_dirty"
        elif source_dirty is None:
            matches = None
            confidence = "unknown"
            mismatch_reason = "runtime_source_dirty_unknown"
        else:
            matches = True
            confidence = "exact_revision" if source_revision == expected else "build_metadata_match"
            mismatch_reason = None
    else:
        matches = None
        confidence = "unknown"
        mismatch_reason = None
    return {
        "runtime_version": info.get("runtime_version"),
        "source_revision": source_revision,
        "branch": info.get("source_branch"),
        "installed_at": info.get("installed_at"),
        "runtime_root": info.get("install_root"),
        "source_dirty": source_dirty,
        "runtime_matches_app_source": matches,
        "runtime_match_confidence": confidence,
        "mismatch_reason": mismatch_reason,
    }


def _session_runtime_truth_from_parts(
    *,
    session_id: str,
    registry: dict | None,
    turn: dict | None,
    transcript: dict | None,
    v1_surface: dict | None,
    v2_surface: dict | None,
    runtime: dict | None,
    stream: dict | None,
    process: dict | None = None,
) -> dict:
    provider, native_id = _parse_agent_session_ref(session_id)
    registry = dict(registry or {})
    process = dict(process or {})
    turn = dict(turn or {})
    transcript = dict(transcript or {})
    runtime = dict(runtime or {})
    stream = dict(stream or {})
    if registry.get("readable_state") == "closed" or registry.get("state") == "terminated":
        turn.update({
            "state": "terminated",
            "source": "registry-closed",
            "observed_at": registry.get("last_seen_at") or turn.get("observed_at"),
        })
    contradictions: list[dict] = []
    degradations: list[dict] = []

    v1_pending_state = _surface_pending_input_state(v1_surface, version="v1")
    v2_pending_state = _surface_pending_input_state(v2_surface, version="v2")
    v1_pending = v1_surface.get("pending_input") if isinstance(v1_surface, dict) else None
    v2_pending = v2_surface.get("pending_input") if isinstance(v2_surface, dict) else None
    v2_detection = _surface_detection(v2_surface, version="v2")
    v2_capabilities = set((v2_surface or {}).get("capabilities") or []) if isinstance(v2_surface, dict) else set()
    terminal_unavailable_reason = None
    terminal_unavailable_sources: list[str] = []
    if isinstance(v2_surface, dict) and v2_surface.get("source") == "unavailable":
        terminal_unavailable_reason = (
            v2_surface.get("degraded_reason")
            or (v2_surface.get("pending_input_detection") or {}).get("reason")
            or terminal_unavailable_reason
        )
        terminal_unavailable_sources.append("terminal_surface_v2")
    if isinstance(v1_surface, dict) and v1_surface.get("source") == "unavailable":
        terminal_unavailable_reason = (
            v1_surface.get("degraded_reason")
            or v1_surface.get("reason")
            or terminal_unavailable_reason
        )
        terminal_unavailable_sources.append("terminal_surface_v1")
    if stream.get("surface_stream_available") is False:
        terminal_unavailable_reason = stream.get("fallback_reason") or terminal_unavailable_reason
        terminal_unavailable_sources.append("terminal_stream")
    v2_renderable = bool(
        isinstance(v2_surface, dict)
        and v2_surface.get("source") != "unavailable"
        and v2_capabilities
        and ({"cells", "text_snapshot"} & v2_capabilities)
    )
    v1_available = isinstance(v1_surface, dict) and v1_surface.get("source") != "unavailable"

    v1_generation = v1_surface.get("generation") if isinstance(v1_surface, dict) else None
    v2_generation = v2_surface.get("generation") if isinstance(v2_surface, dict) else None
    generation_mismatch = bool(
        isinstance(v1_generation, int)
        and not isinstance(v1_generation, bool)
        and isinstance(v2_generation, int)
        and not isinstance(v2_generation, bool)
        and v1_generation != v2_generation
    )
    if v1_available and v2_renderable and generation_mismatch:
        contradictions.append(_truth_issue(
            "terminal_v1_v2_generation_mismatch",
            "error",
            "Terminal state is inconsistent. Refresh the helper before sending input.",
            detail=f"v1 generation {v1_generation} does not match v2 generation {v2_generation}",
            sources=["terminal_surface_v1", "terminal_surface_v2"],
            blocks_control=True,
        ))

    if v1_available and v2_renderable and v1_pending_state != v2_pending_state:
        if "present" in {v1_pending_state, v2_pending_state} and "none" in {v1_pending_state, v2_pending_state}:
            contradictions.append(_truth_issue(
                "terminal_v1_v2_pending_input_mismatch",
                "error",
                "Terminal state is inconsistent. Refresh the helper before sending input.",
                detail="v1 and v2 disagree about pending input",
                sources=["terminal_surface_v1", "terminal_surface_v2"],
                blocks_control=True,
            ))

    stream_source = str(stream.get("source") or stream.get("terminal_source") or "")
    stream_backend = str(stream.get("backend") or stream_source or "unknown")
    stream_live = bool(stream.get("byte_stream_available")) and stream_source in {
        "broker_vt",
        "script_capture",
    }
    if v2_renderable:
        selected_surface = "v2"
        selected = v2_surface or {}
        terminal_backend = str(selected.get("backend") or "unknown")
        surface_agreement = "agree"
    elif v1_available:
        selected_surface = "text_snapshot"
        selected = v1_surface or {}
        terminal_backend = str(selected.get("source") or "unknown")
        surface_agreement = "v2_unavailable"
        degradations.append(_truth_issue(
            "terminal_text_snapshot_fallback",
            "warning",
            "Read only fallback",
            sources=["terminal_surface_v1"],
        ))
    elif stream_live:
        selected_surface = "live_events"
        selected = {
            "source": stream_source,
            "backend": stream_backend,
            "generation": stream.get("generation"),
            "screen_hash": stream.get("screen_hash"),
            "nonce": stream.get("nonce"),
        }
        terminal_backend = stream_backend
        surface_agreement = "v2_unavailable"
        if terminal_unavailable_reason or terminal_unavailable_sources:
            reason_suffix = f" - {terminal_unavailable_reason}" if terminal_unavailable_reason else ""
            degradations.append(_truth_issue(
                "terminal_surface_v2_unavailable",
                "warning",
                f"Using live terminal events{reason_suffix}",
                sources=terminal_unavailable_sources or ["terminal_surface_v2"],
                blocks_control=False,
            ))
    else:
        selected_surface = "none"
        selected = {}
        terminal_backend = "unavailable"
        surface_agreement = "not_applicable"

    if any(issue["code"] == "terminal_v1_v2_generation_mismatch" for issue in contradictions):
        selected_surface = "blocked_by_contradiction"
        terminal_state = "contradictory"
        surface_agreement = "render_mismatch"
    elif any(issue["code"] == "terminal_v1_v2_pending_input_mismatch" for issue in contradictions):
        selected_surface = "blocked_by_contradiction"
        terminal_state = "contradictory"
        surface_agreement = "pending_input_mismatch"
    elif selected_surface == "v2" and v2_detection.get("status") not in {"ran", "not_applicable"}:
        terminal_state = "degraded"
        degradations.append(_truth_issue(
            "v2_pending_input_detection_unavailable",
            "warning",
            "Terminal input detection is unavailable on this helper.",
            sources=["terminal_surface_v2"],
            blocks_control=True,
        ))
    elif isinstance(selected.get("pending_input"), dict):
        terminal_state = "needs_input"
    elif selected_surface == "none":
        terminal_state = "unavailable"
        if terminal_unavailable_reason or terminal_unavailable_sources:
            reason_suffix = f" - {terminal_unavailable_reason}" if terminal_unavailable_reason else ""
            degradations.append(_truth_issue(
                "terminal_surface_unavailable",
                "warning",
                f"Terminal unavailable{reason_suffix}",
                sources=terminal_unavailable_sources or ["terminal_surface"],
                blocks_control=True,
            ))
    elif selected.get("degraded_reason"):
        terminal_state = "degraded"
    else:
        terminal_state = "live"

    transcript_state = str(transcript.get("state") or "unknown")
    if transcript_state in {"missing", "unresolvable", "unavailable"}:
        transcript.setdefault("durable", False)
        transcript.setdefault("searchable", False)
        transcript.setdefault("user_message", "Live terminal only - not in transcript")
        degradations.append(_truth_issue(
            f"transcript_{transcript_state}" if transcript_state != "missing" else "transcript_missing",
            "warning",
            str(transcript.get("user_message") or "Live terminal only - not in transcript"),
            sources=["transcript"],
        ))
    else:
        transcript.setdefault("durable", True)
        transcript.setdefault("searchable", True)

    if runtime.get("runtime_matches_app_source") is False:
        runtime_mismatch_code = str(runtime.get("mismatch_reason") or "runtime_source_mismatch")
        runtime_mismatch_message = (
            "Runtime source has uncommitted changes"
            if runtime_mismatch_code == "runtime_source_dirty"
            else "Runtime stale - source mismatch"
        )
        degradations.append(_truth_issue(
            runtime_mismatch_code,
            "warning",
            runtime_mismatch_message,
            sources=["runtime"],
        ))
    elif runtime.get("runtime_match_confidence") == "revision_drift":
        degradations.append(_truth_issue(
            "runtime_revision_drift",
            "warning",
            "Mac runtime is from a different commit than the app",
            sources=["runtime"],
        ))
    elif runtime.get("runtime_matches_app_source") is None or runtime.get("runtime_match_confidence") == "unknown":
        degradations.append(_truth_issue(
            "runtime_source_unknown",
            "warning",
            "Runtime source parity unknown",
            sources=["runtime"],
        ))

    if not process:
        process = {
            "state": "unknown",
            "source": "unverified",
            "reason": "process_truth_not_sampled",
        }
    if process.get("state") in {None, "", "unknown"}:
        degradations.append(_truth_issue(
            "process_truth_missing",
            "warning",
            "Process truth unavailable",
            sources=["process"],
        ))
    elif process.get("state") == "identity_unverified":
        degradations.append(_truth_issue(
            "process_identity_unverified",
            "warning",
            "The recorded process no longer matches this provider session.",
            sources=["process"],
        ))

    native_broker_v2 = bool(
        selected_surface == "v2"
        and selected.get("source") == "broker_vt"
        and selected.get("backend") not in {"pty_broker_text_snapshot", "terminal_app"}
        and "control_receipts" in v2_capabilities
    )
    direct_terminal_actions = bool(
        stream_source in {"terminal_app_contents", "script_capture"}
        and stream.get("control_profile") == "direct_terminal_receipted"
        and any(
            stream.get(name) is True
            for name in ("can_send_text", "can_interrupt", "can_terminate")
        )
    )
    if terminal_state == "contradictory":
        control_state = "blocked"
        blocked_reason = contradictions[0]["code"] if contradictions else "terminal_surface_contradictory"
    elif direct_terminal_actions and selected_surface in {"v2", "text_snapshot", "live_events"}:
        # Terminal.app and script captures are visually text-only, but their
        # direct action profile separately proves the exact provider PID and
        # TTY. A v2 wrapper around that text must not erase those verified
        # controls merely because the visual surface is degraded.
        control_state = "eligible"
        blocked_reason = None
    elif selected_surface == "v2" and terminal_state in {"live", "needs_input"}:
        control_state = "eligible" if (
            native_broker_v2 and selected.get("screen_hash") and selected.get("nonce")
        ) else "read_only"
        blocked_reason = None if control_state == "eligible" else "surface_not_controllable"
    elif selected_surface == "live_events" and terminal_state in {"live", "needs_input"}:
        control_state = "eligible" if direct_terminal_actions else "read_only"
        blocked_reason = None if control_state == "eligible" else "live_events_read_only"
    elif terminal_state == "degraded":
        control_state = "blocked"
        blocked_reason = "terminal_surface_degraded"
    elif selected_surface == "text_snapshot":
        control_state = "eligible" if direct_terminal_actions else "read_only"
        blocked_reason = None if control_state == "eligible" else "text_snapshot_read_only"
    else:
        control_state = "unavailable"
        blocked_reason = "terminal_surface_unavailable"

    registry_control_state = str(registry.get("control_state") or "")
    if control_state == "eligible" and registry_control_state in {"read_only", "unavailable"}:
        control_state = "read_only"
        blocked_reason = "session_control_identity_unverified"
        degradations.append(_truth_issue(
            "session_control_identity_unverified",
            "warning",
            "Session control identity is not verified on this Mac.",
            sources=["registry", "process"],
            blocks_control=True,
        ))

    supported_actions: list[str] = []
    if control_state == "eligible":
        if native_broker_v2:
            supported_actions = ["choice", "text", "key", "interrupt"]
        elif direct_terminal_actions:
            if stream.get("can_send_text") is True:
                supported_actions.append("text")
            if stream.get("can_interrupt") is True:
                supported_actions.append("interrupt")
        process_can_terminate = bool(
            process.get("state") == "alive"
            and process.get("pid")
            and process.get("process_alive") is True
            and process.get("identity_verified") is True
        )
        if process_can_terminate and (
            native_broker_v2 or stream.get("can_terminate") is True
        ):
            supported_actions.append("terminate")
    elif (
        stream.get("source") == "broker_vt"
        and stream.get("can_interrupt") is True
    ):
        # A broker that still owns a live PTY may remain during runtime drain.
        # Ctrl-C is intentionally independent of screen proof. No other write
        # is advertised until the current atomic v2 broker owns the session.
        supported_actions = ["interrupt"]

    control = {
        "state": control_state,
        "basis_surface": selected_surface,
        "schema_version": 2 if selected_surface == "v2" else 1,
        "screen_hash": selected.get("screen_hash"),
        "nonce": selected.get("nonce"),
        "generation": selected.get("generation"),
        "visible_surface_matches_control_basis": control_state == "eligible",
        "blocked_reason": blocked_reason,
        "supported_actions": supported_actions,
    }

    if contradictions:
        primary = "Terminal state inconsistent"
        tone = "error"
    elif terminal_state == "needs_input":
        primary = "Terminal awaiting selection"
        tone = "attention"
    elif runtime.get("runtime_matches_app_source") is False:
        primary = "Runtime stale"
        tone = "warning"
    elif any(issue["code"] == "terminal_surface_unavailable" for issue in degradations):
        primary = str(registry.get("working_on") or "Terminal unavailable")
        tone = "warning"
    elif terminal_state == "degraded" and transcript_state not in {"live", "archived", "stale"}:
        primary = "Terminal degraded"
        tone = "warning"
    elif registry.get("working_on"):
        primary = str(registry.get("working_on"))
        tone = "normal"
    elif transcript_state in {"live", "archived", "stale"}:
        primary = "Live transcript" if transcript_state == "live" else "Transcript available"
        tone = "normal"
    elif terminal_state == "degraded":
        primary = "Terminal degraded"
        tone = "warning"
    elif terminal_state == "live":
        primary = "Live terminal"
        tone = "normal"
    else:
        primary = "Terminal unavailable"
        tone = "muted"
    secondary_parts: list[str] = []
    for issue in degradations:
        if issue["code"] == "terminal_surface_unavailable" and issue.get("user_message"):
            secondary_parts.append(str(issue["user_message"]))
        if issue["code"] == "terminal_surface_v2_unavailable" and issue.get("user_message"):
            secondary_parts.append(str(issue["user_message"]))
    if transcript.get("user_message"):
        secondary_parts.append(str(transcript.get("user_message")))
    secondary = " · ".join(dict.fromkeys(part for part in secondary_parts if part))
    if not secondary and registry.get("readable_state") == "stale":
        secondary = "Registry stale"

    turn["reconciled_role"] = "secondary" if terminal_state in {"needs_input", "contradictory"} else turn.get("reconciled_role", "primary")
    terminal = {
        "state": terminal_state,
        "backend": terminal_backend,
        "selected_surface": selected_surface,
        "surface_agreement": surface_agreement,
        "v1": v1_surface,
        "v2": v2_surface,
        "pending_input": selected.get("pending_input") if selected_surface != "blocked_by_contradiction" else (v1_pending or v2_pending),
        "pending_input_detection": (
            v2_detection
            if selected_surface in {"v2", "blocked_by_contradiction"}
            else (
                {
                    "status": "not_applicable",
                    "parser_version": None,
                    "surface": "live_events",
                    "confidence": None,
                    "reason": "live event stream does not expose pending input semantics",
                }
                if selected_surface == "live_events"
                else _surface_detection(v1_surface, version="v1")
            )
        ),
        "stream": stream,
        "user_message": primary,
    }
    summary_blocks_control = bool(
        control_state == "blocked"
        or any(issue.get("blocks_control") for issue in [*contradictions, *degradations])
    )
    return {
        "schema_version": 1,
        "session_id": session_id,
        "provider": provider,
        "native_id": native_id,
        "project": registry.get("project"),
        "checked_at": _time.time(),
        "runtime": runtime,
        "registry": registry,
        "process": process,
        "turn": turn,
        "transcript": transcript,
        "terminal": terminal,
        "control": control,
        "summary": {
            "primary_label": primary,
            "secondary_label": secondary,
            "tone": tone,
            "requires_attention": terminal_state == "needs_input",
            "blocks_control": summary_blocks_control,
            "selected_surface": selected_surface,
            "degradation_codes": [issue["code"] for issue in degradations],
            "contradiction_codes": [issue["code"] for issue in contradictions],
        },
        "contradictions": contradictions,
        "degradations": degradations,
    }


def _session_runtime_truth_stream_digest(truth: dict) -> str:
    turn = dict(truth.get("turn") or {})
    # Age is derived from wall time. Hash the observed transition itself so a
    # quiet session does not emit a fake state change on every keeper probe.
    turn.pop("age_seconds", None)
    material = {
        "schema_version": truth.get("schema_version"),
        "session_id": truth.get("session_id"),
        "turn": turn,
        "terminal": truth.get("terminal") or {},
        "transcript": truth.get("transcript") or {},
        "runtime": truth.get("runtime") or {},
        "process": truth.get("process") or {},
        "control": truth.get("control") or {},
        "summary": truth.get("summary") or {},
        "contradictions": truth.get("contradictions") or [],
        "degradations": truth.get("degradations") or [],
    }
    return hashlib.sha256(json.dumps(material, sort_keys=True, separators=(",", ":"), default=str).encode()).hexdigest()


def _public_truth_issue(issue: dict) -> dict:
    return {
        key: (
            redact_public_diagnostic(issue.get(key))
            if key in {"detail", "user_message"}
            else issue.get(key)
        )
        for key in (
            "code",
            "severity",
            "user_message",
            "detail",
            "sources",
            "blocks_control",
        )
    }


def _public_session_runtime_truth(truth: dict) -> dict:
    runtime = truth.get("runtime") or {}
    registry = truth.get("registry") or {}
    process = truth.get("process") or {}
    turn = truth.get("turn") or {}
    transcript = truth.get("transcript") or {}
    terminal = truth.get("terminal") or {}
    control = truth.get("control") or {}
    summary = truth.get("summary") or {}
    return {
        "schema_version": truth.get("schema_version"),
        "session_id": truth.get("session_id"),
        "provider": truth.get("provider"),
        "native_id": truth.get("native_id"),
        "checked_at": truth.get("checked_at"),
        "runtime": {
            key: runtime.get(key)
            for key in (
                "runtime_version",
                "source_revision",
                "branch",
                "installed_at",
                "source_dirty",
                "runtime_matches_app_source",
                "runtime_match_confidence",
                "mismatch_reason",
            )
        },
        "registry": {
            key: (
                redact_public_diagnostic(registry.get(key))
                if key == "working_on"
                else registry.get(key)
            )
            for key in (
                "state",
                "readable_state",
                "control_state",
                "working_on",
                "stale_seconds",
                "source_freshness",
                "last_seen_at",
            )
        },
        "process": {
            key: redact_public_diagnostic(process.get(key))
            if key == "reason"
            else process.get(key)
            for key in (
                "state",
                "source",
                "pid",
                "process_alive",
                "registry_state",
                "last_heartbeat",
                "closed_at",
                "terminal_tty",
                "reason",
            )
        },
        "turn": {
            key: turn.get(key)
            for key in (
                "state",
                "source",
                "observed_at",
                "age_seconds",
                "reconciled_role",
            )
        },
        "transcript": {
            key: (
                redact_public_diagnostic(transcript.get(key))
                if key in {"reason", "user_message"}
                else transcript.get(key)
            )
            for key in (
                "state",
                "http_status",
                "reason",
                "durable",
                "searchable",
                "latest_offset",
                "user_message",
            )
        },
        "terminal": {
            key: (
                redact_public_diagnostic(terminal.get(key))
                if key in {"pending_input_detection", "user_message"}
                else terminal.get(key)
            )
            for key in (
                "state",
                "backend",
                "selected_surface",
                "surface_agreement",
                "pending_input",
                "pending_input_detection",
                "user_message",
            )
        },
        "control": {
            key: control.get(key)
            for key in (
                "state",
                "basis_surface",
                "schema_version",
                "screen_hash",
                "nonce",
                "generation",
                "visible_surface_matches_control_basis",
                "blocked_reason",
                "supported_actions",
            )
        },
        "summary": {
            key: (
                redact_public_diagnostic(summary.get(key))
                if key in {"primary_label", "secondary_label"}
                else summary.get(key)
            )
            for key in (
                "primary_label",
                "secondary_label",
                "tone",
                "requires_attention",
                "blocks_control",
                "selected_surface",
                "degradation_codes",
                "contradiction_codes",
            )
        },
        "contradictions": [
            _public_truth_issue(issue)
            for issue in (truth.get("contradictions") or [])
            if isinstance(issue, dict)
        ],
        "degradations": [
            _public_truth_issue(issue)
            for issue in (truth.get("degradations") or [])
            if isinstance(issue, dict)
        ],
    }


def _session_runtime_truth_stream_payload(truth: dict) -> dict:
    """Return the path-free, stable truth projection used by public streams."""
    return _public_session_runtime_truth(truth)


def _session_live_truth_events(truth: dict, slim_truth: dict) -> list[tuple[str, dict, str]]:
    """Build the ordered truth events written by the multiplexed live stream."""
    events = [("truth", slim_truth, "session-runtime-truth")]
    turn = slim_truth.get("turn") if isinstance(slim_truth.get("turn"), dict) else {}
    if turn:
        events.append(("turn_state", turn, "turn-state"))
    return events


def _terminal_stream_diagnostics_from_truth(truth: dict) -> dict:
    terminal = truth.get("terminal") or {}
    v1 = terminal.get("v1") or {}
    v2 = terminal.get("v2") or {}
    stream = terminal.get("stream") or {}
    transcript = truth.get("transcript") or {}
    control = truth.get("control") or {}
    return {
        "ok": True,
        "schema_version": 1,
        "session_id": truth.get("session_id"),
        "provider": truth.get("provider"),
        "native_id": truth.get("native_id"),
        "checked_at": _time.time(),
        "selected_source": v2.get("source") or v1.get("source") or "unavailable",
        "selected_backend": terminal.get("backend"),
        "stream": {
            key: stream.get(key)
            for key in (
                "byte_stream_available",
                "surface_stream_available",
                "transcript_stream_available",
                "source",
                "backend",
                "can_control",
                "can_send_text",
                "can_interrupt",
                "can_terminate",
                "control_profile",
                "last_chunk_at",
                "capacity_state",
                "capacity_verified",
            )
        } | {
            "fallback_reason": redact_public_diagnostic(stream.get("fallback_reason"))
        },
        "surfaces": {
            "v1": {
                "available": bool(v1),
                "source": v1.get("source"),
                "generation": v1.get("generation"),
                "pending_input_state": (
                    _surface_pending_input_state(v1, version="v1")
                    if v1 else "unknown"
                ),
            },
            "v2": {
                "available": bool(v2),
                "source": v2.get("source"),
                "generation": v2.get("generation"),
                "screen_hash": v2.get("screen_hash"),
                "nonce": v2.get("nonce"),
                "pending_input_state": (
                    _surface_pending_input_state(v2, version="v2")
                    if v2 else "unknown"
                ),
                "pending_input_detection": redact_public_diagnostic(
                    _surface_detection(v2, version="v2") if v2 else None
                ),
            },
            "agreement": terminal.get("surface_agreement"),
        },
        "transcript": {
            key: transcript.get(key)
            for key in (
                "state",
                "http_status",
                "reason",
                "durable",
                "searchable",
                "latest_offset",
                "user_message",
            )
        },
        "control": {
            key: control.get(key)
            for key in (
                "state",
                "basis_surface",
                "schema_version",
                "generation",
                "screen_hash",
                "nonce",
                "visible_surface_matches_control_basis",
                "blocked_reason",
                "supported_actions",
            )
        },
        "runtime": {
            "source_revision": (truth.get("runtime") or {}).get("source_revision"),
            "runtime_matches_app_source": (
                truth.get("runtime") or {}
            ).get("runtime_matches_app_source"),
        },
        "contradictions": redact_public_diagnostic(
            truth.get("contradictions") or []
        ),
        "degradations": redact_public_diagnostic(
            truth.get("degradations") or []
        ),
    }


def _terminal_workspace_from_truth(truth: dict) -> dict:
    terminal = truth.get("terminal") or {}
    v2 = terminal.get("v2") if isinstance(terminal.get("v2"), dict) else None
    public_truth = _session_runtime_truth_stream_payload(truth)
    workspace = {
        "ok": True,
        "schema_version": 1,
        "session_id": truth.get("session_id"),
        "provider": truth.get("provider"),
        "native_id": truth.get("native_id"),
        "checked_at": _time.time(),
        "truth": public_truth,
        # Terminal rows and cells are user content, not diagnostics. They use
        # their dedicated stable surface schema and are intentionally intact.
        "terminal_surface_v2": v2,
        "diagnostics": _terminal_stream_diagnostics_from_truth(truth),
        "transcript": public_truth["transcript"],
        "control": public_truth["control"],
        "summary": public_truth["summary"],
        "stream_policy": {
            "default_streams": ["terminal-workspace-stream"],
            "included": ["session_runtime_truth", "terminal_surface_v2", "stream_diagnostics", "transcript_truth", "control_basis"],
            "lazy_streams": ["transcript-stream"],
            "fallback_streams": ["terminal-surface-stream", "terminal-stream"],
            "text_snapshot_is_read_only": True,
        },
    }
    return workspace


def _terminal_workspace_stream_digest(workspace: dict) -> str:
    material = {
        "schema_version": workspace.get("schema_version"),
        "session_id": workspace.get("session_id"),
        "truth": workspace.get("truth") or {},
        "terminal_surface_v2": workspace.get("terminal_surface_v2") or {},
        "stream_policy": workspace.get("stream_policy") or {},
    }
    return hashlib.sha256(json.dumps(material, sort_keys=True, separators=(",", ":"), default=str).encode()).hexdigest()


TERMINAL_CONTROL_AUDIT_PATH = HOME / ".claude" / "audit" / "terminal-control.jsonl"
CONTROL_RECEIPT_AUDIT_PATH = HOME / ".claude" / "audit" / "control-receipts.jsonl"
TERMINAL_CONTROL_STALE_SCREEN_CODE = "stale_screen"
_CONTROL_RECEIPT_INSTANCE_ID = secrets.token_hex(16)
_CONTROL_RECEIPT_SCHEMA_LOCK = threading.Lock()
_CONTROL_RECEIPT_BOOTSTRAPPED_PATHS: set[str] = set()
_RECEIPTED_REQUEST_LOCAL = threading.local()
TERMINAL_CONTROL_ALLOWED_KEYS = {
    "enter",
    "escape",
    "up",
    "down",
    "left",
    "right",
    "tab",
    "ctrl_c",
}
TERMINAL_CONTROL_TEXT_MAX_CHARS = TERMINAL_TEXT_SUBMIT_MAX_CHARS
_RECEIPT_EXECUTION_STATES = frozenset({
    "queued",
    "running",
    "succeeded",
    "failed",
    "indeterminate",
})
_RECEIPT_TERMINAL_EXECUTION_STATES = frozenset({
    "succeeded",
    "failed",
    "indeterminate",
})
_RECEIPT_EXECUTION_TRANSITIONS = {
    "queued": frozenset({"running", "failed", "indeterminate"}),
    "running": frozenset({"succeeded", "failed", "indeterminate"}),
    "indeterminate": frozenset(),
    "succeeded": frozenset(),
    "failed": frozenset(),
}

def _receipt_action_requires_running(action_kind: str) -> bool:
    normalized = str(action_kind or "").strip()
    return (
        normalized == "send_text"
        or normalized == "terminal_control"
        or normalized.startswith("terminal_input_")
        or normalized.startswith("provider_control:")
        or normalized.startswith("provider_operation:")
    )


def _receipt_execution_state(receipt: dict | None) -> str:
    receipt = receipt if isinstance(receipt, dict) else {}
    explicit = str(receipt.get("execution_state") or "").strip().lower()
    if explicit in _RECEIPT_EXECUTION_STATES:
        return explicit
    # Legacy phase/state fields do not prove that a side effect crossed the
    # durable running boundary or reached a terminal outcome.
    return "indeterminate"

def _execution_state_for_current_receipt_state(state: str) -> str:
    try:
        return {
            "received": "queued",
            "validated": "running",
            "applied": "succeeded",
            "rejected": "failed",
            "failed": "failed",
            "indeterminate": "indeterminate",
        }[str(state or "").strip().lower()]
    except KeyError as exc:
        raise ValueError(f"unsupported receipt state: {state}") from exc


def _receipt_legacy_state(execution_state: str, *, failed_state: str = "failed") -> str:
    return {
        "queued": "received",
        "running": "validated",
        "succeeded": "applied",
        "failed": "rejected" if failed_state == "rejected" else "failed",
        "indeterminate": "indeterminate",
    }[execution_state]


def _receipt_transition_allowed(current: str, next_state: str) -> bool:
    return (
        current == next_state
        or next_state in _RECEIPT_EXECUTION_TRANSITIONS.get(current, ())
    )



def _receipt_body_hash(material) -> str:
    if isinstance(material, bytes):
        data = material
    elif isinstance(material, str):
        data = material.encode()
    else:
        data = json.dumps(material, sort_keys=True).encode()
    return hashlib.sha256(data).hexdigest()


def _receipt_key(device_id: str | None, session_id: str, client_action_id: str) -> str:
    normalized_device_id = str(device_id or "").strip()
    if not normalized_device_id:
        raise ValueError("authenticated device_id is required for mutation receipts")
    return "|".join([normalized_device_id, session_id, client_action_id])






def _valid_client_action_id(value: str) -> bool:
    return re.fullmatch(r"[A-Za-z0-9_.:-]{8,128}", str(value or "")) is not None


def _control_receipt_bootstrap_schema(conn: sqlite3.Connection) -> None:
    conn.execute(
        """
        CREATE TABLE IF NOT EXISTS control_action_receipts (
            device_id TEXT NOT NULL,
            session_id TEXT NOT NULL,
            client_action_id TEXT NOT NULL,
            body_hash TEXT NOT NULL,
            action_kind TEXT NOT NULL,
            state TEXT NOT NULL CHECK (state IN ('in_progress', 'final')),
            execution_state TEXT CHECK (
                execution_state IN (
                    'queued', 'running', 'succeeded', 'failed', 'indeterminate'
                )
            ),
            provider_id TEXT,
            provider_version TEXT,
            provider_channel TEXT,
            operation_id TEXT,
            binding_id TEXT,
            capability_generation INTEGER,
            provider_operation_id TEXT,
            provider_cursor TEXT,
            recovery_correlation_json TEXT,
            receipt_json TEXT,
            owner_instance TEXT NOT NULL,
            created_at REAL NOT NULL,
            updated_at REAL NOT NULL,
            PRIMARY KEY (device_id, session_id, client_action_id)
        )
        """
    )
    control_columns = {
        str(row[1])
        for row in conn.execute(
            "PRAGMA table_info(control_action_receipts)"
        ).fetchall()
    }
    control_column_migrations = {
        "execution_state": (
            "TEXT CHECK (execution_state IN "
            "('queued', 'running', 'succeeded', 'failed', 'indeterminate'))"
        ),
        "provider_id": "TEXT",
        "provider_version": "TEXT",
        "provider_channel": "TEXT",
        "operation_id": "TEXT",
        "binding_id": "TEXT",
        "capability_generation": "INTEGER",
        "provider_operation_id": "TEXT",
        "provider_cursor": "TEXT",
        "recovery_correlation_json": "TEXT",
    }
    for column, declaration in control_column_migrations.items():
        if column not in control_columns:
            conn.execute(
                f"ALTER TABLE control_action_receipts "
                f"ADD COLUMN {column} {declaration}"
            )

    legacy_rows = conn.execute(
        "SELECT * FROM control_action_receipts WHERE execution_state IS NULL"
    ).fetchall()
    for row in legacy_rows:
        try:
            receipt = json.loads(row["receipt_json"] or "{}")
        except (TypeError, ValueError, json.JSONDecodeError):
            receipt = {}
        if not isinstance(receipt, dict):
            receipt = {}
        execution_state = "indeterminate"
        receipt = {
            "client_action_id": str(row["client_action_id"]),
            "state": "indeterminate",
            "execution_state": execution_state,
            "deduped": False,
            "idempotent": True,
            "phases": {
                "received": True,
                "validated": False,
                "applied": False,
                "pty_written": None,
                "pty_write_state": "unknown",
            },
            "server_ts": float(row["updated_at"]),
            "http_status": 409,
            "error_code": "action_outcome_unknown",
            "error_message": (
                "this legacy receipt did not record durable execution proof; "
                "check current state before starting a new attempt"
            ),
        }
        storage_state = "final"
        conn.execute(
            "UPDATE control_action_receipts SET state=?, execution_state=?, "
            "receipt_json=? WHERE device_id=? AND session_id=? "
            "AND client_action_id=?",
            (
                storage_state,
                execution_state,
                json.dumps(receipt, sort_keys=True, separators=(",", ":")),
                str(row["device_id"]),
                str(row["session_id"]),
                str(row["client_action_id"]),
            ),
        )
    conn.execute(
        """
        CREATE TABLE IF NOT EXISTS session_live_receipts (
            receipt_seq INTEGER PRIMARY KEY AUTOINCREMENT,
            receipt_revision INTEGER NOT NULL CHECK (receipt_revision >= 1),
            observed_at REAL NOT NULL,
            device_id TEXT NOT NULL,
            session_id TEXT NOT NULL,
            client_action_id TEXT NOT NULL,
            action_kind TEXT NOT NULL,
            action_json TEXT,
            receipt_json TEXT NOT NULL,
            UNIQUE (
                device_id,
                session_id,
                client_action_id,
                action_kind,
                receipt_revision
            )
        )
        """
    )
    receipt_columns = {
        str(row[1])
        for row in conn.execute("PRAGMA table_info(session_live_receipts)").fetchall()
    }
    if "receipt_revision" not in receipt_columns:
        conn.execute("DROP TABLE IF EXISTS session_live_receipts_migrating")
        conn.execute(
            """
            CREATE TABLE session_live_receipts_migrating (
                receipt_seq INTEGER PRIMARY KEY AUTOINCREMENT,
                receipt_revision INTEGER NOT NULL CHECK (receipt_revision >= 1),
                observed_at REAL NOT NULL,
                device_id TEXT NOT NULL,
                session_id TEXT NOT NULL,
                client_action_id TEXT NOT NULL,
                action_kind TEXT NOT NULL,
                action_json TEXT,
                receipt_json TEXT NOT NULL,
                UNIQUE (
                    device_id,
                    session_id,
                    client_action_id,
                    action_kind,
                    receipt_revision
                )
            )
            """
        )
        conn.execute(
            """
            INSERT INTO session_live_receipts_migrating (
                receipt_seq,
                receipt_revision,
                observed_at,
                device_id,
                session_id,
                client_action_id,
                action_kind,
                action_json,
                receipt_json
            )
            SELECT
                receipt_seq,
                1,
                observed_at,
                device_id,
                session_id,
                client_action_id,
                action_kind,
                action_json,
                receipt_json
            FROM session_live_receipts
            ORDER BY receipt_seq ASC
            """
        )
        conn.execute("DROP TABLE session_live_receipts")
        conn.execute(
            "ALTER TABLE session_live_receipts_migrating RENAME TO session_live_receipts"
        )
    conn.execute(
        "CREATE INDEX IF NOT EXISTS session_live_receipts_session_seq "
        "ON session_live_receipts (session_id, receipt_seq)"
    )


@contextmanager
def _control_receipt_conn():
    db_path = str(CONTROL_RECEIPT_DB)
    Path(db_path).parent.mkdir(parents=True, exist_ok=True)
    conn = sqlite3.connect(db_path, timeout=3.0)
    try:
        conn.row_factory = sqlite3.Row
        conn.execute("PRAGMA busy_timeout=3000")
        conn.execute("PRAGMA synchronous=FULL")
        if db_path not in _CONTROL_RECEIPT_BOOTSTRAPPED_PATHS:
            with _CONTROL_RECEIPT_SCHEMA_LOCK:
                if db_path not in _CONTROL_RECEIPT_BOOTSTRAPPED_PATHS:
                    # Changing journal mode takes a database lock. Keep that
                    # one-time transition out of concurrent request setup.
                    conn.execute("PRAGMA journal_mode=WAL")
                    _control_receipt_bootstrap_schema(conn)
                    conn.commit()
                    _CONTROL_RECEIPT_BOOTSTRAPPED_PATHS.add(db_path)
        yield conn
        conn.commit()
    except Exception:
        conn.rollback()
        raise
    finally:
        conn.close()


def _clear_control_receipt_ledger() -> None:
    """Test helper. Production code never discards idempotency evidence."""
    reservations = getattr(_RECEIPTED_REQUEST_LOCAL, "reservations", None)
    if isinstance(reservations, dict):
        reservations.clear()
    if not Path(CONTROL_RECEIPT_DB).exists():
        return
    with _control_receipt_conn() as conn:
        conn.execute("DELETE FROM control_action_receipts")
        conn.execute("DELETE FROM session_live_receipts")
        conn.execute("DELETE FROM sqlite_sequence WHERE name='session_live_receipts'")


def _session_live_receipt_aliases(session_id: str) -> set[str]:
    if ":" not in str(session_id or ""):
        return set()
    provider, native_id = _parse_agent_session_ref(session_id)
    if provider not in _registered_agent_provider_ids() or not _safe_agent_native_id(native_id):
        return set()
    return {_qualified_session_id(provider, native_id)}


def _session_live_receipt_event_from_row(row: sqlite3.Row) -> dict:
    try:
        receipt = json.loads(row["receipt_json"] or "{}")
    except (TypeError, ValueError, json.JSONDecodeError):
        receipt = {}
    try:
        audit_action = json.loads(row["action_json"]) if row["action_json"] else None
    except (TypeError, ValueError, json.JSONDecodeError):
        audit_action = None
    return {
        "receipt_seq": int(row["receipt_seq"]),
        "receipt_revision": int(row["receipt_revision"]),
        "observed_at": float(row["observed_at"]),
        "device_id": str(row["device_id"] or "") or None,
        "session_id": str(row["session_id"]),
        "client_action_id": str(row["client_action_id"] or "") or None,
        "action_kind": str(row["action_kind"]),
        "action": audit_action,
        "receipt": receipt if isinstance(receipt, dict) else {},
    }


def _insert_session_live_receipt(
    conn: sqlite3.Connection,
    *,
    device_id: str | None,
    session_id: str,
    client_action_id: str | None,
    action_kind: str,
    receipt: dict,
    audit_action: dict | None,
) -> tuple[dict, bool]:
    aliases = _session_live_receipt_aliases(session_id)
    if len(aliases) != 1:
        raise ValueError("session live receipt requires a provider-qualified session")
    canonical_session_id = next(iter(aliases))
    observed_at = _time.time()
    normalized_device_id = str(device_id or "")
    normalized_action_id = str(client_action_id or "")
    action_json = (
        json.dumps(audit_action, sort_keys=True, separators=(",", ":"))
        if audit_action is not None
        else None
    )
    receipt_json = json.dumps(receipt, sort_keys=True, separators=(",", ":"))
    latest = conn.execute(
        "SELECT * FROM session_live_receipts "
        "WHERE device_id=? AND session_id=? AND client_action_id=? AND action_kind=? "
        "ORDER BY receipt_revision DESC, receipt_seq DESC LIMIT 1",
        (
            normalized_device_id,
            canonical_session_id,
            normalized_action_id,
            action_kind,
        ),
    ).fetchone()
    next_revision = 1
    if latest is not None:
        try:
            latest_receipt = json.loads(latest["receipt_json"] or "{}")
        except (TypeError, ValueError, json.JSONDecodeError):
            latest_receipt = {}
        latest_execution_state = _receipt_execution_state(latest_receipt)
        next_execution_state = _receipt_execution_state(receipt)
        if latest_execution_state == next_execution_state:
            return _session_live_receipt_event_from_row(latest), False
        valid_transition = _receipt_transition_allowed(
            latest_execution_state,
            next_execution_state,
        )
        if (
            action_kind == "first_prompt_delivery"
            and latest_execution_state == "indeterminate"
            and next_execution_state in {"succeeded", "failed"}
        ):
            # This legacy broker-delivery stream predates durable mutation
            # receipts and can acquire conclusive delivery evidence later.
            valid_transition = True
        if not valid_transition:
            return _session_live_receipt_event_from_row(latest), False
        next_revision = int(latest["receipt_revision"]) + 1

    inserted = conn.execute(
        "INSERT INTO session_live_receipts "
        "(receipt_revision, observed_at, device_id, session_id, client_action_id, "
        "action_kind, action_json, receipt_json) "
        "VALUES (?, ?, ?, ?, ?, ?, ?, ?)",
        (
            next_revision,
            observed_at,
            normalized_device_id,
            canonical_session_id,
            normalized_action_id,
            action_kind,
            action_json,
            receipt_json,
        ),
    )
    row = conn.execute(
        "SELECT * FROM session_live_receipts WHERE receipt_seq=?",
        (int(inserted.lastrowid),),
    ).fetchone()
    if row is None:
        raise sqlite3.DatabaseError("session live receipt insert was not readable")
    return _session_live_receipt_event_from_row(row), True


def _publish_session_live_receipt_event(event: dict) -> None:
    for alias in _session_live_receipt_aliases(str(event.get("session_id") or "")):
        _publish_session_event(f"receipts:{alias}", {
            "type": "receipt_appended",
            "receipt_seq": event["receipt_seq"],
        })


def _append_session_live_control_receipt(
    *,
    device_id: str | None,
    session_id: str,
    client_action_id: str | None,
    action_kind: str,
    receipt: dict,
    audit_action: dict | None = None,
) -> dict:
    with _control_receipt_conn() as conn:
        conn.execute("BEGIN IMMEDIATE")
        event, inserted = _insert_session_live_receipt(
            conn,
            device_id=device_id,
            session_id=session_id,
            client_action_id=client_action_id,
            action_kind=action_kind,
            receipt=receipt,
            audit_action=audit_action,
        )
    if inserted:
        _publish_session_live_receipt_event(event)
    return dict(event)


def _session_live_control_receipts_since(
    session_id: str,
    since_seq: int = 0,
    *,
    identity_keys: set[str] | None = None,
) -> list[dict]:
    aliases: set[str] = set()
    for identity in identity_keys or _session_live_receipt_aliases(session_id):
        aliases.update(_session_live_receipt_aliases(identity))
    if not aliases or not Path(CONTROL_RECEIPT_DB).exists():
        return []
    ordered_aliases = sorted(aliases)
    placeholders = ",".join("?" for _ in ordered_aliases)
    with _control_receipt_conn() as conn:
        rows = conn.execute(
            f"SELECT * FROM session_live_receipts WHERE session_id IN ({placeholders}) "
            "AND receipt_seq > ? ORDER BY receipt_seq ASC LIMIT 500",
            (*ordered_aliases, max(0, int(since_seq or 0))),
        ).fetchall()
    return [_session_live_receipt_event_from_row(row) for row in rows]


def _session_live_pending_input(truth) -> dict | None:
    """SPEC-p3 §2.1: the pending-input payload the live-events loop diffs.

    Extracts terminal.v2.pending_input from the full runtime truth, paired
    with its detection metadata so the phone can gate rendering by
    parser_version. Non-dict shapes are absent, never coerced into a prompt.
    """
    if not isinstance(truth, dict):
        return None
    control = truth.get("control") if isinstance(truth.get("control"), dict) else {}
    if (
        control.get("state") != "eligible"
        or control.get("basis_surface") != "v2"
        or control.get("schema_version") != 2
    ):
        return None
    terminal = truth.get("terminal") if isinstance(truth.get("terminal"), dict) else {}
    v2 = terminal.get("v2") if isinstance(terminal.get("v2"), dict) else {}
    pending = v2.get("pending_input")
    if not isinstance(pending, dict):
        return None
    detection = v2.get("pending_input_detection")
    if not isinstance(detection, dict):
        detection = {
            "status": "unknown",
            "parser_version": None,
            "surface": "v2",
            "confidence": None,
            "reason": "detection_metadata_missing",
        }
    # SPEC-p3 §2.2: the answer goes through the /terminal-control guard
    # chain, so the card needs the proof material of the frame that showed
    # the prompt.
    screen = {
        "screen_hash": v2.get("screen_hash"),
        "nonce": v2.get("nonce"),
        "generation": v2.get("generation"),
    }
    return {
        "pending_input": pending,
        "detection": detection,
        "screen": screen,
        "control": {
            "state": "eligible",
            "basis_surface": "v2",
            "schema_version": 2,
            "supported_actions": list(control.get("supported_actions") or []),
        },
    }


def _session_live_pending_approval(provider: str, native_id: str) -> dict | None:
    """SPEC-p3 §2.4: the oldest open tool approval for this session, shaped
    for the live stream. The CLI blocks on one dialog at a time, so the
    oldest unresolved row is the dialog actually on screen. Pull-based
    guarantee: a dropped push is no longer a missed approval."""
    provider = (provider or "").strip().lower()
    native_id = (native_id or "").strip()
    if not provider or not native_id:
        return None
    try:
        canonical_native_id = str(
            _agent_registry_resolve_native_alias(provider, native_id) or native_id
        ).strip()
    except Exception:
        canonical_native_id = native_id
    identity_values = {native_id, canonical_native_id}
    for identity in _session_event_identity_keys(
        None, _qualified_session_id(provider, canonical_native_id)
    ):
        identity_provider, identity_native_id = _parse_agent_session_ref(identity)
        if identity_provider == provider and identity_native_id:
            identity_values.add(identity_native_id)
            identity_values.add(
                _qualified_session_id(identity_provider, identity_native_id)
            )
    identity_values.add(_qualified_session_id(provider, native_id))
    identity_values.add(_qualified_session_id(provider, canonical_native_id))
    ordered_identities = sorted(value for value in identity_values if value)
    native_placeholders = ", ".join("?" for _ in ordered_identities)
    session_placeholders = ", ".join("?" for _ in ordered_identities)
    try:
        with _agent_registry_conn() as conn:
            row = conn.execute(
                "SELECT * FROM pending_approvals "
                "WHERE provider=? AND state IN ('pending', 'attention') "
                f"AND (native_id IN ({native_placeholders}) "
                f"OR session_id IN ({session_placeholders})) "
                "ORDER BY created_at ASC LIMIT 1",
                (provider, *ordered_identities, *ordered_identities),
            ).fetchone()
    except Exception:
        return None
    if row is None:
        return None
    approval = dict(row)
    try:
        tool_input = json.loads(approval.get("tool_input_json") or "{}")
    except Exception:
        tool_input = {}
    return {
        "request_nonce": approval.get("request_nonce"),
        "provider": approval.get("provider"),
        "tool_name": approval.get("tool_name"),
        "tool_input": tool_input if isinstance(tool_input, dict) else {},
        "command_preview": approval.get("command_preview"),
        "permission_mode": approval.get("permission_mode"),
        "state": approval.get("state"),
        "created_at": approval.get("created_at"),
    }


def _receipt_phases(*, validated: bool, applied: bool, pty_written: bool | None) -> dict:
    phases = {
        "received": True,
        "validated": bool(validated),
        "applied": bool(applied),
    }
    if pty_written is None:
        phases["pty_written"] = None
        phases["pty_write_state"] = "unknown"
    else:
        phases["pty_written"] = bool(pty_written)
    return phases


def _make_action_receipt(
    *,
    client_action_id: str | None,
    state: str,
    execution_state: str | None = None,
    deduped: bool = False,
    idempotent: bool | None = None,
    phases: dict | None = None,
    backend: str | None = None,
    tty: str | None = None,
    pid: int | None = None,
    source_offset_after: int | None = None,
    source_offset_reason: str | None = None,
) -> dict:
    if idempotent is None:
        idempotent = bool(client_action_id)
    if execution_state is None:
        execution_state = _execution_state_for_current_receipt_state(state)
    if execution_state not in _RECEIPT_EXECUTION_STATES:
        raise ValueError(f"unsupported receipt execution state: {execution_state}")
    receipt = {
        "client_action_id": client_action_id,
        "state": state,
        "execution_state": execution_state,
        "deduped": bool(deduped),
        "idempotent": bool(idempotent),
        "phases": phases or _receipt_phases(validated=False, applied=False, pty_written=False),
        "backend": backend,
        "tty": tty,
        "pid": pid,
        "source_offset_after": source_offset_after,
        "source_offset_reason": source_offset_reason,
        "server_ts": _time.time(),
    }
    return {k: v for k, v in receipt.items() if v is not None}


def _receipt_attach_response(
    receipt: dict,
    *,
    http_status: int,
    error_code: str | None = None,
    error_message: str | None = None,
    fields: dict | None = None,
) -> dict:
    receipt["http_status"] = int(http_status)
    if error_code:
        receipt["error_code"] = str(error_code)
    if error_message:
        receipt["error_message"] = str(error_message)
    if fields:
        receipt["response_fields"] = {
            key: value for key, value in fields.items() if value is not None
        }
    return receipt


def _make_send_text_receipt(receipt_context: dict, **kwargs) -> dict:
    receipt = _make_action_receipt(**kwargs)
    boundary = receipt_context.get("confirmation_boundary")
    if isinstance(boundary, dict):
        transcript_offset = boundary.get("transcript_offset")
        log_seq = boundary.get("log_seq")
        log_generation = boundary.get("log_generation")
        if (
            isinstance(transcript_offset, int)
            and isinstance(log_seq, int)
            and isinstance(log_generation, int)
            and log_generation > 0
        ):
            receipt["confirmation_boundary"] = {
                "transcript_offset": max(0, transcript_offset),
                "log_seq": max(0, log_seq),
                "log_generation": log_generation,
            }
    return receipt


def _receipt_replay_response(receipt: dict, base: dict) -> tuple[dict, int]:
    body = dict(base)
    body["receipt"] = receipt
    status = int(receipt.get("http_status") or 200)
    error_code = str(receipt.get("error_code") or "").strip()
    error_message = str(receipt.get("error_message") or "").strip()
    if error_code:
        body["error_code"] = error_code
        body["error"] = {
            "code": error_code,
            "message": error_message or error_code.replace("_", " "),
        }
    response_fields = receipt.get("response_fields")
    if isinstance(response_fields, dict):
        body.update(response_fields)
    return body, status


def _finalize_spawn_action(
    *,
    device_id: str | None,
    provider: str,
    client_action_id: str | None,
    body_hash: str,
    state: str,
    http_status: int,
    backend: str,
    error_code: str | None = None,
    error_message: str | None = None,
    fields: dict | None = None,
) -> dict:
    receipt = _make_action_receipt(
        client_action_id=client_action_id,
        state=state,
        phases=_receipt_phases(
            validated=state != "rejected",
            applied=state == "applied",
            pty_written=False,
        ),
        backend=backend,
    )
    _receipt_attach_response(
        receipt,
        http_status=http_status,
        error_code=error_code,
        error_message=error_message,
        fields=fields,
    )
    _store_action_receipt(
        device_id,
        "spawn_session",
        client_action_id,
        body_hash,
        receipt,
        action_kind="spawn_session",
        audit_action={
            "type": "spawn_session",
            "provider": provider,
            "state": state,
            "error_code": error_code,
        },
    )
    return receipt


def _append_control_receipt_audit(entry: dict) -> None:
    try:
        CONTROL_RECEIPT_AUDIT_PATH.parent.mkdir(parents=True, exist_ok=True)
        with open(CONTROL_RECEIPT_AUDIT_PATH, "a") as f:
            f.write(json.dumps(entry, sort_keys=True) + "\n")
    except Exception:
        pass


def _track_request_receipt_reservation(context: dict) -> None:
    reservations = getattr(_RECEIPTED_REQUEST_LOCAL, "reservations", None)
    if not isinstance(reservations, dict):
        return
    reservations[str(context["reservation_key"])] = dict(context)
def _update_tracked_receipt_reservation(
    reservation_key: str,
    **updates,
) -> None:
    reservations = getattr(_RECEIPTED_REQUEST_LOCAL, "reservations", None)
    if not isinstance(reservations, dict):
        return
    context = reservations.get(reservation_key)
    if isinstance(context, dict):
        context.update(updates)




def _untrack_request_receipt_reservation(reservation_key: str) -> None:
    reservations = getattr(_RECEIPTED_REQUEST_LOCAL, "reservations", None)
    if isinstance(reservations, dict):
        reservations.pop(reservation_key, None)


def _finalize_abandoned_request_receipts(reservations: dict[str, dict]) -> None:
    """Leave queued work reclaimable; fail closed once execution may have started."""
    for reservation_key, context in list(reservations.items()):
        execution_state = str(
            context.get("execution_state") or "queued"
        ).strip().lower()
        if execution_state == "queued":
            reservations.pop(reservation_key, None)
            continue

        receipt = _make_action_receipt(
            client_action_id=context.get("client_action_id"),
            state="indeterminate",
            execution_state="indeterminate",
            phases=_receipt_phases(
                validated=True,
                applied=False,
                pty_written=None,
            ),
        )
        _receipt_attach_response(
            receipt,
            http_status=409,
            error_code="action_outcome_unknown",
            error_message=(
                "execution started but the request stopped before its outcome "
                "was recorded; check current state before starting a new attempt"
            ),
        )
        try:
            _store_action_receipt(
                context.get("device_id"),
                str(context.get("session_id") or ""),
                context.get("client_action_id"),
                str(context.get("body_hash") or ""),
                receipt,
                action_kind=str(context.get("action_kind") or "mutation"),
                audit_action={"type": "abandoned_running_action_reconciled"},
            )
        except Exception as exc:
            _append_control_receipt_audit({
                "ts": _time.time(),
                "device_id": context.get("device_id"),
                "session_id": context.get("session_id"),
                "client_action_id": context.get("client_action_id"),
                "action_kind": context.get("action_kind"),
                "body_hash": context.get("body_hash"),
                "action": {"type": "abandoned_request_reconcile_failed"},
                "persisted": False,
                "error": type(exc).__name__,
                "receipt": receipt,
            })
        finally:
            reservations.pop(reservation_key, None)


@contextmanager
def _receipted_request_scope():
    """Own every mutation reservation created by one request thread."""
    previous = getattr(_RECEIPTED_REQUEST_LOCAL, "reservations", None)
    reservations: dict[str, dict] = {}
    _RECEIPTED_REQUEST_LOCAL.reservations = reservations
    try:
        yield
    finally:
        _finalize_abandoned_request_receipts(reservations)
        if previous is None:
            try:
                delattr(_RECEIPTED_REQUEST_LOCAL, "reservations")
            except AttributeError:
                pass
        else:
            _RECEIPTED_REQUEST_LOCAL.reservations = previous


def _receipt_duplicate_response(
    device_id: str | None,
    session_id: str,
    client_action_id: str,
    body_hash: str,
    *,
    action_kind: str = "control_action",
    recover_uncertain=None,
    reserve_missing: bool = True,
    defer_running: bool = False,
) -> tuple[dict | None, dict | None]:
    if not client_action_id:
        return None, None
    normalized_device_id = str(device_id or "").strip()
    if not normalized_device_id:
        raise ValueError("authenticated device_id is required for mutation receipts")

    reservation_key = (
        _receipt_key(device_id, session_id, client_action_id)
        if reserve_missing
        else ""
    )
    queued_receipt = None
    queued_receipt_json = None
    now = None
    if reserve_missing:
        now = _time.time()
        queued_receipt = _make_action_receipt(
            client_action_id=client_action_id,
            state="received",
            execution_state="queued",
            phases=_receipt_phases(
                validated=False,
                applied=False,
                pty_written=False,
            ),
        )
        queued_receipt_json = json.dumps(
            queued_receipt,
            sort_keys=True,
            separators=(",", ":"),
        )
    inserted_reservation = False
    outbox_event: dict | None = None
    outbox_inserted = False
    existing = None
    try:
        with _control_receipt_conn() as conn:
            if reserve_missing:
                conn.execute("BEGIN IMMEDIATE")
                inserted = conn.execute(
                    "INSERT OR IGNORE INTO control_action_receipts "
                    "(device_id, session_id, client_action_id, body_hash, "
                    "action_kind, state, execution_state, receipt_json, "
                    "owner_instance, created_at, updated_at) "
                    "VALUES (?, ?, ?, ?, ?, 'in_progress', 'queued', ?, ?, ?, ?)",
                    (
                        normalized_device_id,
                        session_id,
                        client_action_id,
                        body_hash,
                        action_kind,
                        queued_receipt_json,
                        _CONTROL_RECEIPT_INSTANCE_ID,
                        now,
                        now,
                    ),
                )
                if inserted.rowcount == 1:
                    inserted_reservation = True
                    if len(_session_live_receipt_aliases(session_id)) == 1:
                        outbox_event, outbox_inserted = _insert_session_live_receipt(
                            conn,
                            device_id=device_id,
                            session_id=session_id,
                            client_action_id=client_action_id,
                            action_kind=action_kind,
                            receipt=queued_receipt,
                            audit_action={"type": "action_queued"},
                        )
            if not inserted_reservation:
                existing = conn.execute(
                    "SELECT * FROM control_action_receipts "
                    "WHERE device_id=? AND session_id=? AND client_action_id=?",
                    (normalized_device_id, session_id, client_action_id),
                ).fetchone()
                if (
                    reserve_missing
                    and existing is not None
                    and existing["execution_state"] == "queued"
                    and existing["body_hash"] == body_hash
                    and existing["action_kind"] == action_kind
                    and existing["owner_instance"]
                    != _CONTROL_RECEIPT_INSTANCE_ID
                ):
                    reclaimed = conn.execute(
                        "UPDATE control_action_receipts "
                        "SET owner_instance=?, receipt_json=?, updated_at=? "
                        "WHERE device_id=? AND session_id=? "
                        "AND client_action_id=? AND execution_state='queued' "
                        "AND owner_instance IS ?",
                        (
                            _CONTROL_RECEIPT_INSTANCE_ID,
                            queued_receipt_json,
                            now,
                            normalized_device_id,
                            session_id,
                            client_action_id,
                            existing["owner_instance"],
                        ),
                    )
                    if reclaimed.rowcount == 1:
                        inserted_reservation = True
                        existing = None
    except (OSError, sqlite3.Error) as exc:
        receipt = _make_action_receipt(
            client_action_id=client_action_id,
            state="indeterminate",
            execution_state="indeterminate",
            deduped=True,
            phases=_receipt_phases(
                validated=False,
                applied=False,
                pty_written=None,
            ),
        )
        return None, {
            "ok": False,
            "session_id": session_id,
            "receipt": receipt,
            "error": {
                "code": "idempotency_unavailable",
                "message": (
                    "action ledger unavailable: "
                    f"{type(exc).__name__}"
                ),
            },
            "status": 503,
        }

    if outbox_inserted and outbox_event is not None:
        _publish_session_live_receipt_event(outbox_event)
    if inserted_reservation:
        _track_request_receipt_reservation({
            "reservation_key": reservation_key,
            "device_id": device_id,
            "session_id": session_id,
            "client_action_id": client_action_id,
            "body_hash": body_hash,
            "action_kind": action_kind,
            "execution_state": "queued",
        })
        return None, None
    if existing is None:
        return None, None
    if existing["body_hash"] != body_hash or existing["action_kind"] != action_kind:
        mismatch = (
            "different content"
            if existing["body_hash"] != body_hash
            else "a different action kind"
        )
        receipt = _make_action_receipt(
            client_action_id=client_action_id,
            state="rejected",
            execution_state="failed",
            deduped=True,
            phases=_receipt_phases(
                validated=False,
                applied=False,
                pty_written=False,
            ),
        )
        return None, {
            "ok": False,
            "session_id": session_id,
            "receipt": receipt,
            "error": {
                "code": "idempotency_conflict",
                "message": (
                    "client_action_id was reused with "
                    f"{mismatch}"
                ),
            },
            "status": 409,
        }

    try:
        stored_receipt = json.loads(existing["receipt_json"] or "{}")
    except (TypeError, ValueError, json.JSONDecodeError):
        stored_receipt = {}
    if not isinstance(stored_receipt, dict):
        stored_receipt = {}
    execution_state = str(
        existing["execution_state"]
        or _receipt_execution_state(stored_receipt)
    )

    if execution_state == "queued":
        if queued_receipt is None:
            queued_receipt = dict(stored_receipt)
            if not queued_receipt:
                queued_receipt = _make_action_receipt(
                    client_action_id=client_action_id,
                    state="received",
                    execution_state="queued",
                    phases=_receipt_phases(
                        validated=False,
                        applied=False,
                        pty_written=False,
                    ),
                )
        queued_receipt["deduped"] = True
        return None, {
            "ok": False,
            "session_id": session_id,
            "receipt": queued_receipt,
            "error": {
                "code": "action_in_progress",
                "message": "an identical action is queued",
            },
            "status": 409,
        }

    if execution_state == "running":
        if defer_running:
            return None, None
        try:
            recovery_correlation = json.loads(
                existing["recovery_correlation_json"] or "{}"
            )
        except (TypeError, ValueError, json.JSONDecodeError):
            recovery_correlation = {}
        if not isinstance(recovery_correlation, dict):
            recovery_correlation = {}
        recovery_context = {
            "device_id": normalized_device_id,
            "receipt_scope": session_id,
            "client_action_id": client_action_id,
            "action_kind": action_kind,
            "execution_state": execution_state,
            "provider_id": existing["provider_id"],
            "provider_version": existing["provider_version"],
            "provider_channel": existing["provider_channel"],
            "operation_id": existing["operation_id"],
            "binding_id": existing["binding_id"],
            "capability_generation": existing["capability_generation"],
            "recovery_correlation": {
                "provider_operation_id": (
                    existing["provider_operation_id"]
                    or recovery_correlation.get("provider_operation_id")
                ),
                "provider_cursor": (
                    existing["provider_cursor"]
                    if existing["provider_cursor"] is not None
                    else recovery_correlation.get("provider_cursor")
                ),
            },
        }
        recovered_receipt = None
        if recover_uncertain:
            try:
                recovered_receipt = recover_uncertain(recovery_context)
            except Exception as exc:
                _append_control_receipt_audit({
                    "ts": _time.time(),
                    "device_id": normalized_device_id,
                    "session_id": session_id,
                    "client_action_id": client_action_id,
                    "action_kind": action_kind,
                    "body_hash": body_hash,
                    "action": {
                        "type": "action_recovery_proof_failed",
                        "error": type(exc).__name__,
                    },
                    "persisted": False,
                })
        if isinstance(recovered_receipt, dict):
            recovered_state = _receipt_execution_state(recovered_receipt)
            if recovered_state not in {"succeeded", "failed"}:
                raise RuntimeError(
                    "proof-only recovery returned a non-conclusive outcome"
                )
            _store_action_receipt(
                device_id,
                session_id,
                client_action_id,
                body_hash,
                recovered_receipt,
                action_kind=action_kind,
                audit_action={"type": "action_recovered_from_provider_proof"},
                allow_owner_takeover=True,
                recovery_only=True,
            )
            result = dict(recovered_receipt)
            result["deduped"] = True
            return result, None

        indeterminate = _make_action_receipt(
            client_action_id=client_action_id,
            state="indeterminate",
            execution_state="indeterminate",
            deduped=True,
            phases=_receipt_phases(
                validated=True,
                applied=False,
                pty_written=None,
            ),
        )
        _receipt_attach_response(
            indeterminate,
            http_status=409,
            error_code="action_outcome_unknown",
            error_message=(
                "the provider could not prove the outcome; check current "
                "state before starting a new attempt"
            ),
        )
        _store_action_receipt(
            device_id,
            session_id,
            client_action_id,
            body_hash,
            indeterminate,
            action_kind=action_kind,
            audit_action={"type": "action_recovery_proof_unavailable"},
            allow_owner_takeover=True,
            recovery_only=True,
        )
        return indeterminate, None

    stored_receipt["execution_state"] = execution_state
    stored_receipt["deduped"] = True
    return stored_receipt, None


def _store_action_receipt(
    device_id: str | None,
    session_id: str,
    client_action_id: str | None,
    body_hash: str,
    receipt: dict,
    *,
    action_kind: str,
    audit_action: dict | None = None,
    persist: bool = True,
    allow_owner_takeover: bool = False,
    recovery_only: bool = False,
) -> None:
    if not isinstance(receipt, dict):
        raise TypeError("receipt must be a dictionary")
    next_execution_state = _receipt_execution_state(receipt)
    if next_execution_state not in _RECEIPT_TERMINAL_EXECUTION_STATES:
        raise RuntimeError("final receipt must have a terminal execution state")
    receipt["execution_state"] = next_execution_state

    outbox_event: dict | None = None
    outbox_inserted = False
    publish_live_receipt = bool(
        client_action_id
        and persist
        and len(_session_live_receipt_aliases(session_id)) == 1
    )
    if client_action_id and persist:
        normalized_device_id = str(device_id or "").strip()
        if not normalized_device_id:
            raise ValueError("authenticated device_id is required for mutation receipts")
        now = _time.time()
        reservation_key = _receipt_key(device_id, session_id, client_action_id)
        stored_durably = False
        try:
            with _control_receipt_conn() as conn:
                conn.execute("BEGIN IMMEDIATE")
                existing = conn.execute(
                    "SELECT * FROM control_action_receipts "
                    "WHERE device_id=? AND session_id=? AND client_action_id=?",
                    (normalized_device_id, session_id, client_action_id),
                ).fetchone()
                if existing is None:
                    conn.execute(
                        "INSERT INTO control_action_receipts "
                        "(device_id, session_id, client_action_id, body_hash, "
                        "action_kind, state, execution_state, receipt_json, "
                        "owner_instance, created_at, updated_at) "
                        "VALUES (?, ?, ?, ?, ?, 'final', ?, ?, ?, ?, ?)",
                        (
                            normalized_device_id,
                            session_id,
                            client_action_id,
                            body_hash,
                            action_kind,
                            next_execution_state,
                            json.dumps(receipt, sort_keys=True),
                            _CONTROL_RECEIPT_INSTANCE_ID,
                            now,
                            now,
                        ),
                    )
                else:
                    if existing["body_hash"] != body_hash:
                        raise RuntimeError(
                            "refusing to overwrite an idempotency receipt "
                            "with different content"
                        )
                    if existing["action_kind"] != action_kind:
                        raise RuntimeError(
                            "refusing to finalize an idempotency receipt "
                            "with a different action kind"
                        )
                    if (
                        existing["owner_instance"] != _CONTROL_RECEIPT_INSTANCE_ID
                        and not allow_owner_takeover
                    ):
                        raise RuntimeError(
                            "refusing to finalize an action reserved by "
                            "another daemon instance"
                        )
                    try:
                        stored_receipt = json.loads(
                            existing["receipt_json"] or "{}"
                        )
                    except (TypeError, ValueError, json.JSONDecodeError) as exc:
                        raise RuntimeError(
                            "refusing to trust an unreadable idempotency receipt"
                        ) from exc
                    if not isinstance(stored_receipt, dict):
                        raise RuntimeError(
                            "refusing to trust a malformed idempotency receipt"
                        )
                    current_execution_state = str(
                        existing["execution_state"]
                        or _receipt_execution_state(stored_receipt)
                    )
                    if (
                        current_execution_state
                        in _RECEIPT_TERMINAL_EXECUTION_STATES
                    ):
                        if (
                            current_execution_state != next_execution_state
                            or stored_receipt != receipt
                        ):
                            raise RuntimeError(
                                "refusing to replace a final idempotency "
                                "receipt with a different outcome"
                            )
                    else:
                        transition_allowed = _receipt_transition_allowed(
                            current_execution_state,
                            next_execution_state,
                        )
                        if (
                            current_execution_state == "queued"
                            and next_execution_state == "succeeded"
                            and not _receipt_action_requires_running(action_kind)
                        ):
                            transition_allowed = True
                        if not transition_allowed:
                            raise RuntimeError(
                                "refusing invalid receipt transition "
                                f"{current_execution_state}->{next_execution_state}"
                            )
                        conn.execute(
                            "UPDATE control_action_receipts "
                            "SET state='final', execution_state=?, "
                            "receipt_json=?, action_kind=?, owner_instance=?, "
                            "updated_at=? WHERE device_id=? AND session_id=? "
                            "AND client_action_id=?",
                            (
                                next_execution_state,
                                json.dumps(receipt, sort_keys=True),
                                action_kind,
                                _CONTROL_RECEIPT_INSTANCE_ID,
                                now,
                                normalized_device_id,
                                session_id,
                                client_action_id,
                            ),
                        )
                if publish_live_receipt:
                    outbox_event, outbox_inserted = _insert_session_live_receipt(
                        conn,
                        device_id=device_id,
                        session_id=session_id,
                        client_action_id=client_action_id,
                        action_kind=action_kind,
                        receipt=receipt,
                        audit_action=audit_action,
                    )
            stored_durably = True
        finally:
            if stored_durably:
                _untrack_request_receipt_reservation(reservation_key)
    _append_control_receipt_audit({
        "ts": _time.time(),
        "device_id": device_id,
        "session_id": session_id,
        "client_action_id": client_action_id,
        "action_kind": action_kind,
        "body_hash": body_hash,
        "action": audit_action,
        "persisted": bool(client_action_id and persist),
        "receipt": receipt,
    })
    if publish_live_receipt and outbox_event is None:
        _append_session_live_control_receipt(
            device_id=device_id,
            session_id=session_id,
            client_action_id=client_action_id,
            action_kind=action_kind,
            audit_action=audit_action,
            receipt=receipt,
        )
    elif outbox_inserted:
        _publish_session_live_receipt_event(outbox_event)


def _mark_receipted_mutation_running(
    context: dict,
    *,
    provider_id: str,
    provider_version: str,
    provider_channel: str,
    operation_id: str,
    binding_id: str,
    capability_generation: int,
    recovery_correlation: dict,
) -> dict:
    """Commit the exactly-once dispatch boundary before the driver call."""
    normalized = {
        "provider_id": str(provider_id or "").strip().lower(),
        "provider_version": str(provider_version or "").strip(),
        "provider_channel": str(provider_channel or "").strip(),
        "operation_id": str(operation_id or "").strip(),
        "binding_id": str(binding_id or "").strip(),
    }
    if not all(normalized.values()):
        raise ValueError(
            "running receipt requires exact provider binding and operation"
        )
    if not isinstance(capability_generation, int) or capability_generation <= 0:
        raise ValueError("running receipt requires a positive capability generation")
    if not isinstance(recovery_correlation, dict):
        raise ValueError("running receipt requires safe recovery correlation")
    provider_operation_id = str(
        recovery_correlation.get("provider_operation_id") or ""
    ).strip()
    provider_cursor_value = recovery_correlation.get("provider_cursor")
    provider_cursor = (
        str(provider_cursor_value).strip()
        if provider_cursor_value is not None
        else None
    )
    if not provider_operation_id or len(provider_operation_id) > 256:
        raise ValueError("running receipt requires a bounded provider operation ID")
    if provider_cursor is not None and len(provider_cursor) > 512:
        raise ValueError("provider recovery cursor is too large")
    safe_correlation = {
        "provider_operation_id": provider_operation_id,
        "provider_cursor": provider_cursor,
    }

    device_id = context.get("device_id")
    session_id = str(context.get("receipt_scope") or "")
    client_action_id = str(context.get("client_action_id") or "")
    body_hash = str(context.get("body_hash") or "")
    action_kind = str(context.get("action_kind") or "mutation")
    normalized_device_id = str(device_id or "").strip()
    if not normalized_device_id or not client_action_id:
        raise ValueError("running receipt requires a durable mutation identity")

    receipt = _make_action_receipt(
        client_action_id=client_action_id,
        state="validated",
        execution_state="running",
        phases=_receipt_phases(
            validated=True,
            applied=False,
            pty_written=False,
        ),
    )
    receipt["provider_operation_id"] = provider_operation_id
    receipt["provider_cursor"] = provider_cursor
    _receipt_attach_response(
        receipt,
        http_status=409,
        error_code="action_in_progress",
        error_message="the provider operation is running",
    )
    outbox_event: dict | None = None
    outbox_inserted = False
    now = _time.time()
    with _control_receipt_conn() as conn:
        conn.execute("BEGIN IMMEDIATE")
        existing = conn.execute(
            "SELECT * FROM control_action_receipts "
            "WHERE device_id=? AND session_id=? AND client_action_id=?",
            (normalized_device_id, session_id, client_action_id),
        ).fetchone()
        if existing is None:
            raise RuntimeError("running receipt has no queued reservation")
        if existing["body_hash"] != body_hash or existing["action_kind"] != action_kind:
            raise RuntimeError("running receipt identity does not match its reservation")
        if existing["owner_instance"] != _CONTROL_RECEIPT_INSTANCE_ID:
            raise RuntimeError("running receipt is owned by another daemon instance")
        if existing["execution_state"] != "queued":
            raise RuntimeError(
                "only a queued receipt may cross the provider dispatch boundary"
            )
        updated = conn.execute(
            "UPDATE control_action_receipts SET execution_state='running', "
            "receipt_json=?, provider_id=?, provider_version=?, "
            "provider_channel=?, operation_id=?, binding_id=?, "
            "capability_generation=?, provider_operation_id=?, "
            "provider_cursor=?, recovery_correlation_json=?, updated_at=? "
            "WHERE device_id=? AND session_id=? AND client_action_id=? "
            "AND execution_state='queued' AND owner_instance=?",
            (
                json.dumps(receipt, sort_keys=True, separators=(",", ":")),
                normalized["provider_id"],
                normalized["provider_version"],
                normalized["provider_channel"],
                normalized["operation_id"],
                normalized["binding_id"],
                capability_generation,
                provider_operation_id,
                provider_cursor,
                json.dumps(
                    safe_correlation,
                    sort_keys=True,
                    separators=(",", ":"),
                ),
                now,
                normalized_device_id,
                session_id,
                client_action_id,
                _CONTROL_RECEIPT_INSTANCE_ID,
            ),
        )
        if updated.rowcount != 1:
            raise RuntimeError("queued receipt ownership changed before dispatch")
        if len(_session_live_receipt_aliases(session_id)) == 1:
            outbox_event, outbox_inserted = _insert_session_live_receipt(
                conn,
                device_id=device_id,
                session_id=session_id,
                client_action_id=client_action_id,
                action_kind=action_kind,
                receipt=receipt,
                audit_action={
                    "type": "action_running",
                    "provider_id": normalized["provider_id"],
                    "operation_id": normalized["operation_id"],
                },
            )
    reservation_key = _receipt_key(device_id, session_id, client_action_id)
    context["running_committed"] = True
    context["execution_state"] = "running"
    _update_tracked_receipt_reservation(
        reservation_key,
        execution_state="running",
        running_committed=True,
    )
    if outbox_inserted and outbox_event is not None:
        _publish_session_live_receipt_event(outbox_event)
    return receipt


def _mark_send_text_running(
    context: dict,
    *,
    provider_id: str,
    binding_id: str,
) -> dict | None:
    """Commit the send dispatch boundary without persisting prompt content."""
    if (
        context.get("action_kind") != "send_text"
        or not context.get("receipt_scope")
    ):
        # Internal helper probes do not own a durable request reservation.
        return None
    boundary = context.get("confirmation_boundary")
    capability_generation = (
        int(boundary.get("log_generation") or 0)
        if isinstance(boundary, dict)
        else 0
    )
    if capability_generation <= 0:
        raise RuntimeError("send_text dispatch requires a durable proof generation")
    client_action_id = str(context.get("client_action_id") or "")
    return _mark_receipted_mutation_running(
        context,
        provider_id=provider_id,
        provider_version="terminal-surface-v2",
        provider_channel=(
            str(binding_id).partition(":")[0].strip() or "terminal"
        ),
        operation_id="session.prompt.send",
        binding_id=binding_id,
        capability_generation=capability_generation,
        recovery_correlation={
            "provider_operation_id": client_action_id,
            "provider_cursor": None,
        },
    )


def _send_receipted_mutation_duplicate(
    handler,
    stored_receipt: dict | None,
    conflict: dict | None,
) -> bool:
    if conflict is not None:
        conflict_code = str((conflict.get("error") or {}).get("code") or "")
        if conflict_code in {"action_in_progress", "action_outcome_unknown"}:
            conflict["outcome_indeterminate"] = True
        handler._send_json(conflict, status=int(conflict["status"]))
        return True
    if stored_receipt is not None:
        body, status = _receipt_replay_response(
            stored_receipt,
            {
                "ok": _receipt_execution_state(stored_receipt) == "succeeded",
                "deduped": True,
            },
        )
        handler._send_json(body, status=status)
        return True
    return False


def _begin_receipted_mutation(
    handler,
    *,
    receipt_scope: str,
    action_kind: str,
    material,
    action_label: str,
    recover_uncertain=None,
) -> dict | None:
    """Reserve one durable mutation before any external side effect."""
    headers = getattr(handler, "headers", {}) or {}
    client_action_id = str(headers.get("X-Pairling-Action-Id") or "").strip()
    if not _valid_client_action_id(client_action_id):
        handler._send_json({
            "ok": False,
            "error": {
                "code": "action_id_required",
                "message": f"A valid X-Pairling-Action-Id is required for {action_label}.",
            },
        }, status=400)
        return None
    device_id = getattr(getattr(handler, "pairling_auth", None), "device_id", None)
    if not isinstance(device_id, str) or not device_id.strip():
        handler._send_json({
            "ok": False,
            "error": {
                "code": "authenticated_device_required",
                "message": "A paired phone identity is required for this action.",
            },
        }, status=401)
        return None
    device_id = device_id.strip()
    body_hash = _receipt_body_hash(material)
    stored_receipt, conflict = _receipt_duplicate_response(
        device_id,
        receipt_scope,
        client_action_id,
        body_hash,
        action_kind=action_kind,
        recover_uncertain=recover_uncertain,
    )
    if _send_receipted_mutation_duplicate(
        handler,
        stored_receipt,
        conflict,
    ):
        return None
    return {
        "device_id": device_id,
        "receipt_scope": receipt_scope,
        "client_action_id": client_action_id,
        "body_hash": body_hash,
        "action_kind": action_kind,
        "execution_state": "queued",
    }


def _finalize_receipted_mutation(
    context: dict,
    *,
    state: str,
    http_status: int,
    backend: str,
    error_code: str | None = None,
    error_message: str | None = None,
    fields: dict | None = None,
    audit_action: dict | None = None,
    pty_written: bool | None = False,
) -> dict:
    receipt = _make_action_receipt(
        client_action_id=context.get("client_action_id"),
        state=state,
        execution_state=_execution_state_for_current_receipt_state(state),
        phases=_receipt_phases(
            validated=state != "rejected",
            applied=state == "applied",
            pty_written=pty_written,
        ),
        backend=backend,
    )
    _receipt_attach_response(
        receipt,
        http_status=http_status,
        error_code=error_code,
        error_message=error_message,
        fields=fields,
    )
    _store_action_receipt(
        context.get("device_id"),
        str(context.get("receipt_scope") or ""),
        context.get("client_action_id"),
        str(context.get("body_hash") or ""),
        receipt,
        action_kind=str(context.get("action_kind") or "mutation"),
        audit_action=audit_action,
    )
    return receipt


def _terminal_control_error(code: str, message: str, status: int) -> dict:
    return {"ok": False, "error": {"code": code, "message": message}, "status": status}


def _terminal_control_session_id(payload: dict, q: dict) -> tuple[str, dict | None]:
    body_session = str(payload.get("session_id") or "").strip()
    query_values = q.get("session", [""]) if isinstance(q, dict) else [""]
    query_session = str((query_values or [""])[0] or "").strip()
    if body_session and query_session and body_session != query_session:
        return "", _terminal_control_error("session_mismatch", "query session must match body session_id", 400)
    raw_session = body_session or query_session
    if not raw_session:
        return "", _terminal_control_error("missing_session", "session_id is required", 400)
    return raw_session, None


def _terminal_control_normalize_action(payload: dict) -> tuple[dict | None, dict | None]:
    raw_action = payload.get("action")
    if raw_action is None:
        raw_action = payload
    if not isinstance(raw_action, dict):
        return None, _terminal_control_error("bad_action", "action must be a JSON object", 400)

    action_type = str(raw_action.get("type") or raw_action.get("kind") or "").strip().lower()
    if action_type == "key":
        key = str(raw_action.get("key") or "").strip().lower()
        if key not in TERMINAL_CONTROL_ALLOWED_KEYS:
            return None, _terminal_control_error("key_not_allowed", "unsupported terminal key", 400)
        return {"type": "key", "key": key}, None

    if action_type == "choice":
        choice_id = str(raw_action.get("choice_id") or raw_action.get("id") or "").strip()
        if not re.match(r"^[A-Za-z0-9_.:-]{1,64}$", choice_id):
            return None, _terminal_control_error("bad_choice", "choice_id must be a stable symbolic id", 400)
        return {"type": "choice", "choice_id": choice_id}, None

    if action_type == "text":
        text = str(raw_action.get("text") or "")
        mode = str(raw_action.get("mode") or "").strip().lower()
        if mode not in {"submit"}:
            return None, _terminal_control_error("bad_text_mode", "text action requires explicit mode=submit", 400)
        text, sanitize_err = _sanitize_terminal_text_input(
            text,
            allow_newline=False,
            max_chars=TERMINAL_CONTROL_TEXT_MAX_CHARS,
        )
        if sanitize_err:
            return None, _terminal_control_error(
                str(sanitize_err["code"]),
                str(sanitize_err["message"]),
                int(sanitize_err["status"]),
            )
        return {"type": "text", "text": text, "mode": mode}, None

    return None, _terminal_control_error("bad_action", "action type must be key, choice, or text", 400)


def _terminal_control_validate_screen(payload: dict, snapshot: dict, action: dict) -> dict | None:
    screen_hash = str(payload.get("screen_hash") or "").strip()
    nonce = str(payload.get("nonce") or "").strip()
    if not screen_hash:
        return _terminal_control_error("missing_screen_hash", "latest screen_hash is required", 409)
    if not nonce:
        return _terminal_control_error("missing_screen_nonce", "latest screen nonce is required", 409)
    if screen_hash != snapshot.get("screen_hash") or nonce != snapshot.get("nonce"):
        return {
            **_terminal_control_error(TERMINAL_CONTROL_STALE_SCREEN_CODE, "terminal screen advanced; refresh before sending control", 409),
            "current_screen_hash": snapshot.get("screen_hash"),
            "current_nonce": snapshot.get("nonce"),
        }
    snapshot_generation = snapshot.get("generation")
    if snapshot_generation is not None:
        payload_generation = payload.get("generation")
        if type(payload_generation) is not int:
            return {
                **_terminal_control_error("bad_generation", "generation must be the current JSON integer", 400),
                "current_generation": snapshot_generation,
            }
        if payload_generation != snapshot_generation:
            return {
                **_terminal_control_error(TERMINAL_CONTROL_STALE_SCREEN_CODE, "terminal generation advanced; refresh before sending control", 409),
                "current_screen_hash": snapshot.get("screen_hash"),
                "current_nonce": snapshot.get("nonce"),
                "current_generation": snapshot_generation,
            }

    if action.get("type") == "choice":
        pending = snapshot.get("pending_input") or {}
        choices = pending.get("choices") if isinstance(pending, dict) else []
        ids = {str(choice.get("id")) for choice in choices if isinstance(choice, dict)}
        if action.get("choice_id") not in ids:
            return _terminal_control_error("choice_unavailable", "choice is not present on the current terminal surface", 409)
    return None


def _terminal_control_surface_schema_version(payload: dict) -> tuple[int, dict | None]:
    raw = payload.get("surface_schema_version")
    if raw is None:
        return 0, _terminal_control_error(
            "surface_schema_version_required",
            "surface_schema_version must be the JSON integer 2",
            400,
        )
    if type(raw) is not int or raw != 2:
        return 0, _terminal_control_error(
            "bad_surface_schema_version",
            "surface_schema_version must be the JSON integer 2",
            400,
        )
    return 2, None


def _terminal_control_v2_availability_error(snapshot: dict) -> dict | None:
    capabilities = set(snapshot.get("capabilities") or [])
    if snapshot.get("source") == "unavailable" or not capabilities:
        return _terminal_control_error("surface_unavailable", "terminal surface is not available for control", 409)
    if snapshot.get("degraded_reason") or "control_receipts" not in capabilities:
        return _terminal_control_error("surface_not_controllable", "terminal surface is read-only; refresh before sending control", 409)
    return None


def _append_terminal_control_audit(entry: dict) -> None:
    try:
        TERMINAL_CONTROL_AUDIT_PATH.parent.mkdir(parents=True, exist_ok=True)
        with open(TERMINAL_CONTROL_AUDIT_PATH, "a") as f:
            f.write(json.dumps(redact_public_diagnostic(entry), sort_keys=True) + "\n")
    except Exception:
        pass


def _terminal_control_audit_action(action: dict | None) -> dict | None:
    if not isinstance(action, dict):
        return None
    if action.get("type") == "text":
        return {
            "type": "text",
            "mode": action.get("mode"),
            "chars": len(str(action.get("text") or "")),
        }
    return dict(action)


def _codex_terminal_capture_for_registry(reg: dict | None) -> Path | None:
    if not reg:
        return None
    try:
        metadata = json.loads(reg.get("metadata_json") or "{}")
    except Exception:
        return None
    return _terminal_capture_from_metadata(metadata)


def _terminal_script_command(log_path: Path, inner_cmd: str, *,
                             interactive_shell: bool = False) -> str:
    TERMINAL_CAPTURE_DIR.mkdir(parents=True, exist_ok=True)
    shell_flag = "-ic" if interactive_shell else "-lc"
    return (
        f"/usr/bin/script -q -F -t 0 {shlex.quote(str(log_path))} "
        f"/bin/zsh {shell_flag} {shlex.quote(inner_cmd)}"
    )


def _qualified_session_id(provider: str, native_id: str) -> str:
    return f"{provider}:{native_id}"


def _turn_state_path(provider: str, native_id: str) -> Path:
    # Claude's state-track hook and the Codex hook bridge both write by
    # provider-native id. Claude native ids are mapped to claude_uuid before
    # this helper is used.
    return TURN_STATE_DIR / f"{native_id}.json"


def _write_agent_turn_state(provider: str, native_id: str, state: str, *,
                            tool: str | None = None, effort: str | None = None,
                            started_at: float | None = None,
                            event: str = "daemon",
                            request_nonce: str | None = None,
                            mac_install_id: str | None = None) -> dict:
    if provider == "codex":
        native_id = _agent_registry_resolve_native_alias(provider, native_id)
    now = _time.time()
    prior: dict = {}
    path = _turn_state_path(provider, native_id)
    try:
        if path.is_file():
            prior = json.loads(path.read_text())
    except Exception:
        prior = {}
    payload = {
        "session_id": (
            native_id
            if provider == "claude"
            else _qualified_session_id(provider, native_id)
        ),
        "state": state,
        "tool": tool,
        "started_at": float(started_at or prior.get("started_at") or now),
        "last_update": now,
        "effort": effort if effort is not None else prior.get("effort"),
        "event": event,
    }
    if request_nonce:
        payload["request_nonce"] = str(request_nonce)
    if mac_install_id:
        payload["mac_install_id"] = str(mac_install_id)
    try:
        TURN_STATE_DIR.mkdir(parents=True, exist_ok=True)
        tmp = path.with_name(f"{path.name}.tmp.{os.getpid()}")
        tmp.write_text(json.dumps(payload, sort_keys=True))
        tmp.replace(path)
    except Exception:
        pass
    _publish_live_activity_turn_state(provider, native_id, payload)
    summary = {
        "type": "turn_state",
        "provider": provider,
        "native_id": native_id,
        "state": state,
        "tool": tool,
        "effort": payload.get("effort"),
        "started_at": payload.get("started_at"),
        "last_update": payload.get("last_update"),
    }
    _publish_session_event(SESSION_SUMMARIES_TOPIC, dict(summary))
    _publish_session_event(f"turn:{provider}:{native_id}", dict(summary))
    return payload


_CODEX_APPROVAL_NONCES: dict[str, str] = {}
_CODEX_APPROVAL_SCREEN_KEYS: dict[str, str] = {}


def _rows_from_broker_snapshot(snapshot: dict | None) -> list[str]:
    if not isinstance(snapshot, dict):
        return []
    rows = snapshot.get("rows")
    if isinstance(rows, list):
        text_rows: list[str] = []
        for row in rows:
            if isinstance(row, str):
                text_rows.append(row)
            elif isinstance(row, dict):
                cells = row.get("cells")
                if isinstance(cells, list):
                    text_rows.append("".join(str(cell.get("text") or "") for cell in cells if isinstance(cell, dict)).rstrip())
        return text_rows
    return []


def _approval_screen_key(snapshot: dict | None) -> str:
    if not isinstance(snapshot, dict):
        return ""
    return ":".join(str(snapshot.get(key) or "") for key in ("screen_hash", "generation", "raw_offset", "nonce"))


def _clear_codex_approval(broker_id: str, session: dict) -> None:
    nonce = _CODEX_APPROVAL_NONCES.pop(broker_id, None)
    _CODEX_APPROVAL_SCREEN_KEYS.pop(broker_id, None)
    native_id = _agent_registry_resolve_native_alias(
        "codex", str(session.get("native_id") or "")
    )
    if nonce:
        row = _pending_approval_get(nonce)
        row_state = str((row or {}).get("state") or "")
        if row_state in {"attention", "pending"}:
            _pending_approval_cas(nonce, row_state, "resolved_local")
    if native_id:
        _write_agent_turn_state("codex", native_id, "idle", event="codex_approval_cleared")


def _scan_codex_approvals_once() -> None:
    if PTY_BROKER is None or classify_codex_approval is None:
        return
    try:
        live = {
            str(session.get("session_id") or ""): session
            for session in PTY_BROKER.list_sessions()
            if isinstance(session, dict)
            and session.get("provider") == "codex"
            and session.get("session_id")
            and session.get("native_id")
        }
    except Exception:
        return
    for broker_id, session in live.items():
        context = _broker_atomic_control_context_for_id(
            broker_id,
            public_session_id=_qualified_session_id(
                "codex", str(session.get("native_id") or "")
            ),
        )
        if context is None:
            continue
        snapshot = context["v2"]
        rows = _rows_from_broker_snapshot(snapshot)
        screen_key = _approval_screen_key(snapshot)
        if _CODEX_APPROVAL_SCREEN_KEYS.get(broker_id) == screen_key and _CODEX_APPROVAL_NONCES.get(broker_id):
            continue
        pending = (snapshot or {}).get("pending_input") if isinstance(snapshot, dict) else None
        if not isinstance(pending, dict):
            pending = None
        approval = classify_codex_approval(pending, rows, screen_key=screen_key)
        if not approval:
            if broker_id in _CODEX_APPROVAL_NONCES:
                _clear_codex_approval(broker_id, session)
            continue
        summary = str(approval.get("summary") or approval.get("command") or "codex approval")[:300]
        dialog_material = "|".join([broker_id, str(approval.get("dialog_key") or screen_key), summary])
        nonce = "codex-scrape-" + hashlib.sha256(dialog_material.encode("utf-8")).hexdigest()[:24]
        _CODEX_APPROVAL_SCREEN_KEYS[broker_id] = screen_key
        if _CODEX_APPROVAL_NONCES.get(broker_id) == nonce:
            continue
        native_id = _agent_registry_resolve_native_alias(
            "codex", str(session.get("native_id") or "")
        )
        _pending_approval_record(
            request_nonce=nonce,
            provider="codex",
            session_id=_qualified_session_id("codex", native_id),
            tool_name="Bash",
            tool_input={"command": str(approval.get("command") or ""), "summary": summary},
            command_preview=summary,
            permission_mode="",
            broker_id=broker_id,
            state="attention",
            screen_proof=snapshot,
        )
        _CODEX_APPROVAL_NONCES[broker_id] = nonce
        _write_agent_turn_state(
            "codex",
            native_id,
            "attention",
            tool=summary[:80],
            event="codex_approval",
            request_nonce=nonce,
            mac_install_id=getattr(PAIRING_STORE, "install_id", "") if PAIRING_STORE else "",
        )
    for broker_id in list(_CODEX_APPROVAL_NONCES.keys()):
        if broker_id not in live:
            _CODEX_APPROVAL_NONCES.pop(broker_id, None)
            _CODEX_APPROVAL_SCREEN_KEYS.pop(broker_id, None)


def _start_codex_approval_scanner() -> threading.Thread | None:
    if PTY_BROKER is None or classify_codex_approval is None:
        return None
    try:
        interval = max(0.25, float(os.environ.get("PAIRLING_CODEX_APPROVAL_POLL_S", "1.0")))
    except Exception:
        interval = 1.0

    def run() -> None:
        while True:
            try:
                _scan_codex_approvals_once()
            except Exception as exc:
                print(f"[codex-approval-scan] skipped: {type(exc).__name__}: {str(exc)[:120]}", file=sys.stderr, flush=True)
            _time.sleep(interval)

    thread = threading.Thread(target=run, name="pairling-codex-approval-scan", daemon=True)
    thread.start()
    return thread


def _publish_live_activity_turn_state(provider: str, native_id: str, payload: dict) -> None:
    publisher = LIVE_ACTIVITY_PUBLISHER
    if publisher is None or not hasattr(publisher, "publish_turn_state_payload"):
        return
    candidates = [_qualified_session_id(provider, native_id), native_id]
    if provider == "claude":
        resolved = _lookup_claude_session_for_uuid(native_id)
        if resolved:
            candidates.insert(0, f"claude:{resolved}")
    seen: set[str] = set()
    for session_id in candidates:
        session_id = str(session_id or "").strip()
        if not session_id or session_id in seen:
            continue
        seen.add(session_id)
        try:
            publisher.publish_turn_state_payload(session_id=session_id, state_payload=payload)
        except Exception:
            continue


def _claude_native_session_id(raw: str) -> str:
    provider, native_id = _parse_agent_session_ref(raw)
    if provider != "claude" or not _safe_session_id(native_id):
        return ""
    return native_id


def _decorate_claude_session_row(row: dict, native_id: str, claude_pid: int = 0,
                                 terminal_tty: str = "") -> dict:
    registry_row = _agent_registry_get("claude", native_id)
    registry_metadata = _registry_metadata_from_row(registry_row)
    if registry_row:
        claude_pid = int(claude_pid or registry_row.get("pid") or 0)
        terminal_tty = str(terminal_tty or registry_row.get("terminal_tty") or "")
    row["provider"] = "claude"
    row["native_id"] = native_id
    row["id"] = _qualified_session_id("claude", native_id)
    row["terminal_tty"] = terminal_tty
    row["pid"] = claude_pid
    surface = _terminal_surface_capabilities(row["id"])
    broker_id = str(
        _durable_broker_id_from_registry_row(
            registry_row,
            provider="claude",
            native_id=native_id,
        )
        or surface.get("broker_id")
        or ""
    ).strip()
    row["broker_id"] = broker_id or None
    send_scope_id = _durable_send_scope_id_from_registry_row(
        registry_row,
        provider="claude",
        native_id=native_id,
    ) or _normalized_send_scope_id("claude", broker_id)
    row["send_scope_id"] = send_scope_id or None
    can_send_text = bool(surface.get("can_send_text"))
    can_interrupt = bool(surface.get("can_interrupt"))
    can_terminate = bool(surface.get("can_terminate"))
    capabilities = [
        capability
        for capability in CLAUDE_SESSION_CAPABILITIES
        if capability not in {"send_text", "interrupt", "terminate"}
    ]
    capabilities.extend(
        capability
        for capability in (surface.get("capabilities") or [])
        if capability not in capabilities
    )
    for capability, enabled in (
        ("send_text", can_send_text),
        ("interrupt", can_interrupt),
        ("terminate", can_terminate),
    ):
        if enabled:
            capabilities.append(capability)
    row["capabilities"] = capabilities
    reason = None
    if surface.get("control_profile") == "draining_broker_interrupt_only":
        reason = "This live terminal is finishing under the previous runtime; only interrupt is available."
    elif not any((can_send_text, can_interrupt, can_terminate)):
        reason = (
            "This terminal is read only in Pairling."
            if surface.get("available")
            else "no terminal_tty for session yet"
        )
    row["controllability"] = {
        "can_send_text": can_send_text,
        "can_interrupt": can_interrupt,
        "can_terminate": can_terminate,
        "reason": reason,
    }
    launch_metadata = registry_metadata
    if terminal_tty and not launch_metadata:
        launch_metadata = _registry_metadata_from_row(
            _agent_registry_get_by_tty("claude", terminal_tty)
        )
    _apply_launch_context_to_session_row(row, launch_metadata)
    return row


def _collapse_live_session_rows_by_terminal(rows: list[dict]) -> list[dict]:
    by_tty: dict[tuple[str, str], dict] = {}
    passthrough: list[dict] = []
    for row in rows:
        provider = str(row.get("provider") or "")
        tty = str(row.get("terminal_tty") or "")
        if row.get("closed_at") is not None or not provider or not re.match(r"^/dev/ttys[0-9]{3,}$", tty):
            passthrough.append(row)
            continue
        key = (provider, tty)
        current = by_tty.get(key)
        if current is None or _session_row_terminal_score(row) > _session_row_terminal_score(current):
            by_tty[key] = row
    return passthrough + list(by_tty.values())


def _session_meaningful_sort_key(row: dict) -> tuple[int, float, int, str]:
    started_at = int(row.get("started_at") or 0)
    meaningful_at = float(row.get("last_meaningful_turn_at") or started_at)
    return (
        0 if (row.get("terminal_attention") or {}).get("needs_input") else 1,
        -meaningful_at,
        -started_at,
        str(row.get("id") or ""),
    )


def _session_row_terminal_score(row: dict) -> tuple[int, int, int, int, int]:
    caps = set(row.get("capabilities") or [])
    control = row.get("controllability") if isinstance(row.get("controllability"), dict) else {}
    native_id = str(row.get("native_id") or row.get("id") or "")
    return (
        1 if bool(control.get("can_send_text") or control.get("can_terminate")) else 0,
        0 if native_id.startswith("terminal-") else 1,
        1 if row.get("claude_uuid") else 0,
        1 if "transcript" in caps else 0,
        int(row.get("last_heartbeat") or 0),
    )


def _refresh_claude_observed_activity(row: dict, project: str | None, claude_uuid: str | None) -> None:
    """Use transcript/turn-state evidence to correct stale PG heartbeats."""
    observed = int(row.get("last_heartbeat") or 0)
    turn_update = row.get("turn_state_updated_at")
    if isinstance(turn_update, (int, float)):
        observed = max(observed, int(turn_update))
    if project and claude_uuid:
        transcript = HOME / ".claude" / "projects" / _encode_project_dir(project) / f"{claude_uuid}.jsonl"
        try:
            if transcript.is_file():
                observed = max(observed, int(transcript.stat().st_mtime))
        except OSError:
            pass
    if observed:
        row["last_heartbeat"] = observed


def _iso_to_epoch(value: str | None) -> float:
    if not value:
        return 0.0
    try:
        s = value.replace("Z", "+00:00")
        return datetime.fromisoformat(s).timestamp()
    except Exception:
        return 0.0


def _read_jsonl_map(
    path: Path,
    id_key: str = "id",
    *,
    keep_first: bool = False,
) -> dict[str, dict]:
    out: dict[str, dict] = {}
    if not path.is_file():
        return out
    try:
        with path.open(encoding="utf-8", errors="replace") as f:
            for line in f:
                if not line.strip():
                    continue
                try:
                    obj = json.loads(line)
                except (ValueError, json.JSONDecodeError):
                    continue
                if not isinstance(obj, dict):
                    continue
                sid = obj.get(id_key)
                if isinstance(sid, str) and sid:
                    if keep_first and sid in out:
                        continue
                    out[sid] = obj
    except OSError:
        pass
    return out


def _codex_history_map() -> dict[str, dict]:
    return _read_jsonl_map(
        CODEX_HISTORY,
        id_key="session_id",
        keep_first=True,
    )


def _codex_index_map() -> dict[str, dict]:
    return _read_jsonl_map(CODEX_SESSION_INDEX, id_key="id")


def _iter_jsonl_prefix_lines(
    path: Path,
    *,
    max_lines: int,
    max_bytes: int = TRANSCRIPT_TAIL_SCAN_BYTES,
    scan_status: dict[str, str] | None = None,
):
    def stop(reason: str) -> None:
        if scan_status is not None:
            scan_status["stop_reason"] = reason

    stop("unknown")
    remaining = max(1, int(max_bytes))
    try:
        with _open_session_transcript_file(path) as handle:
            for _ in range(max(1, int(max_lines))):
                raw = handle.readline(remaining + 1)
                if not raw:
                    stop("eof")
                    return
                if len(raw) > remaining:
                    stop("byte_limit")
                    return
                remaining -= len(raw)
                yield raw.decode("utf-8", errors="replace")
                if remaining <= 0:
                    stop("eof" if not handle.read(1) else "byte_limit")
                    return
            stop("eof" if not handle.read(1) else "line_limit")
    except OSError:
        stop("io_error")
        return


def _codex_rollout_meta(path: Path) -> dict | None:
    try:
        first = next(
            _iter_jsonl_prefix_lines(
                path,
                max_lines=1,
                max_bytes=CODEX_ROLLOUT_META_SCAN_BYTES,
            ),
            "",
        )
        if not first:
            return None
        obj = json.loads(first)
    except (OSError, ValueError, json.JSONDecodeError):
        return None
    if not isinstance(obj, dict):
        return None
    payload = obj.get("payload") if isinstance(obj.get("payload"), dict) else {}
    sid = payload.get("id") or obj.get("id")
    cwd = payload.get("cwd") or obj.get("cwd")
    if not isinstance(sid, str) or not sid or not isinstance(cwd, str) or not cwd:
        return None
    return {
        "id": sid,
        "cwd": cwd,
        "timestamp": payload.get("timestamp") or obj.get("timestamp"),
        "model": payload.get("model"),
        "source": payload.get("source") or obj.get("source"),
        "originator": payload.get("originator") or obj.get("originator"),
    }


def _codex_rollout_paths() -> list[Path]:
    with _codex_rollout_paths_lock:
        if not CODEX_SESSIONS_DIR.is_dir():
            _codex_rollout_paths_cache["ts"] = 0.0
            _codex_rollout_paths_cache["paths"] = []
            return []
        now = _time.time()
        cached_ts = float(_codex_rollout_paths_cache.get("ts") or 0)
        if now - cached_ts < CODEX_ROLLOUT_PATHS_CACHE_SECONDS:
            return list(_codex_rollout_paths_cache.get("paths") or [])
        try:
            root = CODEX_SESSIONS_DIR.resolve(strict=True)
        except OSError:
            return []
        paths: list[Path] = []
        try:
            for path in root.rglob("rollout-*.jsonl"):
                try:
                    if path.is_symlink():
                        continue
                    resolved = path.resolve(strict=True)
                    resolved.relative_to(root)
                    if resolved.is_file():
                        paths.append(resolved)
                except (OSError, ValueError):
                    continue
        except OSError:
            return []

        def modified_at(path: Path) -> float:
            try:
                return path.stat().st_mtime
            except OSError:
                return 0.0

        paths.sort(key=modified_at, reverse=True)
        _codex_rollout_paths_cache["ts"] = _time.time()
        _codex_rollout_paths_cache["paths"] = paths
        return list(paths)


def _codex_rollout_file_identity(path: Path) -> tuple[str, int, int, int, int, int] | None:
    try:
        link_stat = path.lstat()
        target_stat = path.stat()
    except OSError:
        return None
    return (
        str(path),
        int(link_stat.st_dev),
        int(link_stat.st_ino),
        int(link_stat.st_mode),
        int(target_stat.st_dev),
        int(target_stat.st_ino),
    )


def _codex_rollout_index(paths: list[Path]) -> tuple[list[tuple[Path, dict]], dict[str, Path]]:
    """Index immutable rollout identities without repeatedly opening every file."""
    fingerprinted_paths = [
        (path, identity)
        for path in paths
        if (identity := _codex_rollout_file_identity(path)) is not None
    ]
    signature = tuple(identity for _, identity in fingerprinted_paths)
    with _codex_rollout_index_lock:
        cached_meta = _codex_rollout_index_cache.get("meta_by_file")
        cached_meta_by_file = dict(cached_meta) if isinstance(cached_meta, dict) else {}
        has_incomplete_entry = any(
            not isinstance(cached_meta_by_file.get(identity), dict)
            for identity in signature
        )
        if (
            signature == _codex_rollout_index_cache.get("signature")
            and not has_incomplete_entry
        ):
            cached_entries = _codex_rollout_index_cache.get("entries") or []
            return (
                [(path, copy.deepcopy(meta)) for path, meta in cached_entries],
                dict(_codex_rollout_index_cache.get("by_id") or {}),
            )

        previous_by_file = cached_meta_by_file
        meta_by_file: dict[tuple[str, int, int, int, int, int], dict | None] = {}
        entries: list[tuple[Path, dict]] = []
        by_id: dict[str, Path] = {}
        for path, identity in fingerprinted_paths:
            cached_meta = previous_by_file.get(identity)
            meta = cached_meta if isinstance(cached_meta, dict) else _codex_rollout_meta(path)
            if not isinstance(meta, dict):
                meta_by_file[identity] = None
                continue
            native_id = str(meta.get("id") or "")
            if not _safe_agent_native_id(native_id):
                meta_by_file[identity] = None
                continue
            approved = _approved_codex_transcript_path(path, native_id)
            if approved is None:
                meta_by_file[identity] = None
                continue
            stored_meta = copy.deepcopy(meta)
            meta_by_file[identity] = stored_meta
            entries.append((approved, copy.deepcopy(stored_meta)))
            by_id.setdefault(native_id, approved)

        _codex_rollout_index_cache["signature"] = signature
        _codex_rollout_index_cache["meta_by_file"] = meta_by_file
        _codex_rollout_index_cache["entries"] = entries
        _codex_rollout_index_cache["by_id"] = by_id
        return (
            [(path, copy.deepcopy(meta)) for path, meta in entries],
            dict(by_id),
        )


def _codex_selected_rollout_entries() -> list[tuple[Path, dict]]:
    """Select one verified transcript path for each Codex session identity."""
    indexed, _ = _codex_rollout_index(_codex_rollout_paths())
    selected: dict[str, tuple[Path, dict]] = {}

    def select(native_id: str, candidate: Path) -> None:
        if native_id in selected:
            return
        approved = _approved_codex_transcript_path(candidate, native_id)
        if approved is None:
            return
        meta = _codex_rollout_meta(approved)
        if not isinstance(meta, dict) or meta.get("id") != native_id:
            return
        selected[native_id] = (approved, meta)

    exact_live_paths: dict[str, set[Path]] = {}
    for terminal in _codex_live_terminal_rows():
        if str(terminal.get("identity_probe_state") or "exact") != "exact":
            continue
        native_id = str(terminal.get("native_id") or "")
        output_path = str(terminal.get("output_path") or "")
        if not _safe_agent_native_id(native_id) or not output_path:
            continue
        approved = _approved_codex_transcript_path(Path(output_path), native_id)
        if approved is not None:
            exact_live_paths.setdefault(native_id, set()).add(approved)
    for native_id, paths in exact_live_paths.items():
        if len(paths) == 1:
            select(native_id, next(iter(paths)))

    registry_rows = [
        *_agent_registry_live("codex", limit=1000),
        *_agent_registry_recent("codex", since_min=60 * 24 * 3650, limit=5000),
    ]
    for row in registry_rows:
        native_id = str(row.get("native_id") or "")
        if not _safe_agent_native_id(native_id):
            continue
        if _agent_registry_resolve_native_alias("codex", native_id) != native_id:
            continue
        output_path = _registry_metadata_from_row(row).get("output_path")
        if isinstance(output_path, str) and output_path:
            select(native_id, Path(output_path))

    def indexed_modified_at(entry: tuple[Path, dict]) -> float:
        try:
            return entry[0].stat().st_mtime
        except OSError:
            return 0.0

    for path, meta in sorted(indexed, key=indexed_modified_at, reverse=True):
        native_id = str(meta.get("id") or "")
        if _safe_agent_native_id(native_id):
            select(native_id, path)

    def selected_order(entry: tuple[Path, dict]) -> tuple[float, str]:
        path, meta = entry
        try:
            modified_at = path.stat().st_mtime
        except OSError:
            modified_at = 0.0
        return (-modified_at, str(meta.get("id") or ""))

    return sorted(selected.values(), key=selected_order)


def _approved_codex_transcript_path(path: Path, native_id: str) -> Path | None:
    if path.suffix != ".jsonl":
        return None
    try:
        root, target = _transcript_root_for_path(path)
        if root != CODEX_SESSIONS_DIR.expanduser().resolve(strict=True):
            return None
        with _open_session_transcript_file(target):
            pass
    except (OSError, ValueError):
        return None
    meta = _codex_rollout_meta(target)
    if meta is not None:
        return target if meta.get("id") == native_id else None
    return None


def _resolve_codex_transcript(native_id: str) -> Path | None:
    if not _safe_session_id(native_id):
        return None
    native_id = _agent_registry_resolve_native_alias("codex", native_id)
    reg = _agent_registry_get("codex", native_id)
    if reg:
        try:
            metadata = json.loads(reg.get("metadata_json") or "{}")
            output_path = metadata.get("output_path") if isinstance(metadata, dict) else None
            if isinstance(output_path, str):
                approved = _approved_codex_transcript_path(Path(output_path), native_id)
                if approved is not None:
                    return approved
        except Exception:
            pass
    if not CODEX_SESSIONS_DIR.is_dir():
        return None
    matches = list(CODEX_SESSIONS_DIR.rglob(f"rollout-*{native_id}.jsonl"))
    if matches:
        matches.sort(key=lambda p: p.stat().st_mtime if p.exists() else 0, reverse=True)
        for match in matches:
            approved = _approved_codex_transcript_path(match, native_id)
            if approved is not None:
                return approved
    for path in _codex_rollout_paths():
        approved = _approved_codex_transcript_path(path, native_id)
        if approved is not None:
            return approved
    return None


def _codex_project_for_session(native_id: str) -> str:
    reg = _agent_registry_get("codex", native_id)
    if reg and reg.get("project"):
        return str(reg["project"])
    path = _resolve_codex_transcript(native_id)
    if path:
        meta = _codex_rollout_meta(path)
        if meta and meta.get("cwd"):
            return meta["cwd"]
    return ""


def _codex_latest_task_boundary(path: Path) -> dict[str, object] | None:
    """Return the latest Codex task_started/task_complete event in a rollout.

    Codex provider sessions do not currently have a Stop hook that writes
    `idle` into Pairling's turn-state file. The rollout transcript does have
    explicit task boundary events, so we use them to end stale spinner state.
    """
    try:
        st = path.stat()
    except OSError:
        return None
    key = str(path)
    cached = _codex_task_boundary_cache.get(key)
    if (
        cached
        and cached.get("mtime_ns") == st.st_mtime_ns
        and cached.get("size") == st.st_size
    ):
        boundary = cached.get("boundary")
        return dict(boundary) if isinstance(boundary, dict) else None

    boundary: dict[str, object] | None = None
    try:
        for raw in _tail_lines(path, max_lines=2000, max_bytes=TRANSCRIPT_TAIL_SCAN_BYTES):
            if not raw.strip():
                continue
            try:
                obj = json.loads(raw)
            except (ValueError, json.JSONDecodeError):
                continue
            if obj.get("type") != "event_msg":
                continue
            payload = obj.get("payload") if isinstance(obj.get("payload"), dict) else {}
            event_type = payload.get("type")
            if event_type not in {"task_started", "task_complete"}:
                continue
            ts = _iso_to_epoch(obj.get("timestamp")) or st.st_mtime
            boundary = {
                "type": event_type,
                "timestamp": float(ts),
            }
    except OSError:
        boundary = None

    _codex_task_boundary_cache[key] = {
        "mtime_ns": st.st_mtime_ns,
        "size": st.st_size,
        "boundary": dict(boundary) if boundary else None,
    }
    return boundary


def _persist_codex_turn_state(path: Path, payload: dict) -> None:
    try:
        TURN_STATE_DIR.mkdir(parents=True, exist_ok=True)
        tmp = path.with_name(f"{path.name}.tmp.{os.getpid()}")
        tmp.write_text(json.dumps(payload, sort_keys=True), encoding="utf-8")
        tmp.replace(path)
    except Exception:
        pass
    provider, native_id = _parse_agent_session_ref(str(payload.get("session_id") or path.stem))
    _publish_live_activity_turn_state(provider, native_id or path.stem, payload)


def _apply_codex_task_boundary(native_id: str, payload: dict, state_path: Path) -> dict:
    transcript = _resolve_codex_transcript(native_id)
    if not transcript:
        return payload
    boundary = _codex_latest_task_boundary(transcript)
    if not boundary or boundary.get("type") != "task_complete":
        return payload

    boundary_ts = float(boundary.get("timestamp") or 0)
    last_update = float(payload.get("last_update") or 0)
    if boundary_ts + 0.001 < last_update:
        return payload

    state = str(payload.get("state") or "").strip().lower()
    if state not in {"thinking", "tool", "responding", "starting"}:
        return payload

    updated = dict(payload)
    updated["state"] = "idle"
    updated["tool"] = None
    updated["last_update"] = max(last_update, boundary_ts)
    updated["event"] = "task_complete"
    _persist_codex_turn_state(state_path, updated)
    return updated


def _codex_turn_state_payload(native_id: str, *, apply_boundary: bool = True) -> dict | None:
    if not _safe_agent_native_id(native_id):
        return None
    native_id = _agent_registry_resolve_native_alias("codex", native_id)
    if not _safe_agent_native_id(native_id):
        return None
    path = _turn_state_path("codex", native_id)
    if path.is_file():
        try:
            obj = json.loads(path.read_text())
            if isinstance(obj, dict):
                if apply_boundary:
                    obj = _apply_codex_task_boundary(native_id, obj, path)
                obj["session_id"] = _qualified_session_id("codex", native_id)
                obj["provider"] = "codex"
                obj["native_id"] = native_id
                return obj
        except Exception:
            pass
    reg = _agent_registry_get("codex", native_id)
    if not reg:
        return None
    pid = int(reg.get("pid") or 0)
    state = "idle"
    if pid and _process_alive(pid) and not reg.get("closed_at"):
        state = "idle"
    metadata = {}
    try:
        metadata = json.loads(reg.get("metadata_json") or "{}")
    except Exception:
        metadata = {}
    started = float(reg.get("started_at") or _time.time())
    last = float(reg.get("last_heartbeat") or started)
    payload = {
        "session_id": _qualified_session_id("codex", native_id),
        "provider": "codex",
        "native_id": native_id,
        "state": metadata.get("turn_state") or state,
        "tool": metadata.get("tool"),
        "started_at": float(metadata.get("turn_started_at") or started),
        "last_update": last,
        "effort": metadata.get("effort"),
        "event": metadata.get("turn_event") or "registry",
    }
    if apply_boundary:
        return _apply_codex_task_boundary(native_id, payload, path)
    return payload

def _managed_turn_state_payload(
    provider: str,
    native_id: str,
    *,
    apply_boundary: bool = True,
) -> dict | None:
    if provider == "codex":
        return _codex_turn_state_payload(native_id, apply_boundary=apply_boundary)
    if provider != "omp" or not _safe_agent_native_id(native_id):
        return None
    native_id = _agent_registry_resolve_native_alias(provider, native_id)
    if not _safe_agent_native_id(native_id):
        return None
    path = _turn_state_path(provider, native_id)
    try:
        obj = json.loads(path.read_text())
    except Exception:
        return None
    if not isinstance(obj, dict):
        return None
    obj["session_id"] = _qualified_session_id(provider, native_id)
    obj["provider"] = provider
    obj["native_id"] = native_id
    return obj


def _codex_first_prompt(path: Path, session_id: str, history: dict[str, dict]) -> str | None:
    hist = history.get(session_id) or {}
    history_text = hist.get("text")
    scan_status: dict[str, str] = {}
    malformed_before_prompt = False
    try:
        for line in _iter_jsonl_prefix_lines(
            path,
            max_lines=200,
            scan_status=scan_status,
        ):
            if not line.strip():
                continue
            try:
                obj = json.loads(line)
            except (ValueError, json.JSONDecodeError):
                malformed_before_prompt = True
                break
            if not isinstance(obj, dict):
                malformed_before_prompt = True
                break
            payload = obj.get("payload") if isinstance(obj.get("payload"), dict) else {}
            if obj.get("type") == "event_msg" and payload.get("type") == "user_message":
                text = _text_from_codex_value(
                    payload.get("message") or payload.get("text") or payload.get("content")
                ).strip()
                if text:
                    return text[:500]
            rows = _normalize_codex_line(line, session_id)
            for row in rows:
                msg = row.get("message") or {}
                if msg.get("role") == "user":
                    content = msg.get("content") or []
                    if content and isinstance(content, list):
                        first = content[0]
                        if isinstance(first, dict):
                            t = first.get("text")
                            if isinstance(t, str) and t.strip():
                                candidate = t.strip()
                                is_injected_context = (
                                    candidate.startswith("# AGENTS.md instructions for ")
                                    and "\n\n<INSTRUCTIONS>\n" in candidate
                                )
                                if not is_injected_context:
                                    return candidate[:500]
    except OSError:
        pass
    if (
        not malformed_before_prompt
        and scan_status.get("stop_reason") == "eof"
        and isinstance(history_text, str)
        and history_text.strip()
    ):
        return history_text.strip()[:500]
    return None


_codex_preverified_registry_state = threading.local()
_CODEX_PREVERIFIED_REGISTRY_UNSET = object()


@contextmanager
def _codex_preverified_registry_row(row: dict | None):
    previous_active = getattr(_codex_preverified_registry_state, "active", False)
    previous = getattr(_codex_preverified_registry_state, "row", None)
    _codex_preverified_registry_state.active = True
    _codex_preverified_registry_state.row = dict(row) if row else None
    try:
        yield
    finally:
        _codex_preverified_registry_state.active = previous_active
        _codex_preverified_registry_state.row = previous


def _current_codex_preverified_registry_row(native_id: str):
    if not getattr(_codex_preverified_registry_state, "active", False):
        return _CODEX_PREVERIFIED_REGISTRY_UNSET
    row = getattr(_codex_preverified_registry_state, "row", None)
    if row is None:
        return None
    if (
        isinstance(row, dict)
        and str(row.get("provider") or "codex").strip().lower() == "codex"
        and str(row.get("native_id") or "") == str(native_id or "")
    ):
        return dict(row)
    return _CODEX_PREVERIFIED_REGISTRY_UNSET


def _codex_control_overlay(
    row: dict,
    observed_mtime: float | None = None,
    *,
    verify_process: bool = True,
    observed_output_path: str = "",
    inventory_live_terminal_rows: list[dict] | None = None,
) -> dict:
    if verify_process:
        native_id = row.get("native_id") or ""
        reg = _current_codex_preverified_registry_row(native_id)
        if reg is _CODEX_PREVERIFIED_REGISTRY_UNSET:
            reg = _agent_registry_promote_codex(
                native_id,
                row.get("project") or "",
                float(row.get("started_at") or 0),
                observed_output_path,
            )
    else:
        reg = _agent_registry_get("codex", row.get("native_id") or "")
    if not reg:
        return row
    metadata = _registry_metadata_from_row(reg)
    if metadata.get("terminal_title") and not row.get("terminal_title"):
        row["terminal_title"] = metadata.get("terminal_title")
    _apply_launch_context_to_session_row(row, metadata)
    if reg.get("closed_at"):
        row["closed_at"] = int(float(reg.get("closed_at") or _time.time()))
        row["state"] = "terminated"
        row["capabilities"] = [cap for cap in (row.get("capabilities") or []) if cap in {"transcript", "export", "live_state"}]
        row["controllability"] = {
            "can_send_text": False,
            "can_interrupt": False,
            "can_terminate": False,
            "reason": "Session is closed; transcript remains readable.",
        }
        return row
    pid = int(reg.get("pid") or 0)
    tty = reg.get("terminal_tty") or ""
    if verify_process and pid and not _process_alive(pid):
        _agent_registry_mark_closed("codex", row["native_id"])
        row["closed_at"] = int(_time.time())
        row["state"] = "terminated"
        row["capabilities"] = [
            cap
            for cap in (row.get("capabilities") or [])
            if cap in {"transcript", "export", "live_state"}
        ]
        row["controllability"] = {
            "can_send_text": False,
            "can_interrupt": False,
            "can_terminate": False,
            "reason": "Session is closed; transcript remains readable.",
        }
        return row
    state_payload = _codex_turn_state_payload(row.get("native_id") or "", apply_boundary=False)
    surface_caps = _terminal_surface_capabilities(
        _qualified_session_id("codex", row.get("native_id") or ""),
        inventory_live_terminal_rows=inventory_live_terminal_rows,
    )
    broker_id = str(
        _durable_broker_id_from_registry_row(
            reg,
            provider="codex",
            native_id=str(row.get("native_id") or ""),
        )
        or surface_caps.get("broker_id")
        or ""
    ).strip()
    row["broker_id"] = broker_id or None
    send_scope_id = _durable_send_scope_id_from_registry_row(
        reg,
        provider="codex",
        native_id=str(row.get("native_id") or ""),
    ) or _normalized_send_scope_id("codex", broker_id)
    row["send_scope_id"] = send_scope_id or None
    can_send = bool(surface_caps.get("can_send_text"))
    can_interrupt = bool(surface_caps.get("can_interrupt"))
    can_terminate = bool(surface_caps.get("can_terminate"))
    if tty:
        row["terminal_tty"] = tty
    if pid:
        row["pid"] = pid
    caps = set(row.get("capabilities") or [])
    if state_payload or can_send or can_interrupt or can_terminate:
        caps.add("live_state")
    caps.update({"send_text", "upload", "commands"} if can_send else set())
    caps.update({"interrupt"} if can_interrupt else set())
    caps.update({"terminate"} if can_terminate else set())
    if _codex_terminal_capture_for_registry(reg):
        caps.add("terminal_output")
    caps.update(surface_caps.get("capabilities") or [])
    row["capabilities"] = [cap for cap in CODEX_CONTROL_CAPABILITIES if cap in caps]
    if surface_caps.get("source") == "broker_vt":
        row["terminal_attention"] = _terminal_attention_from_snapshot(
            _broker_snapshot_or_none(surface_caps.get("broker_id"))
        )
    row["controllability"] = {
        "can_send_text": can_send,
        "can_interrupt": can_interrupt,
        "can_terminate": can_terminate,
        "reason": (
            "This live terminal is finishing under the previous runtime; only interrupt is available."
            if surface_caps.get("control_profile") == "draining_broker_interrupt_only"
            else (
                None
                if can_send or can_interrupt or can_terminate
                else "Codex terminal control needs the current Pairling broker."
            )
        ),
    }
    if state_payload:
        row["state"] = state_payload.get("state")
        row["tool"] = state_payload.get("tool")
        row["turn_started_at"] = state_payload.get("started_at")
        row["effort"] = state_payload.get("effort")
    if row.get("launch_context") and row.get("model") is None:
        row["model"] = (row["launch_context"] or {}).get("model")
    row["last_heartbeat"] = max(int(row.get("last_heartbeat") or 0), int(reg.get("last_heartbeat") or 0))
    return row


def _codex_pending_registry_rows(
    seen: set[str],
    live_only: bool,
    active_within_min: int,
    live_terminal_rows: list[dict] | None = None,
) -> list[dict]:
    cutoff = _time.time() - max(1, active_within_min) * 60
    rows: list[dict] = []
    for reg in _agent_registry_live("codex"):
        native_id = reg.get("native_id") or ""
        if not native_id or native_id in seen:
            continue
        heartbeat = float(reg.get("last_heartbeat") or reg.get("started_at") or 0)
        pid = int(reg.get("pid") or 0)
        tty = reg.get("terminal_tty") or ""
        if pid and not _process_alive(pid):
            _agent_registry_mark_closed("codex", native_id)
            continue
        process_alive = bool(pid and _process_alive(pid))
        stale_seconds = max(0, int(_time.time() - heartbeat)) if heartbeat else 0
        surface_caps = _terminal_surface_capabilities(
            _qualified_session_id("codex", native_id),
            inventory_live_terminal_rows=live_terminal_rows,
        )
        can_send = bool(surface_caps.get("can_send_text"))
        can_interrupt = bool(surface_caps.get("can_interrupt"))
        can_terminate = bool(surface_caps.get("can_terminate"))
        process_verified = bool(
            process_alive
            and _codex_inventory_registry_process_matches(
                reg, live_terminal_rows
            )
        )
        broker_verified = bool(
            surface_caps.get("source") == "broker_vt"
            and (can_send or can_interrupt or can_terminate)
        )
        if live_only and not (process_verified or broker_verified):
            continue
        caps = (
            ["live_state"]
            + (["send_text", "upload", "commands"] if can_send else [])
            + (["interrupt"] if can_interrupt else [])
            + (["terminate"] if can_terminate else [])
        )
        if _codex_terminal_capture_for_registry(reg):
            caps.append("terminal_output")
        caps.extend(cap for cap in (surface_caps.get("capabilities") or []) if cap not in caps)
        metadata = _registry_metadata_from_row(reg)
        launch_context = _session_launch_context_from_metadata(metadata)
        row = {
            "id": _qualified_session_id("codex", native_id),
            "provider": "codex",
            "native_id": native_id,
            "send_scope_id": (
                _durable_send_scope_id_from_registry_row(
                    reg,
                    provider="codex",
                    native_id=native_id,
                )
                or _normalized_send_scope_id(
                    "codex", surface_caps.get("broker_id")
                )
                or None
            ),
            "broker_id": (
                _normalized_send_scope_id(
                    "codex", metadata.get("broker_id")
                )
                or _normalized_send_scope_id(
                    "codex", surface_caps.get("broker_id")
                )
                or None
            ),
            "project": reg.get("project") or str(HOME),
            "working_on": "New Codex session",
            "started_at": int(reg.get("started_at") or _time.time()),
            "last_heartbeat": int(heartbeat or _time.time()),
            "stale_seconds": stale_seconds,
            "source_freshness": (
                "registry_stale_process_verified"
                if heartbeat < cutoff and process_verified
                else (
                    "registry_live"
                    if process_verified or broker_verified
                    else "registry_unverified"
                )
            ),
            "terminal_tty": tty,
            "pid": pid,
            "terminal_title": metadata.get("terminal_title"),
            "first_prompt": None,
            "state": "running",
            "tool": None,
            "turn_started_at": None,
            "effort": None,
            "model": (launch_context or {}).get("model"),
            "context_pct": None,
            "capabilities": caps,
            "controllability": {
                "can_send_text": can_send,
                "can_interrupt": can_interrupt,
                "can_terminate": can_terminate,
                "reason": (
                    "This live terminal is finishing under the previous runtime; only interrupt is available."
                    if surface_caps.get("control_profile") == "draining_broker_interrupt_only"
                    else (
                        None
                        if can_send or can_interrupt or can_terminate
                        else "Codex terminal control needs the current Pairling broker."
                    )
                ),
            },
        }
        if launch_context is not None:
            row["launch_context"] = launch_context
        if surface_caps.get("source") == "broker_vt":
            row["terminal_attention"] = _terminal_attention_from_snapshot(
                _broker_snapshot_or_none(surface_caps.get("broker_id"))
            )
        rows.append(row)
    return rows


def _codex_recent_closed_registry_rows(
    seen: set[str],
    active_within_min: int,
    transcript_paths_by_id: dict[str, Path] | None = None,
) -> list[dict]:
    rows: list[dict] = []
    recent = [
        reg
        for reg in _agent_registry_recent(
            "codex", since_min=active_within_min, limit=1000
        )
        if reg.get("closed_at")
    ]
    recent.sort(
        key=lambda reg: (
            str(reg.get("native_id") or "").startswith(("pending-", "terminal-")),
            -float(reg.get("closed_at") or 0),
        )
    )
    for reg in recent:
        native_id = reg.get("native_id") or ""
        if not native_id or native_id in seen:
            continue
        try:
            metadata = json.loads(reg.get("metadata_json") or "{}")
            if not isinstance(metadata, dict):
                metadata = {}
        except Exception:
            metadata = {}
        started_at = int(float(reg.get("started_at") or reg.get("last_heartbeat") or _time.time()))
        last_heartbeat = int(float(reg.get("last_heartbeat") or started_at))
        closed_at = int(float(reg.get("closed_at") or last_heartbeat))
        resolved_native_id = _agent_registry_resolve_native_alias("codex", native_id)
        if not resolved_native_id or resolved_native_id in seen:
            continue
        if transcript_paths_by_id is None:
            transcript_path = _resolve_codex_transcript(resolved_native_id)
        else:
            transcript_path = None
            recorded_path = metadata.get("output_path")
            if isinstance(recorded_path, str) and recorded_path:
                transcript_path = _approved_codex_transcript_path(
                    Path(recorded_path), resolved_native_id
                )
            if transcript_path is None:
                candidate = transcript_paths_by_id.get(resolved_native_id)
                if candidate is not None:
                    transcript_path = _approved_codex_transcript_path(
                        candidate, resolved_native_id
                    )
        turn_stats = _session_transcript_stats(
            transcript_path, "codex", resolved_native_id
        )
        first_prompt = metadata.get("first_prompt")
        if not first_prompt and transcript_path:
            first_prompt = _codex_first_prompt(
                transcript_path, resolved_native_id, _codex_history_map()
            )
        capabilities = ["live_state"]
        if transcript_path:
            capabilities = CODEX_READ_ONLY_CAPABILITIES + ["live_state"]
        row = {
            "id": _qualified_session_id("codex", resolved_native_id),
            "provider": "codex",
            "native_id": resolved_native_id,
            "project": reg.get("project") or str(HOME),
            "working_on": metadata.get("working_on") or "Closed Codex session",
            "started_at": started_at,
            "last_heartbeat": last_heartbeat,
            "closed_at": closed_at,
            "stale_seconds": max(0, int(_time.time() - last_heartbeat)) if last_heartbeat else 0,
            "source_freshness": "registry_closed",
            "terminal_title": metadata.get("terminal_title"),
            "first_prompt": first_prompt,
            "state": "terminated",
            "tool": None,
            "turn_started_at": None,
            "effort": metadata.get("effort"),
            "model": metadata.get("model"),
            "context_pct": None,
            "turn_count": turn_stats.get("turn_count"),
            "last_meaningful_turn_at": turn_stats.get("last_meaningful_turn_at"),
            "capabilities": capabilities,
            "controllability": {
                "can_send_text": False,
                "can_interrupt": False,
                "can_terminate": False,
                "reason": "Session is closed; transcript remains readable.",
            },
        }
        _apply_launch_context_to_session_row(row, metadata)
        rows.append(row)
        seen.add(resolved_native_id)
    return rows


def _list_codex_sessions(live_only: bool, active_within_min: int) -> list[dict]:
    return _cached_runtime_snapshot(
        ("list-codex-sessions", str(HOME), bool(live_only), int(active_within_min or 0)),
        RUNTIME_SNAPSHOT_CACHE_SECONDS,
        lambda: _list_codex_sessions_uncached(live_only, active_within_min),
    )


def _list_codex_sessions_uncached(
    live_only: bool,
    active_within_min: int,
    live_terminal_rows: list[dict] | None = None,
) -> list[dict]:
    with _agent_registry_read_snapshot(
        "codex",
        active_within_min=active_within_min,
    ):
        return _list_codex_sessions_from_read_snapshot(
            live_only,
            active_within_min,
            live_terminal_rows,
        )


def _list_codex_sessions_from_read_snapshot(
    live_only: bool,
    active_within_min: int,
    live_terminal_rows: list[dict] | None = None,
) -> list[dict]:
    """Codex provider backed by transcripts plus live terminal discovery."""
    index = _codex_index_map()
    history = _codex_history_map()
    cutoff = _time.time() - max(1, active_within_min) * 60
    rows: list[dict] = []
    seen: set[str] = set()
    if live_terminal_rows is None:
        live_terminal_rows = _codex_live_terminal_rows()
    live_registry_rows = _agent_registry_live("codex", limit=1000)
    exact_live_native_counts: dict[str, int] = {}
    for terminal in live_terminal_rows:
        native_id = str(terminal.get("native_id") or "")
        if (
            native_id
            and str(terminal.get("identity_probe_state") or "exact") == "exact"
        ):
            exact_live_native_counts[native_id] = (
                exact_live_native_counts.get(native_id, 0) + 1
            )
    exact_live_native_ids = set(exact_live_native_counts)
    ambiguous_live_native_ids = {
        native_id
        for native_id, count in exact_live_native_counts.items()
        if count > 1
    }
    degraded_live_native_ids = {
        str(terminal.get("native_id") or "")
        for terminal in live_terminal_rows
        if terminal.get("native_id")
        and str(terminal.get("identity_probe_state") or "exact") != "exact"
    }
    live_registry_ids = {
        str(reg.get("native_id") or "")
        for reg in live_registry_rows
        if reg.get("native_id")
    }
    live_transcript_paths: list[str] = []
    live_transcript_path_set: set[str] = set()
    priority_transcript_paths: list[str] = []
    priority_transcript_path_set: set[str] = set()
    recent_closed_registry_ids: set[str] = set()

    def add_priority_transcript_path(path: Path) -> None:
        path_text = str(path)
        if path_text not in priority_transcript_path_set:
            priority_transcript_path_set.add(path_text)
            priority_transcript_paths.append(path_text)

    def add_live_transcript_path(path: Path) -> None:
        path_text = str(path)
        if path_text not in live_transcript_path_set:
            live_transcript_path_set.add(path_text)
            live_transcript_paths.append(path_text)
        add_priority_transcript_path(path)

    for terminal in live_terminal_rows:
        native_id = str(terminal.get("native_id") or "")
        output_path = str(terminal.get("output_path") or "")
        if not native_id or not output_path:
            continue
        approved = _approved_codex_transcript_path(Path(output_path), native_id)
        if approved is not None:
            add_live_transcript_path(approved)
    for reg in live_registry_rows:
        native_id = str(reg.get("native_id") or "")
        if not native_id or native_id.startswith("pending-"):
            continue
        metadata = _registry_metadata_from_row(reg)
        output_path = metadata.get("output_path")
        if not isinstance(output_path, str) or not output_path:
            continue
        approved = _approved_codex_transcript_path(Path(output_path), native_id)
        if approved is not None:
            add_live_transcript_path(approved)
    if not live_only:
        closed_rows_by_canonical: dict[str, list[dict]] = {}
        for reg in _agent_registry_recent(
            "codex", since_min=active_within_min, limit=1000
        ):
            if not reg.get("closed_at"):
                continue
            native_id = str(reg.get("native_id") or "")
            resolved_native_id = _agent_registry_resolve_native_alias(
                "codex", native_id
            )
            if not resolved_native_id:
                continue
            recent_closed_registry_ids.add(resolved_native_id)
            closed_rows_by_canonical.setdefault(resolved_native_id, []).append(reg)
        for resolved_native_id, grouped_rows in closed_rows_by_canonical.items():
            canonical_rows = [
                reg
                for reg in grouped_rows
                if str(reg.get("native_id") or "") == resolved_native_id
            ]
            alias_rows = [
                reg
                for reg in grouped_rows
                if str(reg.get("native_id") or "") != resolved_native_id
            ]
            for reg in [*canonical_rows, *alias_rows]:
                output_path = _registry_metadata_from_row(reg).get("output_path")
                if not isinstance(output_path, str) or not output_path:
                    continue
                approved = _approved_codex_transcript_path(
                    Path(output_path), resolved_native_id
                )
                if approved is not None:
                    add_priority_transcript_path(approved)
                    break
    discovered_rollout_paths = _codex_rollout_paths()
    rollout_paths = [Path(path) for path in priority_transcript_paths]
    retained_registry_suffixes = tuple(
        f"{native_id}.jsonl"
        for native_id in sorted(
            live_registry_ids | recent_closed_registry_ids
        )
        if native_id
    )
    for path in discovered_rollout_paths:
        if str(path) in priority_transcript_path_set:
            continue
        try:
            if (
                path.stat().st_mtime < cutoff
                and not (
                    retained_registry_suffixes
                    and path.name.endswith(retained_registry_suffixes)
                )
            ):
                continue
        except OSError:
            continue
        rollout_paths.append(path)
    indexed_rollouts, transcript_paths_by_id = _codex_rollout_index(rollout_paths)
    rollout_entries: list[tuple[Path, os.stat_result, dict]] = []
    for path, meta in indexed_rollouts:
        try:
            st = path.stat()
        except OSError:
            continue
        native_id = str(meta.get("id") or "")
        if (
            st.st_mtime < cutoff
            and str(path) not in live_transcript_path_set
            and native_id not in live_registry_ids
        ):
            continue
        rollout_entries.append((path, st, meta))

    pending_matches_by_rollout: dict[str, list[dict]] = {}
    rollout_ids_by_pending: dict[str, set[str]] = {}
    unidentified_live_rollout_ids: set[str] = set()
    for _path, st, meta in rollout_entries:
        sid = str(meta.get("id") or "")
        if not sid or sid in pending_matches_by_rollout:
            continue
        started = int(_iso_to_epoch(meta.get("timestamp")) or st.st_mtime)
        if any(
            not terminal.get("native_id")
            and str(terminal.get("identity_probe_state") or "exact") == "exact"
            and terminal.get("project") == meta["cwd"]
            and abs(float(terminal.get("started_at") or 0) - started) <= 600
            for terminal in live_terminal_rows
        ):
            unidentified_live_rollout_ids.add(sid)
        matches = _codex_spawn_pending_registry_rows(
            meta["cwd"],
            started,
            registry_rows=live_registry_rows,
        )
        pending_matches_by_rollout[sid] = matches
        for pending in matches:
            pending_id = str(pending.get("native_id") or "")
            if pending_id:
                rollout_ids_by_pending.setdefault(pending_id, set()).add(sid)

    if live_only:
        rollout_entries = [
            (path, st, meta)
            for path, st, meta in rollout_entries
            if (
                str(meta.get("id") or "") in exact_live_native_ids
                or str(meta.get("id") or "") in degraded_live_native_ids
                or str(meta.get("id") or "") in live_registry_ids
                or str(path) in live_transcript_path_set
                or str(meta.get("id") or "") in unidentified_live_rollout_ids
                or bool(pending_matches_by_rollout.get(str(meta.get("id") or "")))
            )
        ]

    for path, st, meta in rollout_entries:
        sid = meta["id"]
        if sid in seen:
            continue
        seen.add(sid)
        idx = index.get(sid) or {}
        first_prompt = _codex_first_prompt(path, sid, history)
        started = int(_iso_to_epoch(meta.get("timestamp")) or st.st_mtime)
        working_on = idx.get("thread_name") if isinstance(idx.get("thread_name"), str) else None
        turn_stats = _session_transcript_stats(path, "codex", sid)
        row = {
            "id": _qualified_session_id("codex", sid),
            "provider": "codex",
            "native_id": sid,
            "project": meta["cwd"],
            "working_on": working_on or first_prompt,
            "started_at": started,
            "last_heartbeat": int(st.st_mtime),
            "first_prompt": first_prompt,
            "state": None,
            "tool": None,
            "turn_started_at": None,
            "effort": None,
            "model": meta.get("model"),
            "context_pct": None,
            "turn_count": turn_stats.get("turn_count"),
            "last_meaningful_turn_at": turn_stats.get("last_meaningful_turn_at"),
            "capabilities": CODEX_READ_ONLY_CAPABILITIES,
            "controllability": {
                "can_send_text": False,
                "can_interrupt": False,
                "can_terminate": False,
                "reason": "Codex sessions are read-only until control metadata is captured.",
            },
        }
        state_payload = _codex_turn_state_payload(sid, apply_boundary=False)
        if state_payload:
            row["capabilities"] = CODEX_READ_ONLY_CAPABILITIES + ["live_state"]
            row["state"] = state_payload.get("state")
            row["tool"] = state_payload.get("tool")
            row["turn_started_at"] = state_payload.get("started_at")
            row["effort"] = state_payload.get("effort")
        matches_unidentified_terminal = sid in unidentified_live_rollout_ids
        pending_matches = pending_matches_by_rollout.get(sid) or []
        pending_match_id = (
            str(pending_matches[0].get("native_id") or "")
            if len(pending_matches) == 1
            else ""
        )
        matches_single_pending_registry = bool(
            pending_match_id
            and len(rollout_ids_by_pending.get(pending_match_id) or set()) == 1
        )
        verify_process = (
            sid not in degraded_live_native_ids
            and sid not in ambiguous_live_native_ids
        ) and (
            sid in exact_live_native_ids
            or sid in live_registry_ids
            or str(path) in live_transcript_path_set
            or matches_unidentified_terminal
            or matches_single_pending_registry
        )
        if verify_process:
            # Promotion writes through a fresh connection, then folds the
            # committed row into a replacement immutable view for the rest of
            # this response. Without this step the live-only check below could
            # consult the pre-promotion snapshot and drop the canonical row.
            refreshed_registry_row = None
            with _agent_registry_read_snapshot_disabled():
                refreshed_registry_row = _agent_registry_promote_codex(
                    row.get("native_id") or "",
                    row.get("project") or "",
                    float(row.get("started_at") or 0),
                    str(path),
                )
                refreshed_pid = int(
                    (refreshed_registry_row or {}).get("pid") or 0
                )
                if refreshed_pid and not _process_alive(refreshed_pid):
                    _agent_registry_mark_closed("codex", sid)
                    refreshed_registry_row = _agent_registry_get("codex", sid)
            if refreshed_registry_row:
                _agent_registry_read_snapshot_replace_after_write(
                    "codex",
                    refreshed_registry_row,
                )
            with _codex_preverified_registry_row(refreshed_registry_row):
                row = _codex_control_overlay(
                    row,
                    st.st_mtime,
                    verify_process=True,
                    observed_output_path=str(path),
                    inventory_live_terminal_rows=live_terminal_rows,
                )
        else:
            row = _codex_control_overlay(
                row,
                st.st_mtime,
                verify_process=False,
                observed_output_path=str(path),
                inventory_live_terminal_rows=live_terminal_rows,
            )
        if sid in ambiguous_live_native_ids:
            reason = (
                "More than one live terminal claims this Codex session; "
                "control is disabled until the identity conflict clears."
            )
            row["source_freshness"] = "identity_ambiguous"
            row["identity_conflict_count"] = exact_live_native_counts[sid]
            row["controllability"] = {
                "can_send_text": False,
                "can_interrupt": False,
                "can_terminate": False,
                "reason": reason,
            }
            row["capabilities"] = [
                capability
                for capability in (row.get("capabilities") or [])
                if capability not in {
                    "send_text",
                    "interrupt",
                    "terminate",
                    "terminal_control",
                }
            ]
        if live_only:
            control = row.get("controllability") or {}
            has_verified_action = any(
                bool(control.get(key))
                for key in ("can_send_text", "can_interrupt", "can_terminate")
            )
            control_reg = _agent_registry_get("codex", sid)
            has_verified_process = bool(
                control_reg
                and _codex_inventory_registry_process_matches(
                    control_reg, live_terminal_rows
                )
            )
            if row.get("closed_at") is not None or not (
                has_verified_action
                or has_verified_process
                or sid in degraded_live_native_ids
                or sid in ambiguous_live_native_ids
            ):
                continue
            if sid in degraded_live_native_ids and not (
                has_verified_action or has_verified_process
            ):
                row["source_freshness"] = "identity_probe_degraded"
                row["controllability"] = {
                    "can_send_text": False,
                    "can_interrupt": False,
                    "can_terminate": False,
                    "reason": "Live identity is being rechecked; this session is temporarily read-only.",
                }
        rows.append(row)
    # Terminal discovery can write or promote registry rows. Leave the
    # immutable read view before that work, then read the committed state.
    with _agent_registry_read_snapshot_disabled():
        _codex_register_terminal_only_rows(seen, live_terminal_rows)
        with _agent_registry_read_snapshot(
            "codex",
            active_within_min=active_within_min,
        ):
            rows.extend(_codex_pending_registry_rows(
                seen,
                live_only,
                active_within_min,
                live_terminal_rows,
            ))
            if not live_only:
                rows.extend(_codex_recent_closed_registry_rows(
                    seen,
                    active_within_min,
                    transcript_paths_by_id,
                ))
    rows = _filter_tombstoned_session_rows(rows)
    rows = _collapse_live_session_rows_by_terminal(rows)
    rows.sort(key=_session_meaningful_sort_key)
    # Callers own their response limits. Keeping the ranked provider candidates
    # here lets the 200-row dashboard and the mixed-provider 50-row endpoint
    # apply their caps only after cross-provider ordering.
    rows = rows[:500]
    return rows


def _session_removal_error(code: str, message: str, status: int, **details) -> dict:
    error = {"code": code, "message": message}
    error.update(details)
    return {"ok": False, "status": status, "error": error}


def _parse_session_removal_ref(raw: str) -> tuple[str, str, dict | None]:
    provider, native_id = _parse_agent_session_ref(str(raw or ""))
    if provider not in {"claude", "codex"}:
        return provider, native_id, _session_removal_error(
            "unsupported_provider",
            f"Session removal is not available for provider {provider or 'unknown'}.",
            422,
            provider=provider,
        )
    valid = _safe_session_id(native_id) if provider == "claude" else _safe_agent_native_id(native_id)
    if not valid:
        return provider, native_id, _session_removal_error(
            "invalid_session_id",
            "session_id must contain a provider and a valid provider-native id.",
            400,
        )
    return provider, native_id, None


def _codex_transcript_candidates(native_id: str) -> list[Path]:
    if not _safe_agent_native_id(native_id):
        return []
    candidates: dict[str, Path] = {}

    reg = _agent_registry_get("codex", native_id)
    if reg:
        metadata = _registry_metadata_from_row(reg)
        output_path = metadata.get("output_path")
        if isinstance(output_path, str) and output_path:
            approved = _approved_codex_transcript_path(Path(output_path), native_id)
            if approved is not None:
                candidates[str(approved)] = approved

    if CODEX_SESSIONS_DIR.is_dir():
        try:
            likely_paths = list(CODEX_SESSIONS_DIR.rglob(f"rollout-*{native_id}.jsonl"))
        except OSError:
            likely_paths = []
        for path in likely_paths + _codex_rollout_paths():
            approved = _approved_codex_transcript_path(path, native_id)
            if approved is not None:
                candidates[str(approved)] = approved
    return sorted(candidates.values(), key=lambda path: str(path))


def _approved_claude_transcript_path(record: dict) -> tuple[Path | None, dict | None]:
    native_id = str(record.get("native_id") or "")
    project = str(record.get("project") or "")
    claude_uuid = str(record.get("claude_uuid") or "")
    if not project or not claude_uuid:
        return None, _session_removal_error(
            "transcript_identity_missing",
            "The session registry does not contain an exact transcript identity.",
            409,
            session_id=_qualified_session_id("claude", native_id),
        )
    backend = _claude_sessions_backend()
    references = sorted(set(backend.session_ids_for_uuid(claude_uuid)))
    if native_id not in references:
        return None, _session_removal_error(
            "transcript_identity_unverified",
            "Pairling could not verify the Claude transcript against the session registry.",
            503,
            session_id=_qualified_session_id("claude", native_id),
        )
    if any(value != native_id for value in references):
        return None, _session_removal_error(
            "transcript_path_ambiguous",
            "More than one session registry row refers to this Claude transcript.",
            409,
            session_id=_qualified_session_id("claude", native_id),
        )

    projects_root = HOME / ".claude" / "projects"
    candidate = projects_root / _encode_project_dir(project) / f"{claude_uuid}.jsonl"
    try:
        if candidate.is_symlink():
            raise ValueError("symlink")
        root = projects_root.resolve(strict=True)
        resolved = candidate.resolve(strict=True)
        resolved.relative_to(root)
    except FileNotFoundError:
        return None, _session_removal_error(
            "transcript_not_found",
            "The exact Claude transcript is no longer present on this Mac.",
            404,
            session_id=_qualified_session_id("claude", native_id),
        )
    except (OSError, ValueError):
        return None, _session_removal_error(
            "transcript_path_unsafe",
            "The Claude transcript path did not pass the local safety check.",
            409,
            session_id=_qualified_session_id("claude", native_id),
        )
    if not resolved.is_file() or resolved.name != f"{claude_uuid}.jsonl":
        return None, _session_removal_error(
            "transcript_path_unsafe",
            "The Claude transcript path did not resolve to the expected JSONL file.",
            409,
            session_id=_qualified_session_id("claude", native_id),
        )
    return resolved, None


def _exact_session_transcript(provider: str, native_id: str, record: dict) -> tuple[Path | None, dict | None]:
    if provider == "claude":
        return _approved_claude_transcript_path(record)
    candidates = _codex_transcript_candidates(native_id)
    if not candidates:
        return None, _session_removal_error(
            "transcript_not_found",
            "The exact Codex transcript is no longer present on this Mac.",
            404,
            session_id=_qualified_session_id(provider, native_id),
        )
    if len(candidates) != 1:
        return None, _session_removal_error(
            "transcript_path_ambiguous",
            "More than one Codex transcript matches this session id.",
            409,
            session_id=_qualified_session_id(provider, native_id),
        )
    return candidates[0], None


def _session_mutation_record(provider: str, native_id: str) -> dict | None:
    if provider == "claude":
        return _claude_sessions_backend().session_record(native_id)
    record = _agent_registry_get("codex", native_id)
    if record:
        result = dict(record)
        result["provider"] = "codex"
        result["pid"] = int(result.get("pid") or 0)
        return result
    candidates = _codex_transcript_candidates(native_id)
    if not candidates:
        return None
    try:
        selected_path = max(candidates, key=lambda path: path.stat().st_mtime)
        stat = selected_path.stat()
    except OSError:
        return None
    metadata = _codex_rollout_meta(selected_path) or {}
    return {
        "provider": "codex",
        "native_id": native_id,
        "pid": 0,
        "terminal_tty": "",
        "last_heartbeat": int(stat.st_mtime),
        "closed_at": int(stat.st_mtime),
        "virtual_transcript_record": True,
        "project": str(metadata.get("cwd") or ""),
    }


def _session_record_is_active(provider: str, native_id: str, record: dict) -> bool:
    pid = int(record.get("pid") or record.get("claude_pid") or 0)
    if pid > 0 and _session_has_verified_provider_process(record, provider):
        return True
    # Inventory failure must not turn a still-live, birth-matched process into
    # permission to delete its transcript.
    if (
        pid > 0
        and _registry_process_birth_matches(record, pid)
        and _process_alive(pid)
    ):
        return True
    qualified = _qualified_session_id(provider, native_id)
    if PTY_BROKER is not None:
        try:
            if PTY_BROKER.get(qualified) is not None:
                return True
        except Exception:
            pass
        tty = str(record.get("terminal_tty") or "")
        if tty:
            try:
                if PTY_BROKER.get_by_tty(tty) is not None:
                    return True
            except Exception:
                pass
    if provider == "codex" and record.get("virtual_transcript_record"):
        project = str(record.get("project") or "")
        if project and any(
            str(candidate.get("project") or "") == project
            for candidate in _codex_live_terminal_rows()
        ):
            return True
    if record.get("closed_at") is not None:
        return False
    heartbeat = float(record.get("last_heartbeat") or 0)
    return heartbeat > 0 and (_time.time() - heartbeat) <= 120


def _close_nonrunning_session_record(provider: str, native_id: str, record: dict) -> tuple[dict | None, dict | None]:
    if record.get("closed_at") is not None or record.get("virtual_transcript_record"):
        return record, None
    if provider == "claude":
        _claude_sessions_backend().tombstone_sessions([native_id])
    else:
        _agent_registry_mark_closed("codex", native_id)
    refreshed = _session_mutation_record(provider, native_id)
    if refreshed is None or refreshed.get("closed_at") is None:
        return None, _session_removal_error(
            "session_close_failed",
            "Pairling could not close the non-running registry row before removal.",
            503,
            session_id=_qualified_session_id(provider, native_id),
        )
    if _session_record_is_active(provider, native_id, refreshed):
        return None, _session_removal_error(
            "session_active",
            "The session became active while Pairling was preparing the removal.",
            409,
            session_id=_qualified_session_id(provider, native_id),
        )
    return refreshed, None


def _delete_session_registry_record(provider: str, native_id: str) -> bool:
    if provider == "claude":
        return _claude_sessions_backend().delete_registry_record(native_id)
    try:
        with _agent_registry_conn() as conn:
            conn.execute(
                "DELETE FROM agent_sessions WHERE provider = 'codex' AND native_id = ?",
                (native_id,),
            )
        return True
    except Exception:
        return False


def _session_registry_identity(record: dict | None) -> dict | None:
    if not isinstance(record, dict):
        return None
    metadata = str(record.get("metadata_json") or "")
    return {
        "provider": str(record.get("provider") or ""),
        "native_id": str(record.get("native_id") or record.get("id") or ""),
        "pid": int(record.get("pid") or record.get("claude_pid") or 0),
        "terminal_tty": str(record.get("terminal_tty") or ""),
        "closed_at": float(record["closed_at"]) if record.get("closed_at") is not None else None,
        "last_heartbeat": float(record.get("last_heartbeat") or 0.0),
        "claude_uuid": str(record.get("claude_uuid") or ""),
        "metadata_sha256": hashlib.sha256(metadata.encode("utf-8")).hexdigest(),
        "virtual": bool(record.get("virtual_transcript_record")),
    }


def _session_file_identity(path: Path) -> dict:
    stat = path.stat()
    return {
        "dev": int(stat.st_dev),
        "ino": int(stat.st_ino),
        "size": int(stat.st_size),
        "mtime_ns": int(stat.st_mtime_ns),
    }


def _session_file_identity_matches(path: Path, expected: dict) -> bool:
    try:
        current = _session_file_identity(path)
    except OSError:
        return False
    return all(current.get(key) == expected.get(key) for key in ("dev", "ino", "size", "mtime_ns"))


def _delete_session_registry_record_if_unchanged(
    provider: str,
    native_id: str,
    expected: dict | None,
) -> bool:
    if expected is None:
        return False
    if expected.get("virtual"):
        return _agent_registry_get(provider, native_id) is None
    if provider == "claude" and _session_backend() == "pg":
        current = _session_mutation_record(provider, native_id)
        if _session_registry_identity(current) != expected:
            return False
        return _delete_session_registry_record(provider, native_id)
    try:
        with _agent_registry_conn() as conn:
            row = conn.execute(
                "SELECT * FROM agent_sessions WHERE provider=? AND native_id=? LIMIT 1",
                (provider, native_id),
            ).fetchone()
            if row is None:
                return True
            if _session_registry_identity(dict(row)) != expected:
                return False
            cursor = conn.execute(
                "DELETE FROM agent_sessions WHERE provider=? AND native_id=?",
                (provider, native_id),
            )
            return cursor.rowcount == 1
    except Exception:
        return False


def _planned_trash_destination(path: Path, provider: str) -> Path:
    trash = HOME / ".Trash"
    if trash.is_symlink():
        raise OSError("Trash directory is a symlink")
    trash.mkdir(mode=0o700, parents=True, exist_ok=True)
    if not trash.is_dir():
        raise OSError("Trash directory is unavailable")

    base = f"Pairling-{provider}-{path.stem}-{secrets.token_hex(8)}{path.suffix}"
    return trash / base


def _trash_destination_from_receipt(name: str) -> Path:
    if not name or Path(name).name != name or len(name) > 300:
        raise OSError("invalid planned Trash name")
    trash = HOME / ".Trash"
    if trash.is_symlink() or not trash.is_dir():
        raise OSError("Trash directory is unavailable")
    return trash / name


def _trash_transcript(path: Path, destination: Path, expected_identity: dict) -> Path:
    if destination.exists():
        try:
            if destination.stat().st_size == 0 and path.exists():
                destination.unlink()
            else:
                raise FileExistsError("planned Trash destination already exists")
        except OSError:
            raise
    if not _session_file_identity_matches(path, expected_identity):
        raise OSError("transcript identity changed before move")

    placeholder_fd = os.open(destination, os.O_WRONLY | os.O_CREAT | os.O_EXCL, 0o600)
    os.close(placeholder_fd)
    try:
        os.replace(path, destination)
    except Exception:
        try:
            destination.unlink(missing_ok=True)
        except OSError:
            pass
        raise
    if not _session_file_identity_matches(destination, expected_identity):
        # The source path changed after the preflight check. Put the exact
        # object we moved back before returning a conflict.
        if path.exists():
            raise OSError("transcript identity changed during move; source path was recreated")
        try:
            os.replace(destination, path)
        except OSError as error:
            raise OSError("transcript identity changed during move and restore failed") from error
        raise OSError("transcript identity changed during move; source restored")
    return destination


def _rollback_transcript_move(source: Path, destination: Path, expected_identity: dict) -> bool:
    if source.exists() or not _session_file_identity_matches(destination, expected_identity):
        return False
    try:
        os.replace(destination, source)
    except OSError:
        return False
    return _session_file_identity_matches(source, expected_identity)


def _restore_unverified_transcript_move(source: Path, destination: Path) -> bool:
    """Restore a moved inode that changed after the first post-move check."""
    if source.exists() or not destination.exists():
        return False
    try:
        os.replace(destination, source)
    except OSError:
        return False
    return source.exists() and not destination.exists()


def _purge_session_event_state(session_key: str) -> dict:
    with _SESSION_LOG_INGESTOR_LOCK:
        ingestor = _SESSION_LOG_INGESTOR
    if ingestor is not None:
        ingestor.remove(session_key)
    log = _ensure_session_event_log()
    return log.purge_session(session_key) if log is not None else {"events": 0, "cursors": 0}


def _pending_delete_error(
    code: str,
    message: str,
    status: int,
    *,
    session_id: str,
    receipt: dict,
) -> dict:
    return _session_removal_error(
        code,
        message,
        status,
        session_id=session_id,
        recovery_pending=True,
        trash_name=receipt.get("planned_trash_name"),
        operation_id=receipt.get("operation_id"),
    )


def _complete_pending_session_delete(
    provider: str,
    native_id: str,
    receipt: dict,
) -> dict:
    session_id = _qualified_session_id(provider, native_id)
    operation_id = str(receipt.get("operation_id") or "")
    source_path = str(receipt.get("source_path") or "")
    expected_file = receipt.get("source_identity")
    expected_registry = receipt.get("registry_identity")
    planned_name = str(receipt.get("planned_trash_name") or "")
    if (
        not operation_id
        or not source_path
        or not isinstance(expected_file, dict)
        or not isinstance(expected_registry, dict)
    ):
        return _pending_delete_error(
            "delete_receipt_invalid",
            "The pending transcript deletion receipt is incomplete.",
            500,
            session_id=session_id,
            receipt=receipt,
        )
    source = Path(source_path)
    try:
        destination = _trash_destination_from_receipt(planned_name)
    except OSError:
        return _pending_delete_error(
            "delete_receipt_invalid",
            "The pending transcript deletion has an invalid Trash destination.",
            500,
            session_id=session_id,
            receipt=receipt,
        )

    source_matches = _session_file_identity_matches(source, expected_file)
    destination_matches = _session_file_identity_matches(destination, expected_file)
    if source.exists() and destination_matches:
        return _pending_delete_error(
            "delete_recovery_conflict",
            "Both the source transcript and its moved copy exist. Pairling refused to overwrite either file.",
            409,
            session_id=session_id,
            receipt=receipt,
        )

    record = _session_mutation_record(provider, native_id)
    if not destination_matches:
        if not source_matches:
            if source.exists() and not destination.exists():
                try:
                    _rollback_session_tombstone(
                        provider, native_id, operation_id=operation_id
                    )
                except (OSError, SessionTombstoneStoreError):
                    pass
                return _session_removal_error(
                    "transcript_identity_changed",
                    "The transcript changed while Pairling was preparing deletion.",
                    409,
                    session_id=session_id,
                )
            return _pending_delete_error(
                "delete_recovery_missing_file",
                "Pairling cannot find either the original transcript or the planned Trash copy.",
                500,
                session_id=session_id,
                receipt=receipt,
            )
        if (
            record is None
            or _session_registry_identity(record) != expected_registry
            or _session_record_is_active(provider, native_id, record)
        ):
            try:
                _rollback_session_tombstone(provider, native_id, operation_id=operation_id)
            except (OSError, SessionTombstoneStoreError):
                pass
            return _session_removal_error(
                "session_changed_during_delete",
                "The session changed or became active before its transcript moved.",
                409,
                session_id=session_id,
            )
        with _SESSION_LOG_INGESTOR_LOCK:
            ingestor = _SESSION_LOG_INGESTOR
        if ingestor is not None:
            ingestor.remove(session_id)
        try:
            destination = _trash_transcript(source, destination, expected_file)
        except OSError as error:
            source_restored = source.exists() and not destination.exists()
            receipt_rolled_back = False
            if source_restored:
                try:
                    receipt_rolled_back = _rollback_session_tombstone(
                        provider, native_id, operation_id=operation_id
                    )
                except (OSError, SessionTombstoneStoreError):
                    receipt_rolled_back = False
            if source_restored and receipt_rolled_back:
                identity_changed = not _session_file_identity_matches(
                    source, expected_file
                )
                return _session_removal_error(
                    "transcript_identity_changed" if identity_changed else "transcript_move_failed",
                    (
                        "The transcript changed while Pairling was preparing deletion."
                        if identity_changed
                        else f"Pairling could not move the transcript to Trash: {str(error)[:160]}"
                    ),
                    409 if identity_changed else 500,
                    session_id=session_id,
                )
            return _pending_delete_error(
                "transcript_move_failed",
                f"Pairling could not move the transcript to Trash: {str(error)[:160]}",
                500,
                session_id=session_id,
                receipt=receipt,
            )
        destination_matches = _session_file_identity_matches(destination, expected_file)
        if not destination_matches:
            restored = _restore_unverified_transcript_move(source, destination)
            receipt_rolled_back = False
            if restored:
                try:
                    receipt_rolled_back = _rollback_session_tombstone(
                        provider, native_id, operation_id=operation_id
                    )
                    if not receipt_rolled_back:
                        receipt_rolled_back = _session_tombstone(provider, native_id) is None
                except (OSError, SessionTombstoneStoreError):
                    receipt_rolled_back = False
            if restored and receipt_rolled_back:
                return _session_removal_error(
                    "transcript_identity_changed",
                    "The transcript changed while Pairling was moving it. Pairling restored the file and stopped deletion.",
                    409,
                    session_id=session_id,
                )
            return _pending_delete_error(
                "transcript_move_unverified",
                "The moved transcript changed and Pairling could not restore it automatically.",
                500,
                session_id=session_id,
                receipt=receipt,
            )

    current_record = _session_mutation_record(provider, native_id)
    if current_record is not None:
        registry_unchanged = _session_registry_identity(current_record) == expected_registry
        active_now = _session_record_is_active(provider, native_id, current_record)
        if active_now or not registry_unchanged:
            rolled_back = _rollback_transcript_move(source, destination, expected_file)
            receipt_rolled_back = False
            if rolled_back:
                try:
                    receipt_rolled_back = _rollback_session_tombstone(
                        provider, native_id, operation_id=operation_id
                    )
                    if not receipt_rolled_back:
                        receipt_rolled_back = _session_tombstone(provider, native_id) is None
                except (OSError, SessionTombstoneStoreError):
                    receipt_rolled_back = False
            if rolled_back and receipt_rolled_back:
                return _session_removal_error(
                    "session_changed_during_delete",
                    "The session changed while its transcript was moving. Pairling restored the transcript and refused registry deletion.",
                    409,
                    session_id=session_id,
                )
            return _pending_delete_error(
                "session_changed_during_delete",
                "The session changed while its transcript was moving. Pairling refused registry deletion.",
                409,
                session_id=session_id,
                receipt=receipt,
            )
        if not _delete_session_registry_record_if_unchanged(
            provider, native_id, expected_registry
        ):
            rolled_back = _rollback_transcript_move(source, destination, expected_file)
            receipt_rolled_back = False
            if rolled_back:
                try:
                    receipt_rolled_back = _rollback_session_tombstone(
                        provider, native_id, operation_id=operation_id
                    )
                    if not receipt_rolled_back:
                        receipt_rolled_back = _session_tombstone(provider, native_id) is None
                except (OSError, SessionTombstoneStoreError):
                    receipt_rolled_back = False
            if rolled_back and receipt_rolled_back:
                return _session_removal_error(
                    "registry_identity_changed",
                    "The session registry changed before deletion could finish. Pairling restored the transcript.",
                    409,
                    session_id=session_id,
                )
            return _pending_delete_error(
                "registry_identity_changed",
                "The session registry changed before deletion could finish.",
                409,
                session_id=session_id,
                receipt=receipt,
            )

    try:
        purged = _purge_session_event_state(session_id)
    except Exception as error:
        return _pending_delete_error(
            "event_log_purge_failed",
            f"The transcript moved, but Pairling could not purge its event log: {str(error)[:160]}",
            500,
            session_id=session_id,
            receipt=receipt,
        )
    try:
        _record_session_tombstone(
            provider,
            native_id,
            action="transcript_deleted",
            updates={
                "operation_id": operation_id,
                "transcript_deleted_at": _time.time(),
                "trash_name": destination.name,
                "planned_trash_name": destination.name,
                "event_rows_purged": int(purged.get("events") or 0),
                "event_cursor_purged": bool(purged.get("cursors")),
                "rollback_receipt": None,
            },
        )
    except (OSError, SessionTombstoneStoreError):
        return _pending_delete_error(
            "tombstone_write_failed_after_move",
            "The transcript moved to Trash, but Pairling could not save the final receipt.",
            500,
            session_id=session_id,
            receipt=receipt,
        )

    _invalidate_session_list_caches()
    _publish_session_event(SESSION_SUMMARIES_TOPIC, {
        "type": "session_removed",
        "provider": provider,
        "native_id": native_id,
        "transcript": "moved_to_trash",
    })
    return {
        "ok": True,
        "status": 200,
        "session_id": session_id,
        "provider": provider,
        "native_id": native_id,
        "removed": True,
        "transcript": "moved_to_trash",
        "trash_name": destination.name,
        "event_rows_purged": int(purged.get("events") or 0),
    }


def _remove_session(provider_ref: str, *, delete_transcript: bool) -> dict:
    provider, native_id, error = _parse_session_removal_ref(provider_ref)
    if error is not None:
        return error
    requested_native_id = native_id
    session_id = _qualified_session_id(provider, requested_native_id)
    if provider == "codex":
        native_id = _agent_registry_resolve_native_alias(provider, native_id)
        if not native_id:
            return _session_removal_error(
                "session_not_found",
                "Pairling could not find this session in the Mac registry or transcript store.",
                404,
                session_id=session_id,
            )

    def externalize(result: dict) -> dict:
        if requested_native_id == native_id:
            return result
        response = dict(result)
        response["session_id"] = session_id
        if "native_id" in response:
            response["native_id"] = requested_native_id
        return response

    with _SESSION_TOMBSTONES_LOCK:
        try:
            existing = _session_tombstone(provider, native_id)
        except SessionTombstoneStoreError as error:
            return _session_removal_error(
                "tombstone_store_unavailable",
                str(error),
                503,
                session_id=session_id,
            )
        if delete_transcript and existing and existing.get("action") == "delete_pending":
            return externalize(
                _complete_pending_session_delete(provider, native_id, existing)
            )
        record = _session_mutation_record(provider, native_id)
        if record is None:
            if existing and (not delete_transcript or existing.get("transcript_deleted_at")):
                return {
                    "ok": True,
                    "status": 200,
                    "session_id": session_id,
                    "provider": provider,
                    "native_id": requested_native_id,
                    "removed": True,
                    "transcript": "moved_to_trash" if existing.get("transcript_deleted_at") else "kept",
                    "trash_name": existing.get("trash_name"),
                    "idempotent": True,
                }
            return _session_removal_error(
                "session_not_found",
                "Pairling could not find this session in the Mac registry or transcript store.",
                404,
                session_id=session_id,
            )
        if _session_record_is_active(provider, native_id, record):
            return _session_removal_error(
                "session_active",
                "Stop or close the session on the Mac before removing it.",
                409,
                session_id=session_id,
            )
        record, close_error = _close_nonrunning_session_record(provider, native_id, record)
        if close_error is not None:
            return close_error

        if not delete_transcript:
            try:
                _record_session_tombstone(provider, native_id, action="removed")
            except (OSError, SessionTombstoneStoreError):
                return _session_removal_error(
                    "tombstone_write_failed",
                    "Pairling could not save the durable removal on this Mac.",
                    500,
                    session_id=session_id,
                )
            _invalidate_session_list_caches()
            _publish_session_event(SESSION_SUMMARIES_TOPIC, {
                "type": "session_removed",
                "provider": provider,
                "native_id": native_id,
                "transcript": "kept",
            })
            return {
                "ok": True,
                "status": 200,
                "session_id": session_id,
                "provider": provider,
                "native_id": requested_native_id,
                "removed": True,
                "transcript": "kept",
            }

        if existing and existing.get("transcript_deleted_at"):
            _purge_session_event_state(session_id)
            _invalidate_session_list_caches()
            return {
                "ok": True,
                "status": 200,
                "session_id": session_id,
                "provider": provider,
                "native_id": requested_native_id,
                "removed": True,
                "transcript": "moved_to_trash",
                "trash_name": existing.get("trash_name"),
                "idempotent": True,
            }

        transcript_path, transcript_error = _exact_session_transcript(provider, native_id, record or {})
        if transcript_error is not None:
            return transcript_error
        try:
            source_identity = _session_file_identity(transcript_path)
            destination = _planned_trash_destination(transcript_path, provider)
        except OSError:
            return _session_removal_error(
                "transcript_identity_unavailable",
                "Pairling could not establish a stable transcript identity.",
                409,
                session_id=session_id,
            )
        operation_id = secrets.token_hex(16)
        registry_identity = _session_registry_identity(record)
        try:
            pending = _record_session_tombstone(
                provider,
                native_id,
                action="delete_pending",
                updates={
                    "operation_id": operation_id,
                    "source_path": str(transcript_path),
                    "source_identity": source_identity,
                    "registry_identity": registry_identity,
                    "planned_trash_name": destination.name,
                    "rollback_receipt": dict(existing) if isinstance(existing, dict) else None,
                },
            )
        except (OSError, SessionTombstoneStoreError):
            return _session_removal_error(
                "tombstone_write_failed",
                "Pairling could not save the durable removal before moving the transcript.",
                500,
                session_id=session_id,
            )
        return externalize(
            _complete_pending_session_delete(provider, native_id, pending)
        )


def _text_from_codex_value(value) -> str:
    if value is None:
        return ""
    if isinstance(value, str):
        return value
    if isinstance(value, list):
        pieces: list[str] = []
        for item in value:
            if isinstance(item, dict):
                t = item.get("text") or item.get("content") or item.get("output_text")
                if isinstance(t, str):
                    pieces.append(t)
            elif isinstance(item, str):
                pieces.append(item)
        return "\n".join(pieces) if pieces else _compact_json_text(value)
    if isinstance(value, dict):
        for key in ("text", "message", "content", "output_text"):
            if isinstance(value.get(key), str):
                return value[key]
        try:
            return json.dumps(value, ensure_ascii=False)
        except Exception:
            return str(value)
    return str(value)


def _codex_content_blocks(content) -> list[dict]:
    if isinstance(content, str):
        return [{"type": "text", "text": content}]
    if isinstance(content, list):
        blocks: list[dict] = []
        for item in content:
            if not isinstance(item, dict):
                if isinstance(item, str):
                    blocks.append({"type": "text", "text": item})
                continue
            typ = item.get("type")
            if typ in ("text", "output_text", "input_text"):
                text = item.get("text") or item.get("content") or ""
                if text:
                    blocks.append({"type": "text", "text": text})
            elif typ == "reasoning":
                text = _text_from_codex_value(item.get("summary") or item.get("content"))
                if text:
                    blocks.append({"type": "thinking", "thinking": text})
            else:
                text = item.get("text") or item.get("content")
                if isinstance(text, str) and text:
                    blocks.append({"type": "text", "text": text})
        return blocks
    text = _text_from_codex_value(content)
    return [{"type": "text", "text": text}] if text else []


def _codex_tool_input(value) -> dict:
    if isinstance(value, dict):
        return value
    if isinstance(value, str):
        try:
            parsed = json.loads(value)
        except (ValueError, json.JSONDecodeError):
            parsed = None
        if isinstance(parsed, dict):
            return parsed
        if parsed is not None:
            return {"input": parsed}
        return {"input": value}
    if value is None:
        return {}
    return {"input": value}


def _codex_row_semantic_key(role: str, blocks: list[dict]) -> str:
    parts: list[str] = [role]
    for block in blocks:
        if not isinstance(block, dict):
            continue
        btype = str(block.get("type") or "")
        parts.append(btype)
        if btype == "text":
            parts.append(_text_from_codex_value(block.get("text")).strip())
        elif btype == "thinking":
            parts.append(_text_from_codex_value(block.get("thinking")).strip())
        elif btype == "tool_use":
            parts.append(str(block.get("id") or ""))
            parts.append(str(block.get("name") or ""))
        elif btype == "tool_result":
            parts.append(str(block.get("tool_use_id") or ""))
            parts.append(_text_from_codex_value(block.get("content")).strip())
        else:
            parts.append(_text_from_codex_value(block).strip())
    digest = hashlib.sha256("\x1f".join(parts).encode("utf-8", errors="replace")).hexdigest()
    return digest[:24]


def _strip_codex_row_metadata(row: dict) -> dict:
    if "_codex_source" not in row and "_codex_semantic_key" not in row:
        return row
    clean = dict(row)
    clean.pop("_codex_source", None)
    clean.pop("_codex_semantic_key", None)
    return clean


def _normalize_codex_line(
    line: str | bytes,
    session_id: str,
    *,
    include_event_messages: bool = False,
    with_metadata: bool = False,
) -> list[dict]:
    if isinstance(line, bytes):
        line = line.decode("utf-8", errors="replace")
    if not line.strip():
        return []
    try:
        obj = json.loads(line)
    except (ValueError, json.JSONDecodeError):
        return []
    ts = obj.get("timestamp")
    payload = obj.get("payload") if isinstance(obj.get("payload"), dict) else {}
    typ = obj.get("type")
    rows: list[dict] = []

    def row(role: str, blocks: list[dict], suffix: str, source: str) -> None:
        if not blocks:
            return
        stable = hashlib.sha256((line + suffix).encode("utf-8", errors="replace")).hexdigest()[:16]
        out = {
            "uuid": f"codex-{stable}",
            "type": role,
            "timestamp": ts,
            "sessionId": _qualified_session_id("codex", session_id),
            "message": {
                "role": role,
                "content": blocks,
            },
        }
        if with_metadata:
            out["_codex_source"] = source
            out["_codex_semantic_key"] = _codex_row_semantic_key(role, blocks)
        rows.append(out)

    if typ == "event_msg":
        if not include_event_messages:
            return rows
        event_type = payload.get("type")
        if event_type == "user_message":
            text = _text_from_codex_value(payload.get("message") or payload.get("text") or payload.get("content"))
            row("user", [{"type": "text", "text": text}], "user", "event_msg")
        elif event_type == "agent_message":
            text = _text_from_codex_value(payload.get("message") or payload.get("text") or payload.get("content"))
            row("assistant", [{"type": "text", "text": text}], "agent", "event_msg")
        elif event_type == "exec_command_end":
            text = _text_from_codex_value(payload.get("aggregated_output") or payload.get("stdout") or payload)
            row("assistant", [{"type": "tool_result", "tool_use_id": payload.get("call_id"), "content": text}], "exec-end", "event_msg")
        return rows

    if typ != "response_item":
        return rows

    item_type = payload.get("type")
    if item_type == "message":
        role = payload.get("role")
        if role not in ("user", "assistant"):
            return rows
        blocks = _codex_content_blocks(payload.get("content"))
        row(role, blocks, "message", "response_item")
    elif item_type == "reasoning":
        text = _text_from_codex_value(payload.get("summary") or payload.get("content"))
        if text:
            row("assistant", [{"type": "thinking", "thinking": text}], "reasoning", "response_item")
    elif item_type == "function_call":
        args = payload.get("arguments") or payload.get("input") or {}
        if isinstance(args, str):
            try:
                args = json.loads(args)
            except (ValueError, json.JSONDecodeError):
                args = {"arguments": args}
        row("assistant", [{
            "type": "tool_use",
            "id": payload.get("call_id") or payload.get("id"),
            "name": payload.get("name") or payload.get("tool_name") or "tool",
            "input": args,
        }], "tool-use", "response_item")
    elif item_type == "function_call_output":
        content = payload.get("output") or payload.get("content") or payload.get("tool_response")
        row("assistant", [{
            "type": "tool_result",
            "tool_use_id": payload.get("call_id") or payload.get("tool_use_id"),
            "content": _text_from_codex_value(content),
        }], "tool-result", "response_item")
    elif item_type in ("custom_tool_call", "tool_search_call"):
        call_id = payload.get("call_id") or payload.get("id")
        name = payload.get("name") or ("tool_search" if item_type == "tool_search_call" else "tool")
        tool_input = payload.get("input")
        if tool_input is None:
            tool_input = payload.get("arguments") or payload.get("execution")
        row("assistant", [{
            "type": "tool_use",
            "id": call_id,
            "name": name,
            "input": _codex_tool_input(tool_input),
        }], f"{item_type}-call", "response_item")
    elif item_type in ("custom_tool_call_output", "tool_search_output"):
        content = payload.get("output")
        if content is None:
            content = payload.get("tools") or payload.get("execution") or payload
        row("assistant", [{
            "type": "tool_result",
            "tool_use_id": payload.get("call_id") or payload.get("id"),
            "content": _text_from_codex_value(content),
        }], f"{item_type}-result", "response_item")
    elif item_type == "web_search_call":
        call_id = payload.get("id") or payload.get("call_id")
        if not call_id:
            stable = hashlib.sha256((line + "web-search-call").encode(
                "utf-8", errors="replace"
            )).hexdigest()[:16]
            call_id = f"codex-web-{stable}"
        blocks = [{
            "type": "tool_use",
            "id": call_id,
            "name": "web_search",
            "input": _codex_tool_input(payload.get("action")),
        }]
        if payload.get("status") in ("completed", "failed", "cancelled"):
            blocks.append({
                "type": "tool_result",
                "tool_use_id": call_id,
                "content": f"Search {payload.get('status')}.",
                "is_error": payload.get("status") == "failed",
            })
        row("assistant", blocks, "web-search", "response_item")
    elif item_type == "agent_message":
        content = _text_from_codex_value(payload.get("content"))
        author = str(payload.get("author") or "agent")
        recipient = str(payload.get("recipient") or "")
        direction = f"{author} to {recipient}" if recipient else author
        if content:
            row("assistant", [{"type": "text", "text": f"{direction}: {content}"}],
                "agent-message", "response_item")
    elif item_type:
        call_id = payload.get("call_id") or payload.get("id") or f"codex-{item_type}"
        visible = {
            key: value for key, value in payload.items()
            if key not in ("type", "internal_chat_message_metadata_passthrough")
        }
        blocks = [{
            "type": "tool_use",
            "id": call_id,
            "name": str(item_type),
            "input": visible,
        }]
        if payload.get("status") in ("completed", "failed", "cancelled"):
            result = payload.get("output") or payload.get("summary") or payload.get("error") or payload.get("status")
            blocks.append({
                "type": "tool_result",
                "tool_use_id": call_id,
                "content": _text_from_codex_value(result),
                "is_error": payload.get("status") == "failed",
            })
        row("assistant", blocks, f"generic-{item_type}", "response_item")
    return rows


def _normalize_codex_ndjson(
    data: bytes | str,
    session_id: str,
    *,
    include_event_fallback: bool = True,
) -> str:
    if isinstance(data, bytes):
        text = data.decode("utf-8", errors="replace")
    else:
        text = data
    rows: list[dict] = []
    canonical_keys: set[str] = set()
    for line in text.splitlines():
        for row in _normalize_codex_line(
            line,
            session_id,
            include_event_messages=include_event_fallback,
            with_metadata=True,
        ):
            if row.get("_codex_source") != "event_msg":
                key = row.get("_codex_semantic_key")
                if isinstance(key, str):
                    canonical_keys.add(key)
            rows.append(row)
    out: list[str] = []
    for row in rows:
        if row.get("_codex_source") == "event_msg":
            key = row.get("_codex_semantic_key")
            if isinstance(key, str) and key in canonical_keys:
                continue
        out.append(json.dumps(_strip_codex_row_metadata(row), ensure_ascii=False))
    return "\n".join(out) + ("\n" if out else "")


TRANSCRIPT_HARNESS_BLOCK_TAGS = (
    "system-reminder",
    "task-notification",
    "persisted-output",
    "command-name",
    "command-message",
    "command-args",
    "local-command-caveat",
    "local-command-stdout",
    "local-command-stderr",
    "oai-mem-citation",
)

_TRANSCRIPT_EXPORT_CLEANUP_PATTERNS = [
    (re.compile(r"\[Image: source: /(?:Users|var|tmp|private)/[^\]]+\]\s*"), ""),
    (re.compile(r"^\s*Output too large.*$\n?", re.MULTILINE), ""),
    (re.compile(r"^\s*Preview \(first.*$\n?", re.MULTILINE), ""),
]


def _strip_transcript_harness_blocks(text: str) -> str:
    for tag in TRANSCRIPT_HARNESS_BLOCK_TAGS:
        escaped = re.escape(tag)
        text = re.sub(rf"<{escaped}>.*?</{escaped}>\s*", "", text, flags=re.DOTALL)
    return text


def _clean_transcript_export_text(text: str) -> str:
    if not isinstance(text, str):
        return ""
    text = _strip_transcript_harness_blocks(text)
    for pat, repl in _TRANSCRIPT_EXPORT_CLEANUP_PATTERNS:
        text = pat.sub(repl, text)
    # Strip standalone "." lines — bracketed-paste flush artifact.
    text = re.sub(r"^\s*\.\s*$", "", text, flags=re.MULTILINE)
    # Collapse runs of blank lines.
    text = re.sub(r"\n{3,}", "\n\n", text).strip()
    return text




_ABSOLUTE_PATH_ROOT_TOKENS = {
    "Applications",
    "Library",
    "System",
    "Users",
    "Volumes",
    "bin",
    "dev",
    "etc",
    "home",
    "opt",
    "private",
    "sbin",
    "tmp",
    "usr",
    "var",
}


def _is_direct_slash_invocation_text(text: str) -> bool:
    """Identify slash commands that need keystroke rather than paste semantics."""
    if "\n" in text or not text.startswith("/") or text.startswith("//"):
        return False
    token = text.split(maxsplit=1)[0]
    if "/" in token[1:]:
        return False
    command = token[1:]
    if not command or command in _ABSOLUTE_PATH_ROOT_TOKENS:
        return False
    return bool(
        re.fullmatch(r"[A-Za-z][A-Za-z0-9_-]*(?::[A-Za-z][A-Za-z0-9_-]*)*", command)
    )


def _peek_cwd_from_transcript(path: Path) -> str:
    """Return the `cwd` from the first transcript line that has one, else empty string."""
    try:
        for line in _iter_jsonl_prefix_lines(path, max_lines=31):
            try:
                obj = json.loads(line)
            except Exception:
                continue
            cwd = obj.get("cwd")
            if isinstance(cwd, str) and cwd:
                return cwd
    except Exception:
        pass
    return ""


def _peek_first_prompt(path: Path, max_chars: int = 200) -> str | None:
    """Return the first real (non-slash-command, non-system) user prompt as a snippet."""
    try:
        for line in _iter_jsonl_prefix_lines(path, max_lines=201):
            try:
                obj = json.loads(line)
            except Exception:
                continue
            if obj.get("type") != "user":
                continue
            msg = obj.get("message") or {}
            content = msg.get("content")
            text = content if isinstance(content, str) else None
            if isinstance(content, list):
                pieces = []
                for block in content:
                    if not isinstance(block, dict):
                        continue
                    if str(block.get("type") or "text") not in {
                        "text", "input_text", "output_text"
                    }:
                        continue
                    value = block.get("text") or block.get("content")
                    if isinstance(value, str):
                        pieces.append(value)
                text = "\n".join(pieces) if pieces else None
            if not text:
                continue
            stripped = text.strip()
            if not stripped:
                continue
            # Skip slash-command boilerplate / hook injections — anything
            # that's purely tag-wrapped meta is not a real user prompt.
            lower = stripped.lower()
            if any(tag in lower for tag in (
                "<local-command-caveat>", "<local-command-stdout>",
                "<local-command-stderr>", "<system-reminder>",
                "<command-name>", "<command-message>", "<command-args>",
                "<task-notification>", "<persisted-output>",
            )):
                continue
            # Strip wrapping tag noise then re-check non-empty
            cleaned = re.sub(r"<[^>]+>", "", stripped).strip()
            if not cleaned or len(cleaned) < 4:
                continue
            # Take first non-empty line of cleaned text
            first_line = cleaned.split("\n", 1)[0].strip()
            return first_line[:max_chars] if first_line else None
    except Exception:
        pass
    return None


def _peek_last_assistant_text(path: Path, max_chars: int = 4000) -> str | None:
    """Return the most recent assistant text content from the transcript JSONL."""
    try:
        # Read whole file in reverse-chunk-friendly form for v1
        last_text = None
        with open(path, encoding="utf-8", errors="replace") as f:
            for line in f:
                try:
                    obj = json.loads(line)
                except Exception:
                    continue
                if obj.get("type") != "assistant":
                    continue
                msg = obj.get("message") or {}
                content = msg.get("content")
                if isinstance(content, list):
                    parts = []
                    for block in content:
                        if isinstance(block, dict) and block.get("type") == "text":
                            t = block.get("text")
                            if isinstance(t, str):
                                parts.append(t)
                    joined = "\n\n".join(p for p in parts if p)
                    if joined:
                        last_text = joined
                elif isinstance(content, str) and content:
                    last_text = content
        if last_text:
            return last_text[:max_chars]
    except Exception:
        pass
    return None


def _worker_stats_payload(since_min: int = 60) -> dict:
    since_min = max(1, min(int(since_min or 60), 60 * 24))
    stat_rows = _claude_sessions_backend().worker_stats_rows(since_min)

    worker_patterns = [
        "biotech-labs/synth-synth-",
        "biotech-labs/crohns-research/scripts",
        "biotech-research-",
    ]
    now_epoch = int(_time.time())
    active_threshold = now_epoch - 5 * 60
    idle_threshold = now_epoch - 60 * 60
    active = 0
    idle = 0
    stale_ids: list[str] = []
    per_project: dict[str, dict] = {}

    for sid, project, heartbeat in stat_rows:
        if not any(pattern in project for pattern in worker_patterns):
            continue
        if heartbeat >= active_threshold:
            active += 1
        else:
            idle += 1
            if heartbeat < idle_threshold:
                stale_ids.append(sid)
        entry = per_project.setdefault(project, {
            "path": project,
            "count": 0,
            "last_heartbeat": 0,
        })
        entry["count"] += 1
        entry["last_heartbeat"] = max(entry["last_heartbeat"], heartbeat)

    return {
        "automated_active": active,
        "automated_idle": idle,
        "total": active + idle,
        "projects": sorted(
            per_project.values(),
            key=lambda item: item["last_heartbeat"],
            reverse=True,
        )[:20],
        "stale_session_ids": stale_ids[:50],
    }


def _human_idle_minutes() -> float | None:
    idle_candidates: list[float] = []
    ok, out, _ = _run_text(["/usr/sbin/ioreg", "-r", "-c", "IOHIDSystem"], timeout=2)
    if ok:
        match = re.search(r'"HIDIdleTime"\s*=\s*(\d+)', out)
        if match:
            idle_candidates.append(int(match.group(1)) / 1_000_000_000 / 60)
    if LAST_HUMAN_ACTIVITY_AT:
        idle_candidates.append(max(0.0, (_time.time() - LAST_HUMAN_ACTIVITY_AT) / 60))
    if not idle_candidates:
        return None
    return round(min(idle_candidates), 2)


class ClientDisconnected(Exception):
    pass


class RequestBodyRejected(Exception):
    def __init__(self, code: str, message: str, *, status: int = 400):
        super().__init__(message)
        self.code = code
        self.message = message
        self.status = status


def _validated_request_content_length(headers, *, required: bool = False) -> int:
    def values(name: str) -> list[str]:
        get_all = getattr(headers, "get_all", None)
        if callable(get_all):
            return list(get_all(name) or [])
        value = headers.get(name) if hasattr(headers, "get") else None
        return [] if value is None else [value]

    transfer_encodings = values("Transfer-Encoding")
    if transfer_encodings:
        raise RequestBodyRejected(
            "unsupported_transfer_encoding",
            "Transfer-Encoding is not supported",
        )
    content_lengths = values("Content-Length")
    if not content_lengths:
        if required:
            raise RequestBodyRejected(
                "content_length_required",
                "exactly one Content-Length is required",
                status=411,
            )
        return 0
    if len(content_lengths) != 1:
        raise RequestBodyRejected("bad_content_length", "exactly one Content-Length is required")
    raw = str(content_lengths[0]).strip()
    if re.fullmatch(r"[0-9]+", raw) is None:
        raise RequestBodyRejected("bad_content_length", "Content-Length must be a nonnegative integer")
    if len(raw) > 20:
        raise RequestBodyRejected(
            "request_too_large",
            "Content-Length exceeds the supported range",
            status=413,
        )
    try:
        return int(raw)
    except ValueError as error:
        raise RequestBodyRejected("bad_content_length", "Content-Length is invalid") from error


PROVIDER_CONTROL_SCHEMA_VERSION = 1
PROVIDER_CONTROL_STREAM_SECONDS = 600.0
PROVIDER_CONTROL_STREAM_POLL_SECONDS = 1.0
PROVIDER_CONTROL_STREAM_KEEPALIVE_SECONDS = 20.0
_PROVIDER_CONTROL_DRIVER_CACHE_MAX = 128
_PROVIDER_CONTROL_DRIVER_CACHE_LOCK = threading.Lock()
_PROVIDER_CONTROL_DRIVER_CACHE: dict[tuple[str, str, str, str], object] = {}
_PROVIDER_CONTROL_DRIVER_OWNERS: dict[str, tuple[str, str, str, str]] = {}
_PROVIDER_CONTROL_CONFIRMATION_TTL_SECONDS = 90.0
_PROVIDER_CONTROL_CONFIRMATION_MAX = 512
_PROVIDER_CONTROL_CONFIRMATION_PER_DEVICE_MAX = 16
_PROVIDER_CONTROL_CONFIRMATION_LOCK = threading.Lock()
_PROVIDER_CONTROL_CONFIRMATIONS: dict[str, dict] = {}
_PROVIDER_CONTROL_SENSITIVE_KEY = re.compile(
    r"(?i)(?:authorization|cookie|credential|password|secret|token|api[_-]?key|"
    r"raw(?:_provider)?_payload|provider_raw|request_headers|response_headers|"
    r"environment|env|file_path|local_path|absolute_path)"
)
_PROVIDER_CONTROL_SECRET_VALUE = re.compile(
    r"(?i)(?:bearer\s+[A-Za-z0-9._~+/=-]{8,}|"
    r"\bsk-[A-Za-z0-9_-]{8,}|"
    r"\b(?:api[_-]?key|token|secret|password)\s*[:=]\s*\S+)"
)


class _ProviderControlRouteError(RuntimeError):
    def __init__(self, code: str, message: str, *, status: int) -> None:
        super().__init__(message)
        self.code = code
        self.message = message
        self.status = int(status)

def _provider_control_confirmation_clear() -> None:
    with _PROVIDER_CONTROL_CONFIRMATION_LOCK:
        _PROVIDER_CONTROL_CONFIRMATIONS.clear()


def _provider_control_confirmation_prune_locked(now: float) -> None:
    for digest, row in tuple(_PROVIDER_CONTROL_CONFIRMATIONS.items()):
        if now >= float(row["expires_at"]):
            _PROVIDER_CONTROL_CONFIRMATIONS.pop(digest, None)


def _provider_control_confirmation_issue(
    binding: dict,
    *,
    prepared_attachments: tuple,
    now: float | None = None,
) -> tuple[str, float]:
    current = _time.time() if now is None else float(now)
    if not math.isfinite(current):
        raise _ProviderControlRouteError(
            "confirmation_challenge_unavailable",
            "provider confirmation is temporarily unavailable",
            status=503,
        )
    expires_at = current + _PROVIDER_CONTROL_CONFIRMATION_TTL_SECONDS
    with _PROVIDER_CONTROL_CONFIRMATION_LOCK:
        _provider_control_confirmation_prune_locked(current)
        if len(_PROVIDER_CONTROL_CONFIRMATIONS) >= _PROVIDER_CONTROL_CONFIRMATION_MAX:
            raise _ProviderControlRouteError(
                "confirmation_challenge_unavailable",
                "too many provider confirmations are pending",
                status=503,
            )
        device_pending = sum(
            1
            for row in _PROVIDER_CONTROL_CONFIRMATIONS.values()
            if row["device_id"] == binding["device_id"]
            and row["profile_install_id"] == binding["profile_install_id"]
        )
        if device_pending >= _PROVIDER_CONTROL_CONFIRMATION_PER_DEVICE_MAX:
            raise _ProviderControlRouteError(
                "confirmation_challenge_rate_limited",
                "too many provider confirmations are pending for this device",
                status=429,
            )
        while True:
            artifact = secrets.token_urlsafe(32)
            digest = hashlib.sha256(artifact.encode("ascii")).hexdigest()
            if digest not in _PROVIDER_CONTROL_CONFIRMATIONS:
                break
        _PROVIDER_CONTROL_CONFIRMATIONS[digest] = {
            **binding,
            "expires_at": expires_at,
            "prepared_attachments": tuple(prepared_attachments),
        }
    return artifact, expires_at


def _provider_control_confirmation_consume(
    artifact,
    expected: dict,
    *,
    now: float | None = None,
) -> tuple:
    value = str(artifact or "")
    if not re.fullmatch(r"[A-Za-z0-9_-]{43,128}", value):
        raise _ProviderControlRouteError(
            "confirmation_challenge_invalid",
            "provider confirmation challenge is invalid or already used",
            status=409,
        )
    current = _time.time() if now is None else float(now)
    digest = hashlib.sha256(value.encode("ascii")).hexdigest()
    with _PROVIDER_CONTROL_CONFIRMATION_LOCK:
        row = _PROVIDER_CONTROL_CONFIRMATIONS.pop(digest, None)
        if row is None:
            raise _ProviderControlRouteError(
                "confirmation_challenge_invalid",
                "provider confirmation challenge is invalid or already used",
                status=409,
            )
        if not math.isfinite(current) or current >= float(row["expires_at"]):
            raise _ProviderControlRouteError(
                "confirmation_challenge_expired",
                "provider confirmation challenge expired",
                status=409,
            )
        bound_fields = (
            "device_id",
            "profile_install_id",
            "provider_id",
            "session_id",
            "binding_id",
            "capability_generation",
            "operation_id",
            "input_hash",
            "client_action_id",
        )
        if any(row.get(field) != expected.get(field) for field in bound_fields):
            raise _ProviderControlRouteError(
                "confirmation_challenge_mismatch",
                "provider confirmation challenge does not match this action",
                status=409,
            )
        return tuple(row["prepared_attachments"])


def _provider_control_confirmation_identity(handler) -> tuple[str, str]:
    auth = getattr(handler, "pairling_auth", None)
    device_id = str(getattr(auth, "device_id", "") or "").strip()
    profile_install_id = str(getattr(auth, "install_id", "") or "").strip()
    if not device_id or not profile_install_id:
        raise _ProviderControlRouteError(
            "confirmation_identity_unavailable",
            "an authenticated device and install profile are required",
            status=401,
        )
    return device_id, profile_install_id


def _provider_control_canonical_input_hash(normalized_input: dict) -> str:
    try:
        canonical = json.dumps(
            normalized_input,
            sort_keys=True,
            separators=(",", ":"),
            ensure_ascii=False,
            allow_nan=False,
        ).encode("utf-8")
    except (TypeError, ValueError, UnicodeError) as exc:
        raise _ProviderControlRouteError(
            "invalid_operation_input",
            "operation input cannot be bound for confirmation",
            status=400,
        ) from exc
    return hashlib.sha256(canonical).hexdigest()


def _provider_control_confirmation_action(
    target: dict,
    definition,
    normalized_input: dict,
) -> dict:
    operation_id = str(definition.operation_id)
    risk = str(getattr(definition.risk, "value", definition.risk))
    requirement = str(
        getattr(
            definition.confirmation_requirement,
            "value",
            definition.confirmation_requirement,
        )
    )

    def exact_label(value) -> str:
        return json.dumps(str(value or ""), ensure_ascii=True)

    session_label = "this provider session"
    provider_label = "this provider"
    title = {
        "session.prompt.send": "Send Prompt",
        "session.turn.steer": "Steer Turn",
        "session.turn.interrupt": "Interrupt Turn",
        "session.terminate": "Terminate Session",
        "session.resume": "Resume Session",
        "session.fork": "Fork Session",
        "session.compact": "Compact Context",
        "session.rewind": "Rewind Session",
        "session.model.set": "Change Model",
        "session.reasoning.set": "Change Reasoning",
        "session.permissions.set": "Change Permissions",
        "session.collaboration_mode.set": "Change Collaboration Mode",
        "session.approval.decide": "Decide Provider Approval",
        "session.question.answer": "Answer Provider Questions",
        "session.review.start": "Start Review",
        "session.plan.start": "Start Plan",
        "provider.mcp.reload": "Reload MCP Server",
        "provider.mcp.reconnect": "Reconnect MCP Server",
        "provider.mcp.set_enabled": "Change MCP Server",
    }.get(operation_id, "Confirm Provider Action")
    button = title
    message = f"{title} for {session_label}."
    if operation_id == "session.terminate":
        message = (
            f"Terminate {session_label}. "
            "This ends the exact provider session currently shown."
        )
    elif operation_id == "session.resume":
        message = (
            "Resume the selected archived provider session using "
            f"{session_label}."
        )
    elif operation_id == "session.rewind":
        message = (
            f"Rewind {session_label} to the selected reviewed turn."
        )
    elif operation_id == "session.permissions.set":
        permissions_label = exact_label(normalized_input.get("permissions"))
        title = button = "Set Provider Permissions"
        message = (
            f"Set permissions for {session_label} to "
            f"{permissions_label}."
        )
    elif operation_id == "session.approval.decide":
        decision = str(normalized_input.get("decision") or "").strip().lower()
        if decision in {
            "allow",
            "accept",
            "once",
            "session",
            "always",
            "proceed_once",
        }:
            title = button = "Allow Provider Request"
            message = (
                f"Allow the pending provider request for {session_label} "
                f"with reviewed decision {exact_label(decision)}."
            )
        elif decision in {"deny", "decline", "reject"}:
            title = button = "Deny Provider Request"
            message = (
                f"Deny the pending provider request for {session_label} "
                f"with reviewed decision {exact_label(decision)}."
            )
        elif decision == "cancel":
            title = button = "Cancel Provider Request"
            message = f"Cancel the pending provider request for {session_label}."
        else:
            raise _ProviderControlRouteError(
                "confirmation_action_unavailable",
                "provider approval decision cannot be rendered safely",
                status=409,
            )
    elif operation_id == "session.question.answer":
        answers = normalized_input.get("answers")
        answer_count = len(answers) if isinstance(answers, list) else 0
        title = button = "Submit Provider Answers"
        message = (
            f"Submit {answer_count} reviewed answer"
            f"{'' if answer_count == 1 else 's'} to {session_label}."
        )
    elif operation_id in {
        "provider.mcp.reload",
        "provider.mcp.reconnect",
        "provider.mcp.set_enabled",
    }:
        server_label = exact_label(normalized_input.get("server_id"))
        if operation_id == "provider.mcp.reload":
            title = button = "Reload MCP Server"
            message = (
                f"Reload MCP server {server_label} for {provider_label}."
            )
        elif operation_id == "provider.mcp.reconnect":
            title = button = "Reconnect MCP Server"
            message = (
                f"Reconnect MCP server {server_label} for {session_label}."
            )
        else:
            enabled = normalized_input.get("enabled") is True
            verb = "Enable" if enabled else "Disable"
            title = button = f"{verb} MCP Server"
            message = (
                f"{verb} MCP server {server_label} for {session_label}."
            )
    if len(title) > 200 or len(message) > 500 or len(button) > 200:
        raise _ProviderControlRouteError(
            "confirmation_action_unavailable",
            "provider confirmation action cannot be rendered safely",
            status=409,
        )
    return {
        "title": title,
        "message": message,
        "confirm_button_label": button,
        "risk": risk,
        "confirmation_requirement": requirement,
    }

def _provider_control_exact_session_id(raw_session) -> tuple[str, str, str]:
    value = str(raw_session or "").strip()
    if ":" not in value:
        raise _ProviderControlRouteError(
            "provider_qualified_session_required",
            "session_id must be provider-qualified",
            status=400,
        )
    provider, native_id = _parse_agent_session_ref(value)
    if (
        not provider
        or not native_id
        or not _safe_agent_native_id(native_id)
        or value != _qualified_session_id(provider, native_id)
    ):
        raise _ProviderControlRouteError(
            "bad_session_id",
            "session_id is not a valid provider-qualified session",
            status=400,
        )
    return value, provider, native_id


def _provider_control_public_json(value, *, depth: int = 0):
    """Return bounded public JSON while dropping provider-owned secret fields."""
    if depth > 8:
        raise _ProviderControlRouteError(
            "provider_payload_invalid",
            "provider result exceeds the public nesting limit",
            status=502,
        )
    if value is None or isinstance(value, (bool, int, float)):
        return value
    if isinstance(value, str):
        bounded = value[:65536]
        return "[redacted]" if _PROVIDER_CONTROL_SECRET_VALUE.search(bounded) else bounded
    if isinstance(value, dict):
        if len(value) > 128:
            raise _ProviderControlRouteError(
                "provider_payload_invalid",
                "provider result contains too many fields",
                status=502,
            )
        public = {}
        for raw_key, item in value.items():
            key = str(raw_key)
            if len(key) > 160 or _PROVIDER_CONTROL_SENSITIVE_KEY.search(key):
                continue
            public[key] = _provider_control_public_json(item, depth=depth + 1)
        return public
    if isinstance(value, (list, tuple)):
        if len(value) > 256:
            raise _ProviderControlRouteError(
                "provider_payload_invalid",
                "provider result contains too many items",
                status=502,
            )
        return [
            _provider_control_public_json(item, depth=depth + 1)
            for item in value
        ]
    raise _ProviderControlRouteError(
        "provider_payload_invalid",
        "provider result is not public JSON",
        status=502,
    )

def _provider_control_instance_id(
    provider: str,
    native_id: str,
    row: dict,
) -> str:
    metadata = _registry_metadata_from_row(row)
    material = {
        "provider_id": provider,
        "native_id": native_id,
        "started_at": row.get("started_at"),
        "pid": row.get("pid") or row.get("claude_pid"),
        "process_start": (
            metadata.get("process_start")
            or metadata.get("process_started_at")
            or metadata.get("process_birth")
        ),
    }
    digest = hashlib.sha256(
        json.dumps(material, sort_keys=True, separators=(",", ":")).encode()
    ).hexdigest()
    return f"{provider}:{native_id}:{digest[:24]}"


def _provider_control_binding_cache_key(binding) -> tuple[str, str, str, str]:
    return (
        str(binding.provider_id),
        str(binding.provider_version),
        str(binding.provider_channel),
        str(binding.binding_id),
    )


def _provider_control_close_driver(driver) -> None:
    close = getattr(driver, "close", None)
    if callable(close):
        try:
            close()
        except Exception:
            pass


def _provider_control_cached_driver(binding, *, owner_id: str):
    """Own one stateful driver per exact binding and stable session owner."""
    if _provider_get_control_driver is None:
        return None
    cache_key = _provider_control_binding_cache_key(binding)
    stale_driver = None
    with _PROVIDER_CONTROL_DRIVER_CACHE_LOCK:
        previous_key = _PROVIDER_CONTROL_DRIVER_OWNERS.get(owner_id)
        if previous_key is not None and previous_key != cache_key:
            stale_driver = _PROVIDER_CONTROL_DRIVER_CACHE.pop(previous_key, None)
            _PROVIDER_CONTROL_DRIVER_OWNERS.pop(owner_id, None)
        cached = _PROVIDER_CONTROL_DRIVER_CACHE.get(cache_key)
        if cached is not None:
            _PROVIDER_CONTROL_DRIVER_OWNERS[owner_id] = cache_key
    if stale_driver is not None:
        _provider_control_close_driver(stale_driver)
    if cached is not None:
        if getattr(cached, "binding", None) == binding:
            return cached
        with _PROVIDER_CONTROL_DRIVER_CACHE_LOCK:
            _PROVIDER_CONTROL_DRIVER_CACHE.pop(cache_key, None)
            _PROVIDER_CONTROL_DRIVER_OWNERS.pop(owner_id, None)
        _provider_control_close_driver(cached)
    driver = _provider_get_control_driver(binding, home=HOME)
    if driver is None:
        return None
    stale_driver = None
    with _PROVIDER_CONTROL_DRIVER_CACHE_LOCK:
        existing = _PROVIDER_CONTROL_DRIVER_CACHE.get(cache_key)
        if existing is not None and getattr(existing, "binding", None) == binding:
            _PROVIDER_CONTROL_DRIVER_OWNERS[owner_id] = cache_key
            winner = existing
        else:
            if len(_PROVIDER_CONTROL_DRIVER_CACHE) >= _PROVIDER_CONTROL_DRIVER_CACHE_MAX:
                evicted_key, stale_driver = next(
                    iter(_PROVIDER_CONTROL_DRIVER_CACHE.items())
                )
                _PROVIDER_CONTROL_DRIVER_CACHE.pop(evicted_key, None)
                for stale_owner, stale_key in tuple(
                    _PROVIDER_CONTROL_DRIVER_OWNERS.items()
                ):
                    if stale_key == evicted_key:
                        _PROVIDER_CONTROL_DRIVER_OWNERS.pop(stale_owner, None)
            _PROVIDER_CONTROL_DRIVER_CACHE[cache_key] = driver
            _PROVIDER_CONTROL_DRIVER_OWNERS[owner_id] = cache_key
            winner = driver
    if winner is not driver:
        _provider_control_close_driver(driver)
    if stale_driver is not None:
        _provider_control_close_driver(stale_driver)
    return winner


def _provider_control_managed_target(session_id: str, provider: str):
    ensure_store = globals().get("_ensure_managed_provider_session_store")
    store = ensure_store() if callable(ensure_store) else None
    truth = store.session_truth(session_id) if store is not None else None
    if not isinstance(truth, dict):
        return None
    ensure_manager = globals().get("_ensure_managed_provider_session_manager")
    manager = ensure_manager() if callable(ensure_manager) else None
    driver = manager.driver(session_id) if manager is not None else None
    synchronize_generation = False
    if manager is not None and driver is not None:
        try:
            live_generation = getattr(driver, "capability_generation", None)
            if callable(live_generation):
                live_generation = live_generation()
            synchronize_generation = (
                live_generation is not None
                and (
                    isinstance(live_generation, bool)
                    or int(live_generation)
                    != int(truth["capability_generation"])
                )
            )
        except (KeyError, TypeError, ValueError):
            synchronize_generation = True
    if synchronize_generation:
        manager.poll(session_id)
        truth = store.session_truth(session_id) if store is not None else None
        driver = manager.driver(session_id) if manager is not None else None
        if not isinstance(truth, dict):
            return None
    if (
        truth.get("provider_id") != provider
        or truth.get("session_id") != session_id
    ):
        raise _ProviderControlRouteError(
            "provider_mismatch",
            "managed session provider identity is mismatched",
            status=409,
        )
    lifecycle = str(truth.get("lifecycle") or "")
    available = bool(truth.get("driver_available"))
    normalized = dict(truth)
    normalized["is_live"] = bool(
        available
        and lifecycle in {"launching", "running", "waiting", "blocked", "closing"}
    )
    normalized["controllable"] = bool(
        available and lifecycle in {"launching", "running", "waiting"}
    )
    return {
        "driver": driver,
        "provider_id": provider,
        "session_id": session_id,
        "managed": True,
        "manager": manager,
        "session_truth": normalized,
    }

def _default_provider_control_target(handler, raw_session: str) -> dict:
    _requested, provider, native_id = _provider_control_exact_session_id(raw_session)
    if provider not in _agent_provider_ids():
        raise _ProviderControlRouteError(
            "unsupported_provider",
            f"provider {provider} does not expose structured sessions",
            status=400,
        )
    canonical_native_id = _agent_registry_resolve_native_alias(provider, native_id)
    canonical_session_id = _qualified_session_id(provider, canonical_native_id)
    managed = _provider_control_managed_target(canonical_session_id, provider)
    if managed is not None:
        return managed

    receipt_scope, row = _session_mutation_receipt_identity(
        handler,
        canonical_session_id,
    )
    if not isinstance(row, dict):
        raise _ProviderControlRouteError(
            "session_not_found",
            "no exact daemon session truth exists for this session",
            status=404,
        )
    row_provider = str(row.get("provider") or provider).strip().lower()
    row_native_id = str(row.get("native_id") or canonical_native_id).strip()
    canonical_session_id = _qualified_session_id(row_provider, row_native_id)
    if row_provider != provider or receipt_scope != canonical_session_id:
        raise _ProviderControlRouteError(
            "provider_mismatch",
            "resolved session provider identity is mismatched",
            status=409,
        )
    if row.get("closed_at") is not None:
        raise _ProviderControlRouteError(
            "session_not_controllable",
            "closed sessions cannot execute provider controls",
            status=409,
        )
    verifier = getattr(handler, "_registry_row_has_verified_control", None)
    verified = bool(
        callable(verifier)
        and verifier(
            row,
            provider=provider,
            native_id=row_native_id,
        )
    )
    instance_id = _provider_control_instance_id(provider, row_native_id, row)
    adapter = _provider_get_adapter(provider, home=HOME) if _provider_get_adapter else None
    driver = None
    if adapter is not None and _ProviderControlBinding is not None:
        try:
            probe = adapter.probe()
        except Exception:
            probe = None
        diagnostics = getattr(probe, "diagnostics", None)
        descriptor = getattr(adapter, "descriptor", None)
        metadata = _registry_metadata_from_row(row)
        version = str(
            metadata.get("provider_version")
            or getattr(diagnostics, "version", None)
            or "unknown"
        )[:160]
        channel = str(
            metadata.get("provider_channel")
            or getattr(descriptor, "kind", None)
            or "local"
        )[:80]
        binding = _ProviderControlBinding(
            provider_id=provider,
            provider_version=version,
            provider_channel=channel,
            binding_id=f"pairling:{hashlib.sha256(instance_id.encode()).hexdigest()[:32]}",
        )
        driver = (
            _provider_control_cached_driver(binding, owner_id=canonical_session_id)
            if verified
            else None
        )
    driver_binding = getattr(driver, "binding", None)
    generation = int(getattr(driver, "capability_generation", 1) or 1)
    if driver_binding is not None:
        binding_id = str(driver_binding.binding_id)
    else:
        binding_id = (
            f"pairling:{hashlib.sha256(instance_id.encode()).hexdigest()[:32]}"
        )
    truth = {
        "provider_id": provider,
        "session_id": canonical_session_id,
        "native_id": row_native_id,
        "binding_id": binding_id,
        "capability_generation": max(1, generation),
        "is_live": verified,
        "controllable": verified,
        "session_instance_id": instance_id,
        "project": str(row.get("project") or ""),
        "cwd": str(row.get("project") or ""),
    }
    return {
        "driver": driver,
        "provider_id": provider,
        "session_id": canonical_session_id,
        "session_truth": truth,
    }


_PROVIDER_CONTROL_TARGET_RESOLVER = _default_provider_control_target


def _provider_control_advertised_operation_id(value) -> str | None:
    if not isinstance(value, dict):
        return None
    operation_id = value.get("operation_id")
    if not isinstance(operation_id, str) or not operation_id:
        return None
    return operation_id


def _provider_control_content_hash(
    session_id: str,
    protocol_session_id: str | None,
    status: dict,
) -> str:
    stable_status = dict(status)
    stable_status.pop("observed_at", None)
    stable_status.pop("valid_until", None)
    material = {
        "schema_version": PROVIDER_CONTROL_SCHEMA_VERSION,
        "session_id": session_id,
        "protocol_session_id": protocol_session_id,
        "status": stable_status,
    }
    return hashlib.sha256(
        json.dumps(material, sort_keys=True, separators=(",", ":")).encode()
    ).hexdigest()


def _provider_control_snapshot_renewal_at(envelope: dict) -> float:
    status = envelope["status"]
    observed_at = float(status["observed_at"])
    valid_until = float(status["valid_until"])
    return observed_at + ((valid_until - observed_at) / 2.0)


def _provider_control_contract_error(exc: Exception) -> dict:
    if _PROVIDER_CONTROL_SERVICE is not None:
        error = _PROVIDER_CONTROL_SERVICE.contract_error(exc)
        return {
            "code": error.code,
            "message": error.message,
            "status": error.status,
        }
    message = str(exc)[:300] or "provider control validation failed"
    return {
        "code": "invalid_operation_input",
        "message": message,
        "status": 400,
    }


def _provider_control_snapshot_envelope(target: dict, *, now: float | None = None) -> dict:
    if (
        _PROVIDER_CONTROL_SERVICE is None
        or _provider_operation_manifest_payload is None
    ):
        raise _ProviderControlRouteError(
            "provider_controls_unavailable",
            "provider control contracts are unavailable",
            status=503,
        )
    try:
        status = _PROVIDER_CONTROL_SERVICE.snapshot_status(target, now=now)
    except _ProviderControlServiceError as exc:
        raise _ProviderControlRouteError(
            exc.code,
            exc.message,
            status=exc.status,
        ) from exc
    public_status = _provider_control_public_json(status)
    raw_protocol_session_id = target.get("session_truth", {}).get(
        "protocol_session_id"
    )
    protocol_session_id = (
        str(raw_protocol_session_id)
        if isinstance(raw_protocol_session_id, str)
        and re.fullmatch(r"ses_[A-Za-z0-9_-]{16,128}", raw_protocol_session_id)
        else None
    )
    if target.get("managed") and protocol_session_id is None:
        raise _ProviderControlRouteError(
            "managed_session_identity_invalid",
            "managed session lacks its durable protocol identity",
            status=409,
        )
    content_hash = _provider_control_content_hash(
        target["session_id"],
        protocol_session_id,
        public_status,
    )
    return {
        "ok": True,
        "schema_version": PROVIDER_CONTROL_SCHEMA_VERSION,
        "session_id": target["session_id"],
        "protocol_session_id": protocol_session_id,
        "operation_catalog": _provider_operation_manifest_payload(),
        "status": public_status,
        "content_hash": content_hash,
    }


def _provider_control_attachment_error(exc: Exception) -> dict:
    code = str(getattr(exc, "code", None) or "attachment_proof_invalid")
    malformed = {
        "bad_attachment_records",
        "too_many_attachments",
        "attachment_too_large",
        "attachments_too_large",
        "bad_attachment_handle",
    }
    missing = {"attachment_not_found", "attachment_deleted", "missing_object"}
    status = 400 if code in malformed else (404 if code in missing else 409)
    return {
        "code": code,
        "message": "attachment resource proof could not be validated",
        "status": status,
    }


def _provider_control_send_error(handler, error) -> None:
    handler._send_json(
        {
            "ok": False,
            "error": {
                "code": str(error.code),
                "message": redact_public_diagnostic(str(error.message)),
            },
        },
        status=int(error.status),
    )

class _RevalidatingStreamWriter:
    """Fail an SSE write after its remote bearer authority changes."""

    def __init__(self, handler, raw, *, interval_seconds: float = 1.0):
        self._handler = handler
        self._raw = raw
        self._interval_seconds = max(0.0, float(interval_seconds))
        self._next_check = 0.0

    def reset(self) -> None:
        self._next_check = 0.0

    def write(self, data):
        now = _time.monotonic()
        if now >= self._next_check:
            self._next_check = now + self._interval_seconds
            if not self._handler._stream_authorization_is_current():
                self._handler.close_connection = True
                raise BrokenPipeError("stream authorization is no longer current")
        return self._raw.write(data)

    def __getattr__(self, name):
        return getattr(self._raw, name)



class Handler(BaseHTTPRequestHandler):
    def _stream_authorization_is_current(self) -> bool:
        """Revalidate remote bearer authority for an already-open stream."""
        snapshot = getattr(self, "_pairling_stream_authorization", None)
        if snapshot is None:
            return True
        token, required_scopes, path, device_id, install_id = snapshot
        if DEVICE_REGISTRY is None:
            return False
        try:
            current = DEVICE_REGISTRY.authenticate(
                token,
                required_scopes=required_scopes,
                path=path,
            )
            current = _bind_auth_result_to_local_install(current)
        except Exception:
            return False
        if current is None or not getattr(current, "ok", False):
            return False
        return (
            secrets.compare_digest(
                str(getattr(current, "device_id", "") or ""),
                device_id,
            )
            and secrets.compare_digest(
                str(getattr(current, "install_id", "") or ""),
                install_id,
            )
        )

    def send_header(self, keyword, value):
        if str(keyword).lower() == "content-type" and str(value).lower() == "text/event-stream":
            self._pairling_sse_response = True
        return super().send_header(keyword, value)

    def end_headers(self):
        super().end_headers()
        if not getattr(self, "_pairling_sse_response", False):
            return
        if isinstance(self.wfile, _RevalidatingStreamWriter):
            self.wfile.reset()
        else:
            self.wfile = _RevalidatingStreamWriter(self, self.wfile)

    def send_error(self, code, message=None, explain=None):
        safe_message = (
            None if message is None else redact_public_text(str(message))
        )
        safe_explain = (
            None if explain is None else redact_public_text(str(explain))
        )
        return super().send_error(code, safe_message, safe_explain)

    timeout = REQUEST_READ_TIMEOUT_SECONDS

    def _release_runtime_admission(self) -> None:
        admission = getattr(self, "_runtime_admission", None)
        if admission is not None:
            admission.release()
            self._runtime_admission = None

    def _release_command_stream_lease(self) -> None:
        active = getattr(self, "_command_stream_lease", None)
        if active is not None:
            _release_command_stream_lease(*active)
            self._command_stream_lease = None

    def _run_dispatch(self):
        self._runtime_admission = None
        self._command_stream_lease = None
        self._pairling_sse_response = False
        try:
            with _receipted_request_scope():
                try:
                    return self._dispatch()
                except socket.timeout:
                    self._release_runtime_admission()
                    self._send_json({"ok": False, "error": {"code": "request_timeout"}}, status=408)
                except RequestBodyRejected as error:
                    self._release_runtime_admission()
                    self.close_connection = True
                    self._send_json({
                        "ok": False,
                        "error": {"code": error.code, "message": error.message},
                    }, status=error.status)
                except ClientDisconnected:
                    return
        finally:
            if self._pairling_sse_response:
                self.close_connection = True

    def do_GET(self):
        return self._run_dispatch()

    def do_POST(self):
        return self._run_dispatch()

    def do_PUT(self):
        return self._run_dispatch()

    def do_DELETE(self):
        return self._run_dispatch()

    def _read_body(self) -> bytes:
        cached = getattr(self, "_cached_body", None)
        if cached is not None:
            return cached
        n = getattr(self, "_expected_body_length", None)
        if n is None:
            n = _validated_request_content_length(self.headers)
        body = self.rfile.read(n) if n > 0 else b""
        if len(body) != n:
            raise RequestBodyRejected(
                "truncated_body",
                f"request body ended after {len(body)} of {n} bytes",
            )
        self._cached_body = body
        return body

    def _dispatch(self):
        self._pairling_sse_response = False
        u = urlparse(self.path)
        q = parse_qs(u.query)
        self._cached_body = None
        funnel_origin = _funnel_origin_request(self.headers, self.client_address)
        try:
            content_length = _validated_request_content_length(
                self.headers,
                required=funnel_origin and self.command == "POST",
            )
        except RequestBodyRejected as error:
            self.close_connection = True
            self._send_json({
                "ok": False,
                "error": {"code": error.code, "message": error.message},
            }, status=error.status)
            return
        self._expected_body_length = content_length
        if funnel_origin and self.command == "POST":
            max_body = MAX_FUNNEL_BOOTSTRAP_BODY_BYTES
        elif u.path == "/upload":
            max_body = MAX_UPLOAD_BODY_BYTES
        elif u.path == "/compose/recordings/sync" and self.command == "POST":
            max_body = MAX_COMPOSE_SYNC_BODY_BYTES
        elif u.path == "/pairdrop/files" and self.command == "POST":
            max_body = MAX_PAIRDROP_SMALL_BODY_BYTES
        elif _pairdrop_upload_bytes_id(u.path) is not None and self.command == "PUT":
            max_body = MAX_PAIRDROP_UPLOAD_CHUNK_BYTES
        else:
            max_body = MAX_REQUEST_BODY_BYTES
        if content_length > max_body:
            self.close_connection = True
            self._send_json({
                "ok": False,
                "error": {
                    "code": "request_too_large",
                    "message": f"request body exceeds {max_body} bytes",
                },
            }, status=413)
            return

        admission = _runtime_admission_for_path(u.path)
        self._runtime_admission = admission
        if not admission.allowed:
            self._send_json({
                "ok": False,
                "error": {
                    "code": admission.reason or "runtime_busy",
                    "message": "Pairling runtime is busy; retry shortly",
                },
                "retry_after": 1,
            }, status=503, headers={"Retry-After": "1"})
            return

        self.pairling_auth = None
        self._pairling_stream_authorization = None

        if getattr(self.server, "pairling_local_control", False):
            try:
                if u.path not in LOCAL_CONTROL_PATHS:
                    self._send_json({
                        "ok": False,
                        "error": {
                            "code": "local_control_path_not_found",
                            "message": "unknown local control path",
                        },
                    }, status=404)
                    return
                if u.path == "/routez":
                    if self.command != "GET" or content_length != 0:
                        self._send_json({
                            "ok": False,
                            "error": {
                                "code": "local_control_method_not_allowed",
                                "message": "bodyless GET required",
                            },
                        }, status=405)
                    else:
                        self._handle_routez(q)
                    return
                if self.command != "POST":
                    self._send_json({
                        "ok": False,
                        "error": {
                            "code": "local_control_method_not_allowed",
                            "message": "POST required",
                        },
                    }, status=405)
                    return
                if u.path == "/pair/start":
                    self._handle_pair_start(q)
                    return
                if content_length != 0:
                    self._send_json({
                        "ok": False,
                        "error": {
                            "code": "local_control_body_not_allowed",
                            "message": "request body must be empty",
                        },
                    }, status=400)
                    return
                if open_connectd_auth is None:
                    self._send_json({
                        "ok": False,
                        "opened": False,
                        "auth_url_present": False,
                        "error": {
                            "code": "connectd_control_unavailable",
                            "message": "Pairling Connect control is unavailable",
                        },
                    }, status=503)
                    return
                try:
                    status, payload = open_connectd_auth(timeout_seconds=5.0)
                except Exception:
                    status, payload = 503, {
                        "ok": False,
                        "opened": False,
                        "auth_url_present": False,
                        "error": {
                            "code": "connectd_control_unavailable",
                            "message": "Pairling Connect control is unavailable",
                        },
                    }
                if not isinstance(payload, dict):
                    status, payload = 502, {
                        "ok": False,
                        "opened": False,
                        "auth_url_present": False,
                        "error": {
                            "code": "connectd_control_invalid_response",
                            "message": "Pairling Connect returned an invalid control response",
                        },
                    }
                self._send_json(payload, status=status if 100 <= int(status) <= 599 else 502)
            finally:
                admission.release()
            return

        if u.path in INTERNAL_LOOPBACK_PATHS:
            # Internal hook tier — loopback IP AND minted token required.
            # Handled entirely outside device auth: a device Bearer never
            # grants access here, and the hook token never grants device
            # endpoints.
            client_ip = _client_address_host(self.client_address)
            presented = str(self.headers.get("X-Pairling-Internal-Token") or "").strip()
            if (
                client_ip not in ("127.0.0.1", "::1")
                or not INTERNAL_HOOK_TOKEN
                or not presented
                or not secrets.compare_digest(presented, INTERNAL_HOOK_TOKEN)
            ):
                admission.release()
                self._send_json({
                    "ok": False,
                    "error": {
                        "code": "internal_forbidden",
                        "message": "loopback internal token required",
                    },
                }, status=403)
                return
            try:
                if u.path == "/pair/start":
                    if self.command != "POST":
                        self.send_error(405, "POST required")
                    else:
                        self._handle_pair_start(q)
                    return
                if u.path == "/internal/session-register":
                    self._handle_internal_session_register(q)
                elif u.path == "/internal/session-heartbeat":
                    self._handle_internal_session_heartbeat(q)
                elif u.path == "/internal/session-close":
                    self._handle_internal_session_close(q)
                elif u.path == "/internal/active-sessions":
                    self._handle_internal_active_sessions(q)
                elif u.path == "/internal/permission-request":
                    self._handle_internal_permission_request(q)
            finally:
                admission.release()
            return

        required_scopes = _required_scopes_for_request(u.path, self.command)
        internal_route_probe = _internal_route_probe_request(u.path, self.headers, self.client_address)
        token = _bearer_token(self.headers)
        if token:
            if DEVICE_REGISTRY is None:
                admission.release()
                self._send_json({
                    "ok": False,
                    "error": {
                        "code": "auth_unavailable",
                        "message": "Pairling device registry is unavailable",
                    },
                }, status=503)
                return
            try:
                auth_result = _authenticate_device(
                    token,
                    required_scopes=required_scopes,
                    path=u.path,
                    method=self.command,
                )
            except Exception as exc:
                admission.release()
                self._send_json({
                    "ok": False,
                    "error": {
                        "code": "auth_unavailable",
                        "message": f"Pairling device auth failed: {type(exc).__name__}",
                    },
                }, status=503)
                return
            if auth_result is None:
                admission.release()
                self._send_json({
                    "ok": False,
                    "error": {
                        "code": "auth_unavailable",
                        "message": "Pairling device registry is unavailable",
                    },
                }, status=503)
                return
            if not auth_result.ok:
                admission.release()
                self._send_json({
                    "ok": False,
                    "error": {
                        "code": auth_result.reason,
                        "message": auth_result.reason.replace("_", " "),
                    },
                }, status=auth_result.status)
                return
            self.pairling_auth = auth_result
            self._pairling_stream_authorization = (
                token,
                frozenset(required_scopes),
                u.path,
                str(getattr(auth_result, "device_id", "") or ""),
                str(getattr(auth_result, "install_id", "") or ""),
            )
        elif not _unauthenticated_request_allowed(
            u.path, self.headers, self.client_address
        ) and not internal_route_probe:
            admission.release()
            self._send_json({
                "ok": False,
                "error": {
                    "code": "missing_token",
                    "message": "Authorization: Bearer token required",
                },
            }, status=401)
            return

        gateway_rejection = _pairling_connect_gateway_rejection(
            u.path, self.headers, self.client_address
        )
        if gateway_rejection is not None:
            admission.release()
            self._send_json({
                "ok": False,
                "error": gateway_rejection,
            }, status=403)
            return

        read_only_picker_path = (
            u.path in READ_ONLY_PICKER_ENDPOINTS
            or u.path.startswith("/pickers/memory/")
        )
        if read_only_picker_path and self.command != "GET":
            admission.release()
            self.send_error(405, "GET required")
            return

        if _is_post_only_endpoint(u.path) and self.command != "POST":
            admission.release()
            self.send_error(405, "POST required")
            return
        if u.path in GET_OR_POST_ENDPOINTS and self.command not in {"GET", "POST"}:
            admission.release()
            self.send_error(405, "GET or POST required")
            return


        proof_verified = False
        if (
            self.pairling_auth is not None
            and _requires_request_proof(u.path, self.command)
        ):
            if verify_request_proof is None or _proof_replay_cache is None:
                admission.release()
                self._send_json({
                    "ok": False,
                    "error": {
                        "code": "proof_unavailable",
                        "message": "request proof verifier is unavailable",
                    },
                }, status=503)
                return
            body = self._read_body()
            local_install_id = str(getattr(PAIRING_STORE, "install_id", "") or getattr(self.pairling_auth, "install_id", "") or "")
            try:
                proof_result = verify_request_proof(
                    headers=self.headers,
                    method=self.command,
                    path_and_query=_path_and_query(u),
                    body=body,
                    auth_result=self.pairling_auth,
                    local_install_id=local_install_id,
                    replay_cache=_proof_replay_cache,
                )
            except Exception:
                admission.release()
                self._send_json({
                    "ok": False,
                    "error": {
                        "code": "proof_unavailable",
                        "message": "request proof verifier is unavailable",
                    },
                }, status=503)
                return
            if not proof_result.ok:
                proof_rate_allowed, proof_retry = _invalid_proof_rate_check(
                    token or "",
                    self.headers,
                    self.client_address,
                )
                admission.release()
                if not proof_rate_allowed:
                    self._send_json({
                        "ok": False,
                        "error": {
                            "code": "invalid_proof_rate_limited",
                            "message": "too many invalid request proofs",
                        },
                        "retry_after": proof_retry,
                    }, status=429, headers={"Retry-After": str(proof_retry)})
                else:
                    self._send_json({
                        "ok": False,
                        "error": {
                            "code": proof_result.code,
                            "message": proof_result.message,
                        },
                    }, status=proof_result.status)
                return
            proof_verified = True
        if self.pairling_auth is not None and _is_high_risk_endpoint(u.path) and DEVICE_REGISTRY is not None:
            max_per_min = _rate_limit_for_high_risk_endpoint(u.path)
            rate_path = _rate_limit_key_path(u.path)
            allowed, retry = _request_rate_check(
                f"{self.pairling_auth.device_id}:{rate_path}",
                max_per_min=max_per_min,
            )
            if not allowed:
                admission.release()
                self._send_json({
                    "ok": False,
                    "error": {
                        "code": "rate_limited",
                        "message": "too many mutating requests",
                    },
                    "retry_after": retry,
                }, status=429, headers={"Retry-After": str(retry)})
                return

        if self.pairling_auth is not None:
            _maybe_persist_tailnet_node_id(
                self.headers,
                self.client_address,
                self.pairling_auth,
                proof_verified=proof_verified,
            )

        if self.pairling_auth is not None and _is_high_risk_endpoint(u.path) and DEVICE_REGISTRY is not None:
            try:
                DEVICE_REGISTRY.record_audit(
                    "request.allowed",
                    device_id=self.pairling_auth.device_id,
                    outcome="ok",
                    path=u.path,
                    detail={"method": self.command, "scopes": sorted(required_scopes)},
                )
            except Exception:
                pass

        if self.pairling_auth is not None:
            try:
                _maybe_audit_authenticated_client_workflow(
                    auth_result=self.pairling_auth,
                    headers=self.headers,
                    client_address=self.client_address,
                    path=u.path,
                    method=self.command,
                    proof_verified=proof_verified,
                )
            except Exception:
                pass

        try:
            if u.path == "/health":
                self._handle_health(q)
            elif u.path == "/power-state":
                self._handle_power_state(q)
            elif u.path == "/readyz":
                self._handle_readyz(q)
            elif u.path == "/routez":
                self._handle_routez(q)
            elif u.path == "/manifest":
                self._handle_manifest(q)
            elif u.path == "/pair/start":
                if self.command != "POST":
                    self._send_json({"ok": False, "error": {"code": "method_not_allowed", "message": "pair start requires POST"}}, status=405)
                elif not _local_authorization_request(self.headers, self.client_address):
                    self._send_json({"ok": False, "error": {"code": "pair_start_local_authorization_required", "message": "pair start requires local CLI authorization"}}, status=403)
                elif _funnel_origin_request(self.headers, self.client_address):
                    self._send_json({"ok": False, "error": {"code": "funnel_forbidden", "message": "pair start is not available over funnel"}}, status=403)
                else:
                    self._handle_pair_start(q)
            elif u.path == "/pair/psk-claim-v2":
                self._handle_pair_psk_claim_v2(q)
            elif u.path == "/pair/psk-activate":
                self._handle_pair_psk_activate(q)
            elif u.path == "/pair/reauth-challenge":
                self._handle_pair_reauth_challenge(q)
            elif u.path == "/pair/reauth-claim":
                self._handle_pair_reauth_claim(q)
            elif u.path == "/pair/revoke":
                self._handle_pair_revoke(q)
            elif u.path == "/pair/rotate-token":
                self._handle_pair_rotate_token(q)
            elif u.path == "/pair/bind-node":
                self._handle_pair_bind_node(q)
            elif u.path == "/healthz":
                self._handle_healthz(q)
            elif u.path == "/health-stream":
                self._handle_health_stream(q)
            elif u.path == "/open":
                self._handle_open(q)
            elif u.path == "/sessions":
                self._handle_sessions(q)
            elif u.path == "/sessions-visible":
                self._handle_sessions_visible(q)
            elif u.path == "/sessions/remove":
                self._handle_session_removal(q, delete_transcript=False)
            elif u.path == "/sessions/delete-transcript":
                self._handle_session_removal(q, delete_transcript=True)
            elif u.path == "/session-source-diagnostics":
                self._handle_session_source_diagnostics(q)
            elif u.path == "/recent-projects":
                self._handle_recent_projects(q)
            elif u.path == "/filesystem/directories":
                self._handle_filesystem_directories(q)
            elif u.path == "/transcript":
                self._handle_transcript(q)
            elif u.path == "/session-live-events":
                with _track_live_stream():
                    self._handle_session_live_events(q)
            elif u.path == "/session-events-v2":
                self._handle_session_events_v2(q)
            elif u.path == "/session-events-v2-raw":
                self._handle_session_events_v2_raw(q)
            elif u.path == "/session-events-v2-content":
                self._handle_session_events_v2_content(q)
            elif u.path == "/device-events":
                self._handle_device_events(q)
            elif u.path == "/transcript-stream":
                self._handle_transcript_stream(q)
            elif u.path == "/terminal-stream":
                self._handle_terminal_stream(q)
            elif u.path == "/terminal-stream-diagnostics":
                self._handle_terminal_stream_diagnostics(q)
            elif u.path == "/terminal-surface":
                self._handle_terminal_surface(q)
            elif u.path == "/terminal-surface-stream":
                self._handle_terminal_surface_stream(q)
            elif u.path == "/terminal-surface-v2":
                self._handle_terminal_surface_v2(q)
            elif u.path == "/terminal-surface-stream-v2":
                self._handle_terminal_surface_stream_v2(q)
            elif u.path == "/session-runtime-truth":
                self._handle_session_runtime_truth(q)
            elif u.path == "/session-runtime-truth-stream":
                self._handle_session_runtime_truth_stream(q)
            elif u.path == "/terminal-workspace":
                self._handle_terminal_workspace(q)
            elif u.path == "/terminal-workspace-stream":
                with _track_live_stream():
                    self._handle_terminal_workspace_stream(q)
            elif u.path == "/terminal-control":
                self._handle_terminal_control(q)
            elif u.path == "/terminal-input":
                self._handle_terminal_input(q)
            elif u.path == "/corpus":
                self._handle_corpus(q)
            elif u.path == "/session-meta":
                self._handle_session_meta(q)
            elif u.path == "/personal-context":
                self._handle_personal_context(q)
            elif u.path == "/postures":
                if self.command == "POST":
                    self._handle_posture_write(q)
                else:
                    self._handle_postures_list(q)
            elif _postures_item_slug(u.path) is not None:
                if self.command == "DELETE":
                    self._handle_posture_delete(q, _postures_item_slug(u.path))
                else:
                    self._handle_posture_read(q, _postures_item_slug(u.path))
            elif u.path == "/llm-route":
                self._handle_llm_route(q)
            elif u.path == "/llm-route-stream":
                self._handle_llm_route_stream(q)
            elif u.path == "/pairling-tools/run":
                self._handle_pairling_tools_run(q)
            elif u.path == "/phone-tools/activity":
                self._handle_phone_tools_activity(q)
            elif u.path == "/phone-tools/availability":
                self._handle_phone_tools_availability(q)
            elif u.path == "/phone-tools/next":
                self._handle_phone_tools_next(q)
            elif u.path == "/phone-tools/result":
                self._handle_phone_tools_result(q)
            elif u.path == "/worker-stats":
                self._handle_worker_stats(q)
            elif u.path == "/push/status":
                self._handle_push_status(q)
            elif u.path == "/push/preferences":
                self._handle_push_preferences(q)
            elif u.path == "/push/test":
                self._handle_push_test(q)
            elif u.path == "/push/permission/allow":
                self._handle_push_permission_allow(q)
            elif u.path == "/push/permission/deny":
                self._handle_push_permission_deny(q)
            elif u.path == "/deepfield/observation":
                self._handle_deepfield_observation(q)
            elif u.path == "/sessions/race/prepare":
                self._handle_race_prepare(q)
            elif u.path.startswith("/sessions/race/") and u.path.endswith("/finish"):
                if self.command != "POST":
                    self._send_json({"ok": False, "error": {"code": "method_not_allowed", "message": "race finish requires POST"}}, status=405)
                else:
                    self._handle_race_finish(q, u.path.split("/")[3])
            elif u.path == "/push/live-activity-token":
                self._handle_push_live_activity_token(q)
            elif u.path == "/push/live-activity-test":
                self._handle_push_live_activity_test(q)
            elif u.path == "/sentinel/status":
                self._handle_sentinel_status(q)
            elif u.path == "/sentinel/preferences":
                self._handle_sentinel_preferences(q)
            elif u.path == "/sentinel/snooze":
                self._handle_sentinel_snooze(q)
            elif u.path == "/sentinel/evaluate-now":
                self._handle_sentinel_evaluate_now(q)
            elif u.path == "/sentinel/events":
                self._handle_sentinel_events(q)
            elif u.path == "/workstate-feed":
                self._handle_workstate_feed(q)
            elif u.path == "/model-status":
                self._handle_model_status(q)
            elif u.path == "/substrate-status":
                self._handle_substrate_status(q)
            elif u.path == "/substrate-feed":
                self._handle_substrate_feed(q)
            elif u.path == "/workers":
                self._handle_workers(q)
            elif u.path.startswith("/sessions/race/") and u.path.count("/") == 3:
                self._handle_race_status(q, u.path.split("/")[3])
            elif u.path == "/fleet/digest":
                self._handle_fleet_digest(q)
            elif u.path == "/activity":
                self._handle_activity(q)
            elif u.path == "/activity-stream":
                self._handle_activity_stream(q)
            elif u.path == "/safety/status":
                self._handle_safety_status(q)
            elif u.path == "/safety/events":
                self._handle_safety_events(q)
            elif u.path == "/safety/ack":
                self._handle_safety_ack(q)
            elif u.path == "/safety/request-activation":
                self._handle_safety_request_activation(q)
            elif u.path == "/safety/open-full-disk-access":
                self._handle_safety_open_full_disk_access(q)
            elif u.path == "/safety/evidence-test":
                self._handle_safety_evidence_test(q)
            elif u.path == "/aperture-cli/status":
                self._handle_aperture_cli_status(q)
            elif u.path == "/aperture-cli/providers":
                self._handle_aperture_cli_providers(q)
            elif u.path == "/aperture-cli/launch-contexts":
                self._handle_aperture_cli_launch_contexts(q)
            elif u.path == "/aperture-cli/open":
                self._handle_aperture_cli_open(q)
            elif u.path == "/mirror/status":
                self._handle_mirror_status(q)
            elif u.path == "/mirror/projects":
                self._handle_mirror_projects(q)
            elif u.path == "/mirror/conflicts":
                self._handle_mirror_conflicts(q)
            elif u.path == "/mirror/flush":
                self._handle_mirror_flush(q)
            elif u.path == "/mirror/resume":
                self._handle_mirror_resume(q)
            elif u.path == ORCHESTRATIONS_ROUTE:
                if self.command == "POST":
                    self._handle_orchestrations_create(q)
                else:
                    self._handle_orchestrations_list(q)
            elif u.path.startswith(f"{ORCHESTRATIONS_ROUTE}/"):
                self._route_orchestration_path(u.path, q)
            elif u.path == "/worker-kill":
                self._handle_worker_kill(q)
            elif u.path == "/spawn-session":
                self._handle_spawn_session(q)
            elif u.path == "/onestream-handoff":
                self._handle_onestream_handoff(q)
            elif u.path == "/compose/recordings/sync":
                self._handle_compose_recording_sync()
            elif u.path == "/send-text":
                self._handle_send_text(q)
            elif u.path == "/sigint":
                self._handle_sigint(q)
            elif u.path == "/sigterm":
                self._handle_sigterm(q)
            elif u.path == "/tokens":
                self._handle_tokens(q)
            elif u.path.startswith("/pairdrop/"):
                self._route_pairdrop_path(u.path, q)
            elif u.path == "/upload":
                self._handle_upload(q)
            elif u.path == "/turn-state-stream":
                self._handle_turn_state_stream(q)
            elif u.path == "/sessions-stream":
                self._handle_sessions_stream(q)
            elif u.path == "/commands":
                self._handle_commands(q)
            elif u.path == "/commands-stream":
                self._handle_commands_stream(q)
            elif u.path == "/invocations":
                self._handle_invocations(q)
            elif u.path == "/invocations-stream":
                self._handle_invocations_stream(q)
            elif u.path == "/provider-status":
                self._handle_provider_status(q)
            elif u.path in SESSION_CONTROL_ROUTES:
                self._route_session_control(u.path, q)
            elif u.path == "/provider-controls/snapshot":
                if self.command != "GET":
                    self.send_error(405, "GET required")
                else:
                    self._handle_provider_controls_snapshot(q)
            elif u.path == "/provider-controls/stream":
                if self.command != "GET":
                    self.send_error(405, "GET required")
                else:
                    self._handle_provider_controls_stream(q)
            elif u.path == "/provider-controls/execute":
                self._handle_provider_controls_execute(q)
            elif u.path == "/providers/visibility":
                if (getattr(self, "command", "") or "").upper() == "POST":
                    self._handle_providers_visibility_post(q)
                else:
                    self._handle_providers_visibility_get(q)
            elif u.path == "/status":
                self._handle_status(q)
            elif u.path == "/pickers/resume":
                self._handle_pickers_resume(q)
            elif u.path == "/pickers/resume/preview":
                self._handle_pickers_resume_preview(q)
            elif u.path == "/pickers/permissions":
                self._handle_pickers_permissions(q)
            elif u.path == "/pickers/hooks":
                self._handle_pickers_hooks(q)
            elif u.path == "/pickers/memory":
                self._handle_pickers_memory(q)
            elif u.path.startswith("/pickers/memory/"):
                self._handle_pickers_memory_one(q, u.path[len("/pickers/memory/"):])
            elif u.path == "/pickers/mcp":
                self._handle_pickers_mcp(q)
            elif u.path == "/search":
                self._handle_search(q)
            elif u.path.startswith("/sessions/") and u.path.endswith("/export"):
                sid = unquote(u.path[len("/sessions/"):-len("/export")])
                self._handle_session_export(q, sid)
            else:
                self.send_error(404, "unknown path")
        except RequestBodyRejected:
            raise
        except (ClientDisconnected, BrokenPipeError, ConnectionResetError):
            return
        except Exception as e:
            if DEVICE_REGISTRY is not None:
                DEVICE_REGISTRY.record_audit(
                    "request.error",
                    device_id=getattr(self.pairling_auth, "device_id", None),
                    outcome=type(e).__name__,
                    path=u.path,
                )
            self._send_json({
                "ok": False,
                "error": {
                    "code": "internal_error",
                    "message": "internal runtime error",
                },
            }, status=500)
        finally:
            self._release_command_stream_lease()
            admission.release()

    # ----- /internal/*: loopback hook tier (claude session registry) -----
    _CLAUDE_UUID_RE = re.compile(
        r"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$"
    )
    _INTERNAL_TTY_RE = re.compile(r"^/dev/ttys[0-9]{3,}$")

    def _internal_claude_uuid(self, payload: dict) -> str:
        uuid = str(payload.get("claude_uuid") or "").strip()
        return uuid if self._CLAUDE_UUID_RE.match(uuid) else ""

    def _internal_provider(self, payload: dict) -> str | None:
        raw_provider = payload.get("provider")
        if raw_provider is None or not str(raw_provider).strip():
            return "claude"
        provider = str(raw_provider).strip().lower()
        return provider if provider in {"claude", "codex"} else None

    def _send_internal_unsupported_provider(self, raw_provider) -> None:
        provider = str(raw_provider or "unknown").strip().lower() or "unknown"
        self._send_json({
            "ok": False,
            "error": {
                "code": "unsupported_provider",
                "message": f"Provider {provider} is not supported by this internal route.",
                "provider": provider,
            },
        }, status=422)

    def _internal_terminal_tty(self, payload: dict) -> str:
        tty = str(payload.get("terminal_tty") or "").strip()
        return tty if self._INTERNAL_TTY_RE.match(tty) else ""

    def _internal_pid(self, payload: dict) -> int:
        try:
            pid = int(payload.get("pid") or payload.get("claude_pid") or payload.get("codex_pid") or 0)
        except (TypeError, ValueError):
            return 0
        return pid if 0 < pid < 10 ** 8 else 0

    def _internal_claude_pid(self, payload: dict) -> int:
        return self._internal_pid(payload)

    def _read_internal_json(self) -> dict | None:
        if self.command != "POST":
            self.send_error(405, "POST required")
            return None
        try:
            payload = json.loads(self._read_body() or b"{}")
        except json.JSONDecodeError:
            self._send_json({"ok": False, "error": {"code": "bad_json"}}, status=400)
            return None
        if not isinstance(payload, dict):
            self._send_json({"ok": False, "error": {"code": "bad_json"}}, status=400)
            return None
        return payload

    def _handle_internal_session_register(self, q):
        payload = self._read_internal_json()
        if payload is None:
            return
        provider = self._internal_provider(payload)
        if provider is None:
            self._send_internal_unsupported_provider(payload.get("provider"))
            return
        session_id = str(payload.get("id") or "").strip()
        project = str(payload.get("project") or "").strip()
        if not _safe_session_id(session_id) or not project:
            self._send_json({
                "ok": False,
                "error": {"code": "bad_request", "message": "id and project required"},
            }, status=400)
            return
        claude_uuid = self._internal_claude_uuid(payload)
        pid = self._internal_pid(payload)
        terminal_tty = self._internal_terminal_tty(payload)
        working_on = str(payload.get("working_on") or "")[:500]
        broker_link = {"state": "not_applicable"}
        if provider == "claude" and claude_uuid:
            broker_link = _agent_registry_link_claude_launch_registration(
                session_id,
                project,
                pid=pid,
                terminal_tty=terminal_tty,
                claude_uuid=claude_uuid,
                working_on=working_on,
            )
        if broker_link.get("state") in {"ambiguous", "conflict", "error"}:
            self._send_json({
                "ok": False,
                "error": {
                    "code": "launch_identity_link_failed",
                    "message": "Claude launch identity could not be linked safely.",
                    "reason": broker_link.get("reason"),
                },
            }, status=409)
            return
        linked = broker_link.get("state") in {"linked", "already_linked"}
        ok = linked or _agent_registry_upsert(
            provider,
            session_id,
            project,
            pid=pid,
            terminal_tty=terminal_tty,
            claude_uuid=claude_uuid if provider == "claude" else "",
            working_on=working_on,
            metadata={"registered_by": "internal_session_register"},
        )
        broker_id = str(broker_link.get("broker_id") or "")
        send_scope_id = str(broker_link.get("send_scope_id") or "")
        broker_alias_registered = False
        if linked and broker_id and PTY_BROKER is not None:
            try:
                PTY_BROKER.register_alias(
                    _qualified_session_id("claude", session_id), broker_id
                )
                broker_alias_registered = True
            except Exception:
                # The canonical row retains broker_id, so every lookup can
                # rebuild this in-memory alias. Registration stays truthful
                # even if the broker reconnects during the hook call.
                broker_alias_registered = False
        # Mirrors the PG pg_notify('session_ready'): only fire once the row
        # carries a claude_uuid — that is what /turn-state-stream waits on.
        if provider == "claude" and ok and claude_uuid:
            _signal_session_ready(session_id)
            pending_native_id = str(
                broker_link.get("pending_native_id")
                or broker_link.get("broker_native_id")
                or ""
            )
            if pending_native_id:
                _signal_session_ready(pending_native_id)
        response = {
            "ok": bool(ok),
            "identity_link_state": broker_link.get("state"),
        }
        if linked:
            response.update({
                "session_id": _qualified_session_id("claude", session_id),
                "send_scope_id": send_scope_id or None,
                "broker_id": broker_id,
                "broker_alias_registered": broker_alias_registered,
            })
        self._send_json(response, status=200 if ok else 503)

    def _handle_internal_session_heartbeat(self, q):
        payload = self._read_internal_json()
        if payload is None:
            return
        provider = self._internal_provider(payload)
        if provider is None:
            self._send_internal_unsupported_provider(payload.get("provider"))
            return
        if provider == "codex":
            session_id = str(payload.get("id") or "").strip()
            if not _safe_session_id(session_id):
                self._send_json({
                    "ok": False,
                    "error": {"code": "bad_request", "message": "id required"},
                }, status=400)
                return
            ok = _agent_registry_heartbeat_by_native_id(
                "codex",
                session_id,
                terminal_tty=self._internal_terminal_tty(payload),
                pid=self._internal_pid(payload),
            )
            self._send_json({"ok": bool(ok)})
            return
        claude_uuid = self._internal_claude_uuid(payload)
        if not claude_uuid:
            self._send_json({
                "ok": False,
                "error": {"code": "bad_request", "message": "claude_uuid required"},
            }, status=400)
            return
        ok = _agent_registry_heartbeat_by_claude_uuid(
            "claude",
            claude_uuid,
            terminal_tty=self._internal_terminal_tty(payload),
            pid=self._internal_pid(payload),
        )
        # ok=false simply means no row matched — same as the PG UPDATE no-op.
        self._send_json({"ok": bool(ok)})

    def _handle_internal_session_close(self, q):
        payload = self._read_internal_json()
        if payload is None:
            return
        provider = self._internal_provider(payload)
        if provider is None:
            self._send_internal_unsupported_provider(payload.get("provider"))
            return
        if provider == "codex":
            session_id = str(payload.get("id") or "").strip()
            if not _safe_session_id(session_id):
                self._send_json({
                    "ok": False,
                    "error": {"code": "bad_request", "message": "id required"},
                }, status=400)
                return
            closed = _agent_registry_mark_closed_by_native_id("codex", session_id)
            self._send_json({"ok": True, "closed": bool(closed)})
            return
        claude_uuid = self._internal_claude_uuid(payload)
        if not claude_uuid:
            self._send_json({
                "ok": False,
                "error": {"code": "bad_request", "message": "claude_uuid required"},
            }, status=400)
            return
        closed = _agent_registry_mark_closed_by_claude_uuid("claude", claude_uuid)
        self._send_json({"ok": True, "closed": bool(closed)})

    def _handle_internal_active_sessions(self, q):
        project = q.get("project", [""])[0].strip()
        provider_filter = str(q.get("provider", ["claude"])[0] or "claude").strip().lower()
        if provider_filter not in {"all", "claude", "codex"}:
            self._send_internal_unsupported_provider(provider_filter)
            return
        providers = ["claude", "codex"] if provider_filter == "all" else [provider_filter]
        cutoff = _time.time() - 300
        items = []
        for provider in providers:
            for row in _agent_registry_live(provider):
                if float(row.get("last_heartbeat") or 0) < cutoff:
                    continue
                if project and row.get("project") != project:
                    continue
                items.append({
                    "id": row.get("native_id"),
                    "provider": provider,
                    "project": row.get("project"),
                    "working_on": row.get("working_on") or None,
                    "started_at": float(row.get("started_at") or 0),
                    "last_heartbeat": float(row.get("last_heartbeat") or 0),
                })
        items.sort(key=lambda r: r["started_at"], reverse=True)
        self._send_json({"ok": True, "count": len(items), "sessions": items})

    def _handle_internal_permission_request(self, q):
        # PermissionRequest hook producer (claude + codex). Notify-only: record
        # the pending approval; the agent's native dialog is the durable block.
        # Phase 3 fires the APNs card + wires the Allow keystroke here.
        payload = self._read_internal_json()
        if payload is None:
            return
        provider = self._internal_provider(payload)
        if provider is None:
            self._send_internal_unsupported_provider(payload.get("provider"))
            return
        session_id = str(payload.get("session_id") or "").strip()
        tool_name = str(payload.get("tool_name") or "").strip()
        tool_input = payload.get("tool_input")
        if not isinstance(tool_input, dict):
            tool_input = {}
        if not session_id or not tool_name:
            self._send_json({
                "ok": False,
                "error": {"code": "bad_request", "message": "session_id and tool_name required"},
            }, status=400)
            return
        request_nonce = str(payload.get("request_nonce") or "").strip() or secrets.token_hex(16)
        command_preview = _approval_command_preview(tool_name, tool_input)
        ok = _pending_approval_record(
            request_nonce=request_nonce,
            provider=provider,
            session_id=session_id,
            tool_name=tool_name,
            tool_input=tool_input,
            command_preview=command_preview,
            permission_mode=str(payload.get("permission_mode") or "")[:40],
            broker_id=str(payload.get("broker_session_id") or "").strip(),
        )
        screen_verified = bool(ok and _pending_approval_capture_screen(request_nonce))
        self._send_json({
            "ok": bool(ok),
            "request_nonce": request_nonce,
            "command_preview": command_preview,
            "screen_verified": screen_verified,
        })

    # ----- /open: open path on Mac (existing behavior) -----
    def _handle_open(self, q):
        raw_path = q.get("path", [""])[0]
        app = q.get("app", ["sublime"])[0]
        try:
            path = _canonical_user_path(raw_path, allow_tmp=True)
            if app == "finder":
                command = ["/usr/bin/open", path]
            else:
                command = ["/usr/bin/open", "-a", SUBLIME_APP, path]
            subprocess.run(command, check=True, timeout=5.0)
        except ValueError:
            self._send_error(400, "invalid_path", "Path is invalid")
            return
        except PermissionError:
            self._send_error(403, "path_not_allowed", "Path is outside allowed roots")
            return
        except FileNotFoundError:
            self._send_error(404, "path_not_found", "Path not found")
            return
        except subprocess.TimeoutExpired:
            self._send_error(503, "open_timeout", "Open request timed out")
            return
        except (subprocess.CalledProcessError, OSError):
            self._send_error(502, "open_failed", "Open request failed")
            return
        self._send_json({"ok": True})

    # ----- /healthz + /health-stream: coordinator health -----
    def _handle_health(self, q):
        self._send_json(_cached_health_payload(
            authenticated=self.pairling_auth is not None,
            auth_result=self.pairling_auth,
        ))

    def _handle_healthz(self, q):
        self._send_json(_cached_health_payload(
            authenticated=self.pairling_auth is not None,
            auth_result=self.pairling_auth,
        ))

    def _handle_readyz(self, q):
        payload = _readyz_payload()
        self._send_json(payload, status=200 if payload.get("ok") is True else 503)

    def _handle_routez(self, q):
        self._send_json(_routez_payload(auth_result=self.pairling_auth))

    def _handle_manifest(self, q):
        authenticated = self.pairling_auth is not None
        try:
            runtime_info = _runtime_info_snapshot()
            if not authenticated:
                runtime_info = _public_runtime_info(runtime_info)
            if _build_manifest_payload is None:
                payload = {
                    "ok": True,
                    "schema_version": 1,
                    "contract_version": RUNTIME_CONTRACT_VERSION,
                    "runtime": runtime_info,
                    "auth": {
                        "mode": RUNTIME_AUTH_MODE,
                        "required": True,
                        "legacy_global_token": False,
                        "authenticated": authenticated,
                    },
                }
            else:
                payload = _build_manifest_payload(
                    runtime_info,
                    authenticated=authenticated,
                    device_id=getattr(self.pairling_auth, "device_id", None),
                    scopes=list(getattr(self.pairling_auth, "scopes", []) or []),
                )
            if not authenticated:
                payload["runtime"] = runtime_info
        except Exception:
            if authenticated:
                raise
            self._send_json({
                "ok": False,
                "schema_version": 1,
                "contract_version": RUNTIME_CONTRACT_VERSION,
                "error": {
                    "code": "manifest_unavailable",
                    "message": "Runtime manifest is unavailable",
                },
            }, status=503)
            return
        self._send_json(payload)

    def _send_session_control_error(
        self,
        code: str,
        message: str,
        *,
        status: int,
    ) -> None:
        self._send_json(
            {
                "ok": False,
                "error": {
                    "code": str(code or "session_control_error"),
                    "message": str(message or "session-control request failed")[
                        :1024
                    ],
                },
            },
            status=int(status),
            headers={"Cache-Control": "no-store"},
        )

    def _session_control_query(
        self,
        query: dict,
        *,
        required: frozenset[str],
        optional: frozenset[str] = frozenset(),
    ) -> dict[str, str]:
        keys = set(query)
        if not required.issubset(keys) or not keys.issubset(required | optional):
            raise ValueError("session-control query parameters are invalid")
        values: dict[str, str] = {}
        for key in keys:
            candidates = query.get(key)
            if (
                not isinstance(candidates, list)
                or len(candidates) != 1
                or not isinstance(candidates[0], str)
                or not candidates[0]
                or len(candidates[0]) > 512
            ):
                raise ValueError(
                    f"session-control query parameter {key} is invalid"
                )
            values[key] = candidates[0]
        return values

    def _require_session_control_empty_body(self) -> None:
        if int(getattr(self, "_expected_body_length", 0) or 0) != 0:
            raise _SessionControlGatewayError(
                "invalid_message",
                "session-control GET requests do not accept a body",
                status=400,
                error_class="transport",
            )

    def _session_control_body(self) -> bytes:
        content_type = str(self.headers.get("Content-Type") or "")
        parts = [part.strip() for part in content_type.split(";")]
        if (
            len(parts) != 2
            or parts[0].lower() != SESSION_CONTROL_MEDIA_TYPE
            or parts[1].lower().replace(" ", "") != "charset=utf-8"
        ):
            raise _SessionControlGatewayError(
                "unsupported_media_type",
                "session-control requests require the schema-owned UTF-8 media type",
                status=415,
                error_class="transport",
            )
        return self._read_body()

    def _send_session_control_message(self, gateway, message: dict) -> None:
        encoded = gateway.encode_message(message)
        self.send_response(200)
        self.send_header(
            "Content-Type",
            f"{SESSION_CONTROL_MEDIA_TYPE}; charset=utf-8",
        )
        self.send_header("Cache-Control", "no-store")
        self.send_header("Content-Length", str(len(encoded)))
        self.end_headers()
        self.wfile.write(encoded)

    def _stream_session_control_events(
        self,
        gateway,
        peer,
        *,
        session_id: str,
        context_id: str,
        after_sequence: int,
        predecessor_digest: str | None,
    ) -> None:
        page = gateway.event_page(
            session_id,
            context_id,
            peer,
            after_sequence=after_sequence,
            predecessor_digest=predecessor_digest,
            now=_time.time(),
        )
        self.send_response(200)
        self.send_header("Content-Type", "text/event-stream")
        self.send_header("Cache-Control", "no-store")
        self.send_header("Connection", "keep-alive")
        self.send_header("X-Accel-Buffering", "no")
        self.end_headers()
        timeout = int(gateway.profile["limits"]["stream_timeout_seconds"])
        keepalive = int(gateway.profile["limits"]["keepalive_seconds"])
        deadline = _time.monotonic() + timeout
        next_keepalive = _time.monotonic() + keepalive
        while True:
            try:
                for message in page["messages"]:
                    encoded = gateway.encode_message(message, event=True)
                    self.wfile.write(
                        b"event: event.publish\ndata: " + encoded + b"\n\n"
                    )
                if page["messages"]:
                    self.wfile.flush()
                after_sequence = int(page["after_sequence"])
                predecessor_digest = page["predecessor_digest"]
                if page["terminal"]:
                    self.close_connection = True
                    return
                current = _time.monotonic()
                if current >= deadline:
                    self.close_connection = True
                    return
                if current >= next_keepalive:
                    self.wfile.write(b": keepalive\n\n")
                    self.wfile.flush()
                    next_keepalive = current + keepalive
                if len(page["messages"]) < 500:
                    _time.sleep(min(0.25, max(0.0, deadline - current)))
                page = gateway.event_page(
                    session_id,
                    context_id,
                    peer,
                    after_sequence=after_sequence,
                    predecessor_digest=predecessor_digest,
                    now=_time.time(),
                )
            except (
                _SessionControlGatewayError,
                BrokenPipeError,
                ConnectionResetError,
            ):
                self.close_connection = True
                return

    def _route_session_control(self, path: str, query: dict) -> None:
        try:
            gateway = _ensure_session_control_gateway()
        except Exception:
            gateway = None
        if gateway is None:
            self._send_session_control_error(
                "session_control_unavailable",
                "session-control runtime authority is unavailable",
                status=503,
            )
            return
        try:
            if path == "/session-control/v1/negotiate":
                if self.command != "POST":
                    raise _SessionControlGatewayError(
                        "method_not_allowed",
                        "negotiation requires POST",
                        status=405,
                    )
                if query:
                    raise ValueError(
                        "negotiation does not accept query parameters"
                    )
                peer = _session_control_peer(self)
                result = gateway.negotiate(
                    self._session_control_body(),
                    peer,
                    now=_time.time(),
                )
                self._send_session_control_message(gateway, result)
                return
            if path == "/session-control/v1/snapshot":
                if self.command != "GET":
                    raise _SessionControlGatewayError(
                        "method_not_allowed",
                        "snapshot publication requires GET",
                        status=405,
                    )
                self._require_session_control_empty_body()
                values = self._session_control_query(
                    query,
                    required=frozenset({"session", "context_id"}),
                )
                peer = _session_control_peer(self)
                result = gateway.snapshot(
                    values["session"],
                    values["context_id"],
                    peer,
                    now=_time.time(),
                )
                self._send_session_control_message(gateway, result)
                return
            if path == "/session-control/v1/execute":
                if self.command != "POST":
                    raise _SessionControlGatewayError(
                        "method_not_allowed",
                        "execution requires POST",
                        status=405,
                    )
                if query:
                    raise ValueError("execution does not accept query parameters")
                peer = _session_control_peer(self, attachments=True)
                body = self._session_control_body()
                observed_at = _time.time()
                gateway.admit_execute_confirmation(
                    body,
                    peer,
                    now=observed_at,
                )
                result = gateway.execute(body, peer, now=observed_at)
                self._send_session_control_message(gateway, result)
                return
            if path == "/session-control/v1/recover":
                if self.command != "POST":
                    raise _SessionControlGatewayError(
                        "method_not_allowed",
                        "recovery requires POST",
                        status=405,
                    )
                if query:
                    raise ValueError("recovery does not accept query parameters")
                peer = _session_control_peer(self)
                result = gateway.recover(
                    self._session_control_body(),
                    peer,
                    now=_time.time(),
                )
                self._send_session_control_message(gateway, result)
                return
            if path == "/session-control/v1/events":
                if self.command != "GET":
                    raise _SessionControlGatewayError(
                        "method_not_allowed",
                        "event delivery requires GET",
                        status=405,
                    )
                self._require_session_control_empty_body()
                values = self._session_control_query(
                    query,
                    required=frozenset(
                        {"session_id", "context_id", "after_sequence"}
                    ),
                    optional=frozenset({"predecessor_digest"}),
                )
                sequence_text = values["after_sequence"]
                if re.fullmatch(r"(?:-1|0|[1-9][0-9]*)", sequence_text) is None:
                    raise ValueError(
                        "session-control event cursor is invalid"
                    )
                peer = _session_control_peer(self)
                self._stream_session_control_events(
                    gateway,
                    peer,
                    session_id=values["session_id"],
                    context_id=values["context_id"],
                    after_sequence=int(sequence_text),
                    predecessor_digest=values.get("predecessor_digest"),
                )
                return
            raise ValueError("unknown session-control route")
        except _SessionControlGatewayError as exc:
            if not getattr(self, "_pairling_sse_response", False):
                self._send_session_control_error(
                    getattr(exc, "code", "session_control_error"),
                    getattr(exc, "message", str(exc)),
                    status=getattr(exc, "status", 400),
                )
        except ValueError as exc:
            if not getattr(self, "_pairling_sse_response", False):
                self._send_session_control_error(
                    "invalid_message",
                    str(exc),
                    status=400,
                )

    def _read_json_object(self) -> dict:
        body = self._read_body()
        if not body:
            return {}
        payload = json.loads(body.decode("utf-8"))
        if not isinstance(payload, dict):
            raise ValueError("body must be a JSON object")
        return payload

    def _resolve_self_device_target(self, requested_device_id) -> str | None:
        device_id, error = _self_device_target(self.pairling_auth, requested_device_id)
        if error is not None:
            self._send_json({
                "ok": False,
                "error": {
                    "code": error["code"],
                    "message": error["message"],
                },
            }, status=int(error["status"]))
            return None
        return device_id

    def _handle_pairling_tools_run(self, q):
        if run_pairling_tool is None:
            self._send_json({
                "ok": False,
                "error": {
                    "code": "pairling_tools_unavailable",
                    "message": "Pairling tools router is unavailable",
                },
            }, status=503)
            return
        try:
            payload = self._read_json_object()
        except (json.JSONDecodeError, ValueError) as exc:
            self._send_json({"ok": False, "error": {"code": "bad_request", "message": str(exc)}}, status=400)
            return

        payload, target_error = _pairling_tools_payload_for_auth(self.pairling_auth, payload)
        if target_error is not None:
            self._send_json({
                "ok": False,
                "error": {
                    "code": target_error["code"],
                    "message": target_error["message"],
                },
            }, status=int(target_error["status"]))
            return
        result = run_pairling_tool(payload)
        if DEVICE_REGISTRY is not None and audit_detail_for_tool_run is not None:
            error_payload = result.get("error") if isinstance(result.get("error"), dict) else {}
            DEVICE_REGISTRY.record_audit(
                "pairling_tools.run",
                device_id=getattr(self.pairling_auth, "device_id", None),
                outcome="ok" if result.get("ok") else str(error_payload.get("code") or "error"),
                path="/pairling-tools/run",
                detail=audit_detail_for_tool_run(payload, result),
            )
        error_payload = result.get("error") if isinstance(result.get("error"), dict) else {}
        status = 200
        if not result.get("ok"):
            status = 400 if error_payload.get("code") in {"bad_request", "invalid_tool", "invalid_strategy", "missing_input"} else 502
        self._send_json(result, status=status)

    def _handle_phone_tools_activity(self, q):
        if self.command != "GET":
            self.send_error(405, "GET required")
            return
        if DEVICE_REGISTRY is None:
            self._send_json({
                "ok": False,
                "error": {
                    "code": "phone_tools_activity_unavailable",
                    "message": "Phone Tools activity history is unavailable",
                },
            }, status=503)
            return
        try:
            limit = int(q.get("limit", ["50"])[0])
        except (TypeError, ValueError):
            self._send_json({
                "ok": False,
                "error": {
                    "code": "bad_request",
                    "message": "limit must be an integer",
                },
            }, status=400)
            return
        agent_provider = str(q.get("agent_provider", [""])[0] or "").strip().lower() or None
        session_identity = str(q.get("session_identity", [""])[0] or "").strip() or None
        if (agent_provider is None) != (session_identity is None) or (
            agent_provider is not None
            and re.fullmatch(r"[a-z0-9_-]{1,48}", agent_provider) is None
        ) or (
            session_identity is not None
            and re.fullmatch(r"[A-Za-z0-9._:-]{1,160}", session_identity) is None
        ):
            self._send_json({
                "ok": False,
                "error": {
                    "code": "bad_request",
                    "message": "agent_provider and session_identity must be valid and supplied together",
                },
            }, status=400)
            return
        try:
            page = DEVICE_REGISTRY.recent_phone_tool_activity(
                limit=limit,
                agent_provider=agent_provider,
                session_identity=session_identity,
            )
        except (OSError, ValueError) as exc:
            self._send_json({
                "ok": False,
                "error": {
                    "code": "phone_tools_activity_unavailable",
                    "message": f"Phone Tools activity history could not be read: {type(exc).__name__}",
                },
            }, status=503)
            return
        items = page["items"]
        self._send_json({
            "ok": True,
            "schema_version": 1,
            "count": len(items),
            "items": items,
            "filtered": bool(page.get("filtered")),
            "unbound_count": max(0, int(page.get("unbound_count") or 0)),
        })

    def _handle_phone_tools_availability(self, q):
        if PHONE_TOOL_AVAILABILITY is None:
            self._send_json({
                "ok": False,
                "error": {
                    "code": "phone_tools_availability_unavailable",
                    "message": "Phone tools availability store is unavailable",
                },
            }, status=503)
            return
        try:
            payload = self._read_json_object()
        except (json.JSONDecodeError, ValueError) as exc:
            self._send_json({"ok": False, "error": {"code": "bad_request", "message": str(exc)}}, status=400)
            return
        device_id = getattr(self.pairling_auth, "device_id", None)
        if not isinstance(payload.get("listener_running"), bool):
            self._send_json({
                "ok": False,
                "error": {
                    "code": "invalid_boolean",
                    "message": "listener_running must be a JSON boolean",
                },
            }, status=400)
            return
        worker_id = current_worker_id(payload.get("worker_id")) if current_worker_id is not None else None
        if worker_id is None:
            self._send_json({
                "ok": False,
                "error": {
                    "code": "invalid_worker_id",
                    "message": "worker_id must be a current Phone Tools worker ID.",
                },
            }, status=400)
            return
        raw_supersedes = payload.get("supersedes_worker_id")
        supersedes_worker_id = None
        if raw_supersedes is not None:
            supersedes_worker_id = current_worker_id(raw_supersedes) if current_worker_id is not None else None
            if supersedes_worker_id is None:
                self._send_json({
                    "ok": False,
                    "error": {
                        "code": "invalid_supersedes_worker_id",
                        "message": "supersedes_worker_id must name a current Phone Tools worker.",
                    },
                }, status=400)
                return
        listener_running = payload["listener_running"]
        if PHONE_TOOL_WORK_QUEUE is not None:
            if listener_running:
                if not PHONE_TOOL_WORK_QUEUE.activate_worker(
                    device_id=device_id,
                    worker_id=worker_id,
                    supersedes_worker_id=supersedes_worker_id,
                ):
                    self._send_json({
                        "ok": False,
                        "error": {
                            "code": "phone_tools_worker_stale",
                            "message": "This Phone Tools worker lifecycle has already stopped.",
                        },
                    }, status=409)
                    return
            else:
                PHONE_TOOL_WORK_QUEUE.deactivate_worker(device_id=device_id, worker_id=worker_id)
        state = PHONE_TOOL_AVAILABILITY.update(
            payload,
            device_id=device_id,
        )
        self._send_json({
            "ok": True,
            "schema_version": 1,
            "availability": state,
        })

    def _handle_phone_tools_next(self, q):
        if PHONE_TOOL_WORK_QUEUE is None:
            self._send_json({
                "ok": False,
                "error": {
                    "code": "phone_tools_queue_unavailable",
                    "message": "Phone tools work queue is unavailable",
                },
            }, status=503)
            return
        try:
            payload = self._read_json_object()
        except (json.JSONDecodeError, ValueError) as exc:
            self._send_json({"ok": False, "error": {"code": "bad_request", "message": str(exc)}}, status=400)
            return
        tools = payload.get("tools") if isinstance(payload.get("tools"), list) else []
        raw_wait_seconds = payload.get("wait_seconds", 10)
        if isinstance(raw_wait_seconds, bool):
            wait_seconds = None
        else:
            try:
                wait_seconds = int(raw_wait_seconds)
            except (TypeError, ValueError):
                wait_seconds = None
        if wait_seconds is None:
            self._send_json({
                "ok": False,
                "error": {
                    "code": "invalid_wait_seconds",
                    "message": "wait_seconds must be an integer",
                },
            }, status=400)
            return
        wait_seconds = max(1, min(wait_seconds, 25))
        worker_id = current_worker_id(payload.get("worker_id")) if current_worker_id is not None else None
        if worker_id is None:
            self._send_json({
                "ok": False,
                "error": {
                    "code": "invalid_worker_id",
                    "message": "worker_id must be a current Phone Tools worker ID.",
                },
            }, status=400)
            return
        device_id = getattr(self.pairling_auth, "device_id", None)
        if not PHONE_TOOL_WORK_QUEUE.worker_is_active(device_id=device_id, worker_id=worker_id):
            self._send_json({
                "ok": False,
                "error": {
                    "code": "phone_tools_worker_stale",
                    "message": "This Phone Tools worker is no longer active.",
                },
            }, status=409)
            return
        if PHONE_TOOL_AVAILABILITY is not None:
            PHONE_TOOL_AVAILABILITY.update({
                "listener_running": True,
                "port": 0,
                "tools": tools,
                "app_state": "foreground-worker",
                "expires_in_seconds": max(20, min(int(wait_seconds or 10) + 20, 120)),
                "worker_id": worker_id,
            }, device_id=device_id)
        request = PHONE_TOOL_WORK_QUEUE.next_request(
            device_id=device_id,
            tools=tools,
            wait_seconds=wait_seconds,
            worker_id=worker_id,
        )
        self._send_json({
            "ok": True,
            "schema_version": 1,
            "request": request,
            "worker": PHONE_TOOL_WORK_QUEUE.snapshot(device_id=device_id),
        })

    def _handle_phone_tools_result(self, q):
        if PHONE_TOOL_WORK_QUEUE is None:
            self._send_json({
                "ok": False,
                "error": {
                    "code": "phone_tools_queue_unavailable",
                    "message": "Phone tools work queue is unavailable",
                },
            }, status=503)
            return
        try:
            payload = self._read_json_object()
        except (json.JSONDecodeError, ValueError) as exc:
            self._send_json({"ok": False, "error": {"code": "bad_request", "message": str(exc)}}, status=400)
            return
        if not isinstance(payload.get("ok"), bool):
            self._send_json({
                "ok": False,
                "error": {
                    "code": "invalid_boolean",
                    "message": "ok must be a JSON boolean",
                },
            }, status=400)
            return
        worker_id = current_worker_id(payload.get("worker_id")) if current_worker_id is not None else None
        if worker_id is None:
            self._send_json({
                "ok": False,
                "error": {
                    "code": "invalid_worker_id",
                    "message": "worker_id must be a current Phone Tools worker ID.",
                },
            }, status=400)
            return
        completion = PHONE_TOOL_WORK_QUEUE.complete(
            request_id=str(payload.get("request_id") or ""),
            ok=payload["ok"],
            result=str(payload.get("result") or ""),
            error=str(payload.get("error") or ""),
            device_id=getattr(self.pairling_auth, "device_id", None),
            worker_id=worker_id,
        )
        if completion != "accepted":
            self._send_json({
                "ok": False,
                "schema_version": 1,
                "error": {
                    "code": "phone_tools_result_stale",
                    "message": "This Phone Tools result no longer belongs to an active request.",
                    "state": completion,
                },
            }, status=409)
            return
        self._send_json({"ok": True, "schema_version": 1})

    def _pairing_host_chain(self) -> list[str]:
        hosts: list[str] = []
        for route in self._pairling_connect_routes():
            host = route.get("host")
            if isinstance(host, str) and host:
                hosts.append(host)
        tailnet_name = os.environ.get("PAIRLING_TAILNET_HOST")
        if tailnet_name:
            hosts.append(tailnet_name)
        tailnet_ip = _tailnet_ip()
        if tailnet_ip:
            hosts.append(tailnet_ip)
        hosts.extend(_lan_ips()[:2])
        hostname = _bonjour_hostname(
            os.environ.get("PAIRLING_HOSTNAME") or os.uname().nodename
        )
        if hostname:
            hosts.append(hostname)
        seen: set[str] = set()
        deduped: list[str] = []
        for host in hosts:
            if host and host not in seen:
                seen.add(host)
                deduped.append(host)
        return deduped or ["127.0.0.1"]

    def _pairling_connect_routes(self) -> list[dict]:
        if fetch_connectd_status is None or advertised_pairling_connect_routes is None:
            return []
        try:
            return advertised_pairling_connect_routes(fetch_connectd_status(timeout_seconds=0.7))
        except Exception:
            return []

    def _pairing_runtime_routes(self, host_chain: list[str]) -> list[dict]:
        routes: list[dict] = []
        seen_base_urls: set[str] = set()
        for route in self._pairling_connect_routes():
            base_url = route.get("base_url")
            if isinstance(base_url, str) and base_url not in seen_base_urls:
                seen_base_urls.add(base_url)
                routes.append(dict(route))
        for host in host_chain:
            if not host:
                continue
            base_url = f"http://{host}:{PORT}"
            if base_url in seen_base_urls:
                continue
            seen_base_urls.add(base_url)
            kind = "tailnet" if host.startswith("100.") or host.endswith(".ts.net") else "bonjour" if host.endswith(".local") else "lan"
            routes.append({
                "id": f"{kind}-fallback",
                "kind": kind,
                "source": "pairlingd",
                "priority": 30 if kind == "bonjour" else 40 if kind == "lan" else 60,
                "base_url": base_url,
                "host": host,
                "port": PORT,
                "status": "fallback",
            })
        routes.sort(key=lambda item: int(item.get("priority") or 0), reverse=True)
        return routes

    def _handle_pair_start(self, q):
        if PAIRING_STORE is None:
            self._send_json({
                "ok": False,
                "error": {
                    "code": "pairing_unavailable",
                    "message": "Pairing store is unavailable",
                },
            }, status=503)
            return
        # Rate-limit pair starts. The loopback peer is shared by requests
        # proxied through connectd, so this is a global circuit breaker rather
        # than a per-source-IP defense. Same-UID local-control requests use a
        # stable private-socket key because AF_UNIX has no IP peer address.
        peer = _client_address_host(self.client_address)
        if not peer and getattr(self.server, "pairling_local_control", False):
            peer = "local-control"
        allowed, retry_after = _request_rate_check(
            f"pair_start:{peer or 'unknown'}", max_per_min=5
        )
        if not allowed:
            self.send_response(429)
            self.send_header("Retry-After", str(retry_after))
            self.send_header("Content-Type", "application/json")
            self.end_headers()
            self.wfile.write(json.dumps({
                "ok": False,
                "error": {"code": "rate_limited", "message": "too many pair starts"},
            }).encode("utf-8"))
            return
        try:
            payload = self._read_json_object()
            ttl = int(payload.get("ttl_seconds") or DEFAULT_PAIR_TTL_SECONDS)
            purpose = str(payload.get("purpose") or "").strip()
            start_kwargs = {"ttl_seconds": ttl}
            raw_role = payload.get("role")
            if raw_role is not None:
                if not isinstance(raw_role, str) or not raw_role.strip():
                    raise ValueError("role must be a non-empty string")
                start_kwargs["role"] = raw_role
            if purpose:
                raw_scopes = payload.get("scopes")
                if raw_scopes is not None and (
                    not isinstance(raw_scopes, list)
                    or not all(isinstance(scope, str) and scope for scope in raw_scopes)
                ):
                    raise ValueError("scopes must be a list of non-empty strings")
                start_kwargs.update({
                    "purpose": purpose,
                    "scopes": raw_scopes,
                    "lease_ttl_seconds": int(
                        payload.get("lease_ttl_seconds") or DEFAULT_SMOKE_LEASE_TTL_SECONDS
                    ),
                })
            if purpose != "runtime_truth_smoke":
                permission_error = _pairing_terminal_permissions_error()
                if permission_error is not None:
                    self._send_json(permission_error, status=409)
                    return
            started = PAIRING_STORE.start_pair(**start_kwargs)
            bonjour = {
                "ok": False,
                "reason": (
                    "smoke_pairing_not_advertised"
                    if purpose == "runtime_truth_smoke"
                    else "out_of_band_pairing_required"
                ),
            }
            pairling_connect_routes = self._pairling_connect_routes()
        except PairingError as exc:
            self._send_json({
                "ok": False,
                "error": {"code": exc.code, "message": exc.message},
            }, status=exc.status)
            return
        except ValueError as exc:
            self._send_json({"ok": False, "error": {"code": "bad_request", "message": str(exc)}}, status=400)
            return
        self._send_json({
            "ok": True,
            "pair_id": started.pair_id,
            "secret": started.secret,
            "attest_challenge": started.attest_challenge,
            "mac_ake_pub": started.mac_ake_pub,
            "expires_at": started.expires_at,
            "install_id": started.install_id,
            "runtime_port": PORT,
            "purpose": started.purpose,
            "role": started.role,
            "lease_expires_at": started.lease_expires_at,
            "pair_service": {
                "type": started.service_type,
                "txt": started.txt,
                "runtime_api_advertised": bool(pairling_connect_routes),
                "bonjour": bonjour,
                "routes": pairling_connect_routes,
            },
            "claim": {
                "url": "https://pairling.dev/pair/",
                "pair_id": started.pair_id,
                "secret": started.secret,
                "attest_challenge": started.attest_challenge,
                "mac_ake_pub": started.mac_ake_pub,
                "role": started.role,
                "pv": "2",
            },
        })

    def _handle_pair_psk_claim_v2(self, q):
        # WS3: PSK-authenticated ECDH claim. The secret is NEVER received; the
        # phone proves knowledge of it by completing the key exchange. The
        # bearer token is returned AES-GCM-sealed under K_token, so a passive
        # on-LAN sniffer learns nothing.
        if PAIRING_STORE is None:
            self._send_json({"ok": False, "error": {"code": "pairing_unavailable", "message": "Pairing store is unavailable"}}, status=503)
            return
        try:
            payload = self._read_json_object()
            if payload.get("seal_proof_secret") is not True:
                raise PairingError(
                    "upgrade_required",
                    426,
                    "this Pairling version requires sealed proof credentials",
                )
            if payload.get("activation_contract") != "pairling.psk.activate.v1":
                raise PairingError(
                    "upgrade_required",
                    426,
                    "update Pairling on this iPhone before pairing with this Mac",
                )
            if "attested_claim_ticket" in payload:
                raise PairingError(
                    "plaintext_attested_claim_forbidden",
                    400,
                    "v2 pairing requires an encrypted relay claim ticket",
                )
            raw_protocol_version = payload.get("pv")
            if (
                isinstance(raw_protocol_version, bool)
                or not isinstance(raw_protocol_version, int)
            ):
                raise PairingError(
                    "psk_request_binding_invalid",
                    400,
                    "v2 pairing requires an integer protocol version",
                )
            if "direct_attest_object" in payload and not isinstance(
                payload.get("direct_attest_object"), dict
            ):
                raise PairingError(
                    "psk_request_binding_invalid",
                    400,
                    "v2 direct attestation must be an object",
                )
            pair_id = str(payload.get("pair_id") or "")
            pair_digest = hashlib.sha256(pair_id.encode("utf-8")).hexdigest()[:24]
            headers = getattr(self, "headers", {})
            origin_digest = _request_origin_key(headers, self.client_address)
            rate_keys = [
                f"pair_psk:source:{origin_digest}",
                f"pair_psk:pair:{pair_digest}",
            ]
            for rate_key in rate_keys:
                allowed, retry_after = _pairing_rate_check(rate_key, max_per_min=5)
                if not allowed:
                    self._send_json(
                        {
                            "ok": False,
                            "error": {
                                "code": "rate_limited",
                                "message": "too many psk claims",
                            },
                        },
                        status=429,
                        headers={"Retry-After": str(retry_after)},
                    )
                    return
            purpose = PAIRING_STORE.pairing_purpose(pair_id)
            if purpose != "runtime_truth_smoke":
                permission_error = _pairing_terminal_permissions_error()
                if permission_error is not None:
                    self._send_json(permission_error, status=409)
                    return
            host_chain = self._pairing_host_chain()
            runtime_routes = self._pairing_runtime_routes(list(host_chain))
            transport = "pairling-connect" if any(
                route.get("source") == "pairling_connectd" and route.get("status") == "ready"
                for route in runtime_routes
            ) else "http-local"
            funnel_origin = _funnel_origin_request(headers, self.client_address)
            require_direct_attest = _pair_claim_requires_app_attest(headers, self.client_address)
            relay_required, relay_claim_verifier = _relay_claim_assurance()
            sealed_claim = PAIRING_STORE.psk_claim_pair(
                pair_id=pair_id,
                b_pub_b64=str(payload.get("b_pub") or ""),
                confirm_b64=str(payload.get("confirm") or ""),
                device_name=str(payload.get("device_name") or "Pairling iPhone"),
                role=(payload.get("role") if "role" in payload else None),
                host_chain=host_chain,
                se_public_key_der=(
                    payload.get("se_public_key_der")
                    if "se_public_key_der" in payload
                    else None
                ),
                attest_object=(payload.get("direct_attest_object") if isinstance(payload.get("direct_attest_object"), dict) else None),
                attest_key_id=(payload.get("attest_key_id") if "attest_key_id" in payload else None),
                attest_environment=(payload.get("attest_environment") if "attest_environment" in payload else None),
                enc_attested_claim_ticket=(
                    payload.get("enc_attested_claim_ticket")
                    if "enc_attested_claim_ticket" in payload
                    else None
                ),
                attested_claim_ticket_nonce=(
                    payload.get("attested_claim_ticket_nonce")
                    if "attested_claim_ticket_nonce" in payload
                    else None
                ),
                relay_device_id=(payload.get("relay_device_id") if "relay_device_id" in payload else None),
                relay_required=relay_required,
                relay_claim_verifier=relay_claim_verifier,
                funnel_origin=funnel_origin,
                require_direct_attest=require_direct_attest,
                seal_proof_secret=True,
                request_contract=(payload.get("request_contract") if "request_contract" in payload else None),
                request_binding=(payload.get("request_binding") if "request_binding" in payload else None),
                protocol_version=raw_protocol_version,
                activation_contract=str(payload.get("activation_contract") or ""),
                runtime_routes=runtime_routes,
                transport=transport,
            )
        except PairingError as exc:
            self._send_json({"ok": False, "error": {"code": exc.code, "message": exc.message}}, status=exc.status)
            return
        except ValueError as exc:
            self._send_json({"ok": False, "error": {"code": "bad_request", "message": str(exc)}}, status=400)
            return
        if sealed_claim.response_payload is not None:
            self._send_json(sealed_claim.response_payload)
            return
        self._send_json(
            {
                "ok": False,
                "error": {
                    "code": "pair_response_unsigned",
                    "message": "The Mac could not produce a verified pairing response.",
                },
            },
            status=503,
        )

    def _handle_pair_psk_activate(self, q):
        if PAIRING_STORE is None:
            self._send_json(
                {
                    "ok": False,
                    "error": {
                        "code": "pairing_unavailable",
                        "message": "Pairing store is unavailable",
                    },
                },
                status=503,
            )
            return
        pair_id = ""
        device_id = ""
        remote_activation = False
        remote_notification_marker_created = False

        def clear_remote_notification_marker():
            nonlocal remote_notification_marker_created
            if not remote_notification_marker_created or PUSH_DISPATCHER is None:
                return
            try:
                PUSH_DISPATCHER.complete_remote_pairing_notification(
                    pair_id=pair_id,
                    device_id=device_id,
                )
            except Exception:
                pass
            remote_notification_marker_created = False

        try:
            payload = self._read_json_object()
            pair_id = str(payload.get("pair_id") or "")
            device_id = str(payload.get("device_id") or "")
            activation_nonce = str(payload.get("activation_nonce") or "")
            token_hash = str(payload.get("token_hash") or "")
            activation_proof = str(payload.get("activation_proof") or "")
            if (
                not pair_id
                or not device_id
                or not activation_nonce
                or not re.fullmatch(r"[0-9a-f]{64}", token_hash)
                or not re.fullmatch(r"[0-9a-f]{64}", activation_proof)
            ):
                raise ValueError("activation payload is incomplete")
            pair_digest = hashlib.sha256(pair_id.encode("utf-8")).hexdigest()[:24]
            headers = getattr(self, "headers", {})
            trusted_gateway = _pairdrop_gateway_provenance_ok(headers, self.client_address)
            remote_activation = trusted_gateway or not _loopback_client_address(self.client_address)
            origin_digest = _request_origin_key(headers, self.client_address)
            rate_keys = [
                f"pair_psk_activate:source:{origin_digest}",
                f"pair_psk_activate:pair:{pair_digest}",
            ]
            for rate_key in rate_keys:
                allowed, retry_after = _pairing_rate_check(rate_key, max_per_min=10)
                if not allowed:
                    self._send_json(
                        {
                            "ok": False,
                            "error": {
                                "code": "rate_limited",
                                "message": "too many pairing activations",
                            },
                        },
                        status=429,
                        headers={"Retry-After": str(retry_after)},
                    )
                    return
            pending_activation = PAIRING_STORE.pending_psk_activation_context(
                pair_id=pair_id,
                device_id=device_id,
            )
            if (
                pending_activation is not None
                and pending_activation.purpose != "runtime_truth_smoke"
            ):
                permission_error = _pairing_terminal_permissions_error()
                if permission_error is not None:
                    self._send_json(permission_error, status=409)
                    return
            if PUSH_DISPATCHER is not None:
                try:
                    if not remote_activation:
                        pending_reader = getattr(
                            PUSH_DISPATCHER,
                            "remote_pairing_notification_pending",
                            None,
                        )
                        if callable(pending_reader):
                            remote_activation = bool(pending_reader(
                                pair_id=pair_id,
                                device_id=device_id,
                            ))
                except Exception:
                    self._send_json(
                        {
                            "ok": False,
                            "error": {
                                "code": "push_notification_pending",
                                "message": "pairing cannot continue until its security notification is durable",
                            },
                        },
                        status=503,
                    )
                    return
            elif remote_activation:
                self._send_json(
                    {
                        "ok": False,
                        "error": {
                            "code": "push_notification_pending",
                            "message": "pairing cannot continue until its security notification is durable",
                        },
                    },
                    status=503,
                )
                return

            before_activation = None
            if remote_activation:
                def persist_remote_notification_marker():
                    nonlocal remote_notification_marker_created
                    try:
                        PUSH_DISPATCHER.mark_remote_pairing_notification_pending(
                            pair_id=pair_id,
                            device_id=device_id,
                        )
                    except Exception as exc:
                        raise PairingError(
                            "push_notification_pending",
                            503,
                            "pairing cannot continue until its security notification is durable",
                        ) from exc
                    remote_notification_marker_created = True

                before_activation = persist_remote_notification_marker

            activated = PAIRING_STORE.activate_psk_claim(
                pair_id=pair_id,
                device_id=device_id,
                activation_nonce=activation_nonce,
                token_hash=token_hash,
                activation_proof=activation_proof,
                before_activation=before_activation,
            )
            if remote_activation and not remote_notification_marker_created:
                raise RuntimeError("remote activation did not persist its notification marker")
            # Activation may revoke a previous credential for the same phone.
            # Do not leave that device authorized by the short GET cache.
            _clear_auth_result_cache()
        except PairingError as exc:
            clear_remote_notification_marker()
            response = {
                "ok": False,
                "error": {"code": exc.code, "message": exc.message},
            }
            if isinstance(getattr(exc, "activation_result", None), dict):
                response.update(exc.activation_result)
                response["error"] = {"code": exc.code, "message": exc.message}
            self._send_json(
                response,
                status=exc.status,
            )
            return
        except ValueError as exc:
            self._send_json(
                {"ok": False, "error": {"code": "bad_request", "message": str(exc)}},
                status=400,
            )
            return
        except Exception:
            clear_remote_notification_marker()
            self._send_json(
                {
                    "ok": False,
                    "error": {
                        "code": "pair_activation_failed",
                        "message": "pairing activation could not be completed",
                    },
                },
                status=503,
            )
            return
        if activated.superseded_device_ids:
            try:
                if PUSH_DISPATCHER is None:
                    raise RuntimeError("push dispatcher unavailable")
                for superseded_device_id in activated.superseded_device_ids:
                    cleanup = PUSH_DISPATCHER.drop_device(
                        device_id=superseded_device_id,
                        reason="pair_superseded",
                    )
                    if not isinstance(cleanup, dict) or cleanup.get("ok") is not True:
                        raise RuntimeError("push cleanup did not confirm success")
            except Exception:
                # Activation is already durable. Fail this acknowledgement so
                # the phone retains its staged credentials and retries the
                # idempotent activation until revoked push tokens are gone.
                self._send_json(
                    {
                        "ok": False,
                        "error": {
                            "code": "push_cleanup_pending",
                            "message": "pairing is active but notification cleanup is still pending",
                        },
                    },
                    status=503,
                )
                return
        if remote_activation:
            try:
                if PUSH_DISPATCHER is None:
                    raise RuntimeError("push dispatcher unavailable")
                remote_event_id = "remote_join:" + hashlib.sha256(
                    f"{pair_id}\0{device_id}".encode("utf-8")
                ).hexdigest()[:32]
                broadcast = PUSH_DISPATCHER.broadcast_alert(
                    exclude_device_id=device_id,
                    exclude_device_ids=activated.superseded_device_ids,
                    event_id=remote_event_id,
                    kind="remote_join",
                    route="pairling-connect",
                    title="New device paired remotely",
                    body="A device joined this Mac through Pairling Connect.",
                    pairling_extra={"source": "pairing_activation"},
                )
                if (
                    not isinstance(broadcast, dict)
                    or int(broadcast.get("persistence_errors") or 0) > 0
                ):
                    raise RuntimeError("remote join notification was not durably recorded")
                PUSH_DISPATCHER.complete_remote_pairing_notification(
                    pair_id=pair_id,
                    device_id=device_id,
                )
            except Exception:
                # Activation is durable and idempotent. Withholding its
                # acknowledgement makes the phone retry until every existing
                # device has a durable remote-join outbox record.
                self._send_json(
                    {
                        "ok": False,
                        "error": {
                            "code": "push_notification_pending",
                            "message": "pairing is active but its security notification is still pending",
                        },
                    },
                    status=503,
                )
                return
        if not isinstance(activated.activation_result, dict):
            self._send_json(
                {
                    "ok": False,
                    "error": {
                        "code": "activation_result_unavailable",
                        "message": "pairing activation result could not be authenticated",
                    },
                },
                status=503,
            )
            return
        self._send_json(activated.activation_result)

    def _handle_pair_reauth_challenge(self, q):
        if REAUTH_STORE is None:
            self._send_json({"ok": False, "error": {"code": "pairing_unavailable", "message": "reauth unavailable"}}, status=503)
            return
        try:
            payload = self._read_json_object()
        except ValueError as exc:
            self._send_json({"ok": False, "error": {"code": "bad_request", "message": str(exc)}}, status=400)
            return
        device_id = str(payload.get("device_id") or "")
        if not device_id:
            self._send_json({"ok": False, "error": {"code": "device_id_required", "message": "device_id required"}}, status=400)
            return
        allowed, retry_after = _reauth_rate_check(device_id, self.headers, self.client_address)
        if not allowed:
            self._send_json(
                {"ok": False, "error": {"code": "rate_limited", "message": "too many reauth attempts"}},
                status=429,
                headers={"Retry-After": str(retry_after)},
            )
            return
        # A challenge is issued for ANY device_id (even unknown / revoked) so
        # this endpoint never reveals whether a device exists.
        challenge = REAUTH_STORE.issue_challenge(device_id)
        self._send_json({"ok": True, "challenge": challenge, "ttl_seconds": REAUTH_STORE.ttl_seconds})

    def _handle_pair_reauth_claim(self, q):
        if REAUTH_STORE is None or DEVICE_REGISTRY is None:
            self._send_json({"ok": False, "error": {"code": "pairing_unavailable", "message": "reauth unavailable"}}, status=503)
            return
        try:
            payload = self._read_json_object()
        except ValueError as exc:
            self._send_json({"ok": False, "error": {"code": "bad_request", "message": str(exc)}}, status=400)
            return
        device_id = str(payload.get("device_id") or "")
        challenge = str(payload.get("challenge") or "")
        signature_b64 = str(payload.get("signature") or "")
        if not device_id:
            self._send_json({"ok": False, "error": {"code": "reauth_failed", "message": "reauth failed"}}, status=401)
            return
        allowed, retry_after = _reauth_rate_check(device_id, self.headers, self.client_address)
        if not allowed:
            self._send_json(
                {"ok": False, "error": {"code": "rate_limited", "message": "too many reauth attempts"}},
                status=429,
                headers={"Retry-After": str(retry_after)},
            )
            return
        try:
            signature = base64.b64decode(signature_b64, validate=True) if signature_b64 else b""
        except Exception:
            signature = b""
        expected_token_hash = DEVICE_REGISTRY.rotation_token_hash(device_id)
        verified = REAUTH_STORE.verify_and_consume(device_id, challenge, signature)
        if not verified or expected_token_hash is None:
            new_token = None
        else:
            try:
                new_token = DEVICE_REGISTRY.rotate_token(
                    device_id,
                    expected_token_hash=expected_token_hash,
                )
            except DeviceRegistryError as exc:
                self._send_json(
                    {
                        "ok": False,
                        "error": {
                            "code": exc.code,
                            "message": exc.message,
                        },
                    },
                    status=exc.status,
                )
                return
        if not verified or not new_token:
            # Uniform failure: never distinguish unknown device / no SE key /
            # bad signature / expired-or-used challenge. No enumeration oracle.
            self._send_json({"ok": False, "error": {"code": "reauth_failed", "message": "reauth failed"}}, status=401)
            return
        _clear_auth_result_cache()
        self._invalidate_phone_tools_device(device_id, reason="iphone_credential_changed")
        self._send_json({"ok": True, "device": {"id": device_id, "token": new_token}})

    def _invalidate_phone_tools_device(self, device_id: str, *, reason: str) -> None:
        if PHONE_TOOL_WORK_QUEUE is not None:
            PHONE_TOOL_WORK_QUEUE.deactivate_device(device_id, reason=reason)
        if PHONE_TOOL_AVAILABILITY is not None:
            PHONE_TOOL_AVAILABILITY.remove_device(device_id)

    def _handle_pair_revoke(self, q):
        if DEVICE_REGISTRY is None:
            self._send_json({"ok": False, "error": {"code": "auth_unavailable"}}, status=503)
            return
        try:
            payload = self._read_json_object()
        except ValueError as exc:
            self._send_json({"ok": False, "error": {"code": "bad_request", "message": str(exc)}}, status=400)
            return
        device_id = self._resolve_self_device_target(payload.get("device_id"))
        if device_id is None:
            return
        revoked = DEVICE_REGISTRY.revoke_device(device_id, reason="api")
        if revoked:
            _clear_auth_result_cache()
            self._invalidate_phone_tools_device(device_id, reason="iphone_pairing_revoked")
        if revoked and PUSH_DISPATCHER is not None:
            # A revoked pairing's push tokens are permanently undeliverable;
            # cascade the revocation into the push registry so nothing keeps
            # emitting at a dead device.
            try:
                PUSH_DISPATCHER.drop_device(device_id=device_id, reason="pair_revoked")
            except Exception:
                pass
        self._send_json({"ok": revoked, "device_id": device_id}, status=200 if revoked else 404)

    def _handle_pair_rotate_token(self, q):
        if DEVICE_REGISTRY is None:
            self._send_json({"ok": False, "error": {"code": "auth_unavailable"}}, status=503)
            return
        try:
            payload = self._read_json_object()
        except ValueError as exc:
            self._send_json({"ok": False, "error": {"code": "bad_request", "message": str(exc)}}, status=400)
            return
        device_id = self._resolve_self_device_target(payload.get("device_id"))
        if device_id is None:
            return
        expected_token_hash = str(
            getattr(self.pairling_auth, "token_hash", "") or ""
        )
        try:
            token = DEVICE_REGISTRY.rotate_token(
                device_id,
                expected_token_hash=expected_token_hash,
            )
        except DeviceRegistryError as exc:
            self._send_json(
                {
                    "ok": False,
                    "error": {
                        "code": exc.code,
                        "message": exc.message,
                    },
                },
                status=exc.status,
            )
            return
        if token is None:
            self._send_json({"ok": False, "error": {"code": "device_not_found"}}, status=404)
            return
        _clear_auth_result_cache()
        self._invalidate_phone_tools_device(device_id, reason="iphone_credential_changed")
        self._send_json({"ok": True, "device_id": device_id, "token": token})

    def _handle_pair_bind_node(self, q):
        # Minimal proof-required POST whose sole purpose is to trip the
        # interactive provenance bind. The bind itself already ran in
        # _maybe_persist_tailnet_node_id BEFORE routing (it fires only when this
        # request was bearer-authed AND passed request-proof, which a POST to a
        # PROOF_REQUIRED_ENDPOINTS path is). Here we only report whether the
        # device now carries a tailnet_node_id. NO other side effects.
        if self.pairling_auth is None:
            self._send_json({
                "ok": False,
                "error": {
                    "code": "missing_token",
                    "message": "Authorization: Bearer token required",
                },
            }, status=401)
            return
        bound = bool(
            DEVICE_REGISTRY
            and DEVICE_REGISTRY.tailnet_node_id(self.pairling_auth.device_id)
        )
        self._send_json({"ok": True, "tailnet_node_id_bound": bound})

    def _handle_mirror_status(self, q):
        project = q.get("project", [None])[0]
        args = ["status"]
        if project:
            args.extend(["--project", project])
        code, payload = _mirror_cli_json(args, timeout=45)
        if code != 0 and not payload.get("projects"):
            self.send_response(502)
            self.send_header("Content-Type", "application/json")
            body = json.dumps(payload).encode()
            self.send_header("Content-Length", str(len(body)))
            self.end_headers()
            self.wfile.write(body)
            return
        self._send_json(payload)

    def _handle_mirror_projects(self, q):
        state = None
        try:
            state = json.loads(PROJECT_MIRROR_STATE.read_text())
        except Exception:
            pass
        if not isinstance(state, dict):
            code, state = _mirror_cli_json(["status"], timeout=45)
            if code != 0 and not state.get("projects"):
                self.send_response(502)
                self.send_header("Content-Type", "application/json")
                body = json.dumps(state).encode()
                self.send_header("Content-Length", str(len(body)))
                self.end_headers()
                self.wfile.write(body)
                return
        self._send_json({
            "contract_version": PROJECT_MIRROR_CONTRACT,
            "summary": state.get("summary") if isinstance(state, dict) else None,
            "projects": state.get("projects") if isinstance(state, dict) else [],
            "ts": _time.time(),
        })

    def _handle_mirror_conflicts(self, q):
        project = q.get("project", [None])[0]
        args = ["conflicts"]
        if project:
            args.extend(["--project", project])
        code, payload = _mirror_cli_json(args, timeout=45)
        if code not in (0, 1):
            self.send_response(502)
            self.send_header("Content-Type", "application/json")
            body = json.dumps(payload).encode()
            self.send_header("Content-Length", str(len(body)))
            self.end_headers()
            self.wfile.write(body)
            return
        self._send_json(payload)

    def _handle_mirror_flush(self, q):
        try:
            payload = json.loads(self._read_body() or b"{}")
        except json.JSONDecodeError:
            self.send_error(400, "body must be JSON")
            return
        project = (payload.get("project") or q.get("project", [None])[0] or "").strip()
        timeout = int(payload.get("timeout") or q.get("timeout", ["60"])[0] or 60)
        args = ["flush", "--timeout", str(max(10, min(timeout, 300)))]
        if project:
            args.extend(["--project", project])
        else:
            args.append("--all")
        code, result = _mirror_cli_json(args, timeout=max(20, min(timeout + 20, 330)))
        if code != 0:
            self.send_response(409)
            self.send_header("Content-Type", "application/json")
            body = json.dumps(result).encode()
            self.send_header("Content-Length", str(len(body)))
            self.end_headers()
            self.wfile.write(body)
            return
        self._send_json(result)

    def _handle_mirror_resume(self, q):
        try:
            payload = json.loads(self._read_body() or b"{}")
        except json.JSONDecodeError:
            self.send_error(400, "body must be JSON")
            return
        project = (payload.get("project") or q.get("project", [None])[0] or "").strip()
        args = ["resume"]
        if project:
            args.extend(["--project", project])
        else:
            args.append("--all")
        code, result = _mirror_cli_json(args, timeout=60)
        if code != 0:
            self.send_response(409)
            self.send_header("Content-Type", "application/json")
            body = json.dumps(result).encode()
            self.send_header("Content-Length", str(len(body)))
            self.end_headers()
            self.wfile.write(body)
            return
        self._send_json(result)

    def _handle_health_stream(self, q):
        self.send_response(200)
        self.send_header("Content-Type", "text/event-stream")
        self.send_header("Cache-Control", "no-store")
        self.send_header("Connection", "keep-alive")
        self.send_header("X-Accel-Buffering", "no")
        self.end_headers()

        last_hash: str | None = None
        last_keepalive = 0.0
        deadline = _time.time() + 600
        while _time.time() < deadline:
            if not self._stream_authorization_is_current():
                return
            payload = _cached_health_payload(
                authenticated=self.pairling_auth is not None,
                auth_result=self.pairling_auth,
            )
            digest = _health_diff_digest(payload)
            if digest != last_hash:
                try:
                    self.wfile.write(b"event: snapshot\ndata: " + json.dumps(payload).encode() + b"\n\n")
                    self.wfile.flush()
                except (BrokenPipeError, ConnectionResetError):
                    return
                last_hash = digest
            if _time.time() - last_keepalive >= 15:
                try:
                    keepalive = json.dumps({"ts": _time.time()}).encode()
                    self.wfile.write(b"event: keepalive\ndata: " + keepalive + b"\n\n")
                    self.wfile.flush()
                except (BrokenPipeError, ConnectionResetError):
                    return
                last_keepalive = _time.time()
            _time.sleep(5)
        try:
            self.wfile.write(b"event: done\ndata: {}\n\n")
            self.wfile.flush()
        except (BrokenPipeError, ConnectionResetError):
            return
        return

    # ----- /recent-projects: cheap project picker for new-session sheet -----
    def _handle_recent_projects(self, q):
        try:
            within_min = int(q.get("active_within_min", ["10080"])[0])
        except ValueError:
            within_min = 10080
        try:
            limit = int(q.get("limit", ["30"])[0])
        except ValueError:
            limit = 30

        within_min = max(1, min(within_min, 60 * 24 * 30))
        limit = max(1, min(limit, 100))

        payload = _cached_runtime_snapshot(
            ("recent-projects", within_min, limit),
            RECENT_PROJECTS_CACHE_SECONDS,
            lambda: self._recent_projects_payload(within_min, limit),
        )
        self._send_json(payload)

    def _recent_projects_payload(self, within_min: int, limit: int) -> dict:
        projects: dict[str, int] = {}
        sources: dict[str, set[str]] = {}

        def add_project(project: str | None, last_heartbeat: int | float | None, source: str) -> None:
            if not isinstance(project, str):
                return
            project = project.strip()
            if not project or not _is_recent_project_candidate(project):
                return
            last = int(last_heartbeat or 0)
            projects[project] = max(projects.get(project, 0), last)
            sources.setdefault(project, set()).add(source)

        # Keep this endpoint intentionally lightweight. /sessions enriches rows
        # with turn state, transcript signals, and first prompts; the spawn sheet
        # only needs recent project paths. The source is deliberately canonical:
        # Claude registry rows plus Codex rollouts/registry rows, so the picker
        # does not show a false empty state when only one provider has history.
        # Visibility (SPEC-p1 §2.3): an excluded provider's history must not
        # feed the spawn picker. Filesystem candidates stay — they are not
        # provider history.
        visible = _visible_agent_provider_ids()
        if "claude" in visible:
            for project, last_heartbeat in _claude_sessions_backend().recent_project_rows(
                within_min, limit * 3
            ):
                add_project(project, last_heartbeat, "claude")

        if "codex" in visible:
            for row in _list_codex_sessions(live_only=False, active_within_min=within_min):
                add_project(row.get("project"), row.get("last_heartbeat"), "codex")

            for row in _agent_registry_recent("codex", since_min=within_min, limit=500):
                add_project(row.get("project"), row.get("last_heartbeat"), "registry")

        for project, last_heartbeat in _filesystem_project_candidates(limit=limit * 4):
            add_project(project, last_heartbeat, "filesystem")

        sorted_projects = sorted(projects.items(), key=lambda kv: kv[1], reverse=True)
        filesystem_projects = [
            (project, heartbeat)
            for project, heartbeat in sorted_projects
            if "filesystem" in sources.get(project, set())
        ]
        history_projects = [
            (project, heartbeat)
            for project, heartbeat in sorted_projects
            if "filesystem" not in sources.get(project, set())
        ]
        filesystem_reserve = min(len(filesystem_projects), max(3, limit // 3), limit)
        selected: list[tuple[str, int]] = []
        selected.extend(history_projects[: max(0, limit - filesystem_reserve)])
        seen = {project for project, _ in selected}
        for project, heartbeat in filesystem_projects:
            if len(selected) >= limit:
                break
            if project in seen:
                continue
            selected.append((project, heartbeat))
            seen.add(project)
        if len(selected) < limit:
            for project, heartbeat in sorted_projects:
                if len(selected) >= limit:
                    break
                if project in seen:
                    continue
                selected.append((project, heartbeat))
                seen.add(project)

        items = [
            {
                "path": project,
                "name": os.path.basename(project.rstrip("/")) or project,
                "last_heartbeat": heartbeat,
            }
            for project, heartbeat in selected
        ]

        return {"count": len(items), "items": items, "ts": _time.time()}

    # ----- /filesystem/directories: folder-only browser for launch targets -----
    def _handle_filesystem_directories(self, q):
        raw_root = (q.get("root", [""])[0] or "").strip()
        try:
            offset = max(0, int(q.get("offset", ["0"])[0]))
        except (TypeError, ValueError):
            offset = 0
        try:
            limit = max(1, min(int(q.get("limit", ["100"])[0]), 250))
        except (TypeError, ValueError):
            limit = 100
        root_input = os.path.expanduser(raw_root) if raw_root else os.path.expanduser("~")
        try:
            root = _canonical_user_directory(root_input, allow_tmp=True)
            home = _canonical_user_directory(str(HOME), allow_tmp=False)
            tmp = str(Path("/tmp").resolve(strict=True))
        except PermissionError:
            self.send_error(403, "directory root must resolve under the user's home directory or /tmp")
            return
        except (FileNotFoundError, NotADirectoryError):
            self.send_error(404, f"directory not found: {os.path.abspath(root_input)}")
            return
        except ValueError as error:
            self.send_error(400, str(error))
            return
        home = str(HOME.resolve())
        tmp = str(Path("/tmp").resolve())

        try:
            payload = _cached_runtime_snapshot(
                ("filesystem-directories", root, offset, limit),
                FILESYSTEM_DIRECTORIES_CACHE_SECONDS,
                lambda: self._filesystem_directories_payload(root, home, tmp, offset, limit),
            )
        except PermissionError:
            self.send_error(403, f"permission denied: {root}")
            return
        except OSError as exc:
            self.send_error(500, f"could not list directory: {str(exc)[:160]}")
            return
        self._send_json(payload)

    def _filesystem_directories_payload(self, root: str, home: str, tmp: str, offset: int, limit: int) -> dict:
        authorized = _authorized_user_path(root, allow_tmp=True)
        directory_fd = open_directory_fd(authorized.path, root=authorized.root)
        try:
            items = []
            with os.scandir(directory_fd) as entries:
                for entry in entries:
                    if entry.name in {".", ".."}:
                        continue
                    try:
                        is_directory = entry.is_dir(follow_symlinks=False)
                    except OSError:
                        continue
                    if not is_directory:
                        continue
                    items.append({
                        "name": entry.name,
                        "path": str(authorized.path / entry.name),
                    })
        finally:
            os.close(directory_fd)

        items.sort(key=lambda item: (item["name"].startswith("."), item["name"].lower()))
        page = items[offset:offset + limit]
        next_offset = offset + len(page)
        has_more = next_offset < len(items)
        parent = None
        if root != home and root != tmp:
            try:
                parent = _canonical_user_directory(os.path.dirname(root), allow_tmp=True)
            except (FileNotFoundError, NotADirectoryError, PermissionError, ValueError):
                parent = None

        return {
            "root": root,
            "parent": parent,
            "count": len(items),
            "items": page,
            "has_more": has_more,
            "next_offset": next_offset if has_more else None,
            "ts": _time.time(),
        }

    # ----- /sessions: list active sessions, enriched with first-prompt preview -----
    def _handle_session_removal(self, q, *, delete_transcript: bool) -> None:
        try:
            body = self._read_body()
            payload = json.loads(body.decode("utf-8")) if body else {}
        except (UnicodeDecodeError, ValueError, json.JSONDecodeError):
            self._send_json({
                "ok": False,
                "error": {
                    "code": "bad_json",
                    "message": "Request body must be a JSON object.",
                },
            }, status=400)
            return
        if not isinstance(payload, dict):
            self._send_json({
                "ok": False,
                "error": {
                    "code": "bad_json",
                    "message": "Request body must be a JSON object.",
                },
            }, status=400)
            return
        session_id = str(payload.get("session_id") or payload.get("session") or "").strip()
        if not session_id:
            self._send_json({
                "ok": False,
                "error": {
                    "code": "session_id_required",
                    "message": "session_id is required.",
                },
            }, status=400)
            return
        result = _remove_session(session_id, delete_transcript=delete_transcript)
        status = int(result.pop("status", 200))
        self._send_json(result, status=status)

    def _handle_sessions_visible(self, q):
        provider_filter = q.get("provider", ["all"])[0].lower()
        if not _valid_provider_filter(provider_filter):
            _send_unknown_provider(self, provider_filter)
            return
        try:
            within_min = int(q.get("active_within_min", [str(60 * 24 * 7)])[0])
        except ValueError:
            within_min = 60 * 24 * 7
        within_min = max(1, min(within_min, 60 * 24 * 14))

        visible = _visible_agent_provider_ids()
        requested = (
            set(visible)
            if provider_filter == "all"
            else ({provider_filter} if provider_filter in visible else set())
        )
        (
            provider_inventories,
            inventory_state,
            inventory_generation,
            membership_generation,
        ) = (
            _sessions_provider_inventory_bundle(requested)
        )
        provider_inventory = {
            provider: list(inventory.get("rows") or [])
            for provider, inventory in provider_inventories.items()
        }

        def load_visible_snapshot() -> dict:
            metadata: dict[str, object] = {}
            degraded: dict | None = None
            try:
                items = self._collect_visible_session_rows_from_inventory(
                    provider_filter,
                    active_within_min=within_min,
                    limit=200,
                    authoritative_inventory=True,
                    provider_inventory=provider_inventory,
                    collection_metadata=metadata,
                )
            except Exception as error:
                items = []
                degraded = {
                    "reason": "agent_session_store_unavailable",
                    "detail": (
                        "Pairling could not build the Mac session list. "
                        f"{type(error).__name__}: {str(error)[:160]}"
                    ),
                }
            if degraded is None:
                degraded = self._sessions_backend_degradation(
                    provider_filter,
                    require_fresh=True,
                    provider_inventories=provider_inventories,
                )
            if degraded is None:
                degraded = _sessions_inventory_degradation(inventory_state)
            (
                membership_complete,
                membership_checked_at,
                proof_degradation,
            ) = self._sessions_membership_proof(
                provider_filter,
                degraded,
                provider_inventories,
                items,
                truncated=bool(metadata.get("truncated")),
                allow_readable_history=True,
            )
            if degraded is None and proof_degradation is not None:
                degraded = proof_degradation
            with _sessions_inventory_bundle_lock:
                generation_changed = bool(requested) and (
                    int(_sessions_inventory_bundle.get("generation") or 0)
                    != inventory_generation
                    or int(
                        _sessions_inventory_bundle.get(
                            "membership_generation"
                        ) or 0
                    )
                    != membership_generation
                )
            state = "refreshing" if generation_changed else inventory_state
            if generation_changed:
                membership_complete = False
                membership_checked_at = 0.0
                degraded = _sessions_inventory_degradation(state)
            payload = {
                "source": _sessions_stream_source(),
                "items": items,
                "inventory_state": state,
                "membership_complete": membership_complete,
                "membership_checked_at": membership_checked_at,
                "ts": _time.time(),
            }
            if degraded is not None:
                payload["degraded"] = degraded
            return payload

        payload = _cached_runtime_snapshot(
            (
                "sessions-visible",
                provider_filter,
                within_min,
                200,
                inventory_state,
                inventory_generation,
            ),
            RUNTIME_SNAPSHOT_CACHE_SECONDS,
            load_visible_snapshot,
            store_after_loader_invalidation=True,
        )
        payload["count"] = len(payload.get("items") or [])
        self._send_json(payload, headers={"Cache-Control": "no-store"})

    def _collect_visible_session_rows(
        self,
        provider_filter: str,
        active_within_min: int,
        limit: int = 200,
        *,
        live_only: bool = False,
        authoritative_inventory: bool = False,
        provider_inventory: dict[str, list[dict]] | None = None,
        collection_metadata: dict | None = None,
    ) -> list[dict]:
        rows: list[dict] = []
        visible = _visible_agent_provider_ids()
        claude_live_terminal_rows = (
            provider_inventory.get("claude", [])
            if provider_inventory is not None
            else None
        )
        codex_inventory_rows = (
            provider_inventory.get("codex", [])
            if provider_inventory is not None
            else None
        )
        if provider_filter in ("all", "claude") and "claude" in visible:
            claude_rows = (
                self._collect_session_rows_uncached(
                    since_min=active_within_min,
                    live_only=live_only,
                    limit=max(limit + 1, 50),
                    include_first_prompt=True,
                    live_terminal_rows=claude_live_terminal_rows,
                    require_complete=True,
                )
                if authoritative_inventory
                else self._collect_session_rows(
                    since_min=active_within_min,
                    live_only=live_only,
                    limit=max(limit, 50),
                    include_first_prompt=True,
                )
            )
            for raw in claude_rows:
                native_id = raw.get("id") or ""
                claude_pid = int(raw.get("claude_pid") or 0)
                terminal_tty = raw.get("terminal_tty") or ""
                claude_uuid = raw.get("claude_uuid") or ""
                row = dict(raw)
                _decorate_claude_session_row(row, native_id, claude_pid, terminal_tty)
                row.update(self._turn_state_summary(claude_uuid))
                _refresh_claude_observed_activity(row, row.get("project"), claude_uuid)
                rows.append(row)

        if provider_filter in ("all", "codex") and "codex" in visible:
            codex_rows = (
                _list_codex_sessions_uncached(
                    live_only=live_only,
                    active_within_min=active_within_min,
                    live_terminal_rows=codex_inventory_rows,
                )
                if authoritative_inventory
                else _list_codex_sessions(
                    live_only=live_only,
                    active_within_min=active_within_min,
                )
            )
            for row in codex_rows:
                rows.append(row)
        managed_rows = _managed_session_rows(
            provider_filter=provider_filter,
            live_only=live_only,
            active_within_min=active_within_min,
            limit=max(limit, 50),
            poll_live=not authoritative_inventory,
        )
        if authoritative_inventory and provider_inventory is not None:
            captured_managed_rows = [
                copy.deepcopy(row)
                for inventory_rows in provider_inventory.values()
                for row in inventory_rows
                if bool(row.get("managed"))
            ]
            captured_managed_providers = {
                str(row.get("provider") or "")
                for row in captured_managed_rows
            }
            managed_rows = [
                row
                for row in managed_rows
                if not (
                    str(row.get("provider") or "")
                    in captured_managed_providers
                    and row.get("closed_at") is None
                    and str(row.get("lifecycle") or "")
                    in {"launching", "running", "waiting", "blocked", "closing"}
                )
            ]
            managed_rows.extend(captured_managed_rows)
        managed_rows = [
            row for row in managed_rows
            if str(row.get("provider") or "") in visible
        ]
        rows = _merge_managed_session_rows(rows, managed_rows)

        if (
            provider_filter in ("all", "omp")
            and "omp" in visible
            and provider_inventory is not None
        ):
            rows.extend(_omp_sessions_from_inventory({
                "checked_at": _time.time(),
                "terminals": provider_inventory.get("omp", []),
            }))

        rows = _filter_tombstoned_session_rows(rows)
        rows = _collapse_live_session_rows_by_terminal(rows)
        if codex_inventory_rows is not None:
            codex_live_terminal_rows = codex_inventory_rows
        else:
            codex_live_terminal_rows = (
                _codex_live_terminal_rows()
                if any(
                    row.get("provider") == "codex"
                    and row.get("closed_at") is None
                    for row in rows
                )
                else []
            )
        if not live_only:
            rows.sort(key=_session_meaningful_sort_key)
            rows = self._limit_visible_session_rows(
                rows,
                limit=limit,
                codex_live_terminal_rows=codex_live_terminal_rows,
            )

        enriched_rows: list[dict] = []
        for row in rows:
            if row.get("provider") == "claude" and not row.get("managed"):
                native_id = row.get("native_id") or row.get("id") or ""
                claude_uuid = row.get("claude_uuid") or ""
                signal = self._recent_session_signal(
                    native_id,
                    project=row.get("project"),
                    claude_uuid=claude_uuid,
                )
                row["recent_anomaly"] = signal.get("anomaly")
                row["latest_command"] = signal.get("latest_command")
                row["latest_edit"] = signal.get("latest_edit")
            if row.get("managed"):
                enriched_rows.append(row)
                continue
            if provider_inventory is None:
                enriched_rows.append(self._decorate_session_lifecycle_row(row))
            else:
                enriched_rows.append(
                    self._decorate_session_lifecycle_row(
                        row,
                        provider_inventory=provider_inventory,
                    )
                )
        rows = enriched_rows

        if live_only:
            projected_rows = []
            for row in rows:
                if row.get("managed"):
                    if (
                        row.get("closed_at") is None
                        and row.get("lifecycle")
                        in {"launching", "running", "waiting", "blocked", "closing"}
                    ):
                        projected_rows.append(row)
                    continue
                if provider_inventory is None:
                    projected = self._strict_live_projection(
                        row,
                        codex_live_terminal_rows,
                    )
                else:
                    projected = self._strict_live_projection(
                        row,
                        codex_live_terminal_rows,
                        claude_live_terminal_rows,
                    )
                if projected is not None:
                    projected_rows.append(projected)
            rows = projected_rows
        rows.sort(key=_session_meaningful_sort_key)
        pre_limit_count = len(rows)
        rows = self._limit_visible_session_rows(
            rows,
            limit=limit,
            codex_live_terminal_rows=codex_live_terminal_rows,
            claude_live_terminal_rows=claude_live_terminal_rows,
        )
        if collection_metadata is not None:
            collection_metadata["pre_limit_count"] = pre_limit_count
            collection_metadata["truncated"] = len(rows) < pre_limit_count
        for row in rows:
            row["runtime_truth_summary"] = self._runtime_truth_summary_for_row(row)
        _record_sessions_scan(rows)
        return rows

    def _collect_visible_session_rows_from_inventory(
        self,
        provider_filter: str,
        active_within_min: int,
        limit: int = 200,
        **kwargs,
    ) -> list[dict]:
        previous_scan_state = _sessions_inventory_scan_active()
        _sessions_inventory_scan_context.active = True
        try:
            return self._collect_visible_session_rows(
                provider_filter,
                active_within_min,
                limit,
                **kwargs,
            )
        finally:
            _sessions_inventory_scan_context.active = previous_scan_state

    @classmethod
    def _limit_visible_session_rows(
        cls,
        rows: list[dict],
        limit: int,
        codex_live_terminal_rows: list[dict] | None = None,
        claude_live_terminal_rows: list[dict] | None = None,
    ) -> list[dict]:
        """Keep verified live terminals inside an archive-heavy response cap."""
        cap = max(1, min(int(limit or 200), 500))
        if len(rows) <= cap:
            return rows

        def is_strictly_live(row: dict) -> bool:
            if row.get("managed"):
                return (
                    row.get("closed_at") is None
                    and row.get("lifecycle")
                    in {"launching", "running", "waiting", "blocked", "closing"}
                )
            if claude_live_terminal_rows is None:
                return cls._session_row_is_strictly_live(
                    row,
                    codex_live_terminal_rows,
                )
            return cls._session_row_is_strictly_live(
                row,
                codex_live_terminal_rows,
                claude_live_terminal_rows,
            )

        live_rows = [
            row
            for row in rows
            if is_strictly_live(row)
        ]
        if len(live_rows) >= cap:
            return live_rows[:cap]

        live_objects = {id(row) for row in live_rows}
        selected = live_rows + [
            row for row in rows
            if id(row) not in live_objects
        ][:cap - len(live_rows)]
        selected.sort(key=_session_meaningful_sort_key)
        return selected

    def _runtime_truth_summary_for_row(self, row: dict) -> dict:
        capabilities = set(row.get("capabilities") or [])
        terminal_backed = bool({"terminal_output", "terminal_surface", "terminal_control"} & capabilities)
        transcript_missing = terminal_backed and "transcript" not in capabilities
        transcript_message = "Live terminal only - not in transcript" if transcript_missing else ""
        attention = row.get("terminal_attention") if isinstance(row.get("terminal_attention"), dict) else None
        if attention and attention.get("needs_input"):
            return {
                "primary_label": "Terminal awaiting selection",
                "secondary_label": transcript_message,
                "tone": "attention",
                "requires_attention": True,
                "blocks_control": False,
                "selected_surface": "v2" if "terminal_surface" in capabilities else "unknown",
                "degradation_codes": ["transcript_missing"] if transcript_missing else [],
                "contradiction_codes": [],
            }
        secondary_label = transcript_message
        if not secondary_label and row.get("readable_state") == "stale":
            secondary_label = "Registry stale"
        return {
            "primary_label": row.get("working_on") or row.get("first_prompt") or "Session",
            "secondary_label": secondary_label,
            "tone": "muted" if row.get("readable_state") in {"closed", "offline"} else "normal",
            "requires_attention": False,
            "blocks_control": False,
            "selected_surface": "v2" if "terminal_surface" in capabilities else "none",
            "degradation_codes": ["transcript_missing"] if transcript_missing else [],
            "contradiction_codes": [],
        }

    def _sessions_backend_degradation(
        self,
        provider_filter: str = "all",
        *,
        require_fresh: bool = False,
        provider_inventories: dict[str, dict] | None = None,
    ) -> dict | None:
        """Cheap cached probe distinguishing "PG answered: zero sessions"
        from "PG unreachable" (Docker down). Without it the sessions stream
        emitted an empty snapshot during outages and the phone wiped its
        list — sessions looked deleted instead of unreadable.

        Process inventory remains a separate truth axis in every storage mode.
        The database probe only applies when Claude uses Postgres."""
        try:
            _read_session_tombstones()
        except SessionTombstoneStoreError as error:
            return {
                "reason": "session_tombstone_store_unavailable",
                "detail": str(error),
            }
        if require_fresh:
            try:
                with _agent_registry_conn() as conn:
                    conn.execute("SELECT 1").fetchone()
            except Exception as error:
                return {
                    "reason": "agent_session_store_unavailable",
                    "detail": (
                        "Pairling could not verify the Mac session registry. "
                        f"{type(error).__name__}: {str(error)[:160]}"
                    ),
                }
        visible = _visible_agent_provider_ids()
        requested = (
            set(visible)
            if provider_filter == "all"
            else ({provider_filter} if provider_filter in visible else set())
        )
        unsupported = sorted(
            requested - _session_membership_provider_ids()
        )
        if unsupported:
            return {
                "reason": "session_provider_inventory_unsupported",
                "detail": (
                    "Pairling cannot prove live session membership for: "
                    + ", ".join(unsupported)
                    + ". The last trusted session list is being kept."
                ),
                "providers": unsupported,
            }

        def inventory_state(provider: str) -> tuple[str, bool]:
            if provider_inventories is not None:
                inventory = provider_inventories.get(provider) or {}
                return (
                    str(inventory.get("probe_state") or "unknown"),
                    bool(inventory.get("membership_complete")),
                )
            if provider == "codex":
                lock = _codex_terminal_scan_lock
                cache = _codex_terminal_scan_cache
            else:
                lock = _claude_terminal_scan_lock
                cache = _claude_terminal_scan_cache
            with lock:
                return (
                    str(cache.get("probe_state") or "unknown"),
                    bool(cache.get("membership_complete")),
                )

        codex_relevant = "codex" in requested
        if codex_relevant:
            codex_probe_state, codex_membership_complete = inventory_state(
                "codex"
            )
            if codex_probe_state == "failed" and not codex_membership_complete:
                return {
                    "reason": "codex_process_scan_unavailable",
                    "detail": (
                        "Pairling could not verify the full Codex process list on "
                        "the Mac. The last trusted session list is being kept."
                    ),
                }
        claude_relevant = "claude" in requested
        if claude_relevant:
            claude_probe_state, claude_membership_complete = inventory_state(
                "claude"
            )
            if (
                claude_probe_state == "failed"
                and not claude_membership_complete
            ):
                return {
                    "reason": "claude_process_scan_unavailable",
                    "detail": (
                        "Pairling could not verify the full Claude process list "
                        "on the Mac. The last trusted session list is being kept."
                    ),
                }
        if not claude_relevant or _session_backend() == "sqlite":
            return None

        def probe() -> dict:
            ok, _, _ = _run_text(
                ["docker", "exec", "continuous-claude-postgres",
                 "psql", "-U", "claude", "-d", "continuous_claude",
                 "-tAc", "SELECT 1"],
                timeout=4,
            )
            return {"ok": bool(ok)}

        result = (
            probe()
            if require_fresh
            else _cached_probe("sessions_backend_pg", 10.0, probe)
        )
        if result.get("ok"):
            return None
        return {
            "reason": "sessions_backend_unreachable",
            "detail": "Session database is unreachable on the Mac (is Docker running?).",
        }

    def _sessions_membership_proof(
        self,
        provider_filter: str,
        degraded: dict | None,
        provider_inventories: dict[str, dict],
        rows: list[dict],
        *,
        truncated: bool = False,
        allow_readable_history: bool = False,
    ) -> tuple[bool, float, dict | None]:
        """Prove that one exact scan generation is fully represented on wire."""
        visible = _visible_agent_provider_ids()
        requested = (
            set(visible)
            if provider_filter == "all"
            else ({provider_filter} if provider_filter in visible else set())
        )
        membership_providers = _session_membership_provider_ids()
        checked_at = [
            float((provider_inventories.get(provider) or {}).get("checked_at") or 0)
            for provider in sorted(requested & membership_providers)
        ]
        proof_times = [value for value in checked_at if value > 0]
        proof_at = min(proof_times) if proof_times else _time.time()

        if degraded is not None:
            return False, proof_at, None
        unsupported = sorted(requested - membership_providers)
        if unsupported:
            return False, proof_at, {
                "reason": "session_provider_inventory_unsupported",
                "detail": (
                    "Pairling cannot prove live session membership for: "
                    + ", ".join(unsupported)
                    + "."
                ),
                "providers": unsupported,
            }
        if truncated:
            return False, proof_at, {
                "reason": "session_snapshot_truncated",
                "detail": (
                    "The Mac found more live sessions than this snapshot can "
                    "carry. The last trusted session list is being kept."
                ),
            }

        missing: list[dict] = []
        unexpected: list[dict] = []
        for provider in sorted(requested):
            inventory = provider_inventories.get(provider) or {}
            if (
                inventory.get("probe_state") != "exact"
                or not bool(inventory.get("membership_complete"))
                or float(inventory.get("checked_at") or 0) <= 0
            ):
                return False, proof_at, None
            for terminal in inventory.get("rows") or []:
                matching_rows = [
                    row
                    for row in rows
                    if _session_inventory_terminal_matches_row(
                        provider,
                        terminal,
                        row,
                    )
                    and row.get("readable_state") == "live"
                ]
                if len(matching_rows) != 1:
                    missing.append({
                        "provider": provider,
                        "pid": int(terminal.get("pid") or 0),
                        "terminal_tty": str(
                            terminal.get("terminal_tty")
                            or terminal.get("provider_tty")
                            or terminal.get("tty")
                            or ""
                        ),
                        "native_id": str(terminal.get("native_id") or "") or None,
                        "match_count": len(matching_rows),
                    })
        for row in rows:
            provider = str(row.get("provider") or "")
            inventory_rows = list(
                (provider_inventories.get(provider) or {}).get("rows") or []
            )
            matching_terminals = [
                terminal
                for terminal in inventory_rows
                if _session_inventory_terminal_matches_row(
                    provider,
                    terminal,
                    row,
                )
            ]
            if allow_readable_history and row.get("readable_state") != "live":
                continue
            if provider not in requested or len(matching_terminals) != 1:
                unexpected.append({
                    "provider": provider,
                    "id": str(row.get("id") or ""),
                    "native_id": str(row.get("native_id") or "") or None,
                    "pid": int(row.get("pid") or row.get("claude_pid") or 0),
                    "terminal_tty": str(row.get("terminal_tty") or ""),
                    "match_count": len(matching_terminals),
                })
        if missing or unexpected:
            return False, proof_at, {
                "reason": "session_inventory_materialization_incomplete",
                "detail": (
                    "The Mac could not map live provider terminals and session "
                    "rows one to one. The last trusted session list is being "
                    "kept."
                ),
                "missing": missing[:20],
                "unexpected": unexpected[:20],
            }
        if len(proof_times) != len(checked_at):
            return False, proof_at, None
        return True, proof_at, None

    def _collect_sessions_stream_snapshot(
        self,
        provider_filter: str,
        *,
        bypass_snapshot_cache: bool = False,
        wait_for_inventory: bool = False,
    ) -> dict:
        visible = _visible_agent_provider_ids()
        requested = (
            set(visible)
            if provider_filter == "all"
            else ({provider_filter} if provider_filter in visible else set())
        )
        (
            provider_inventories,
            inventory_state,
            inventory_generation,
            membership_generation,
        ) = (
            _sessions_provider_inventory_bundle(
                requested,
                wait_timeout=(
                    _SESSION_INVENTORY_REFRESH_WAIT_SECONDS
                    if wait_for_inventory
                    else 0.0
                ),
            )
        )

        def load_snapshot() -> dict:
            provider_inventory = {
                provider: list(inventory.get("rows") or [])
                for provider, inventory in provider_inventories.items()
            }
            metadata: dict[str, object] = {}
            rows: list[dict] = []
            degraded: dict | None = None
            try:
                rows = self._collect_visible_session_rows_from_inventory(
                    provider_filter,
                    active_within_min=60,
                    limit=200,
                    live_only=True,
                    authoritative_inventory=True,
                    provider_inventory=provider_inventory,
                    collection_metadata=metadata,
                )
            except Exception as error:
                degraded = {
                    "reason": "agent_session_store_unavailable",
                    "detail": (
                        "Pairling could not build the Mac session list. "
                        f"{type(error).__name__}: {str(error)[:160]}"
                    ),
                }
            if degraded is None:
                degraded = self._sessions_backend_degradation(
                    provider_filter,
                    require_fresh=True,
                    provider_inventories=provider_inventories,
                )
            if degraded is None:
                degraded = _sessions_inventory_degradation(inventory_state)
            (
                membership_complete,
                membership_checked_at,
                proof_degradation,
            ) = self._sessions_membership_proof(
                provider_filter,
                degraded,
                provider_inventories,
                rows,
                truncated=bool(metadata.get("truncated")),
            )
            if degraded is None and proof_degradation is not None:
                degraded = proof_degradation
            with _sessions_inventory_bundle_lock:
                generation_changed = bool(requested) and (
                    int(_sessions_inventory_bundle.get("generation") or 0)
                    != inventory_generation
                    or int(
                        _sessions_inventory_bundle.get(
                            "membership_generation"
                        ) or 0
                    )
                    != membership_generation
                )
            final_inventory_state = (
                inventory_state
                if inventory_state == "timeout"
                else ("refreshing" if generation_changed else inventory_state)
            )
            if generation_changed:
                membership_complete = False
                membership_checked_at = 0.0
                degraded = _sessions_inventory_degradation(
                    final_inventory_state
                )
            snapshot = {
                "items": rows,
                "ts": _time.time(),
                "membership_complete": membership_complete,
                "membership_checked_at": membership_checked_at,
                "inventory_state": final_inventory_state,
            }
            if degraded is not None:
                snapshot["degraded"] = degraded
            return snapshot

        return _cached_runtime_snapshot(
            (
                "sessions-stream-snapshot",
                provider_filter,
                inventory_state,
                inventory_generation,
            ),
            RUNTIME_SNAPSHOT_CACHE_SECONDS,
            load_snapshot,
            force_refresh=bypass_snapshot_cache,
            # Authoritative discovery can register a terminal while building
            # this exact snapshot. That registry write invalidates older
            # snapshots, but this completed value already includes the write.
            store_after_loader_invalidation=True,
        )

    def _collect_sessions_stream_rows(self, provider_filter: str) -> list[dict]:
        snapshot = self._collect_sessions_stream_snapshot(provider_filter)
        return list(snapshot.get("items") or [])

    @staticmethod
    def _session_row_is_strictly_live(
        row: dict,
        codex_live_terminal_rows: list[dict] | None = None,
        claude_live_terminal_rows: list[dict] | None = None,
    ) -> bool:
        if row.get("closed_at") is not None:
            return False
        if (
            row.get("provider") == "codex"
            and row.get("source_freshness") == "identity_ambiguous"
            and int(row.get("identity_conflict_count") or 0) > 1
        ):
            # The Codex scanner found more than one exact live terminal for
            # the same transcript identity. Membership is real, but choosing
            # a mutation target would be unsafe.
            return True
        pid = int(row.get("pid") or row.get("claude_pid") or 0)
        tty = str(row.get("terminal_tty") or "")
        has_real_tty = bool(re.match(r"^/dev/ttys[0-9]{3,}$", tty))
        if row.get("provider") == "omp":
            return bool(
                row.get("source_freshness") == "inventory_live"
                and pid > 0
                and has_real_tty
            )
        if (
            row.get("provider") == "codex"
            and row.get("source_freshness") == "identity_probe_degraded"
            and pid > 0
            and has_real_tty
        ):
            # The Codex provider list only emits this marker for a row that
            # was exact during the scanner grace window. Preserve membership
            # while removing every mutation capability until the probe heals.
            return True
        if pid > 0 or has_real_tty:
            verification_row = row
            if row.get("provider") == "codex":
                verification_row = _codex_registry_row_for_strict_live_display(row)
                if verification_row is None:
                    return False
                return _codex_inventory_registry_process_matches(
                    verification_row, codex_live_terminal_rows
                )
            native_id = str(row.get("native_id") or "").strip()
            verification_row = _agent_registry_get("claude", native_id)
            return _claude_inventory_registry_process_matches(
                verification_row,
                claude_live_terminal_rows,
            )
        # Older Claude hook rows may not have a pid yet. A fresh hook-backed
        # UUID is still stronger evidence than transcript mtime alone, but it
        # is membership proof only. Without a pid or TTY the row is read-only.
        if (
            row.get("provider") == "claude"
            and claude_live_terminal_rows is None
            and row.get("claude_uuid")
        ):
            age = max(0, int(_time.time()) - int(row.get("last_heartbeat") or 0))
            return age <= 120
        return False

    @classmethod
    def _strict_live_projection(
        cls,
        row: dict,
        codex_live_terminal_rows: list[dict] | None = None,
        claude_live_terminal_rows: list[dict] | None = None,
    ) -> dict | None:
        is_live = (
            cls._session_row_is_strictly_live(
                row,
                codex_live_terminal_rows,
            )
            if claude_live_terminal_rows is None
            else cls._session_row_is_strictly_live(
                row,
                codex_live_terminal_rows,
                claude_live_terminal_rows,
            )
        )
        if not is_live:
            return None
        projected = dict(row)
        projected["readable_state"] = "live"
        pid = int(row.get("pid") or row.get("claude_pid") or 0)
        tty = str(row.get("terminal_tty") or "")
        if (
            row.get("provider") == "codex"
            and row.get("source_freshness") in {
                "identity_probe_degraded",
                "identity_ambiguous",
            }
        ):
            if row.get("source_freshness") == "identity_ambiguous":
                reason = (
                    "More than one live terminal claims this Codex session; "
                    "control is disabled until the identity conflict clears."
                )
            else:
                reason = "Live identity is being rechecked; this session is temporarily read-only."
            projected["control_state"] = "read_only"
            projected["control_reason"] = reason
            projected["controllability"] = {
                "can_send_text": False,
                "can_interrupt": False,
                "can_terminate": False,
                "reason": reason,
            }
            projected["capabilities"] = [
                capability
                for capability in (row.get("capabilities") or [])
                if capability not in {
                    "send_text",
                    "interrupt",
                    "terminate",
                    "terminal_control",
                }
            ]
            return projected
        if pid > 0 or re.match(r"^/dev/ttys[0-9]{3,}$", tty):
            return projected

        reason = "Live hook seen; process control is not verified yet."
        projected["control_state"] = "read_only"
        projected["control_reason"] = reason
        projected["controllability"] = {
            "can_send_text": False,
            "can_interrupt": False,
            "can_terminate": False,
            "reason": reason,
        }
        projected["capabilities"] = [
            capability
            for capability in (row.get("capabilities") or [])
            if capability in {"transcript", "export", "live_state"}
        ]
        return projected

    def _decorate_session_lifecycle_row(
        self,
        row: dict,
        *,
        provider_inventory: dict[str, list[dict]] | None = None,
    ) -> dict:
        row.setdefault("closed_at", None)
        provider = row.get("provider") or "claude"
        native_id = row.get("native_id") or row.get("id") or ""
        transcript_path = None
        has_transcript_stats = (
            "turn_count" in row and "last_meaningful_turn_at" in row
        )
        if not has_transcript_stats:
            if provider == "codex" and native_id:
                transcript_path = _resolve_codex_transcript(native_id)
            elif provider == "claude" and row.get("project") and row.get("claude_uuid"):
                transcript_path = HOME / ".claude" / "projects" / _encode_project_dir(row["project"]) / f"{row['claude_uuid']}.jsonl"
            stats = _session_transcript_stats(transcript_path, provider, native_id)
            row.setdefault("turn_count", stats.get("turn_count"))
            row.setdefault(
                "last_meaningful_turn_at",
                stats.get("last_meaningful_turn_at"),
            )
        identity = _session_workspace_identity(row.get("project"))
        row["branch"] = identity.get("branch")
        row["worktree"] = identity.get("worktree")
        row["terminal_title"] = _session_terminal_title(row)
        decorated = self._decorate_visible_session_row(
            row,
            provider_inventory=provider_inventory,
        )
        decorated.setdefault("closed_at", None)
        decorated.setdefault("turn_count", None)
        if decorated.get("readable_state") == "closed":
            decorated["state"] = decorated.get("state") or "terminated"
        return decorated

    def _decorate_visible_session_row(
        self,
        row: dict,
        *,
        provider_inventory: dict[str, list[dict]] | None = None,
    ) -> dict:
        now = int(_time.time())
        last = int(row.get("last_heartbeat") or 0)
        closed_at = row.get("closed_at")
        age = max(0, now - last) if last else 0

        controllability = dict(row.get("controllability") or {})
        capabilities = set(row.get("capabilities") or [])
        can_control = bool(
            not closed_at
            and (
                controllability.get("can_send_text")
                or controllability.get("can_interrupt")
                or controllability.get("can_terminate")
                or (
                    controllability.get("can_control")
                    and "terminal_control" in capabilities
                )
            )
        )
        has_verified_process = can_control
        if not closed_at and not has_verified_process:
            try:
                provider = str(row.get("provider") or "claude")
                if provider == "codex":
                    registry_row = _codex_registry_row_for_strict_live_display(
                        row
                    )
                    has_verified_process = bool(
                        registry_row
                        and _codex_inventory_registry_process_matches(
                            registry_row,
                            (
                                provider_inventory.get("codex", [])
                                if provider_inventory is not None
                                else None
                            ),
                        )
                    )
                else:
                    live_inventory = (
                        provider_inventory.get(provider, [])
                        if provider_inventory is not None
                        else None
                    )
                    if live_inventory is not None:
                        has_verified_process = any(
                            _session_inventory_terminal_matches_row(
                                provider,
                                terminal,
                                row,
                            )
                            for terminal in live_inventory
                        )
                    else:
                        has_verified_process = _session_has_verified_provider_process(
                            row,
                            provider,
                        )
            except Exception:
                has_verified_process = False

        if closed_at:
            readable_state = "closed"
        elif has_verified_process or (
            provider_inventory is None and age <= 60 * 60
        ):
            readable_state = "live"
        elif age <= 60 * 24 * 60:
            readable_state = "stale"
        else:
            readable_state = "offline"

        if can_control:
            control_state = "controllable"
            control_reason = None
        else:
            read_capabilities = set(row.get("capabilities") or [])
            control_state = (
                "read_only"
                if readable_state == "closed"
                or bool(read_capabilities & {
                    "transcript",
                    "resume",
                    "terminal_output",
                    "terminal_surface",
                })
                else "unavailable"
            )
            if readable_state == "closed":
                control_reason = "Session is closed; transcript remains readable."
            elif readable_state in {"stale", "offline"}:
                control_reason = "Session is not live on the Mac; transcript remains readable."
            else:
                control_reason = controllability.get("reason") or "Live control metadata is unavailable; transcript remains readable."
            controllability = {
                "can_send_text": False,
                "can_interrupt": False,
                "can_terminate": False,
                "reason": control_reason,
            }
            allowed_read_only = {"transcript", "export", "live_state"}
            if readable_state == "live":
                allowed_read_only.update({"resume", "terminal_output", "terminal_surface"})
            row["capabilities"] = [
                capability
                for capability in (row.get("capabilities") or [])
                if capability in allowed_read_only
            ]

        row["readable_state"] = readable_state
        row["control_state"] = control_state
        row["control_reason"] = control_reason
        row["controllability"] = controllability
        row["stale_seconds"] = age
        return row

    def _handle_sessions(self, q):
        # Live filter: ?live=true returns only currently-running terminals
        # (no tombstone AND heartbeat within 2 min). Uses partial index
        # idx_sessions_live for fast lookups. iOS Dashboard should pass live=true.
        # Without the param, legacy behavior is preserved (heartbeat-window only,
        # no tombstone awareness) for any existing callers.
        live_only = q.get("live", ["false"])[0].lower() in ("true", "1", "yes")
        provider_filter = q.get("provider", ["all"])[0].lower()
        if not _valid_provider_filter(provider_filter):
            _send_unknown_provider(self, provider_filter)
            return

        try:
            within_min = int(q.get("active_within_min", ["60"])[0])
        except ValueError:
            within_min = 60

        if live_only:
            if (
                provider_filter != "all"
                and provider_filter not in _session_membership_provider_ids()
            ):
                _send_unsupported_provider(
                    self,
                    provider_filter,
                    "live session inventory",
                )
                return
            if (
                provider_filter != "all"
                and provider_filter not in _visible_agent_provider_ids()
            ):
                _send_provider_hidden(self, provider_filter)
                return
            snapshot = self._collect_sessions_stream_snapshot(
                provider_filter,
                bypass_snapshot_cache=True,
                wait_for_inventory=True,
            )
            snapshot["source"] = _sessions_stream_source()
            snapshot["count"] = len(snapshot.get("items") or [])
            self._send_json(
                snapshot,
                status=503 if snapshot.get("degraded") is not None else 200,
                headers={"Cache-Control": "no-store"},
            )
            return

        if provider_filter != "all" and provider_filter not in _agent_provider_ids():
            self._send_json({"count": 0, "items": []})
            return

        # SPEC-p1 §2.3: an excluded provider disappears from list surfaces —
        # and is not even scanned, so exclusion is also cheap.
        if provider_filter != "all" and not _provider_visible(provider_filter):
            self._send_json({"count": 0, "items": []})
            return
        if provider_filter not in {"all", "claude", "codex"}:
            rows = _managed_session_rows(
                provider_filter=provider_filter,
                live_only=False,
                active_within_min=within_min,
                limit=50,
            )
            rows = _filter_tombstoned_session_rows(rows)
            rows.sort(key=_session_meaningful_sort_key)
            rows = rows[:50]
            _record_sessions_scan(rows)
            self._send_json({"count": len(rows), "items": rows})
            return

        if provider_filter == "codex":
            try:
                _session_tombstone_keys()
            except SessionTombstoneStoreError:
                self._send_json({
                    "count": 0,
                    "items": [],
                    "degraded": {
                        "reason": "session_tombstone_store_unavailable",
                        "detail": "Durable session removals are unreadable on the Mac.",
                    },
                }, status=503)
                return
            codex_rows = _list_codex_sessions(
                live_only=live_only,
                active_within_min=within_min,
            )
            if live_only:
                degraded = self._sessions_backend_degradation(provider_filter)
                if degraded is not None:
                    self._send_json({
                        "count": 0,
                        "items": [],
                        "degraded": degraded,
                    }, status=503)
                    return
            rows = [
                self._decorate_session_lifecycle_row(row)
                for row in codex_rows
            ]
            rows = _merge_managed_session_rows(
                rows,
                _managed_session_rows(
                    provider_filter="codex",
                    live_only=False,
                    active_within_min=within_min,
                    limit=50,
                ),
            )
            rows.sort(key=_session_meaningful_sort_key)
            rows = _filter_tombstoned_session_rows(rows)
            rows = _collapse_live_session_rows_by_terminal(rows)
            rows = rows[:50]
            _record_sessions_scan(rows)
            body = json.dumps({"count": len(rows), "items": rows}).encode()
            self.send_response(200)
            self.send_header("Content-Type", "application/json")
            self.send_header("Content-Length", str(len(body)))
            self.end_headers()
            self.wfile.write(body)
            return

        # OMP exposes live terminal inventory only. It has no transcript-backed
        # history surface, so a non-live filter must never reach Claude.
        if provider_filter == "omp":
            self._send_json({"count": 0, "items": []})
            return

        # Live filter semantics (live_only): keep sessions with either a fresh
        # claude_uuid-backed hook row or a live Claude process on the recorded
        # terminal. The freshness gate hides mute zombie rows, while terminal
        # discovery keeps already-open Claude windows controllable.
        _claude_register_terminal_only_rows(set())
        backend = _claude_sessions_backend()
        backend_rows = []
        if _provider_visible("claude"):
            try:
                backend_rows = backend.sessions_rows(live_only, within_min)
            except RuntimeError as exc:
                self._send_json({
                    "count": 0,
                    "items": [],
                    "degraded": {
                        "reason": "sessions_backend_unreachable",
                        "detail": str(exc)[:220],
                    },
                }, status=503)
                return

        rows = []
        try:
            _session_tombstone_keys()
        except SessionTombstoneStoreError:
            self._send_json({
                "count": 0,
                "items": [],
                "degraded": {
                    "reason": "session_tombstone_store_unavailable",
                    "detail": "Durable session removals are unreadable on the Mac.",
                },
            }, status=503)
            return
        for raw in backend_rows:
            session_id = raw["id"]
            project = raw["project"]
            if _is_excluded_project(project):
                continue
            claude_pid = int(raw.get("claude_pid") or 0)
            claude_uuid = raw.get("claude_uuid") or ""
            terminal_tty = raw.get("terminal_tty") or ""

            # A read may exclude a row whose process cannot be proved, but one
            # transient process-scan miss must never mutate durable identity.
            # SessionEnd and the guarded stale sweep own registry closure.
            if live_only and claude_pid > 0:
                if not _session_has_verified_provider_process({
                    "provider": "claude",
                    "pid": claude_pid,
                    "terminal_tty": terminal_tty,
                    "project": project,
                }):
                    continue

            row = {
                "id": session_id,
                "project": project,
                "working_on": raw.get("working_on") or None,
                "started_at": int(raw.get("started_at") or 0),
                "last_heartbeat": int(raw.get("last_heartbeat") or 0),
                "closed_at": raw.get("closed_at"),
                "first_prompt": None,
            }
            _decorate_claude_session_row(row, session_id, claude_pid, terminal_tty)
            row.update(self._turn_state_summary(claude_uuid))
            _refresh_claude_observed_activity(row, project, claude_uuid)
            signal = self._recent_session_signal(session_id, project=project, claude_uuid=claude_uuid)
            row["recent_anomaly"] = signal.get("anomaly")
            row["latest_command"] = signal.get("latest_command")
            row["latest_edit"] = signal.get("latest_edit")
            if project and claude_uuid:
                transcript = (
                    HOME / ".claude" / "projects" / _encode_project_dir(project)
                    / f"{claude_uuid}.jsonl"
                )
                if transcript.is_file():
                    row["first_prompt"] = _peek_first_prompt(transcript)
            rows.append(row)

        rows = [self._decorate_session_lifecycle_row(row) for row in rows]

        if provider_filter == "all":
            if _provider_visible("codex"):
                rows.extend(
                    self._decorate_session_lifecycle_row(row)
                    for row in _list_codex_sessions(live_only=live_only, active_within_min=within_min)
                )
            rows = _merge_managed_session_rows(
                rows,
                [
                    row
                    for row in _managed_session_rows(
                        provider_filter="all",
                        live_only=False,
                        active_within_min=within_min,
                        limit=100,
                    )
                    if _provider_visible(str(row.get("provider") or ""))
                ],
            )
            rows = _filter_tombstoned_session_rows(rows)
            rows = _collapse_live_session_rows_by_terminal(rows)
            rows.sort(key=_session_meaningful_sort_key)
            rows = rows[:50]
        elif provider_filter == "claude":
            rows = _merge_managed_session_rows(
                rows,
                _managed_session_rows(
                    provider_filter="claude",
                    live_only=False,
                    active_within_min=within_min,
                    limit=50,
                ),
            )
            rows = _filter_tombstoned_session_rows(rows)
            rows = _collapse_live_session_rows_by_terminal(rows)
        else:
            rows = _filter_tombstoned_session_rows(rows)
            rows = _collapse_live_session_rows_by_terminal(rows)

        if live_only:
            degraded = self._sessions_backend_degradation(provider_filter)
            if degraded is not None:
                self._send_json({
                    "count": 0,
                    "items": [],
                    "degraded": degraded,
                }, status=503)
                return

        _record_sessions_scan(rows)
        body = json.dumps({"count": len(rows), "items": rows}).encode()

        self.send_response(200)
        self.send_header("Content-Type", "application/json")
        self.send_header("Content-Length", str(len(body)))
        self.end_headers()
        self.wfile.write(body)

    def _handle_session_source_diagnostics(self, q):
        try:
            since_min = int(q.get("since_min", ["1440"])[0])
        except ValueError:
            since_min = 1440
        since_min = max(1, min(since_min, 60 * 24 * 14))

        claude_live = self._collect_session_rows(
            since_min=since_min,
            live_only=True,
            limit=500,
            include_first_prompt=False,
        )
        codex_registry = _agent_registry_recent("codex", since_min=since_min, limit=500)
        codex_live_registry = _agent_registry_live("codex")
        codex_rollouts = _codex_rollout_paths()
        now = int(_time.time())
        live_codex_rows = _list_codex_sessions(live_only=True, active_within_min=since_min)

        items = [
            {
                "id": "claude:postgres",
                "provider": "claude",
                "source": "postgres_sessions",
                "total": len(claude_live),
                "live": len(claude_live),
                "fresh": sum(1 for row in claude_live if now - int(row.get("last_heartbeat") or 0) < 120),
                "stale": sum(1 for row in claude_live if now - int(row.get("last_heartbeat") or 0) >= 120),
                "notes": [
                    "Uses claude_uuid-backed hook rows plus live terminal discovery.",
                    "Terminal-only rows are controllable even before a transcript id is known.",
                ],
            },
            {
                "id": "codex:registry",
                "provider": "codex",
                "source": "agent_registry",
                "total": len(codex_registry),
                "live": len(codex_live_registry),
                "fresh": sum(1 for row in codex_live_registry if now - int(row.get("last_heartbeat") or 0) < 120),
                "stale": sum(1 for row in codex_live_registry if now - int(row.get("last_heartbeat") or 0) >= 120),
                "notes": [
                    "Registry rows with a live pid stay visible even when heartbeat is stale.",
                    "These rows provide Codex control metadata.",
                ],
            },
            {
                "id": "codex:rollouts",
                "provider": "codex",
                "source": "codex_rollout_jsonl",
                "total": len(codex_rollouts),
                "live": len([row for row in live_codex_rows if row.get("provider") == "codex"]),
                "fresh": len([row for row in live_codex_rows if int(row.get("last_heartbeat") or 0) >= now - 120]),
                "stale": len([row for row in live_codex_rows if int(row.get("last_heartbeat") or 0) < now - 120]),
                "notes": [
                    "Read-only rollout transcripts backfill session history.",
                    "Registry overlay adds control when metadata exists.",
                ],
            },
        ]
        self._send_json({"count": len(items), "items": items, "ts": _time.time()})

    def _turn_state_summary(self, claude_uuid: str) -> dict:
        """Cheap status payload for session-list rows. The heavier branch,
        dirty-count, and cost fields stay in /status; dashboard rows only need
        enough to show whether a claude is thinking, using a tool, or idle."""
        if not claude_uuid:
            return {}
        try:
            path = TURN_STATE_DIR / f"{claude_uuid}.json"
            if not path.is_file():
                return {}
            obj = json.loads(path.read_text())
        except Exception:
            return {}
        # The statusline sidecar (<uuid>.status.json, written by the rig's
        # statusline pipeline) contributes model, context percentage, and the
        # rendered statusline verbatim: the hook's stdin never carries those,
        # and the phone renders status_text as the row's own voice. Sidecar
        # fields fill gaps; the turn-state file wins where both speak.
        sidecar = {}
        try:
            sidecar_path = TURN_STATE_DIR / f"{claude_uuid}.status.json"
            if sidecar_path.is_file():
                loaded = json.loads(sidecar_path.read_text())
                if isinstance(loaded, dict):
                    sidecar = loaded
        except Exception:
            sidecar = {}
        status_text = str(sidecar.get("status_text") or "").strip()
        return {
            "state": obj.get("state"),
            "tool": obj.get("tool"),
            "turn_started_at": obj.get("started_at"),
            "turn_state_updated_at": obj.get("last_update"),
            "effort": obj.get("effort"),
            "model": obj.get("model") or sidecar.get("model"),
            "context_pct": obj.get("context_pct") if obj.get("context_pct") is not None else sidecar.get("context_pct"),
            "status_text": status_text[:500] or None,
        }

    # ----- /sessions-stream: live SSE feed of every active session -----
    def _handle_sessions_stream(self, q):
        """SSE stream of the live-sessions list. Polls PG every 1.5s, emits
        only when the result set changes (by hash). Powers a single
        SessionStore on the iPhone that every view binds to — replaces the
        Dashboard's on-appear + pull-to-refresh polling pattern.

        Event shapes:
          event: snapshot     data: {"items":[...], "ts":<epoch>}
          event: keepalive    data: {} (every 20s for NAT)
          event: done         data: {} (10-min cap; iOS reconnects)

        The full snapshot is re-sent on every diff — payload is small (<50
        rows × <500 bytes each), and computing per-session deltas would
        complicate iOS-side reconciliation for negligible bandwidth gain.
        """
        provider_filter = q.get("provider", ["all"])[0].lower()
        if not _valid_provider_filter(provider_filter):
            _send_unknown_provider(self, provider_filter)
            return
        if (
            provider_filter != "all"
            and provider_filter not in _session_membership_provider_ids()
        ):
            _send_unsupported_provider(
                self,
                provider_filter,
                "live session inventory",
            )
            return
        if (
            provider_filter != "all"
            and provider_filter not in _visible_agent_provider_ids()
        ):
            _send_provider_hidden(self, provider_filter)
            return

        def collect_live() -> dict:
            _agent_registry_close_stale()
            return self._collect_sessions_stream_snapshot(provider_filter)

        def snapshot_payload(snapshot: dict) -> tuple[bytes, str]:
            source = _sessions_stream_source()
            rows = list(snapshot.get("items") or [])
            degraded = snapshot.get("degraded")
            membership_complete = bool(
                snapshot.get("membership_complete", False)
            )
            body: dict = {
                "source": source,
                "items": rows,
                "ts": float(snapshot.get("ts") or _time.time()),
                "membership_complete": membership_complete,
                "membership_checked_at": float(
                    snapshot.get("membership_checked_at") or 0
                ),
            }
            if degraded is not None:
                body["degraded"] = degraded
            stable_rows = _stable_sessions_stream_rows(rows)
            digest = hashlib.sha256(
                json.dumps(
                    {
                        "rows": stable_rows,
                        "degraded": degraded,
                        "membership_complete": membership_complete,
                    },
                    sort_keys=True,
                ).encode()
            ).hexdigest()
            return json.dumps(body).encode(), digest

        sessions_wakes = (
            SESSION_EVENT_HUB.subscribe(SESSION_SUMMARIES_TOPIC)
            if SESSION_EVENT_HUB is not None
            else None
        )
        try:
            # Subscribe before collecting the first authoritative snapshot.
            # Any mutation during that scan stays queued and triggers an
            # immediate follow-up scan after the initial snapshot is sent.
            try:
                initial = collect_live()
                payload, last_hash = snapshot_payload(initial)
            except Exception:
                self._send_json({
                    "ok": False,
                    "error": {
                        "code": "sessions_initial_snapshot_unavailable",
                        "message": "The Mac could not confirm the current session list. Pairling will retry.",
                    },
                }, status=503)
                return

            self.send_response(200)
            self.send_header("Content-Type", "text/event-stream")
            self.send_header("Cache-Control", "no-store")
            self.send_header("Connection", "keep-alive")
            self.send_header("X-Accel-Buffering", "no")
            self.end_headers()

            last_keepalive = _time.time()
            deadline = _time.time() + 600  # 10 min

            # Emit initial snapshot immediately so the iPhone never paints
            # an empty Dashboard while waiting for the first poll.
            # Initial snapshot body contract: {"items": initial}.
            self.wfile.write(b"event: snapshot\ndata: " + payload + b"\n\n")
            self.wfile.flush()

            pending_wake = False
            if sessions_wakes is not None:
                wake = sessions_wakes.get(timeout=0)
                while wake is not None:
                    pending_wake = True
                    wake = sessions_wakes.get(timeout=0)

            last_scan = _time.time()
            while _time.time() < deadline:
                if not self._stream_authorization_is_current():
                    return
                woke = pending_wake
                pending_wake = False
                if sessions_wakes is not None:
                    if not woke:
                        wake = sessions_wakes.get(timeout=1.5)
                        while wake is not None:
                            woke = True
                            wake = sessions_wakes.get(timeout=0)
                else:
                    _time.sleep(1.5)
                    woke = True
                # Registry writes publish summaries, so the scan runs on
                # wake; the 5 s safety covers unpublished mutations such as
                # close sweeps.
                if not woke and _time.time() - last_scan < 5.0:
                    if _time.time() - last_keepalive >= 20:
                        try:
                            self.wfile.write(b"event: keepalive\ndata: {}\n\n")
                            self.wfile.flush()
                        except (BrokenPipeError, ConnectionResetError):
                            return
                        last_keepalive = _time.time()
                    continue
                last_scan = _time.time()
                snapshot = collect_live()
                payload, h = snapshot_payload(snapshot)
                if h != last_hash:
                    try:
                        self.wfile.write(b"event: snapshot\ndata: " + payload + b"\n\n")
                        self.wfile.flush()
                        last_hash = h
                    except (BrokenPipeError, ConnectionResetError):
                        return
                if _time.time() - last_keepalive >= 20:
                    try:
                        self.wfile.write(b"event: keepalive\ndata: {}\n\n")
                        self.wfile.flush()
                    except (BrokenPipeError, ConnectionResetError):
                        return
                    last_keepalive = _time.time()
            try:
                self.wfile.write(b"event: done\ndata: {}\n\n")
                self.wfile.flush()
            except Exception:
                pass
        except (BrokenPipeError, ConnectionResetError):
            return
        finally:
            if sessions_wakes is not None:
                sessions_wakes.close()

    # ----- /transcript: stream JSONL by byte offset -----
    def _handle_transcript(self, q):
        session_id = q.get("session", [""])[0]
        if not session_id:
            self.send_error(400, "session required")
            return
        try:
            since = int(q.get("since", ["0"])[0])
        except ValueError:
            self.send_error(400, "since must be int bytes")
            return
        max_bytes_raw = q.get("max_bytes", [None])[0]
        max_bytes = None
        if max_bytes_raw is not None:
            try:
                max_bytes = int(max_bytes_raw)
            except ValueError:
                self.send_error(400, "max_bytes must be int bytes")
                return
            if max_bytes <= 0 or max_bytes > TRANSCRIPT_RANGE_FETCH_MAX_BYTES:
                self.send_error(400, f"max_bytes must be between 1 and {TRANSCRIPT_RANGE_FETCH_MAX_BYTES}")
                return

        provider, native_id = _parse_agent_session_ref(session_id)
        managed_session_id = (
            _qualified_session_id(provider, native_id) if native_id else ""
        )
        managed_store = _ensure_managed_provider_session_store()
        managed_row = (
            managed_store.get(managed_session_id)
            if managed_store is not None and managed_session_id
            else None
        )
        if managed_row is not None:
            data, next_since, total = _managed_transcript_ndjson(
                managed_session_id,
                since=max(0, since),
            )
            if max_bytes is not None and len(data) > max_bytes:
                selected = bytearray()
                selected_next = max(0, since)
                for line in data.splitlines(keepends=True):
                    if selected and len(selected) + len(line) > max_bytes:
                        break
                    if len(line) > max_bytes:
                        break
                    selected.extend(line)
                    try:
                        selected_next = int(
                            json.loads(line).get("seq") or selected_next
                        )
                    except Exception:
                        pass
                data = bytes(selected)
                next_since = selected_next
            self.send_response(200)
            self.send_header("Content-Type", "application/x-ndjson")
            self.send_header("X-Total-Bytes", str(total))
            self.send_header("X-Bytes-Read", str(len(data)))
            self.send_header("X-Next-Since", str(next_since))
            self.send_header("X-Offset-Unit", "normalized-event-sequence")
            self.send_header(
                "X-Log-Generation",
                str(int(managed_row["capability_generation"])),
            )
            self.send_header("X-Resolved-Path", "managed-provider-events")
            self.end_headers()
            self.wfile.write(data)
            return
        launch_context = _session_launch_context_from_metadata(
            _registry_metadata_from_row(_agent_registry_get(provider, native_id))
        ) if native_id else None
        try:
            path = self._resolve_session_transcript_path(
                provider,
                native_id,
                session_id,
            )
        except _UnsupportedTranscriptProviderError as error:
            _send_unsupported_provider(
                self,
                error.provider,
                error.capability,
                status=422,
            )
            return
        if path is None:
            self.send_error(404, f"no transcript resolvable for session={session_id}")
            return

        try:
            with _open_session_transcript_file(path) as f:
                stat = os.fstat(f.fileno())
                size = max(0, int(stat.st_size))
                session_key = _qualified_session_id(provider, native_id)
                ingestor = _ensure_session_log_ingestor()
                log_generation = None
                if ingestor is not None:
                    log_generation = ingestor.generation_for_open_source(
                        session_key,
                        provider,
                        native_id,
                        path,
                        (int(stat.st_dev), int(stat.st_ino)),
                        size,
                    )
                if max_bytes is not None:
                    # Exact byte-range mode, used to recover regions named by an
                    # oversized notice: no initial-window clamp and no forward line
                    # alignment, and next_since advances by the raw bytes read rather
                    # than jumping to end of file.
                    start = min(since, size)
                    f.seek(start)
                    data = f.read(min(max_bytes, size - start))
                    next_since = start + len(data)
                else:
                    start = min(since, size)
                    if since == 0 and size > TRANSCRIPT_INITIAL_STREAM_BYTES:
                        start = max(0, size - TRANSCRIPT_INITIAL_STREAM_BYTES)
                    f.seek(start)
                    data = f.read()
                    if start > 0:
                        first_newline = data.find(b"\n")
                        if first_newline >= 0:
                            data = data[first_newline + 1:]
                    next_since = size
        except OSError:
            self._send_json(
                {
                    "ok": False,
                    "error": {
                        "code": "transcript_unavailable",
                        "message": "The session transcript is temporarily unavailable.",
                    },
                },
                status=503,
                headers={"Retry-After": "1"},
            )
            return
        if provider == "codex":
            data = _normalize_codex_ndjson(data, native_id).encode("utf-8")

        self.send_response(200)
        self.send_header("Content-Type", "application/x-ndjson")
        self.send_header("X-Total-Bytes", str(size))
        self.send_header("X-Bytes-Read", str(len(data)))
        self.send_header("X-Next-Since", str(next_since))
        if log_generation is not None:
            self.send_header("X-Log-Generation", str(log_generation))
        self.send_header("X-Resolved-Path", path.name)
        self.end_headers()
        self.wfile.write(data)

    def _handle_managed_transcript_stream(
        self, session_id: str, since: int
    ) -> None:
        self.send_response(200)
        self.send_header("Content-Type", "text/event-stream")
        self.send_header("Cache-Control", "no-store")
        self.send_header("Connection", "keep-alive")
        self.send_header("X-Accel-Buffering", "no")
        self.send_header("X-Offset-Unit", "normalized-event-sequence")
        self.end_headers()
        cursor = max(0, int(since))
        last_keepalive = _time.time()
        deadline = _time.time() + 600.0
        subscription = (
            SESSION_EVENT_HUB.subscribe(f"log:{session_id}")
            if SESSION_EVENT_HUB is not None
            else None
        )
        try:
            if not self._stream_authorization_is_current():
                return
            while _time.time() < deadline:
                if not self._stream_authorization_is_current():
                    return
                data, next_since, total = _managed_transcript_ndjson(
                    session_id,
                    since=cursor,
                )
                if data:
                    if not _sse_write_json_event(
                        self.wfile,
                        "tail",
                        {
                            "next_since": next_since,
                            "total_bytes": total,
                            "ndjson": data.decode("utf-8", errors="replace"),
                            "offset_unit": "normalized_event_sequence",
                        },
                        max_bytes=SSE_TRANSCRIPT_MAX_EVENT_BYTES,
                    ):
                        return
                    cursor = next_since
                    last_keepalive = _time.time()
                    continue
                if subscription is not None:
                    subscription.get(timeout=1.0)
                else:
                    _time.sleep(0.25)
                if _time.time() - last_keepalive >= 20.0:
                    if not _sse_write_json_event(self.wfile, "keepalive", {}):
                        return
                    last_keepalive = _time.time()
            _sse_write_json_event(self.wfile, "done", {})
        except (BrokenPipeError, ConnectionResetError):
            return
        finally:
            if subscription is not None:
                subscription.close()

    # ----- /transcript-stream: live SSE feed of a session's JSONL -----
    def _handle_transcript_stream(self, q):
        """SSE stream of one session's JSONL. Resolves the path ONCE at
        connect time, opens the file ONCE and keeps the handle, and polls
        os.fstat() every 100ms. On each tick that the size has grown,
        reads the new bytes and advances ONLY through the last complete
        '\\n' — trailing partial-line bytes are buffered server-side until
        the next tick completes them. Without that, mid-write reads would
        emit a partial JSONL line and the iOS-side per-line JSON decode
        would silently drop the half-formed entry's eventual content.

        Path resolution happens once per connection. If the JSONL rotates
        mid-stream (a /resume swap to a different claude_uuid, or an
        external truncate), the file size shrinks below our offset and
        we disconnect — the client reconnects via its outer auto-retry
        loop and we re-resolve on the new connection. Keeps this handler
        focused; rotation is a rare, fully-recoverable edge case.

        Worst-case end-to-end latency: 100ms (poll cadence) + network
        round-trip. Replaces the iPhone's 1500ms /transcript polling.

        Params:
          session — required; PG s-id or claude_uuid
          since   — initial byte offset (default 0)
        """
        session_id = q.get("session", [""])[0]
        if not session_id:
            self.send_error(400, "session required")
            return
        try:
            since = int(q.get("since", ["0"])[0])
        except ValueError:
            since = 0

        provider, native_id = _parse_agent_session_ref(session_id)
        managed_session_id = (
            _qualified_session_id(provider, native_id) if native_id else ""
        )
        managed_store = _ensure_managed_provider_session_store()
        if (
            managed_store is not None
            and managed_session_id
            and managed_store.get(managed_session_id) is not None
        ):
            self._handle_managed_transcript_stream(
                managed_session_id,
                since,
            )
            return
        try:
            path = self._resolve_session_transcript_path(
                provider,
                native_id,
                session_id,
            )
        except _UnsupportedTranscriptProviderError as error:
            _send_unsupported_provider(
                self,
                error.provider,
                error.capability,
                status=422,
            )
            return
        if path is None:
            self.send_error(404, f"no transcript resolvable for session={session_id}")
            return

        self.send_response(200)
        self.send_header("Content-Type", "text/event-stream")
        self.send_header("Cache-Control", "no-store")
        self.send_header("Connection", "keep-alive")
        self.send_header("X-Accel-Buffering", "no")
        self.end_headers()

        POLL_INTERVAL = 0.1
        KEEPALIVE_INTERVAL = 20.0
        MAX_DURATION = 600.0

        last_emitted_offset = since
        pending_partial = b""
        last_keepalive = _time.time()
        deadline = _time.time() + MAX_DURATION

        # Wake on appends instead of the 100 ms poll; the tick becomes the
        # degraded fallback and the rotation checks keep their cadence.
        transcript_wakes = None
        transcript_watch = None
        if SESSION_EVENT_HUB is not None:
            watch_topic = f"transcript:{_qualified_session_id(provider, native_id)}"
            transcript_wakes = SESSION_EVENT_HUB.subscribe(watch_topic)
            watcher = _ensure_session_file_watcher()
            if watcher is not None:
                transcript_watch = watcher.watch(path, watch_topic)

        f = None
        try:
            f = _session_transcript_handle(path)
            opened_stat = os.fstat(f.fileno())
            last_emitted_offset = _bounded_transcript_stream_start(since=since, size=opened_stat.st_size)
            if last_emitted_offset > 0:
                f.seek(last_emitted_offset - 1)
                previous = f.read(1)
                if previous != b"\n":
                    skipped = f.readline()
                    last_emitted_offset = min(opened_stat.st_size, last_emitted_offset + len(skipped))
            f.seek(last_emitted_offset)

            def _emit_reset(total_bytes: int = 0):
                payload = {
                    "next_since": 0,
                    "total_bytes": max(0, total_bytes),
                    "ndjson": "",
                    "reset": True,
                }
                _sse_write_json_event(self.wfile, "tail", payload, max_bytes=SSE_TRANSCRIPT_MAX_EVENT_BYTES)

            def _emit_complete_lines():
                """Read what's currently available, accumulate into
                pending_partial, emit complete lines through the last
                '\\n', advance last_emitted_offset. Returns False on a
                broken pipe so the caller can clean up."""
                nonlocal last_emitted_offset, pending_partial, last_keepalive
                try:
                    new_data = f.read()
                except OSError:
                    return False
                if new_data:
                    pending_partial += new_data
                idx = pending_partial.rfind(b"\n")
                if idx < 0:
                    return True  # All trailing partial; nothing to emit yet.
                complete = pending_partial[:idx + 1]
                pending_partial = pending_partial[idx + 1:]
                new_offset = last_emitted_offset + len(complete)
                raw_lines = complete.splitlines(keepends=True)
                chunk = b""
                chunk_start_offset = last_emitted_offset
                final_total = new_offset + len(pending_partial)

                def _emit_raw_chunk(raw_chunk: bytes, next_offset: int) -> bool:
                    ndjson = raw_chunk.decode("utf-8", errors="replace")
                    if provider == "codex":
                        ndjson = _normalize_codex_ndjson(raw_chunk, native_id, include_event_fallback=False)
                    return _sse_write_json_event(
                        self.wfile,
                        "tail",
                        {
                            "next_since": next_offset,
                            "total_bytes": final_total,
                            "ndjson": ndjson,
                        },
                        max_bytes=SSE_TRANSCRIPT_MAX_EVENT_BYTES,
                    )

                for raw_line in raw_lines:
                    candidate = chunk + raw_line
                    ndjson = candidate.decode("utf-8", errors="replace")
                    if provider == "codex":
                        ndjson = _normalize_codex_ndjson(candidate, native_id, include_event_fallback=False)
                    _, diagnostic = _sse_json_event(
                        "tail",
                        {
                            "next_since": chunk_start_offset + len(candidate),
                            "total_bytes": final_total,
                            "ndjson": ndjson,
                        },
                        max_bytes=SSE_TRANSCRIPT_MAX_EVENT_BYTES,
                    )
                    if diagnostic and chunk:
                        if not _emit_raw_chunk(chunk, chunk_start_offset + len(chunk)):
                            return False
                        chunk_start_offset += len(chunk)
                        chunk = raw_line
                    elif diagnostic:
                        if not _sse_write_json_event(
                            self.wfile,
                            "tail",
                            {
                                "next_since": chunk_start_offset + len(raw_line),
                                "total_bytes": final_total,
                                "ndjson": raw_line.decode("utf-8", errors="replace"),
                            },
                            max_bytes=SSE_TRANSCRIPT_MAX_EVENT_BYTES,
                        ):
                            return False
                        chunk_start_offset += len(raw_line)
                        chunk = b""
                    else:
                        chunk = candidate
                if chunk and not _emit_raw_chunk(chunk, new_offset):
                    return False
                last_emitted_offset = new_offset
                last_keepalive = _time.time()
                return True

            # Initial snapshot — emit anything from `since` to current EOF
            # (through the last \n) so the client has a baseline even if
            # no new writes happen for a while.
            if not self._stream_authorization_is_current():
                return
            if not _emit_complete_lines():
                return

            while _time.time() < deadline:
                if not self._stream_authorization_is_current():
                    return
                if transcript_wakes is not None:
                    wake = transcript_wakes.get(timeout=1.0)
                    while wake is not None:
                        wake = transcript_wakes.get(timeout=0)
                else:
                    _time.sleep(POLL_INTERVAL)

                try:
                    size = os.fstat(f.fileno()).st_size
                except OSError:
                    return

                # Rotation/rebind: the path now points at a different JSONL
                # inode than the handle we opened. Tell the client to reset its
                # byte offset, then close so its reconnect re-resolves the path.
                try:
                    current_stat = path.stat()
                    if (current_stat.st_ino, current_stat.st_dev) != (opened_stat.st_ino, opened_stat.st_dev):
                        _emit_reset(current_stat.st_size)
                        return
                except OSError:
                    _emit_reset(0)
                    return

                # Rotation/truncate: shrunk below our position. Disconnect;
                # the client's auto-retry will reconnect and we'll re-resolve.
                if size < last_emitted_offset + len(pending_partial):
                    _emit_reset(size)
                    return

                if size > last_emitted_offset + len(pending_partial):
                    if not _emit_complete_lines():
                        return

                now = _time.time()
                if now - last_keepalive >= KEEPALIVE_INTERVAL:
                    try:
                        self.wfile.write(b"event: keepalive\ndata: {}\n\n")
                        self.wfile.flush()
                    except (BrokenPipeError, ConnectionResetError):
                        return
                    last_keepalive = now

            try:
                self.wfile.write(b"event: done\ndata: {}\n\n")
                self.wfile.flush()
            except (BrokenPipeError, ConnectionResetError):
                pass
        except (BrokenPipeError, ConnectionResetError):
            return
        except OSError as e:
            self.log_message("transcript-stream OSError for %s: %s", session_id, e)
            return
        finally:
            if transcript_wakes is not None:
                transcript_wakes.close()
            if transcript_watch is not None:
                try:
                    transcript_watch.close()
                except Exception:
                    pass
            if f is not None:
                try:
                    f.close()
                except OSError:
                    pass

    # ----- /terminal-stream: live terminal output by byte offset -----
    def _session_live_event_envelope(
        self,
        *,
        event_seq: int,
        event_type: str,
        session_id: str,
        provider: str,
        native_id: str,
        payload: dict,
        truth: dict | None = None,
        source: str = "session-live-events",
        terminal_offset: int | None = None,
        transcript_offset: int | None = None,
        log_generation: int | None = None,
    ) -> dict:
        truth = truth or {}
        runtime = truth.get("runtime") if isinstance(truth.get("runtime"), dict) else {}
        process = truth.get("process") if isinstance(truth.get("process"), dict) else {}
        terminal = truth.get("terminal") if isinstance(truth.get("terminal"), dict) else {}
        v2 = terminal.get("v2") if isinstance(terminal.get("v2"), dict) else {}
        stream = terminal.get("stream") if isinstance(terminal.get("stream"), dict) else {}
        return {
            "schema_version": 1,
            "event_seq": event_seq,
            "event_type": event_type,
            "observed_at": _time.time(),
            "emitted_at": _time.time(),
            "source": source,
            "session_id": session_id,
            "provider": provider,
            "native_id": native_id,
            "broker_id": v2.get("broker_id") or stream.get("broker_id") or process.get("broker_id"),
            "pid": process.get("pid"),
            "tty": process.get("terminal_tty") or v2.get("tty") or stream.get("tty"),
            "terminal_generation": v2.get("generation"),
            "terminal_offset": terminal_offset,
            "transcript_offset": transcript_offset,
            "log_generation": log_generation,
            "runtime_version": RUNTIME_CONTRACT_VERSION,
            "source_revision": runtime.get("source_revision") or runtime.get("app_source_revision"),
            "payload": payload,
        }

    def _session_live_transcript_tail(self, provider: str, native_id: str, raw_session: str, since: int) -> dict | None:
        path = self._resolve_session_transcript_path(
            provider,
            native_id,
            raw_session,
        )
        if path is None:
            return None
        try:
            handle = _session_transcript_handle(path)
        except OSError:
            return None
        with handle:
            try:
                stat = os.fstat(handle.fileno())
            except OSError:
                return None
            size = max(0, int(stat.st_size))
            session_key = _qualified_session_id(provider, native_id)
            ingestor = _ensure_session_log_ingestor()
            log_generation = None
            if ingestor is not None:
                log_generation = ingestor.generation_for_open_source(
                    session_key,
                    provider,
                    native_id,
                    path,
                    (int(stat.st_dev), int(stat.st_ino)),
                    size,
                )
            since = max(0, int(since or 0))
            if since > size:
                return {
                    "next_since": 0,
                    "total_bytes": size,
                    "ndjson": "",
                    "reset": True,
                    "log_generation": log_generation,
                }
            start = _bounded_transcript_stream_start(since=since, size=size)
            if start >= size:
                return None
            # Size the read window so the JSON-escaped ndjson plus the event
            # envelope stays under SSE_TRANSCRIPT_MAX_EVENT_BYTES. Escaping can
            # roughly double the byte count.
            read_cap = max(16 * 1024, SSE_TRANSCRIPT_MAX_EVENT_BYTES // 2 - 8 * 1024)
            try:
                f = handle
                f.seek(start)
                data = f.read(min(size - start, read_cap))
                idx = data.rfind(b"\n")
                if idx < 0 and len(data) >= read_cap:
                    # A single transcript line larger than the read window
                    # (giant tool dump). It can never fit in one SSE event;
                    # without this branch the tail re-read the same window
                    # forever and the live view wedged at "Connecting".
                    # Scan forward to the line end and skip past it.
                    scan_pos = start + len(data)
                    line_end = None
                    while scan_pos < size:
                        f.seek(scan_pos)
                        chunk = f.read(1024 * 1024)
                        if not chunk:
                            break
                        newline_at = chunk.find(b"\n")
                        if newline_at >= 0:
                            line_end = scan_pos + newline_at
                            break
                        scan_pos += len(chunk)
                    if line_end is None:
                        # Oversized line with no terminator yet — still being
                        # appended. Try again on a later pass.
                        return None
                    return {
                        "next_since": line_end + 1,
                        "total_bytes": size,
                        "ndjson": "",
                        "reset": start != since,
                        "log_generation": log_generation,
                        "skipped_oversized_bytes": line_end + 1 - start,
                        # Typed notice: the client renders a truncation card and
                        # recovers the content via GET /transcript with
                        # since=start and max_bytes=bytes. start equals the true
                        # line start on the sequential tail path; on a clamped
                        # re-entry it is the resume point inside the line.
                        "oversized": {
                            "start": start,
                            "end": line_end + 1,
                            "bytes": line_end + 1 - start,
                        },
                    }
            except OSError:
                return None
            if idx < 0:
                return None
            complete = data[:idx + 1]
            if not complete:
                return None
            ndjson = complete.decode("utf-8", errors="replace")
            if provider == "codex":
                ndjson = _normalize_codex_ndjson(complete, native_id, include_event_fallback=False)
            return {
                "next_since": start + len(complete),
                "total_bytes": size,
                "ndjson": ndjson,
                "reset": start != since,
                "log_generation": log_generation,
            }

    def _session_live_terminal_capture_path(self, provider: str, native_id: str, raw_session: str) -> Path | None:
        if provider == "claude":
            session_id = _claude_native_session_id(raw_session)
            if not session_id:
                return None
            tty = self._lookup_terminal_tty(session_id)
            project = self._lookup_pg_project(session_id)
            return _terminal_capture_for_tty(tty, project)
        if provider == "codex":
            registry_native_id = _agent_registry_resolve_native_alias(
                "codex", native_id
            )
            reg = _agent_registry_get("codex", registry_native_id) or {}
            try:
                metadata = json.loads(reg.get("metadata_json") or "{}")
            except Exception:
                metadata = {}
            return _terminal_capture_from_metadata(metadata)
        return None

    def _session_live_terminal_tail(self, raw_session: str, since: int, *, broker_hint=None) -> dict | None:
        provider, native_id = _parse_agent_session_ref(raw_session)
        since = max(0, int(since or 0))
        if broker_hint is not None:
            # ("", None) style sentinel from the caller's cache means a
            # verified absent broker; a tuple is a verified present one.
            broker_found = broker_hint or None
        else:
            try:
                broker_found = self._broker_session_for(raw_session)
            except Exception as e:
                broker_found = None
                self.log_message("session-live terminal broker lookup failed for %s: %s", raw_session, str(e)[:200])
        if broker_found and PTY_BROKER:
            broker_id, _ = broker_found
            try:
                tail = _session_live_broker_raw_tail(broker_id, since)
            except Exception as e:
                self.log_message("session-live broker tail failed for %s: %s", raw_session, str(e)[:200])
                tail = None
            if tail is None:
                return None
            data, next_offset, total_bytes, reset, gap_bytes, feed_at = tail
            if reset:
                return {
                    "next_since": 0,
                    "total_bytes": total_bytes,
                    "text": "",
                    "reset": True,
                    "backend": "pty_broker",
                    "broker_id": broker_id,
                }
            if not data:
                return None
            send_data, payload = _bounded_terminal_stream_chunk(
                data,
                # The chunk resumes after any ring gap, so the cursor base is
                # the requested offset plus the dropped bytes; the gap itself
                # is surfaced on the payload instead of silently skipped.
                last_offset=since + gap_bytes,
                total_bytes=total_bytes,
                clean_text=lambda chunk: chunk.decode("utf-8", errors="replace").replace("\r\n", "\n").replace("\r", "\n"),
            )
            if not send_data:
                return None
            payload["backend"] = "pty_broker"
            payload["broker_id"] = broker_id
            payload["raw_byte_count"] = len(send_data)
            combined_gap = gap_bytes + int(payload.get("gap_bytes") or 0)
            if combined_gap > 0:
                payload["gap_bytes"] = combined_gap
            if feed_at is not None:
                payload["feed_at"] = feed_at
            return payload

        log_path = self._session_live_terminal_capture_path(provider, native_id, raw_session)
        if log_path is None or not _is_terminal_capture_path(log_path) or not log_path.exists():
            return None
        try:
            stat = log_path.stat()
        except OSError:
            return None
        size = max(0, int(stat.st_size))
        if since > size:
            return {
                "next_since": 0,
                "total_bytes": size,
                "text": "",
                "reset": True,
                "backend": "script_capture",
            }
        if since >= size:
            return None
        try:
            with open(log_path, "rb") as f:
                f.seek(since)
                data = f.read(min(size - since, SSE_TERMINAL_CHUNK_BYTES))
        except OSError:
            return None
        if not data:
            return None
        send_data, payload = _bounded_terminal_stream_chunk(
            data,
            last_offset=since,
            total_bytes=size,
            clean_text=lambda chunk: chunk.decode("utf-8", errors="replace")
                .replace("^D\x08\x08", "")
                .replace("\r\n", "\n")
                .replace("\r", "\n"),
        )
        if not send_data:
            return None
        payload["backend"] = "script_capture"
        payload["raw_byte_count"] = len(send_data)
        return payload

    def _handle_managed_session_live_events(
        self,
        q,
        *,
        session_id: str,
        provider: str,
        native_id: str,
    ) -> None:
        try:
            transcript_offset = max(
                0, int(q.get("since_transcript", ["0"])[0])
            )
        except ValueError:
            transcript_offset = 0
        try:
            receipt_seq = max(0, int(q.get("client_event_seq", ["0"])[0]))
        except ValueError:
            receipt_seq = 0
        self.send_response(200)
        self.send_header("Content-Type", "text/event-stream")
        self.send_header("Cache-Control", "no-store")
        self.send_header("Connection", "keep-alive")
        self.send_header("X-Accel-Buffering", "no")
        self.end_headers()
        event_seq = 0
        last_keepalive = _time.time()
        last_truth_hash = ""
        last_receipt_check = 0.0
        deadline = _time.time() + 600.0
        subscription = (
            SESSION_EVENT_HUB.subscribe(f"log:{session_id}")
            if SESSION_EVENT_HUB is not None
            else None
        )

        def emit(event_type: str, payload: dict, *, source: str) -> bool:
            nonlocal event_seq, last_keepalive
            event_seq += 1
            envelope = self._session_live_event_envelope(
                event_seq=event_seq,
                event_type=event_type,
                session_id=session_id,
                provider=provider,
                native_id=native_id,
                payload=payload,
                truth=_managed_session_runtime_truth(session_id),
                source=source,
                terminal_offset=0,
                transcript_offset=transcript_offset,
                log_generation=None,
            )
            ok = _sse_write_json_event(
                self.wfile,
                event_type,
                envelope,
                max_bytes=(
                    SSE_TRANSCRIPT_MAX_EVENT_BYTES
                    if event_type == "transcript_entries"
                    else SSE_MAX_EVENT_BYTES
                ),
            )
            if ok:
                last_keepalive = _time.time()
            return ok

        try:
            if not self._stream_authorization_is_current():
                return
            if not emit("hello", {
                "session_id": session_id,
                "since_terminal": 0,
                "since_transcript": transcript_offset,
                "client_event_seq": receipt_seq,
                "stream": "session-live-events",
                "terminal_backed": False,
            }, source="managed-provider-sessions"):
                return
            while _time.time() < deadline:
                if not self._stream_authorization_is_current():
                    return
                truth = _managed_session_runtime_truth(session_id)
                if truth is None:
                    emit("error", {
                        "reason": "managed_session_missing",
                        "message": "Managed session binding is unavailable.",
                    }, source="managed-provider-sessions")
                    return
                digest = _session_runtime_truth_stream_digest(truth)
                if digest != last_truth_hash:
                    last_truth_hash = digest
                    if not emit(
                        "truth",
                        _session_runtime_truth_stream_payload(truth),
                        source="session-runtime-truth",
                    ):
                        return
                data, next_since, total = _managed_transcript_ndjson(
                    session_id,
                    since=transcript_offset,
                )
                if data:
                    transcript_offset = next_since
                    if not emit("transcript_entries", {
                        "next_since": next_since,
                        "total_bytes": total,
                        "ndjson": data.decode("utf-8", errors="replace"),
                        "offset_unit": "normalized_event_sequence",
                    }, source="managed-provider-events"):
                        return
                    continue
                now = _time.time()
                if now - last_receipt_check >= 2.0:
                    last_receipt_check = now
                    for receipt_event in _session_live_control_receipts_since(
                        session_id,
                        receipt_seq,
                        identity_keys={session_id},
                    ):
                        receipt_seq = max(
                            receipt_seq,
                            int(receipt_event.get("receipt_seq") or 0),
                        )
                        if not emit(
                            "control_receipt",
                            receipt_event,
                            source="control-receipts",
                        ):
                            return
                if subscription is not None:
                    subscription.get(timeout=1.0)
                else:
                    _time.sleep(0.25)
                if _time.time() - last_keepalive >= 20.0:
                    if not _sse_write_json_event(self.wfile, "keepalive", {}):
                        return
                    last_keepalive = _time.time()
            emit("done", {}, source="managed-provider-sessions")
        except (BrokenPipeError, ConnectionResetError):
            return
        finally:
            if subscription is not None:
                subscription.close()

    def _handle_session_live_events(self, q):
        raw_session = q.get("session", [""])[0]
        provider, native_id = _parse_agent_session_ref(raw_session)
        if not native_id:
            self.send_error(400, "session required")
            return
        session_id = _qualified_session_id(provider, native_id)
        managed_store = _ensure_managed_provider_session_store()
        if (
            managed_store is not None
            and managed_store.get(session_id) is not None
        ):
            self._handle_managed_session_live_events(
                q,
                session_id=session_id,
                provider=provider,
                native_id=native_id,
            )
            return
        if provider not in _SUPPORTED_TRANSCRIPT_PROVIDERS:
            _send_unsupported_provider(
                self,
                provider,
                "session_transcript",
                status=422,
            )
            return

        expected_source_revision = self._expected_source_revision_for_request(q)
        try:
            terminal_offset = int(q.get("since_terminal", ["0"])[0])
        except ValueError:
            terminal_offset = 0
        try:
            transcript_offset = int(q.get("since_transcript", ["0"])[0])
        except ValueError:
            transcript_offset = 0
        try:
            receipt_seq = int(q.get("client_event_seq", ["0"])[0])
        except ValueError:
            receipt_seq = 0

        self.send_response(200)
        self.send_header("Content-Type", "text/event-stream")
        self.send_header("Cache-Control", "no-store")
        self.send_header("Connection", "keep-alive")
        self.send_header("X-Accel-Buffering", "no")
        self.end_headers()

        event_seq = 0
        last_truth_hash = ""
        last_truth: dict | None = None
        last_pending_input: dict | None = None
        last_approval: dict | None = None
        last_approval_check = 0.0
        last_transcript_check = 0.0
        last_freshness_at = 0.0
        last_keepalive = _time.time()
        last_truth_error_message = ""
        last_truth_recovery_seq = 0
        terminal_line_buffer = ""
        deadline = _time.time() + 600.0

        # Runtime truth can block for seconds while the native helper probes
        # Terminal.app. Computing it inline starved transcript/terminal tails.
        # The probe runs in a worker shared across every stream on this session;
        # stream on this session (refcounted); the writer loop only ever
        # reads the latest result, so tail latency stays decoupled from
        # probe latency and extra viewers add no probe cost.
        truth_slot, truth_worker_key = _acquire_shared_truth_worker(self, session_id, expected_source_revision)

        def emit(event_type: str, payload: dict, *, source: str = "session-live-events") -> bool:
            nonlocal event_seq, last_keepalive
            event_seq += 1
            envelope = self._session_live_event_envelope(
                event_seq=event_seq,
                event_type=event_type,
                session_id=session_id,
                provider=provider,
                native_id=native_id,
                payload=payload,
                truth=last_truth,
                source=source,
                terminal_offset=terminal_offset,
                transcript_offset=transcript_offset,
                log_generation=(
                    payload.get("log_generation")
                    if event_type == "transcript_entries"
                    else None
                ),
            )
            max_bytes = SSE_TRANSCRIPT_MAX_EVENT_BYTES if event_type == "transcript_entries" else SSE_MAX_EVENT_BYTES
            ok = _sse_write_json_event(self.wfile, event_type, envelope, max_bytes=max_bytes, stats_key=event_type)
            if ok:
                last_keepalive = _time.time()
            return ok

        merged_events = None
        transcript_watch = None
        try:
            if not self._stream_authorization_is_current():
                return
            if not emit("hello", {
                "session_id": session_id,
                "since_terminal": max(0, terminal_offset),
                "since_transcript": max(0, transcript_offset),
                "client_event_seq": max(0, receipt_seq),
                "stream": "session-live-events",
            }):
                return

            # Event-driven scheduling (Phase 1): the loop blocks on the hub
            # instead of sleeping on a cadence. Every emit block below is
            # unchanged; only WHEN it runs changed. Cadence guards remain as
            # degraded fallbacks so behavior fails open to the old timings
            # when a wakeup source is unavailable.
            identity_keys = _session_event_identity_keys(self, session_id)
            canonical_native_id = _agent_registry_resolve_native_alias(provider, native_id)
            canonical_session_id = _qualified_session_id(provider, canonical_native_id)
            identity_keys.add(canonical_session_id)
            transcript_topic = f"transcript:{canonical_session_id}"

            def live_watch_topics(identities: set[str]) -> set[str]:
                topics = {BROKER_GLOBAL_TOPIC}
                for identity in identities:
                    identity_provider, identity_native_id = _parse_agent_session_ref(identity)
                    topics.update({
                        f"terminal:{identity}",
                        f"transcript:{identity}",
                        f"turn:{identity}",
                        f"turn:{identity_provider}:{identity_native_id}",
                        f"approvals:{identity_provider}:{identity_native_id}",
                        f"approvals:{identity_provider}:{identity}",
                    })
                for identity in identities:
                    topics.add(f"receipts:{identity}")
                return topics

            last_terminal_push_at = 0.0
            last_terminal_check = 0.0
            last_receipt_check = 0.0
            last_watch_retry = 0.0
            broker_hint = None
            broker_hint_at = -10.0
            terminal_silent_streak = 0
            if SESSION_EVENT_HUB is not None:
                _ensure_broker_output_listener()
                watch_topics = live_watch_topics(identity_keys)
                merged_events = SESSION_EVENT_HUB.subscribe_many(sorted(watch_topics))
                watcher = _ensure_session_file_watcher()
                if watcher is not None:
                    try:
                        transcript_path = self._resolve_session_transcript_path(
                            provider,
                            native_id,
                            session_id,
                        )
                    except Exception:
                        transcript_path = None
                    if transcript_path is not None:
                        transcript_watch = watcher.watch(transcript_path, transcript_topic)
                        _publish_session_event(transcript_topic, {
                            "type": "transcript_resolved",
                            "path": str(transcript_path),
                        })

            while _time.time() < deadline:
                if not self._stream_authorization_is_current():
                    return
                want_terminal = want_transcript = want_receipts = want_approval = False
                if merged_events is not None:
                    wake = merged_events.get(
                        timeout=_session_live_event_wait_timeout(terminal_silent_streak)
                    )
                    while wake is not None:
                        wake_kind = str(wake.get("type") or "")
                        if wake_kind == "broker_output":
                            want_terminal = True
                            last_terminal_push_at = _time.time()
                        elif wake_kind in ("file_changed", "file_rotated"):
                            want_transcript = True
                        elif wake_kind == "receipt_appended":
                            want_receipts = True
                        elif wake_kind == "approval_changed":
                            want_approval = True
                        elif wake_kind == "session_identity_linked":
                            # Refresh the broker and canonical topic set in
                            # this pass. Waiting for the normal five-second
                            # broker hint refresh leaves a newly linked Claude
                            # viewer attached only to its temporary identity.
                            want_terminal = want_transcript = want_receipts = want_approval = True
                            broker_hint_at = -10.0
                        else:
                            # queue_gap and broker transitions: unknown scope,
                            # so drain every plane once.
                            want_terminal = want_transcript = want_receipts = want_approval = True
                        wake = merged_events.get(timeout=0)
                else:
                    _time.sleep(0.25)
                    want_terminal = want_transcript = want_receipts = want_approval = True
                now = _time.time()

                if merged_events is not None and transcript_watch is None and now - last_watch_retry >= 1.0:
                    # Fresh sessions may not have a transcript file yet.
                    last_watch_retry = now
                    watcher = _ensure_session_file_watcher()
                    if watcher is not None:
                        try:
                            transcript_path = self._resolve_session_transcript_path(
                                provider,
                                native_id,
                                session_id,
                            )
                        except Exception:
                            transcript_path = None
                        if transcript_path is not None:
                            transcript_watch = watcher.watch(transcript_path, transcript_topic)
                            _publish_session_event(transcript_topic, {
                                "type": "transcript_resolved",
                                "path": str(transcript_path),
                            })
                            want_transcript = True

                slot_result = truth_slot.get("result")
                slot_error = truth_slot.get("error")
                if slot_error is not None:
                    reason, message = slot_error
                    if truth_slot.get("fatal"):
                        emit("error", {"reason": reason, "message": message})
                        return
                    if message != last_truth_error_message:
                        last_truth_error_message = message
                        if not emit("error", {"reason": reason, "message": message}):
                            return
                truth_updated = False
                if slot_result is not None:
                    truth, slim_truth, digest = slot_result
                    last_truth = truth
                    recovery_seq = int(truth_slot.get("recovery_seq") or 0)
                    force_recovered_truth = recovery_seq > last_truth_recovery_seq
                    if force_recovered_truth:
                        last_truth_recovery_seq = recovery_seq
                        last_truth_error_message = ""
                    if digest != last_truth_hash or force_recovered_truth:
                        last_truth_hash = digest
                        truth_updated = True
                        if not emit("truth", slim_truth, source="session-runtime-truth"):
                            return
                        for event_type, payload, source in _session_live_truth_events(truth, slim_truth)[1:]:
                            if not emit(event_type, payload, source=source):
                                return

                # Pending input rides the same shared per-session truth probe
                # as the rest of the control basis. Terminal output wakes that
                # worker immediately and its debounce keeps the card inside the
                # one-second product budget. Compare the raw truth whenever a
                # worker result is present, even when the slim truth digest did
                # not change: v2 pending-input fields are intentionally removed
                # from the slim truth payload. Do not ask the broker for another
                # surface snapshot in every attached SSE writer.
                if slot_result is not None and last_truth is not None:
                    current_pending = _session_live_pending_input(last_truth)
                    if current_pending != last_pending_input:
                        if current_pending is not None:
                            if not emit("pending_input", current_pending):
                                return
                        else:
                            if not emit("pending_input_cleared", {
                                "reason": "no_longer_pending",
                                "detection": (last_pending_input or {}).get("detection"),
                            }):
                                return
                        last_pending_input = current_pending

                # SPEC-p3 §2.4: the open permission dialog rides the same
                # stream, so opening the session shows the waiting approval
                # even when the push was dropped. SQLite poll at 1s cadence.
                # approval_changed events arrive from the self-write publish
                # sites, so the cadence is only a safety net against a missed
                # in-process publish, not the delivery mechanism.
                if want_approval or now - last_approval_check >= 5.0:
                    last_approval_check = now
                    try:
                        current_approval = _session_live_pending_approval(provider, native_id)
                    except Exception:
                        current_approval = last_approval
                    if current_approval != last_approval:
                        if current_approval is not None:
                            if not emit("approval_request", current_approval, source="pending-approvals"):
                                return
                        else:
                            if not emit("approval_request_cleared", {
                                "request_nonce": (last_approval or {}).get("request_nonce"),
                            }, source="pending-approvals"):
                                return
                        last_approval = current_approval

                if want_receipts or now - last_receipt_check >= 2.0:
                    last_receipt_check = now
                    try:
                        receipt_events = _session_live_control_receipts_since(
                            session_id,
                            receipt_seq,
                            identity_keys=identity_keys,
                        )
                    except Exception as e:
                        receipt_events = []
                        self.log_message("session-live control receipts failed for %s: %s", session_id, str(e)[:200])
                    for receipt_event in receipt_events:
                        receipt_seq = max(receipt_seq, int(receipt_event.get("receipt_seq") or 0))
                        if not emit("control_receipt", receipt_event, source="control-receipts"):
                            return

                # Pushed sessions drain on their events; sessions without push
                # coverage (script capture, or the broker listener down) fall
                # back to a 0.25 s cadence that relaxes to 1 s while silent,
                # still ahead of any client cadence. The broker lookup is
                # cached per connection: uncached it costs a registry
                # connection per call, which multiplied across silent streams
                # burned a core.
                if now - broker_hint_at >= 5.0:
                    broker_hint_at = now
                    try:
                        broker_hint = self._broker_session_for(session_id) or ""
                    except Exception:
                        broker_hint = ""
                    if SESSION_EVENT_HUB is not None:
                        refreshed_identities = _session_event_identity_keys(
                            self,
                            session_id,
                        )
                        if refreshed_identities != identity_keys:
                            identity_keys = refreshed_identities
                            if merged_events is not None:
                                merged_events.close()
                            merged_events = SESSION_EVENT_HUB.subscribe_many(
                                sorted(live_watch_topics(identity_keys))
                            )
                silent_fallback_interval = 0.25 if terminal_silent_streak < 3 else 1.0
                if want_terminal or (now - last_terminal_push_at >= 0.5 and now - last_terminal_check >= silent_fallback_interval):
                    last_terminal_check = now
                    saw_terminal_data = False
                    for _ in range(8):
                        try:
                            terminal_payload = self._session_live_terminal_tail(session_id, terminal_offset, broker_hint=broker_hint)
                        except Exception as e:
                            terminal_payload = None
                            self.log_message("session-live terminal tail failed for %s: %s", session_id, str(e)[:200])
                        if terminal_payload is None:
                            break
                        saw_terminal_data = True
                        if terminal_payload.get("reset"):
                            terminal_offset = 0
                        else:
                            terminal_offset = int(terminal_payload.get("next_since") or terminal_offset)
                        if not emit("terminal_chunk", terminal_payload, source=str(terminal_payload.get("backend") or "terminal")):
                            return
                        terminal_line_buffer, display_lines = _terminal_display_lines(
                            terminal_line_buffer,
                            terminal_payload,
                        )
                        for line in display_lines:
                            if not emit("terminal_line", {
                                "text": line,
                                "line_id": f"{session_id}:{terminal_offset}:{event_seq}",
                                "terminal_offset": terminal_offset,
                            }, source=str(terminal_payload.get("backend") or "terminal")):
                                return
                        if terminal_payload.get("reset"):
                            break
                    terminal_silent_streak = 0 if saw_terminal_data else terminal_silent_streak + 1

                if want_transcript or now - last_transcript_check >= 1.0:
                    transcript_payload = self._session_live_transcript_tail(provider, native_id, session_id, transcript_offset)
                    last_transcript_check = now
                    if transcript_payload is not None:
                        # ALWAYS advance to next_since — including on reset.
                        # `reset` tells the CLIENT to clear its accumulated
                        # entries; the tail's next_since is the correct server
                        # continuation in every reset case (bounded first-pass
                        # clamp, oversized-line skip, shrunk file → 0).
                        # Zeroing the offset here made the loop re-read the
                        # same tail window forever — and when that window
                        # began inside an oversized line, the skip pass
                        # repeated with empty ndjson and the phone never
                        # received any transcript content.
                        transcript_offset = int(transcript_payload.get("next_since") or 0)
                        if not emit("transcript_entries", transcript_payload, source="transcript"):
                            return

                if now - last_freshness_at >= 1.0:
                    truth_checked_at = None
                    if isinstance(last_truth, dict):
                        truth_checked_at = last_truth.get("checked_at")
                    transcript_state = None
                    if isinstance(last_truth, dict) and isinstance(last_truth.get("transcript"), dict):
                        transcript_state = last_truth["transcript"].get("state")
                    if not emit("freshness", {
                        "terminal_offset": terminal_offset,
                        "transcript_offset": transcript_offset,
                        "receipt_seq": receipt_seq,
                        "truth_age_seconds": max(0.0, now - float(truth_checked_at or now)),
                        "transcript_state": transcript_state,
                    }):
                        return
                    last_freshness_at = now

                if now - last_keepalive >= 20.0:
                    if not emit("keepalive", {}):
                        return

            emit("done", {})
        except (BrokenPipeError, ConnectionResetError):
            return
        except Exception as e:
            try:
                _sse_write_json_event(
                    self.wfile,
                    "error",
                    {"reason": "session_live_events_unavailable", "message": str(e)[:200]},
                    max_bytes=SSE_MAX_EVENT_BYTES,
                )
            except Exception:
                pass
        finally:
            _release_shared_truth_worker(truth_worker_key)
            try:
                if merged_events is not None:
                    merged_events.close()
            except Exception:
                pass
            try:
                if transcript_watch is not None:
                    transcript_watch.close()
            except Exception:
                pass

    # ----- Contract v2: session event log endpoints -------------------------

    def _handle_managed_session_events_v2(
        self, q, session_key: str
    ) -> None:
        try:
            since_seq = max(0, int(q.get("since_seq", ["0"])[0]))
        except ValueError:
            self.send_error(400, "since_seq must be int")
            return
        try:
            client_generation = max(
                0, int(q.get("generation", ["0"])[0])
            )
        except ValueError:
            self.send_error(400, "generation must be int")
            return
        store = _ensure_managed_provider_session_store()
        row = store.get(session_key) if store is not None else None
        if row is None:
            self.send_error(404, "managed session not found")
            return
        server_generation = int(row["capability_generation"])
        if q.get("once", ["0"])[0] in {"1", "true"}:
            try:
                limit = max(
                    1,
                    min(
                        SESSION_EVENTS_V2_PAGE_MAX_ROWS,
                        int(q.get("limit", ["200"])[0]),
                    ),
                )
            except ValueError:
                self.send_error(400, "limit must be int")
                return
            page = _managed_session_events_v2_page(
                session_key,
                since_seq=since_seq,
                limit=limit,
            )
            server_generation = int(page["generation"])
            if client_generation and client_generation != server_generation:
                self._send_json({
                    "ok": False,
                    "error": {
                        "code": "log_generation_mismatch",
                        "message": (
                            "The managed provider binding changed. "
                            "Restart history from sequence zero."
                        ),
                    },
                    "generation": server_generation,
                    "client_generation": client_generation,
                    "last_seq": page["last_seq"],
                    "reset_required": True,
                }, status=409)
                return
            self._send_json(page)
            return

        self.send_response(200)
        self.send_header("Content-Type", "text/event-stream")
        self.send_header("Cache-Control", "no-store")
        self.send_header("Connection", "keep-alive")
        self.send_header("X-Accel-Buffering", "no")
        self.end_headers()
        cursor = since_seq
        last_keepalive = _time.time()
        deadline = _time.time() + 600.0
        subscription = (
            SESSION_EVENT_HUB.subscribe(f"log:{session_key}")
            if SESSION_EVENT_HUB is not None
            else None
        )
        try:
            page = _managed_session_events_v2_page(
                session_key, since_seq=cursor, limit=1
            )
            server_generation = int(page["generation"])
            if not _sse_write_json_event(self.wfile, "hello", {
                "schema_versions": [SESSION_EVENTS_V2_SCHEMA_VERSION],
                "session_key": session_key,
                "since_seq": cursor,
                "last_seq": page["last_seq"],
                "generation": server_generation,
                "client_generation": client_generation,
                "stream": "session-events-v2",
                "source": "managed_provider_events",
            }, stats_key="v2_hello"):
                return
            if (
                client_generation != server_generation
                or cursor > page["last_seq"]
            ):
                if not _sse_write_json_event(self.wfile, "log_reset", {
                    "reason": (
                        "generation_mismatch"
                        if client_generation != server_generation
                        else "cursor_ahead"
                    ),
                    "generation": server_generation,
                    "client_generation": client_generation,
                    "requested_since_seq": cursor,
                    "last_seq": page["last_seq"],
                    "replay_since_seq": 0,
                }, stats_key="v2_log_reset"):
                    return
                cursor = 0
            cursor, backlog_gap = _bounded_session_event_cursor(
                cursor, page["last_seq"]
            )
            if backlog_gap is not None:
                if not _sse_write_json_event(self.wfile, "backlog_gap", {
                    **backlog_gap,
                    "generation": server_generation,
                }, stats_key="v2_backlog_gap"):
                    return
            while _time.time() < deadline:
                if not self._stream_authorization_is_current():
                    return
                page = _managed_session_events_v2_page(
                    session_key,
                    since_seq=cursor,
                    limit=SESSION_EVENTS_V2_BACKLOG_LIMIT,
                )
                page_generation = int(page["generation"])
                if page_generation != server_generation:
                    if not _sse_write_json_event(self.wfile, "log_reset", {
                        "reason": "generation_mismatch",
                        "generation": page_generation,
                        "client_generation": server_generation,
                        "requested_since_seq": cursor,
                        "last_seq": page["last_seq"],
                        "replay_since_seq": 0,
                    }, stats_key="v2_log_reset"):
                        return
                    server_generation = page_generation
                    cursor = 0
                    continue
                for event in page["events"]:
                    if not _sse_write_json_event(
                        self.wfile,
                        "session_event",
                        event,
                        max_bytes=SSE_TRANSCRIPT_MAX_EVENT_BYTES,
                        stats_key="v2_session_event",
                    ):
                        return
                    cursor = max(cursor, int(event.get("seq") or 0))
                    last_keepalive = _time.time()
                if page["events"]:
                    continue
                if subscription is not None:
                    subscription.get(timeout=1.0)
                else:
                    _time.sleep(0.25)
                if _time.time() - last_keepalive >= 20.0:
                    if not _sse_write_json_event(
                        self.wfile,
                        "keepalive",
                        {},
                        stats_key="v2_keepalive",
                    ):
                        return
                    last_keepalive = _time.time()
            _sse_write_json_event(self.wfile, "done", {})
        except (BrokenPipeError, ConnectionResetError):
            return
        finally:
            if subscription is not None:
                subscription.close()

    def _v2_session_key_and_ensure(self, raw_session: str) -> tuple[str, str, str] | None:
        provider, native_id = _parse_agent_session_ref(raw_session)
        if not native_id:
            return None
        if provider not in _SUPPORTED_TRANSCRIPT_PROVIDERS:
            raise _UnsupportedTranscriptProviderError(provider)
        session_key = _qualified_session_id(provider, native_id)
        ingestor = _ensure_session_log_ingestor()
        if ingestor is not None and not _session_transcript_delete_is_pending_or_done(provider, native_id):
            try:
                transcript_path = self._resolve_session_transcript_path(
                    provider,
                    native_id,
                    raw_session,
                )
            except Exception:
                transcript_path = None
            if transcript_path is not None:
                ingestor.ensure(session_key, provider, native_id, transcript_path)
        return provider, native_id, session_key

    def _handle_session_events_v2(self, q):
        raw_session = q.get("session", [""])[0]
        provider, native_id = _parse_agent_session_ref(raw_session)
        managed_session_key = (
            _qualified_session_id(provider, native_id) if native_id else ""
        )
        managed_store = _ensure_managed_provider_session_store()
        if (
            managed_store is not None
            and managed_session_key
            and managed_store.get(managed_session_key) is not None
        ):
            self._handle_managed_session_events_v2(q, managed_session_key)
            return
        try:
            resolved = self._v2_session_key_and_ensure(raw_session)
        except _UnsupportedTranscriptProviderError as error:
            _send_unsupported_provider(
                self,
                error.provider,
                error.capability,
                status=422,
            )
            return
        if resolved is None:
            self.send_error(400, "session required")
            return
        provider, native_id, session_key = resolved
        log = _ensure_session_event_log()
        if log is None or SESSION_EVENT_HUB is None:
            self.send_error(503, "session event log unavailable")
            return
        try:
            since_seq = int(q.get("since_seq", ["0"])[0])
        except ValueError:
            self.send_error(400, "since_seq must be int")
            return
        try:
            client_generation = max(0, int(q.get("generation", ["0"])[0]))
        except ValueError:
            self.send_error(400, "generation must be int")
            return
        server_generation = log.get_generation(session_key)
        last_seq_now = log.last_seq(session_key)

        if q.get("once", ["0"])[0] in {"1", "true"}:
            # History paging: one JSON page, no stream. The client walks
            # older history upward to seq 0 with repeated pages.
            try:
                limit = max(1, min(SESSION_EVENTS_V2_PAGE_MAX_ROWS,
                                   int(q.get("limit", ["200"])[0])))
            except ValueError:
                self.send_error(400, "limit must be int")
                return
            page_generation, rows, page_last_seq, source_bytes, source_limited = (
                log.read_history_page_bounded(
                    session_key,
                    since_seq=max(0, since_seq),
                    limit=limit,
                    source_byte_limit=SESSION_EVENTS_V2_SOURCE_READ_MAX_BYTES,
                )
            )
            if client_generation and client_generation != page_generation:
                self._send_json({
                    "ok": False,
                    "error": {
                        "code": "log_generation_mismatch",
                        "message": "The session log changed. Restart history from sequence zero.",
                    },
                    "generation": page_generation,
                    "client_generation": client_generation,
                    "last_seq": page_last_seq,
                    "reset_required": True,
                }, status=409)
                return
            wire_rows = [_session_event_v2_wire_row(session_key, row) for row in rows]
            page_limited_by_bytes = False
            if wire_rows:
                # Keep the suffix nearest the rows the phone already has. If
                # the byte cap removed the prefix, the next upward page starts
                # immediately before this page instead of leaving a hole.
                selected = []
                selected_bytes = 2
                row_budget = max(1, SESSION_EVENTS_V2_PAGE_MAX_BYTES - 2048)
                for wire_row in reversed(wire_rows):
                    row_bytes = len(json.dumps(
                        wire_row, separators=(",", ":")
                    ).encode("utf-8"))
                    addition = row_bytes + (1 if selected else 0)
                    if selected and selected_bytes + addition > row_budget:
                        page_limited_by_bytes = True
                        break
                    selected.append(wire_row)
                    selected_bytes += addition
                wire_rows = list(reversed(selected))

            response_payload = {
                "schema_version": SESSION_EVENTS_V2_SCHEMA_VERSION,
                "session_key": session_key,
                "events": wire_rows,
                "last_seq": page_last_seq,
                "generation": page_generation,
                "first_seq": wire_rows[0]["seq"] if wire_rows else None,
                "has_more_before": bool(wire_rows and wire_rows[0]["seq"] > 1),
                "page_limited_by_bytes": page_limited_by_bytes,
                "page_limited_by_source_bytes": source_limited,
                "source_bytes": source_bytes,
            }
            body = json.dumps(response_payload, separators=(",", ":")).encode("utf-8")
            while len(body) > SESSION_EVENTS_V2_PAGE_MAX_BYTES and len(wire_rows) > 1:
                page_limited_by_bytes = True
                wire_rows.pop(0)
                response_payload["events"] = wire_rows
                response_payload["first_seq"] = wire_rows[0]["seq"]
                response_payload["has_more_before"] = wire_rows[0]["seq"] > 1
                response_payload["page_limited_by_bytes"] = True
                body = json.dumps(response_payload, separators=(",", ":")).encode("utf-8")
            self.send_response(200)
            self.send_header("Content-Type", "application/json")
            self.send_header("Content-Length", str(len(body)))
            self.end_headers()
            self.wfile.write(body)
            return

        self.send_response(200)
        self.send_header("Content-Type", "text/event-stream")
        self.send_header("Cache-Control", "no-store")
        self.send_header("Connection", "keep-alive")
        self.send_header("X-Accel-Buffering", "no")
        self.end_headers()

        deadline = _time.time() + 600.0
        last_keepalive = _time.time()
        last_ingest_resolve_at = 0.0
        cursor = max(0, since_seq)
        subscription = SESSION_EVENT_HUB.subscribe(f"log:{session_key}")

        def emit_ingest_state(event: dict) -> bool:
            nonlocal last_keepalive
            event_type = str(event.get("type") or "")
            if event_type == "log_ingest_error":
                payload = {
                    "code": str(event.get("code") or "transcript_ingest_failed"),
                    "message": str(event.get("message") or "Transcript ingestion failed."),
                    "error_type": event.get("error_type"),
                    "retryable": event.get("retryable") is not False,
                    "session_key": session_key,
                    "generation": event.get("generation"),
                }
                ok = _sse_write_json_event(
                    self.wfile, "error", payload, stats_key="v2_ingest_error"
                )
            elif event_type == "log_ingest_recovered":
                ok = _sse_write_json_event(self.wfile, "ingest_recovered", {
                    "code": str(event.get("code") or "transcript_ingest_recovered"),
                    "session_key": session_key,
                    "generation": event.get("generation"),
                }, stats_key="v2_ingest_recovered")
            else:
                return True
            if ok:
                last_keepalive = _time.time()
            return ok

        try:
            if not _sse_write_json_event(self.wfile, "hello", {
                "schema_versions": [SESSION_EVENTS_V2_SCHEMA_VERSION],
                "session_key": session_key,
                "since_seq": cursor,
                "last_seq": last_seq_now,
                "generation": server_generation,
                "client_generation": client_generation,
                "stream": "session-events-v2",
            }, stats_key="v2_hello"):
                return
            active_ingestor = _ensure_session_log_ingestor()
            current_ingest_error = (
                active_ingestor.current_error(session_key)
                if active_ingestor is not None else None
            )
            if current_ingest_error is not None and not emit_ingest_state(current_ingest_error):
                return
            reset_reason = None
            if client_generation != server_generation:
                reset_reason = "generation_mismatch"
            elif cursor > last_seq_now:
                reset_reason = "cursor_ahead"
            if reset_reason is not None:
                if not _sse_write_json_event(self.wfile, "log_reset", {
                    "reason": reset_reason,
                    "generation": server_generation,
                    "client_generation": client_generation,
                    "requested_since_seq": cursor,
                    "last_seq": last_seq_now,
                    "replay_since_seq": 0,
                }, stats_key="v2_log_reset"):
                    return
                cursor = 0
            cursor, backlog_gap = _bounded_session_event_cursor(cursor, last_seq_now)
            if backlog_gap is not None:
                # Bounded cold replay, announced instead of silently clipped.
                # The skipped range pages through once=1.
                if not _sse_write_json_event(self.wfile, "backlog_gap", {
                    **backlog_gap,
                    "generation": server_generation,
                }, stats_key="v2_backlog_gap"):
                    return
            while _time.time() < deadline:
                if not self._stream_authorization_is_current():
                    return
                if getattr(self.wfile, "closed", False):
                    return
                now = _time.time()
                if now - last_ingest_resolve_at >= 0.5:
                    # A fresh terminal may create its transcript after this
                    # stream opens. /resume and corrected sibling resolution
                    # can also move the same session to a different JSONL.
                    # Re-resolve while connected so the ingestor can bind or
                    # reset without making the phone reconnect first.
                    last_ingest_resolve_at = now
                    try:
                        self._v2_session_key_and_ensure(raw_session)
                    except Exception:
                        pass
                current_generation, rows, current_last_seq, _source_bytes, _source_limited = (
                    log.read_with_generation_bounded(
                        session_key,
                        since_seq=cursor,
                        limit=200,
                        source_byte_limit=SESSION_EVENTS_V2_SOURCE_READ_MAX_BYTES,
                    )
                )
                if current_generation != server_generation:
                    previous_generation = server_generation
                    server_generation = current_generation
                    last_seq_now = current_last_seq
                    if not _sse_write_json_event(self.wfile, "log_reset", {
                        "reason": "generation_changed",
                        "generation": server_generation,
                        "client_generation": previous_generation,
                        "requested_since_seq": cursor,
                        "last_seq": last_seq_now,
                        "replay_since_seq": 0,
                    }, stats_key="v2_log_reset"):
                        return
                    cursor = 0
                    continue
                if cursor > current_last_seq:
                    if not _sse_write_json_event(self.wfile, "log_reset", {
                        "reason": "cursor_ahead",
                        "generation": current_generation,
                        "client_generation": server_generation,
                        "requested_since_seq": cursor,
                        "last_seq": current_last_seq,
                        "replay_since_seq": 0,
                    }, stats_key="v2_log_reset"):
                        return
                    cursor = 0
                    continue
                bounded_cursor, backlog_gap = _bounded_session_event_cursor(
                    cursor, current_last_seq
                )
                if backlog_gap is not None:
                    if not _sse_write_json_event(self.wfile, "backlog_gap", {
                        **backlog_gap,
                        "generation": current_generation,
                    }, stats_key="v2_backlog_gap"):
                        return
                    cursor = bounded_cursor
                    continue
                for row in rows:
                    cursor = row["seq"]
                    if not _sse_write_json_event(
                        self.wfile, "session_event",
                        _session_event_v2_wire_row(session_key, row),
                        max_bytes=SSE_TRANSCRIPT_MAX_EVENT_BYTES,
                        stats_key="v2_session_event",
                    ):
                        return
                    last_keepalive = _time.time()
                if rows:
                    continue
                wake = subscription.get(timeout=0.5)
                while wake is not None:
                    if not emit_ingest_state(wake):
                        return
                    wake = subscription.get(timeout=0)
                if _time.time() - last_keepalive >= 20.0:
                    if not _sse_write_json_event(self.wfile, "keepalive", {}, stats_key="v2_keepalive"):
                        return
                    last_keepalive = _time.time()
            _sse_write_json_event(self.wfile, "done", {})
        except (BrokenPipeError, ConnectionResetError):
            return
        finally:
            subscription.close()

    def _handle_session_events_v2_content(self, q):
        """The full untruncated payload for one event, as JSON. The stream
        caps content and text fields inline; this serves the whole value so
        the phone never re-parses provider formats to recover it."""
        raw_session = q.get("session", [""])[0]
        managed_provider, managed_native_id = _parse_agent_session_ref(
            raw_session
        )
        managed_session_key = (
            _qualified_session_id(managed_provider, managed_native_id)
            if managed_native_id
            else ""
        )
        managed_store = _ensure_managed_provider_session_store()
        managed_row = (
            managed_store.get(managed_session_key)
            if managed_store is not None and managed_session_key
            else None
        )
        if managed_row is not None:
            try:
                seq = int(q.get("seq", ["0"])[0])
                client_generation = max(
                    0, int(q.get("generation", ["0"])[0])
                )
            except ValueError:
                self.send_error(400, "seq and generation must be ints")
                return
            server_generation = int(managed_row["capability_generation"])
            if client_generation != server_generation:
                self._send_json({
                    "ok": False,
                    "error": {
                        "code": "log_generation_mismatch",
                        "message": (
                            "The managed provider binding changed. "
                            "Refresh before loading full content."
                        ),
                    },
                    "generation": server_generation,
                    "client_generation": client_generation,
                    "reset_required": True,
                }, status=409)
                return
            page = _managed_session_events_v2_page(
                managed_session_key,
                since_seq=max(0, seq - 1),
                limit=1,
            )
            if not page["events"] or page["events"][0]["seq"] != seq:
                self.send_error(404, f"no event at seq={seq}")
                return
            event = page["events"][0]
            self._send_json({
                "schema_version": SESSION_EVENTS_V2_SCHEMA_VERSION,
                "session_key": managed_session_key,
                "seq": seq,
                "kind": event["kind"],
                "payload": event["payload"],
                "generation": server_generation,
            })
            return
        try:
            resolved = self._v2_session_key_and_ensure(raw_session)
        except _UnsupportedTranscriptProviderError as error:
            _send_unsupported_provider(
                self,
                error.provider,
                error.capability,
                status=422,
            )
            return
        if resolved is None:
            self.send_error(400, "session required")
            return
        _provider, _native_id, session_key = resolved
        log = _ensure_session_event_log()
        if log is None:
            self.send_error(503, "session event log unavailable")
            return
        try:
            seq = int(q.get("seq", ["0"])[0])
        except ValueError:
            self.send_error(400, "seq must be int")
            return
        try:
            client_generation = max(0, int(q.get("generation", ["0"])[0]))
        except ValueError:
            self.send_error(400, "generation must be int")
            return
        server_generation, rows = log.read_at_generation(
            session_key, client_generation, since_seq=seq - 1, limit=1
        )
        if client_generation != server_generation:
            self._send_json({
                "ok": False,
                "error": {
                    "code": "log_generation_mismatch",
                    "message": "The session log changed. Refresh before loading full content.",
                },
                "generation": server_generation,
                "client_generation": client_generation,
                "reset_required": True,
            }, status=409)
            return
        if not rows or rows[0]["seq"] != seq:
            self.send_error(404, f"no event at seq={seq}")
            return
        body = json.dumps({
            "schema_version": SESSION_EVENTS_V2_SCHEMA_VERSION,
            "session_key": session_key,
            "seq": seq,
            "kind": rows[0]["kind"],
            "payload": rows[0]["payload"],
            "generation": server_generation,
        }, separators=(",", ":")).encode("utf-8")
        self.send_response(200)
        self.send_header("Content-Type", "application/json")
        self.send_header("Content-Length", str(len(body)))
        self.end_headers()
        self.wfile.write(body)

    def _handle_session_events_v2_raw(self, q):
        raw_session = q.get("session", [""])[0]
        managed_provider, managed_native_id = _parse_agent_session_ref(
            raw_session
        )
        managed_session_key = (
            _qualified_session_id(managed_provider, managed_native_id)
            if managed_native_id
            else ""
        )
        managed_store = _ensure_managed_provider_session_store()
        if (
            managed_store is not None
            and managed_session_key
            and managed_store.get(managed_session_key) is not None
        ):
            self._send_json({
                "ok": False,
                "error": {
                    "code": "raw_provider_event_unavailable",
                    "message": (
                        "Managed sessions expose only normalized, redacted "
                        "provider events."
                    ),
                },
            }, status=404)
            return
        try:
            resolved = self._v2_session_key_and_ensure(raw_session)
        except _UnsupportedTranscriptProviderError as error:
            _send_unsupported_provider(
                self,
                error.provider,
                error.capability,
                status=422,
            )
            return
        if resolved is None:
            self.send_error(400, "session required")
            return
        _provider, _native_id, session_key = resolved
        log = _ensure_session_event_log()
        if log is None:
            self.send_error(503, "session event log unavailable")
            return
        try:
            seq = int(q.get("seq", ["0"])[0])
        except ValueError:
            self.send_error(400, "seq must be int")
            return
        try:
            client_generation = max(0, int(q.get("generation", ["0"])[0]))
        except ValueError:
            self.send_error(400, "generation must be int")
            return
        response_started = False
        try:
            with log.open_raw_at_generation(
                session_key, client_generation, seq
            ) as (server_generation, stream, byte_count, checksum):
                if client_generation != server_generation:
                    self._send_json({
                        "ok": False,
                        "error": {"code": "log_generation_mismatch"},
                        "generation": server_generation,
                        "client_generation": client_generation,
                        "reset_required": True,
                    }, status=409)
                    return
                if stream is None:
                    self.send_error(404, f"no raw content for seq={seq}")
                    return
                self.send_response(200)
                self.send_header("Content-Type", "application/x-ndjson")
                self.send_header("X-Seq", str(seq))
                self.send_header("X-Generation", str(server_generation))
                if checksum:
                    self.send_header("X-Content-SHA256", checksum)
                self.send_header("Content-Length", str(byte_count))
                self.end_headers()
                response_started = True
                while True:
                    chunk = stream.read(SESSION_EVENTS_V2_RAW_STREAM_CHUNK)
                    if not chunk:
                        break
                    self.wfile.write(chunk)
        except (BrokenPipeError, ConnectionResetError):
            return
        except (OSError, ValueError):
            if not response_started:
                self.send_error(503, "raw content is temporarily unavailable")

    def _handle_device_events(self, q):
        """One connection per device carrying every subscribed session, so a
        phone stops costing two stream slots per open screen. sessions is a
        comma list of session@cursor entries. summaries=1 switches to the
        dashboard-grade summary plane instead: an initial registry snapshot,
        then compact events published at the daemon's own write sites, with
        no per-session subscription cap because it rides one topic."""
        if q.get("summaries", ["0"])[0] in {"1", "true"}:
            self._serve_device_summaries()
            return
        raw_subscriptions = q.get("sessions", [""])[0]
        if not raw_subscriptions:
            self.send_error(400, "sessions required")
            return
        log = _ensure_session_event_log()
        if log is None or SESSION_EVENT_HUB is None:
            self.send_error(503, "session event log unavailable")
            return
        cursors: dict[str, int] = {}
        raw_sessions: dict[str, str] = {}
        generations: dict[str, int] = {}
        for part in raw_subscriptions.split(",")[:16]:
            part = part.strip()
            if not part:
                continue
            if "@" in part:
                raw_session, _, raw_cursor = part.rpartition("@")
                try:
                    cursor = int(raw_cursor)
                except ValueError:
                    cursor = 0
            else:
                raw_session, cursor = part, 0
            try:
                resolved = self._v2_session_key_and_ensure(raw_session)
            except _UnsupportedTranscriptProviderError as error:
                _send_unsupported_provider(
                    self,
                    error.provider,
                    error.capability,
                    status=422,
                )
                return
            if resolved is None:
                continue
            session_key = resolved[2]
            cursors[session_key] = max(0, cursor)
            raw_sessions[session_key] = raw_session
            generations[session_key] = log.get_generation(session_key)
        if not cursors:
            self.send_error(400, "no resolvable sessions")
            return

        self.send_response(200)
        self.send_header("Content-Type", "text/event-stream")
        self.send_header("Cache-Control", "no-store")
        self.send_header("Connection", "keep-alive")
        self.send_header("X-Accel-Buffering", "no")
        self.end_headers()

        deadline = _time.time() + 600.0
        last_keepalive = _time.time()
        last_ingest_resolve_at = 0.0
        subscription = SESSION_EVENT_HUB.subscribe_many([f"log:{key}" for key in cursors])

        def emit_device_ingest_state(event: dict) -> bool:
            nonlocal last_keepalive
            event_type = str(event.get("type") or "")
            event_session_key = str(event.get("session_key") or "")
            if event_session_key not in cursors:
                return True
            if event_type == "log_ingest_error":
                ok = _sse_write_json_event(self.wfile, "error", {
                    "code": str(event.get("code") or "transcript_ingest_failed"),
                    "message": str(event.get("message") or "Transcript ingestion failed."),
                    "error_type": event.get("error_type"),
                    "retryable": event.get("retryable") is not False,
                    "session_key": event_session_key,
                    "generation": event.get("generation"),
                }, stats_key="v2_ingest_error")
            elif event_type == "log_ingest_recovered":
                ok = _sse_write_json_event(self.wfile, "ingest_recovered", {
                    "code": str(event.get("code") or "transcript_ingest_recovered"),
                    "session_key": event_session_key,
                    "generation": event.get("generation"),
                }, stats_key="v2_ingest_recovered")
            else:
                return True
            if ok:
                last_keepalive = _time.time()
            return ok

        try:
            if not _sse_write_json_event(self.wfile, "hello", {
                "schema_versions": [SESSION_EVENTS_V2_SCHEMA_VERSION],
                "sessions": {key: log.last_seq(key) for key in cursors},
                "cursors": dict(cursors),
                "generations": dict(generations),
                "stream": "device-events",
            }, stats_key="v2_hello"):
                return
            active_ingestor = _ensure_session_log_ingestor()
            if active_ingestor is not None:
                for session_key in cursors:
                    current_error = active_ingestor.current_error(session_key)
                    if current_error is not None and not emit_device_ingest_state(current_error):
                        return
            while _time.time() < deadline:
                if not self._stream_authorization_is_current():
                    return
                if getattr(self.wfile, "closed", False):
                    return
                emitted = False
                now = _time.time()
                if now - last_ingest_resolve_at >= 0.5:
                    last_ingest_resolve_at = now
                    for raw_session in raw_sessions.values():
                        try:
                            self._v2_session_key_and_ensure(raw_session)
                        except Exception:
                            pass
                for session_key in list(cursors):
                    generation, rows, current_last_seq, _source_bytes, _source_limited = (
                        log.read_with_generation_bounded(
                            session_key,
                            since_seq=cursors[session_key],
                            limit=100,
                            source_byte_limit=SESSION_EVENTS_V2_SOURCE_READ_MAX_BYTES,
                        )
                    )
                    if generation != generations[session_key]:
                        previous_generation = generations[session_key]
                        requested_since_seq = cursors[session_key]
                        generations[session_key] = generation
                        cursors[session_key] = 0
                        emitted = True
                        if not _sse_write_json_event(self.wfile, "log_reset", {
                            "reason": "generation_changed",
                            "session_key": session_key,
                            "generation": generation,
                            "client_generation": previous_generation,
                            "requested_since_seq": requested_since_seq,
                            "last_seq": current_last_seq,
                            "replay_since_seq": 0,
                        }, stats_key="v2_log_reset"):
                            return
                        last_keepalive = _time.time()
                        continue
                    if cursors[session_key] > current_last_seq:
                        requested_since_seq = cursors[session_key]
                        cursors[session_key] = 0
                        emitted = True
                        if not _sse_write_json_event(self.wfile, "log_reset", {
                            "reason": "cursor_ahead",
                            "session_key": session_key,
                            "generation": generation,
                            "client_generation": generations[session_key],
                            "requested_since_seq": requested_since_seq,
                            "last_seq": current_last_seq,
                            "replay_since_seq": 0,
                        }, stats_key="v2_log_reset"):
                            return
                        last_keepalive = _time.time()
                        continue
                    bounded_cursor, backlog_gap = _bounded_session_event_cursor(
                        cursors[session_key], current_last_seq
                    )
                    if backlog_gap is not None:
                        cursors[session_key] = bounded_cursor
                        emitted = True
                        if not _sse_write_json_event(self.wfile, "backlog_gap", {
                            **backlog_gap,
                            "session_key": session_key,
                            "generation": generation,
                        }, stats_key="v2_backlog_gap"):
                            return
                        last_keepalive = _time.time()
                        continue
                    for row in rows:
                        cursors[session_key] = row["seq"]
                        emitted = True
                        if not _sse_write_json_event(
                            self.wfile, "session_event",
                            _session_event_v2_wire_row(session_key, row),
                            max_bytes=SSE_TRANSCRIPT_MAX_EVENT_BYTES,
                            stats_key="v2_session_event",
                        ):
                            return
                        last_keepalive = _time.time()
                if emitted:
                    continue
                wake = subscription.get(timeout=0.5)
                while wake is not None:
                    if not emit_device_ingest_state(wake):
                        return
                    wake = subscription.get(timeout=0)
                if _time.time() - last_keepalive >= 20.0:
                    if not _sse_write_json_event(self.wfile, "keepalive", {}, stats_key="v2_keepalive"):
                        return
                    last_keepalive = _time.time()
            _sse_write_json_event(self.wfile, "done", {})
        except (BrokenPipeError, ConnectionResetError):
            return
        finally:
            subscription.close()

    def _serve_device_summaries(self):
        if SESSION_EVENT_HUB is None:
            self.send_error(503, "session event hub unavailable")
            return
        self.send_response(200)
        self.send_header("Content-Type", "text/event-stream")
        self.send_header("Cache-Control", "no-store")
        self.send_header("Connection", "keep-alive")
        self.send_header("X-Accel-Buffering", "no")
        self.end_headers()

        deadline = _time.time() + 600.0
        last_keepalive = _time.time()
        subscription = SESSION_EVENT_HUB.subscribe(SESSION_SUMMARIES_TOPIC, max_queue=1024)
        try:
            try:
                rows = _agent_registry_live() or []
            except Exception:
                rows = []
            snapshot_sessions = [{
                "provider": str(row.get("provider") or ""),
                "native_id": str(row.get("native_id") or ""),
                "project": str(row.get("project") or ""),
                "state": str(row.get("state") or ""),
                "working_on": str(row.get("working_on") or ""),
                "heartbeat_at": float(row.get("last_heartbeat") or 0.0),
            } for row in rows]
            if not _sse_write_json_event(self.wfile, "summary_snapshot", {
                "schema_version": SESSION_EVENTS_V2_SCHEMA_VERSION,
                "sessions": snapshot_sessions,
                "emitted_at": _time.time(),
            }, stats_key="summary_snapshot"):
                return
            while _time.time() < deadline:
                if not self._stream_authorization_is_current():
                    return
                if getattr(self.wfile, "closed", False):
                    return
                wake = subscription.get(timeout=1.0)
                while wake is not None:
                    event = dict(wake)
                    event["emitted_at"] = _time.time()
                    if not _sse_write_json_event(self.wfile, "summary", event, stats_key="summary"):
                        return
                    last_keepalive = _time.time()
                    wake = subscription.get(timeout=0)
                if _time.time() - last_keepalive >= 20.0:
                    if not _sse_write_json_event(self.wfile, "keepalive", {}):
                        return
                    last_keepalive = _time.time()
            _sse_write_json_event(self.wfile, "done", {})
        except (BrokenPipeError, ConnectionResetError):
            return
        finally:
            subscription.close()

    def _resolve_session_transcript_path(
        self,
        provider: str,
        native_id: str,
        raw_session: str,
    ) -> Path | None:
        if provider == "codex":
            return _resolve_codex_transcript(native_id)
        if provider == "claude":
            return self._resolve_transcript(raw_session)
        if provider == "omp":
            reg = _agent_registry_get("omp", native_id) or {}
            project = str(reg.get("project") or "")
            if not project or _omp_saved_sessions is None:
                return None
            matches = [
                record
                for record in _omp_saved_sessions(project=project, limit=200)
                if str(record.session_id) == native_id
            ]
            if len(matches) != 1:
                return None
            return Path(matches[0].session_path).resolve(strict=True)
        raise _UnsupportedTranscriptProviderError(provider)

    def _transcript_truth_for_session(
        self,
        provider: str,
        native_id: str,
        raw_session: str,
        *,
        resolved_path: Path | None = None,
        path_is_resolved: bool = False,
    ) -> dict:
        if provider not in _SUPPORTED_TRANSCRIPT_PROVIDERS:
            return {
                "state": "unsupported",
                "http_status": 422,
                "reason": "unsupported_provider",
                "provider": provider,
                "capability": "session_transcript",
                "durable": False,
                "searchable": False,
                "latest_offset": None,
                "path": None,
                "user_message": (
                    f"Provider {provider} does not support deep transcript ingestion."
                ),
            }
        path = (
            resolved_path
            if path_is_resolved
            else self._resolve_session_transcript_path(provider, native_id, raw_session)
        )
        latest_offset = None
        if path is not None:
            try:
                with _open_session_transcript_file(path) as handle:
                    latest_offset = os.fstat(handle.fileno()).st_size
            except OSError:
                path = None
        if path is None:
            return {
                "state": "missing",
                "http_status": 404,
                "reason": "no_transcript_resolvable",
                "durable": False,
                "searchable": False,
                "latest_offset": None,
                "path": None,
                "user_message": "Live terminal only - not in transcript",
            }
        return {
            "state": "live",
            "http_status": 200,
            "reason": None,
            "durable": True,
            "searchable": True,
            "latest_offset": latest_offset,
            "path": str(path),
            "user_message": None,
        }

    @staticmethod
    def _unknown_registry_truth() -> dict:
        return {
            "state": "unknown",
            "readable_state": "stale",
            "control_state": "unavailable",
            "working_on": None,
            "source_freshness": "unknown",
        }

    def _target_registry_row_for_session(
        self,
        provider: str,
        native_id: str,
        *,
        transcript_path: Path | None = None,
        transcript_path_is_resolved: bool = False,
    ) -> tuple[dict | None, Path | None]:
        """Resolve one session without invoking the fleet-wide collector.

        The live viewer runs this path for every open session. A global
        provider scan here multiplies transcript discovery and process probes
        by the number of viewed sessions. Keep the normal registry fast path,
        then use one provider-specific fallback for records that predate the
        registry.
        """
        row = _agent_registry_get(provider, native_id)
        if row is None and provider == "claude":
            try:
                row = _claude_sessions_backend().session_record(native_id)
            except Exception:
                row = None

        if provider == "codex":
            if not transcript_path_is_resolved:
                transcript_path = _resolve_codex_transcript(native_id)
            if row is None and transcript_path is not None:
                try:
                    stat = transcript_path.stat()
                    meta = _codex_rollout_meta(transcript_path)
                except OSError:
                    stat = None
                    meta = None
                if (
                    stat is not None
                    and meta is not None
                    and meta.get("id") == native_id
                    and stat.st_mtime >= _time.time() - (14 * 24 * 60 * 60)
                ):
                    first_prompt = _codex_first_prompt(transcript_path, native_id, {})
                    row = {
                        "provider": "codex",
                        "native_id": native_id,
                        "project": meta.get("cwd") or "",
                        "working_on": first_prompt,
                        "started_at": int(_iso_to_epoch(meta.get("timestamp")) or stat.st_mtime),
                        "last_heartbeat": int(stat.st_mtime),
                        "closed_at": None,
                        "state": None,
                        "pid": 0,
                        "terminal_tty": "",
                        "source_freshness": "transcript_live",
                        "virtual_transcript_record": True,
                    }

        if row is None:
            return None, transcript_path
        resolved = dict(row)
        resolved.setdefault("provider", provider)
        resolved.setdefault("native_id", native_id)
        resolved.setdefault("closed_at", None)
        return resolved, transcript_path

    def _registry_row_has_verified_control(
        self,
        row: dict,
        *,
        provider: str,
        native_id: str,
    ) -> bool:
        if row.get("closed_at") is not None:
            return False
        try:
            broker_found = self._broker_session_for(
                _qualified_session_id(provider, native_id)
            )
        except Exception:
            broker_found = None
        if broker_found:
            _public_id, broker_session = broker_found
            if _broker_session_owns_identity(broker_session, provider, native_id):
                return True
        try:
            return _session_has_verified_provider_process(row, provider)
        except Exception:
            return False

    def _registry_truth_projection(
        self,
        row: dict,
        *,
        provider: str,
        native_id: str,
        transcript_path: Path | None,
    ) -> dict:
        now = _time.time()
        original_heartbeat = float(row.get("last_heartbeat") or 0)
        observed_heartbeat = original_heartbeat
        state = row.get("state")
        closed_at = row.get("closed_at")
        has_live_control = self._registry_row_has_verified_control(
            row,
            provider=provider,
            native_id=native_id,
        )

        if provider == "codex" and not closed_at and has_live_control:
            try:
                turn = _codex_turn_state_payload(native_id, apply_boundary=False) or {}
            except Exception:
                turn = {}
            if turn.get("state"):
                state = turn.get("state")
            observed_heartbeat = max(
                observed_heartbeat,
                float(turn.get("last_update") or turn.get("turn_state_updated_at") or 0),
            )
        elif provider == "claude" and not closed_at and has_live_control:
            claude_uuid = str(row.get("claude_uuid") or "")
            try:
                turn = self._turn_state_summary(claude_uuid) if claude_uuid else {}
            except Exception:
                turn = {}
            if turn.get("state"):
                state = turn.get("state")
            observed_heartbeat = max(
                observed_heartbeat,
                float(turn.get("last_update") or turn.get("turn_state_updated_at") or 0),
            )
            if transcript_path is None and row.get("project") and claude_uuid:
                transcript_path = (
                    HOME
                    / ".claude"
                    / "projects"
                    / _encode_project_dir(str(row["project"]))
                    / f"{claude_uuid}.jsonl"
                )

        transcript_available = False
        if transcript_path is not None:
            try:
                stat = transcript_path.stat()
                transcript_available = transcript_path.is_file()
                if has_live_control:
                    observed_heartbeat = max(observed_heartbeat, float(stat.st_mtime))
            except OSError:
                transcript_available = False

        stale_seconds = max(0, int(now - observed_heartbeat)) if observed_heartbeat else 0

        if closed_at:
            readable_state = "closed"
        elif has_live_control or stale_seconds <= 60 * 60:
            readable_state = "live"
        elif stale_seconds <= 60 * 24 * 60:
            readable_state = "stale"
        else:
            readable_state = "offline"

        if has_live_control:
            control_state = "controllable"
        elif readable_state == "closed" or transcript_available:
            control_state = "read_only"
        else:
            control_state = "unavailable"

        source_freshness = str(row.get("source_freshness") or "")
        if closed_at:
            source_freshness = "registry_closed"
        elif observed_heartbeat > original_heartbeat:
            source_freshness = "provider_observed_live"
        elif not source_freshness:
            source_freshness = "registry_live"

        return {
            "state": "terminated" if closed_at else state,
            "readable_state": readable_state,
            "control_state": control_state,
            "working_on": row.get("working_on"),
            "stale_seconds": stale_seconds,
            "source_freshness": source_freshness,
            "last_seen_at": observed_heartbeat or None,
            "project": row.get("project"),
        }

    def _registry_truth_for_session(
        self,
        raw_session: str,
        *,
        transcript_path: Path | None = None,
        transcript_path_is_resolved: bool = False,
    ) -> dict:
        provider, native_id = _parse_agent_session_ref(raw_session)
        registry_native_id = _agent_registry_resolve_native_alias(
            provider, native_id
        )
        try:
            row, transcript_path = self._target_registry_row_for_session(
                provider,
                registry_native_id,
                transcript_path=transcript_path,
                transcript_path_is_resolved=transcript_path_is_resolved,
            )
            visible = _filter_tombstoned_session_rows([row]) if row is not None else []
            if visible:
                return self._registry_truth_projection(
                    visible[0],
                    provider=provider,
                    native_id=registry_native_id,
                    transcript_path=transcript_path,
                )
        except Exception:
            pass
        return self._unknown_registry_truth()

    def _turn_truth_for_session(self, provider: str, native_id: str) -> dict:
        try:
            payload = (
                _managed_turn_state_payload(
                    provider,
                    native_id,
                    apply_boundary=False,
                )
                if provider in {"codex", "omp"}
                else {}
            )
            if not payload and provider == "claude":
                payload = self._turn_state_summary(_lookup_claude_uuid_for_session(native_id))
            return {
                "state": payload.get("state"),
                "source": "turn-state-stream" if payload else "unavailable",
                "observed_at": payload.get("last_update") or payload.get("turn_state_updated_at"),
                "age_seconds": max(0, _time.time() - float(payload.get("last_update") or payload.get("turn_state_updated_at") or _time.time())) if payload else None,
            }
        except Exception:
            return {"state": "unknown", "source": "error"}

    def _terminal_stream_truth_for_session(
        self,
        raw_session: str,
        *,
        transcript_truth: dict | None = None,
    ) -> dict:
        provider, native_id = _parse_agent_session_ref(raw_session)
        try:
            source = _terminal_surface_source(raw_session)
        except Exception as e:
            source = {
                "available": False,
                "source": "unavailable",
                "reason": str(e)[:160] or "terminal_surface_source_failed",
            }
        backend = source.get("source")
        byte_stream_available = bool(source.get("available")) and backend in {"broker_vt", "script_capture"}
        if transcript_truth is None:
            try:
                transcript_truth = self._transcript_truth_for_session(provider, native_id, raw_session)
            except Exception:
                transcript_truth = {"state": "unknown", "path": None}
        transcript_stream_available = bool(
            transcript_truth.get("state") in {"live", "archived", "stale"}
            and transcript_truth.get("path")
        )
        capacity_state = str(source.get("capacity_state") or "unknown")
        return {
            "byte_stream_available": bool(byte_stream_available),
            "surface_stream_available": bool(source.get("available")),
            "transcript_stream_available": transcript_stream_available,
            "source": backend,
            "backend": backend,
            "broker_id": source.get("broker_id"),
            "tty": source.get("tty"),
            "terminal_log": source.get("terminal_log"),
            "can_control": bool(source.get("can_control")),
            "can_send_text": bool(source.get("can_send_text")),
            "can_interrupt": bool(source.get("can_interrupt")),
            "can_terminate": bool(source.get("can_terminate")),
            "control_profile": source.get("control_profile"),
            "last_chunk_at": None,
            "capacity_state": capacity_state,
            "capacity_verified": "capacity_state" in source,
            "fallback_reason": None if source.get("available") else source.get("reason"),
        }

    def _process_truth_for_session(self, provider: str, native_id: str) -> dict:
        if provider == "codex":
            native_id = _agent_registry_resolve_native_alias("codex", native_id)
            reg = _agent_registry_get("codex", native_id)
            if not reg:
                return {
                    "state": "unknown",
                    "source": "agent_registry",
                    "reason": "registry_row_missing",
                }
            pid = int(reg.get("pid") or 0)
            closed_at = reg.get("closed_at")
            process_alive = bool(pid and _process_alive(pid))
            identity_verified = bool(
                pid
                and process_alive
                and _session_signal_target_is_verified(reg, "codex", pid)
            )
            if closed_at:
                state = "closed"
            elif identity_verified:
                state = "alive"
            elif pid and process_alive:
                state = "identity_unverified"
            elif pid:
                state = "stale_pid"
            else:
                state = "registry_only"
            return {
                "state": state,
                "source": "agent_registry",
                "pid": pid or None,
                "process_alive": process_alive if pid else None,
                "identity_verified": identity_verified if pid else None,
                "registry_state": reg.get("state"),
                "last_heartbeat": reg.get("last_heartbeat"),
                "closed_at": closed_at,
                "terminal_tty": reg.get("terminal_tty") or None,
            }
        if provider == "claude":
            native_id = _agent_registry_resolve_native_alias("claude", native_id)
            try:
                record = _agent_registry_get("claude", native_id)
                if record is None:
                    record = _claude_sessions_backend().session_record(native_id)
                record = dict(record or {})
                record.setdefault("provider", "claude")
                pid = int(record.get("pid") or record.get("claude_pid") or 0)
            except Exception as exc:
                return {
                    "state": "unknown",
                    "source": "claude_sessions",
                    "reason": f"pid_lookup_failed:{type(exc).__name__}",
                }
            closed_at = record.get("closed_at")
            process_alive = bool(pid and _process_alive(pid))
            identity_verified = bool(
                pid
                and process_alive
                and _session_signal_target_is_verified(record, "claude", pid)
            )
            if closed_at:
                state = "closed"
            elif identity_verified:
                state = "alive"
            elif pid and process_alive:
                state = "identity_unverified"
            elif pid:
                state = "stale_pid"
            else:
                state = "session_only"
            return {
                "state": state,
                "source": "claude_sessions",
                "pid": pid or None,
                "process_alive": process_alive if pid else None,
                "identity_verified": identity_verified if pid else None,
                "closed_at": closed_at,
                "terminal_tty": record.get("terminal_tty") or None,
            }
        return {
            "state": "unknown",
            "source": "unverified",
            "reason": "process_truth_not_implemented_for_provider",
        }

    def _expected_source_revision_for_request(self, q) -> str | None:
        query_value = (
            q.get("expected_source_revision", [""])[0]
            or q.get("app_source_revision", [""])[0]
        ).strip()
        if query_value:
            return query_value
        try:
            header_value = str(self.headers.get("X-Pairling-App-Source-Revision") or "").strip()
        except Exception:
            header_value = ""
        return header_value or None

    def _session_runtime_truth(self, raw_session: str, expected_source_revision: str | None = None) -> dict:
        provider, native_id = _parse_agent_session_ref(raw_session)
        if not native_id:
            raise ValueError("session required")
        session_id = _qualified_session_id(provider, native_id)
        managed_truth = _managed_session_runtime_truth(
            session_id,
            expected_source_revision=expected_source_revision,
        )
        if managed_truth is not None:
            return managed_truth
        if not _provider_supports(provider, "terminal_surface"):
            raise ValueError(f"unsupported provider: {provider}")

        try:
            transcript_path = self._resolve_session_transcript_path(
                provider,
                native_id,
                session_id,
            )
        except Exception:
            transcript_path = None
        transcript_truth = self._transcript_truth_for_session(
            provider,
            native_id,
            session_id,
            resolved_path=transcript_path,
            path_is_resolved=True,
        )
        v1 = None
        v2 = None
        terminal_probe_error = None
        try:
            pair = self._broker_surface_pair_snapshot(session_id)
        except Exception as e:
            terminal_probe_error = str(e)[:160]
            pair = None
        if isinstance(pair, dict):
            pair_v1 = pair.get("v1")
            pair_v2 = pair.get("v2")
            if isinstance(pair_v1, dict) and isinstance(pair_v2, dict):
                v1 = pair_v1
                v2 = pair_v2
            else:
                terminal_probe_error = "atomic broker surface pair was incomplete"
        if v1 is not None:
            if v2 is None:
                v2 = _terminal_surface_v2_from_text_snapshot(v1, provider=provider, native_id=native_id)
        else:
            try:
                v1 = self._terminal_app_surface_snapshot(
                    session_id,
                    automation_timeout=TERMINAL_APP_SNAPSHOT_TIMEOUT_SECONDS,
                )
                v2 = _terminal_surface_v2_from_text_snapshot(v1, provider=provider, native_id=native_id)
            except Exception as e:
                terminal_probe_error = str(e)[:160]
                v1 = None
                v2 = _terminal_surface_v2_unavailable(
                    provider=provider,
                    native_id=native_id,
                    reason=terminal_probe_error or "terminal surface unavailable",
                )
        registry_truth = self._registry_truth_for_session(
            session_id,
            transcript_path=transcript_path,
            transcript_path_is_resolved=True,
        )
        return _session_runtime_truth_from_parts(
            session_id=session_id,
            registry=registry_truth,
            turn=self._turn_truth_for_session(provider, native_id),
            transcript=transcript_truth,
            v1_surface=v1,
            v2_surface=v2,
            runtime=_runtime_freshness_truth(expected_source_revision=expected_source_revision),
            stream=self._terminal_stream_truth_for_session(
                session_id,
                transcript_truth=transcript_truth,
            ),
            process=self._process_truth_for_session(provider, native_id),
        )

    def _handle_session_runtime_truth(self, q):
        raw_session = q.get("session", [""])[0]
        expected_source_revision = self._expected_source_revision_for_request(q)
        try:
            truth = self._session_runtime_truth(raw_session, expected_source_revision=expected_source_revision)
        except ValueError as e:
            self.send_error(400, str(e))
            return
        except Exception as e:
            self._send_json({"ok": False, "error": "session_runtime_truth_unavailable", "message": redact_public_text(str(e))[:200]}, status=502)
            return
        self._send_json({"ok": True, "truth": _public_session_runtime_truth(truth)})

    def _handle_session_runtime_truth_stream(self, q):
        raw_session = q.get("session", [""])[0]
        if not raw_session:
            self.send_error(400, "session required")
            return
        expected_source_revision = self._expected_source_revision_for_request(q)
        self.send_response(200)
        self.send_header("Content-Type", "text/event-stream")
        self.send_header("Cache-Control", "no-store")
        self.send_header("Connection", "keep-alive")
        self.send_header("X-Accel-Buffering", "no")
        self.end_headers()

        last_hash = ""
        last_keepalive = _time.time()
        deadline = _time.time() + 600
        while _time.time() < deadline:
            if not self._stream_authorization_is_current():
                return
            try:
                truth = self._session_runtime_truth(raw_session, expected_source_revision=expected_source_revision)
                slim = _session_runtime_truth_stream_payload(truth)
                current_hash = _session_runtime_truth_stream_digest(slim)
                if current_hash != last_hash:
                    if not _sse_write_json_event(self.wfile, "snapshot", slim, max_bytes=SSE_MAX_EVENT_BYTES):
                        return
                    last_hash = current_hash
                    last_keepalive = _time.time()
                elif _time.time() - last_keepalive >= 20:
                    if not _sse_write_json_event(self.wfile, "keepalive", {}, max_bytes=SSE_MAX_EVENT_BYTES):
                        return
                    last_keepalive = _time.time()
            except ValueError as e:
                _sse_write_json_event(self.wfile, "error", {"reason": "bad_session", "message": redact_public_text(str(e))[:200]}, max_bytes=SSE_MAX_EVENT_BYTES)
                return
            except Exception as e:
                _sse_write_json_event(self.wfile, "error", {"reason": "session_runtime_truth_unavailable", "message": redact_public_text(str(e))[:200]}, max_bytes=SSE_MAX_EVENT_BYTES)
            _time.sleep(1.0)
        _sse_write_json_event(self.wfile, "done", {}, max_bytes=SSE_MAX_EVENT_BYTES)

    def _handle_terminal_workspace(self, q):
        raw_session = q.get("session", [""])[0]
        # Scrollback paging (SPEC-p4 §2.3): a windowed fetch serves a history
        # slice from the broker's retained scrollback — no runtime-truth
        # recompute, the page is static cells with absolute indexes.
        raw_window_start = (q.get("window_start", [None]) or [None])[0]
        raw_window_size = (q.get("window_size", [None]) or [None])[0]
        if raw_window_start is not None:
            try:
                window_start = max(0, int(raw_window_start))
                window_size = max(1, min(int(raw_window_size or 200), 500))
            except ValueError:
                self.send_error(400, "window_start and window_size must be integers")
                return
            try:
                surface = self._broker_surface_v2_snapshot(
                    raw_session, window_start=window_start, window_size=window_size
                )
            except Exception as e:
                self._send_json({"ok": False, "error": "terminal_workspace_unavailable", "message": redact_public_text(str(e))[:200]}, status=502)
                return
            if surface is None:
                self._send_json({
                    "ok": False,
                    "error": {"code": "scrollback_unavailable", "message": "Scrollback pages need a Pairling-owned PTY."},
                }, status=404)
                return
            self._send_json({"ok": True, "terminal_surface_v2": surface})
            return
        expected_source_revision = self._expected_source_revision_for_request(q)
        try:
            truth = self._session_runtime_truth(raw_session, expected_source_revision=expected_source_revision)
            workspace = _terminal_workspace_from_truth(truth)
        except ValueError as e:
            self.send_error(400, str(e))
            return
        except Exception as e:
            self._send_json({"ok": False, "error": "terminal_workspace_unavailable", "message": redact_public_text(str(e))[:200]}, status=502)
            return
        self._send_json(workspace)

    def _handle_terminal_workspace_stream(self, q):
        raw_session = q.get("session", [""])[0]
        if not raw_session:
            self.send_error(400, "session required")
            return
        expected_source_revision = self._expected_source_revision_for_request(q)
        self.send_response(200)
        self.send_header("Content-Type", "text/event-stream")
        self.send_header("Cache-Control", "no-store")
        self.send_header("Connection", "keep-alive")
        self.send_header("X-Accel-Buffering", "no")
        self.end_headers()

        last_hash = ""
        last_keepalive = _time.time()
        deadline = _time.time() + 600
        while _time.time() < deadline:
            if not self._stream_authorization_is_current():
                return
            try:
                truth = self._session_runtime_truth(raw_session, expected_source_revision=expected_source_revision)
                workspace = _terminal_workspace_from_truth(truth)
                current_hash = _terminal_workspace_stream_digest(workspace)
                if current_hash != last_hash:
                    if not _sse_write_chunked_json_event(
                        self.wfile,
                        "snapshot",
                        workspace,
                        stats_key="terminal_workspace_snapshot",
                    ):
                        return
                    last_hash = current_hash
                    last_keepalive = _time.time()
                elif _time.time() - last_keepalive >= 20:
                    if not _sse_write_json_event(self.wfile, "keepalive", {}, max_bytes=SSE_MAX_EVENT_BYTES):
                        return
                    last_keepalive = _time.time()
            except ValueError as e:
                _sse_write_json_event(
                    self.wfile,
                    "error",
                    {
                        "reason": "bad_session",
                        "message": redact_public_text(str(e)[:200]),
                    },
                    max_bytes=SSE_MAX_EVENT_BYTES,
                )
                return
            except Exception as e:
                _sse_write_json_event(
                    self.wfile,
                    "error",
                    {
                        "reason": "terminal_workspace_unavailable",
                        "message": redact_public_text(str(e)[:200]),
                    },
                    max_bytes=SSE_MAX_EVENT_BYTES,
                )
            # 0.35s keeps the phone's raw-terminal mirror near-realtime when
            # someone types on the Mac; truth composition is local state +
            # files, no PG, so the tighter cadence is cheap.
            _time.sleep(0.35)
        _sse_write_json_event(self.wfile, "done", {}, max_bytes=SSE_MAX_EVENT_BYTES)

    def _handle_terminal_stream_diagnostics(self, q):
        raw_session = q.get("session", [""])[0]
        expected_source_revision = self._expected_source_revision_for_request(q)
        try:
            truth = self._session_runtime_truth(raw_session, expected_source_revision=expected_source_revision)
        except ValueError as e:
            self.send_error(400, str(e))
            return
        except Exception as e:
            self._send_json({"ok": False, "error": "terminal_stream_diagnostics_unavailable", "message": redact_public_text(str(e))[:200]}, status=502)
            return
        self._send_json(_terminal_stream_diagnostics_from_truth(truth))

    def _handle_terminal_stream(self, q):
        """SSE stream of the captured Terminal output for an app-spawned
        session. This is intentionally separate from /transcript-stream:
        transcript JSONL remains the durable semantic history, while this
        stream mirrors Claude Code's terminal output as bytes arrive.

        Params:
          session — provider-qualified or legacy Claude session id
          since   — initial byte offset in the terminal log (default 0)
        """
        raw_session = q.get("session", [""])[0]
        provider, native_id = _parse_agent_session_ref(raw_session)
        if not native_id:
            self.send_error(400, "session required")
            return
        registry_native_id = _agent_registry_resolve_native_alias(provider, native_id)
        raw_since = q.get("since", ["0"])[0]
        try:
            since = -1 if raw_since in ("end", "tail") else int(raw_since)
        except ValueError:
            since = 0
        start_at_end = since < 0
        since = max(0, since)

        broker_found = self._broker_session_for(raw_session)
        if broker_found:
            broker_id, _ = broker_found
            self.send_response(200)
            self.send_header("Content-Type", "text/event-stream")
            self.send_header("Cache-Control", "no-store")
            self.send_header("Connection", "keep-alive")
            self.send_header("X-Accel-Buffering", "no")
            self.end_headers()

            last_offset = since
            if start_at_end and PTY_BROKER:
                tail = PTY_BROKER.raw_tail(broker_id, since=0)
                last_offset = tail[1] if tail else 0
            last_keepalive = _time.time()
            deadline = _time.time() + 600

            terminal_wakes = None
            if SESSION_EVENT_HUB is not None:
                _ensure_broker_output_listener()
                terminal_wakes = SESSION_EVENT_HUB.subscribe(
                    f"terminal:{_qualified_session_id(provider, native_id)}"
                )
            try:
                if not self._stream_authorization_is_current():
                    return
                while _time.time() < deadline and PTY_BROKER:
                    if not self._stream_authorization_is_current():
                        return
                    tail = PTY_BROKER.raw_tail(broker_id, since=last_offset)
                    if tail is None:
                        break
                    data, next_offset, total_bytes, reset, gap_bytes, _feed_at = tail
                    if reset:
                        payload = {"next_since": 0, "total_bytes": total_bytes, "text": "", "reset": True}
                        last_offset = 0
                    else:
                        last_offset = last_offset + gap_bytes
                        send_data, payload = _bounded_terminal_stream_chunk(
                            data,
                            last_offset=last_offset,
                            total_bytes=total_bytes,
                            clean_text=lambda chunk: chunk.decode("utf-8", errors="replace").replace("\r\n", "\n").replace("\r", "\n"),
                        )
                        combined_gap = gap_bytes + int(payload.get("gap_bytes") or 0)
                        if combined_gap > 0:
                            payload["gap_bytes"] = combined_gap
                    if send_data or reset:
                        if not _sse_write_json_event(self.wfile, "chunk", payload, max_bytes=SSE_MAX_EVENT_BYTES):
                            return
                        if data and not reset:
                            last_offset += len(send_data)
                        last_keepalive = _time.time()
                    elif _time.time() - last_keepalive >= 20:
                        try:
                            self.wfile.write(b"event: keepalive\ndata: {}\n\n")
                            self.wfile.flush()
                        except (BrokenPipeError, ConnectionResetError):
                            return
                        last_keepalive = _time.time()
                    # Broker output pushes the wake; the tick is the degraded
                    # fallback while the listener is unavailable.
                    if terminal_wakes is not None:
                        wake = terminal_wakes.get(timeout=0.5)
                        while wake is not None:
                            wake = terminal_wakes.get(timeout=0)
                    else:
                        _time.sleep(0.05)
                try:
                    self.wfile.write(b"event: done\ndata: {}\n\n")
                    self.wfile.flush()
                except (BrokenPipeError, ConnectionResetError):
                    pass
                return
            finally:
                if terminal_wakes is not None:
                    terminal_wakes.close()

        log_path: Path | None = None
        if provider == "claude":
            session_id = _claude_native_session_id(raw_session)
            if not session_id:
                self.send_error(400, "invalid Claude session")
                return
            tty = self._lookup_terminal_tty(session_id)
            project = self._lookup_pg_project(session_id)
            log_path = _terminal_capture_for_tty(tty, project)
        elif provider == "codex":
            reg = _agent_registry_get("codex", registry_native_id) or {}
            try:
                metadata = json.loads(reg.get("metadata_json") or "{}")
            except Exception:
                metadata = {}
            log_path = _terminal_capture_from_metadata(metadata)

        if log_path is None:
            self.send_error(404, "no terminal capture for session")
            return
        if not _is_terminal_capture_path(log_path):
            self.send_error(403, "terminal capture path rejected")
            return
        if not log_path.exists():
            self.send_error(404, "terminal capture log not found")
            return

        self.send_response(200)
        self.send_header("Content-Type", "text/event-stream")
        self.send_header("Cache-Control", "no-store")
        self.send_header("Connection", "keep-alive")
        self.send_header("X-Accel-Buffering", "no")
        self.end_headers()

        POLL_INTERVAL = 0.05
        KEEPALIVE_INTERVAL = 20.0
        MAX_DURATION = 600.0
        last_emitted_offset = since
        last_keepalive = _time.time()
        deadline = _time.time() + MAX_DURATION

        def _clean_terminal_bytes(data: bytes) -> str:
            text = data.decode("utf-8", errors="replace")
            # Defensive cleanup for script logs produced from noninteractive
            # probes; real Terminal-launched captures do not include this.
            text = text.replace("^D\x08\x08", "")
            text = text.replace("\r\n", "\n").replace("\r", "\n")
            return text

        def _emit_chunk(data: bytes, total_bytes: int) -> int | None:
            send_data, payload = _bounded_terminal_stream_chunk(
                data,
                last_offset=last_emitted_offset,
                total_bytes=total_bytes,
                clean_text=_clean_terminal_bytes,
            )
            if not send_data:
                return 0
            if not _sse_write_json_event(self.wfile, "chunk", payload, max_bytes=SSE_MAX_EVENT_BYTES):
                return None
            return len(send_data)

        def _emit_reset(total_bytes: int) -> bool:
            payload = {
                "next_since": 0,
                "total_bytes": max(0, total_bytes),
                "text": "",
                "reset": True,
            }
            return _sse_write_json_event(self.wfile, "chunk", payload, max_bytes=SSE_MAX_EVENT_BYTES)

        f = None
        try:
            if not self._stream_authorization_is_current():
                return
            f = open(log_path, "rb")
            opened_stat = os.fstat(f.fileno())
            size = opened_stat.st_size
            if start_at_end:
                last_emitted_offset = size
            if last_emitted_offset > size:
                if not _emit_reset(size):
                    return
                last_emitted_offset = 0
            f.seek(last_emitted_offset)
            if size > last_emitted_offset:
                data = f.read(min(size - last_emitted_offset, SSE_TERMINAL_CHUNK_BYTES))
                if data:
                    sent_len = _emit_chunk(data, size)
                    if sent_len is None:
                        return
                    last_emitted_offset += sent_len
                    f.seek(last_emitted_offset)

            while _time.time() < deadline:
                if not self._stream_authorization_is_current():
                    return
                _time.sleep(POLL_INTERVAL)
                try:
                    current_stat = log_path.stat()
                    if (current_stat.st_ino, current_stat.st_dev) != (opened_stat.st_ino, opened_stat.st_dev):
                        _emit_reset(current_stat.st_size)
                        return
                    size = os.fstat(f.fileno()).st_size
                except OSError:
                    return

                if size < last_emitted_offset:
                    _emit_reset(size)
                    return
                if size > last_emitted_offset:
                    data = f.read(min(size - last_emitted_offset, SSE_TERMINAL_CHUNK_BYTES))
                    if data:
                        sent_len = _emit_chunk(data, size)
                        if sent_len is None:
                            return
                        last_emitted_offset += sent_len
                        f.seek(last_emitted_offset)
                        last_keepalive = _time.time()

                now = _time.time()
                if now - last_keepalive >= KEEPALIVE_INTERVAL:
                    try:
                        self.wfile.write(b"event: keepalive\ndata: {}\n\n")
                        self.wfile.flush()
                    except (BrokenPipeError, ConnectionResetError):
                        return
                    last_keepalive = now

            try:
                self.wfile.write(b"event: done\ndata: {}\n\n")
                self.wfile.flush()
            except (BrokenPipeError, ConnectionResetError):
                pass
        except (BrokenPipeError, ConnectionResetError):
            return
        except OSError as e:
            self.log_message("terminal-stream OSError for %s: %s", raw_session, e)
            return
        finally:
            if f is not None:
                try:
                    f.close()
                except OSError:
                    pass

    # ----- /terminal-surface: rendered terminal screen snapshot -----
    def _broker_session_for(self, raw_session: str):
        if PTY_BROKER is None:
            return None
        provider, native_id = _parse_agent_session_ref(raw_session)
        if not native_id:
            return None
        qualified = _qualified_session_id(provider, native_id)
        try:
            direct_session = PTY_BROKER.get(qualified)
        except Exception:
            direct_session = None
        if direct_session is not None and _broker_session_owns_identity(
            direct_session, provider, native_id
        ):
            return qualified, direct_session
        if provider == "codex":
            registry_session_id = _agent_registry_resolve_native_alias(
                "codex", native_id
            )
            reg = _agent_registry_get("codex", registry_session_id) or {}
            try:
                metadata = json.loads(reg.get("metadata_json") or "{}")
            except Exception:
                metadata = {}
            broker_id = str(metadata.get("broker_id") or "").strip()
            if broker_id:
                try:
                    session = PTY_BROKER.get(broker_id)
                except Exception:
                    session = None
                if session and _broker_session_owns_identity(
                    session, "codex", native_id
                ):
                    try:
                        PTY_BROKER.register_alias(qualified, _broker_session_id(session))
                    except Exception:
                        pass
                    return qualified, session
            tty = reg.get("terminal_tty") or ""
            if tty:
                try:
                    session = PTY_BROKER.get_by_tty(tty)
                except Exception:
                    session = None
                if session and _broker_session_owns_identity(
                    session, "codex", native_id
                ):
                    try:
                        PTY_BROKER.register_alias(qualified, _broker_session_id(session))
                    except Exception:
                        pass
                    return qualified, session
        if provider == "omp":
            registry_native_id = _agent_registry_resolve_native_alias(
                "omp", native_id
            )
            reg = _agent_registry_get("omp", registry_native_id) or {}
            broker_id = str(
                _registry_metadata_from_row(reg).get("broker_id") or ""
            ).strip()
            if broker_id:
                try:
                    session = PTY_BROKER.get(broker_id)
                except Exception:
                    session = None
                if session and _broker_session_owns_identity(
                    session, "omp", native_id
                ):
                    try:
                        PTY_BROKER.register_alias(
                            qualified, _broker_session_id(session)
                        )
                    except Exception:
                        pass
                    return qualified, session
        if provider == "claude":
            session_id = _claude_native_session_id(raw_session)
            if not session_id:
                return None
            registry_session_id = _agent_registry_resolve_native_alias(
                "claude", session_id
            )
            reg = _agent_registry_get("claude", registry_session_id) or {}
            try:
                metadata = json.loads(reg.get("metadata_json") or "{}")
            except Exception:
                metadata = {}
            broker_id = str(metadata.get("broker_id") or "").strip()
            if broker_id:
                try:
                    session = PTY_BROKER.get(broker_id)
                except Exception:
                    session = None
                if session and _broker_session_owns_identity(
                    session, "claude", session_id
                ):
                    try:
                        PTY_BROKER.register_alias(qualified, _broker_session_id(session))
                    except Exception:
                        pass
                    return qualified, session
            tty = self._lookup_terminal_tty(session_id)
            if tty:
                try:
                    session = PTY_BROKER.get_by_tty(tty)
                except Exception:
                    session = None
                if session and _broker_session_owns_identity(
                    session, "claude", session_id
                ):
                    qualified = _qualified_session_id("claude", session_id)
                    try:
                        PTY_BROKER.register_alias(qualified, _broker_session_id(session))
                    except Exception:
                        pass
                    return qualified, session
        return None

    def _broker_surface_snapshot(self, raw_session: str) -> dict | None:
        found = self._broker_session_for(raw_session)
        if not found:
            return None
        public_session_id, session = found
        return PTY_BROKER.snapshot(_broker_session_id(session), public_session_id=public_session_id) if PTY_BROKER else None

    def _broker_surface_pair_snapshot(self, raw_session: str) -> dict | None:
        found = self._broker_session_for(raw_session)
        if (
            not found
            or PTY_BROKER is None
            or not hasattr(PTY_BROKER, "snapshot_pair")
            or not _broker_is_current_runtime()
        ):
            return None
        public_session_id, session = found
        pair = PTY_BROKER.snapshot_pair(
            _broker_session_id(session),
            public_session_id=public_session_id,
        )
        return pair if isinstance(pair, dict) else None

    def _broker_surface_v2_snapshot(
        self,
        raw_session: str,
        window_start: int | None = None,
        window_size: int | None = None,
    ) -> dict | None:
        found = self._broker_session_for(raw_session)
        if not found:
            return None
        public_session_id, session = found
        if PTY_BROKER is None or not hasattr(PTY_BROKER, "snapshot_v2"):
            return None
        if window_start is not None and window_size is not None:
            return PTY_BROKER.snapshot_v2(
                _broker_session_id(session),
                public_session_id=public_session_id,
                window_start=window_start,
                window_size=window_size,
            )
        return PTY_BROKER.snapshot_v2(_broker_session_id(session), public_session_id=public_session_id)

    def _terminal_surface_tty(self, raw_session: str) -> tuple[str, str, str]:
        provider, native_id = _parse_agent_session_ref(raw_session)
        if not native_id:
            return provider, "", ""
        if provider in {"claude", "codex", "omp"}:
            session_id = (
                _claude_native_session_id(raw_session)
                if provider == "claude"
                else native_id
            )
            registry_session_id = _agent_registry_resolve_native_alias(
                provider, session_id
            )
            reg = _agent_registry_get(provider, registry_session_id) or {}
            pid = int(reg.get("pid") or reg.get("claude_pid") or 0)
            tty = str(reg.get("terminal_tty") or "")
            if (
                reg.get("closed_at") is not None
                or pid <= 0
                or not _process_alive(pid)
                or not _registry_process_birth_matches(reg, pid)
                or not _session_signal_target_is_verified(reg, provider, pid)
                or not _direct_terminal_binding_is_verified(reg, provider, pid)
            ):
                return provider, session_id, ""
            return provider, session_id, tty
        return provider, native_id, ""

    def _terminal_app_surface_snapshot(
        self,
        raw_session: str,
        *,
        automation_timeout: float = 15.0,
    ) -> dict:
        provider, native_id, tty = self._terminal_surface_tty(raw_session)
        if not native_id:
            raise ValueError("session required")
        if not tty:
            raise FileNotFoundError("no terminal_tty for session")
        if not re.match(r"^/dev/ttys[0-9]{3,}$", tty):
            raise PermissionError("invalid terminal_tty")

        timeout_milliseconds = max(250, min(15_000, round(automation_timeout * 1_000)))
        try:
            raw_result = _automation_helper_client().read_tab(
                tty,
                timeout_ms=timeout_milliseconds,
            )
        except AutomationHelperUnavailableError as exc:
            raise RuntimeError(str(exc) or "terminal contents unavailable") from exc
        result = _automation_helper_response(raw_result, mutation=False)
        if not result.get("ok"):
            if result.get("error_code") == "terminal_tab_not_found":
                raise FileNotFoundError("matching Terminal tab not found")
            if result.get("error_code") == "mac_permissions_needed":
                raise PermissionError("Pairling needs Mac permission before it can read Terminal.")
            raise RuntimeError(result.get("reason") or "terminal contents unavailable")

        text = result.get("history")
        if not isinstance(text, str):
            raise RuntimeError("malformed terminal contents response")
        try:
            rows = int(result.get("rows"))
            columns = int(result.get("columns"))
        except (TypeError, ValueError):
            rows, columns = 24, 80
        return _terminal_surface_snapshot_from_text(
            session_id=_qualified_session_id(provider, native_id),
            source="terminal_app_contents",
            text=text,
            columns=columns,
            rows=rows,
        )

    def _handle_terminal_surface(self, q):
        raw_session = q.get("session", [""])[0]
        try:
            payload = self._broker_surface_snapshot(raw_session) or self._terminal_app_surface_snapshot(raw_session)
        except ValueError as e:
            self.send_error(400, str(e))
            return
        except PermissionError as e:
            self.send_error(403, str(e))
            return
        except FileNotFoundError as e:
            self.send_error(404, str(e))
            return
        except Exception as e:
            self.send_error(502, str(e)[:200])
            return
        body = json.dumps(payload).encode()
        self.send_response(200)
        self.send_header("Content-Type", "application/json")
        self.send_header("Content-Length", str(len(body)))
        self.end_headers()
        self.wfile.write(body)

    def _terminal_surface_v2_snapshot(self, raw_session: str, *, automation_timeout: float = 15.0) -> dict:
        provider, native_id = _parse_agent_session_ref(raw_session)
        if not native_id:
            raise ValueError("session required")
        if not _provider_supports(provider, "terminal_surface"):
            raise ValueError(f"unsupported provider: {provider}")
        broker_payload = self._broker_surface_v2_snapshot(raw_session)
        if broker_payload is not None:
            return broker_payload
        try:
            v1 = self._terminal_app_surface_snapshot(raw_session, automation_timeout=automation_timeout)
        except (FileNotFoundError, RuntimeError) as e:
            return _terminal_surface_v2_unavailable(provider=provider, native_id=native_id, reason=str(e))
        return _terminal_surface_v2_from_text_snapshot(v1, provider=provider, native_id=native_id)

    def _terminal_surface_v2_delta(
        self,
        raw_session: str,
        *,
        since_generation: int | None,
        since_offset: int | None,
    ) -> tuple[str, dict | None]:
        """("delta", payload) when the broker serves a dirty-row delta after
        since_generation, ("unchanged", None) when the generation has not
        moved, else ("snapshot", payload). The dirty-row correctness the old
        forced-snapshot comment demanded is proven by the replay-corpus
        reconstruction test in test_terminal_dirty_delta_contract."""
        if since_generation is not None and since_generation > 0:
            try:
                found = self._broker_session_for(raw_session)
            except Exception:
                found = None
            if found and PTY_BROKER is not None and hasattr(PTY_BROKER, "delta_v2"):
                public_session_id, session = found
                delta = PTY_BROKER.delta_v2(
                    _broker_session_id(session),
                    since_generation,
                    public_session_id=public_session_id,
                )
                if delta is not None:
                    return ("delta", delta)
                return ("unchanged", None)
        return ("snapshot", self._terminal_surface_v2_snapshot(raw_session))

    def _handle_terminal_surface_v2(self, q):
        raw_session = q.get("session", [""])[0]
        try:
            payload = self._terminal_surface_v2_snapshot(raw_session)
        except ValueError as e:
            self.send_error(400, str(e))
            return
        except PermissionError as e:
            self.send_error(403, str(e))
            return
        except FileNotFoundError as e:
            self.send_error(404, str(e))
            return
        except Exception as e:
            self.send_error(502, str(e)[:200])
            return
        body = json.dumps(payload, separators=(",", ":")).encode()
        self.send_response(200)
        self.send_header("Content-Type", "application/json")
        self.send_header("Content-Length", str(len(body)))
        self.end_headers()
        self.wfile.write(body)

    def _handle_terminal_surface_stream_v2(self, q):
        raw_session = q.get("session", [""])[0]
        if not raw_session:
            self.send_error(400, "session required")
            return
        try:
            since_generation = int(q.get("since_generation", ["0"])[0])
        except ValueError:
            since_generation = None
        try:
            since_offset = int(q.get("since_offset", ["0"])[0])
        except ValueError:
            since_offset = None

        self.send_response(200)
        self.send_header("Content-Type", "text/event-stream")
        self.send_header("Cache-Control", "no-store")
        self.send_header("Connection", "keep-alive")
        self.send_header("X-Accel-Buffering", "no")
        self.end_headers()

        last_hash = ""
        last_keepalive = _time.time()
        deadline = _time.time() + 600
        first = True
        surface_subscription = None
        if SESSION_EVENT_HUB is not None:
            provider, native_id = _parse_agent_session_ref(raw_session)
            topic_key = _qualified_session_id(provider, native_id) if native_id else raw_session
            _ensure_broker_output_listener()
            surface_subscription = SESSION_EVENT_HUB.subscribe_many([
                f"terminal:{topic_key}", BROKER_GLOBAL_TOPIC,
            ])

        try:
            while _time.time() < deadline:
                if not self._stream_authorization_is_current():
                    return
                try:
                    if not first and since_generation:
                        kind, payload = self._terminal_surface_v2_delta(
                            raw_session,
                            since_generation=since_generation,
                            since_offset=since_offset,
                        )
                    else:
                        kind, payload = ("snapshot", self._terminal_surface_v2_snapshot(raw_session))
                except ValueError as e:
                    _sse_write_json_event(self.wfile, "error", {
                        "schema_version": 2,
                        "event": "error",
                        "session_id": raw_session,
                        "reason": "bad_session",
                        "message": str(e)[:200],
                        "retryable": False,
                        "degraded_source_available": None,
                    })
                    _sse_write_json_event(self.wfile, "done", {})
                    return
                except FileNotFoundError as e:
                    _sse_write_json_event(self.wfile, "error", {
                        "schema_version": 2,
                        "event": "error",
                        "session_id": raw_session,
                        "reason": "terminal_surface_unavailable",
                        "message": str(e)[:200],
                        "retryable": True,
                        "degraded_source_available": None,
                    })
                    _sse_write_json_event(self.wfile, "done", {})
                    return
                except Exception as e:
                    _sse_write_json_event(self.wfile, "error", {
                        "schema_version": 2,
                        "event": "error",
                        "session_id": raw_session,
                        "reason": "terminal_surface_unavailable",
                        "message": str(e)[:200],
                        "retryable": True,
                        "degraded_source_available": "terminal_app_contents",
                    })
                    _time.sleep(1.0)
                    continue

                if kind == "delta" and payload is not None:
                    if not _sse_write_chunked_json_event(
                        self.wfile,
                        "delta",
                        payload,
                        stats_key="surface_delta",
                    ):
                        return
                    last_keepalive = _time.time()
                    last_hash = str(payload.get("screen_hash") or last_hash)
                    since_generation = int(payload.get("generation") or since_generation or 0)
                    since_offset = int(payload.get("raw_offset") or since_offset or 0)
                elif kind == "snapshot" and payload is not None:
                    current_hash = str(payload.get("screen_hash") or "")
                    if first or current_hash != last_hash:
                        if not _sse_write_chunked_json_event(
                            self.wfile,
                            "snapshot",
                            payload,
                            stats_key="surface_snapshot",
                        ):
                            return
                        first = False
                        last_hash = current_hash
                        since_generation = int(payload.get("generation") or 0)
                        since_offset = int(payload.get("raw_offset") or 0)
                        last_keepalive = _time.time()

                if _time.time() - last_keepalive >= 20:
                    if not _sse_write_json_event(self.wfile, "keepalive", {}, max_bytes=SSE_MAX_EVENT_BYTES):
                        return
                    last_keepalive = _time.time()

                if surface_subscription is not None:
                    wake = surface_subscription.get(timeout=0.5)
                    while wake is not None:
                        wake = surface_subscription.get(timeout=0)
                else:
                    _time.sleep(0.5)
            _sse_write_json_event(self.wfile, "done", {}, max_bytes=SSE_MAX_EVENT_BYTES)
        finally:
            if surface_subscription is not None:
                try:
                    surface_subscription.close()
                except Exception:
                    pass

    def _handle_terminal_surface_stream(self, q):
        raw_session = q.get("session", [""])[0]
        if not raw_session:
            self.send_error(400, "session required")
            return
        self.send_response(200)
        self.send_header("Content-Type", "text/event-stream")
        self.send_header("Cache-Control", "no-store")
        self.send_header("Connection", "keep-alive")
        self.send_header("X-Accel-Buffering", "no")
        self.end_headers()

        last_hash = ""
        last_keepalive = _time.time()
        deadline = _time.time() + 600

        def emit(event: str, payload: dict) -> bool:
            return _sse_write_json_event(self.wfile, event, payload, max_bytes=SSE_MAX_EVENT_BYTES)

        while _time.time() < deadline:
            if not self._stream_authorization_is_current():
                return
            try:
                snap = self._broker_surface_snapshot(raw_session) or self._terminal_app_surface_snapshot(raw_session)
            except ValueError as e:
                emit("error", {"message": str(e)[:200], "reason": "bad_session"})
                emit("done", {})
                return
            except PermissionError as e:
                emit("error", {"message": str(e)[:200], "reason": "invalid_tty"})
                emit("done", {})
                return
            except FileNotFoundError as e:
                emit("error", {"message": str(e)[:200], "reason": "terminal_tab_not_found"})
                emit("done", {})
                return
            except Exception as e:
                if not emit("error", {"message": str(e)[:200]}):
                    return
                _time.sleep(1.0)
                continue

            if snap.get("screen_hash") != last_hash:
                if not emit("snapshot", snap):
                    return
                last_hash = str(snap.get("screen_hash") or "")
                last_keepalive = _time.time()
            elif _time.time() - last_keepalive >= 20:
                if not emit("keepalive", {}):
                    return
                last_keepalive = _time.time()
            _time.sleep(0.5)
        emit("done", {})

    def _terminal_control_target(self, raw_session: str) -> dict:
        if ":" not in raw_session:
            raise ValueError("provider-qualified session_id required")
        provider, native_id = _parse_agent_session_ref(raw_session)
        if not native_id:
            raise ValueError("provider-qualified session_id required")
        if not _valid_provider_filter(provider, allow_all=False):
            raise ValueError(f"unknown provider: {provider}")
        if provider not in _agent_provider_ids():
            raise ValueError(f"unsupported provider: {provider}")
        requested_native_id = native_id
        native_id = _agent_registry_resolve_native_alias(provider, native_id)
        broker_found = self._broker_session_for(raw_session)
        if broker_found:
            public_session_id, session = broker_found
            if not _broker_session_owns_identity(
                session, provider, requested_native_id
            ):
                raise ProcessIdentityDriftError("broker ownership changed; refresh before sending control")
            return {
                "source": "broker_vt",
                "provider": provider,
                "native_id": native_id,
                "session_id": public_session_id,
                "broker_id": _broker_session_id(session),
                "tty": _broker_slave_tty(session),
                "tty_candidates": [_broker_slave_tty(session)] if _broker_slave_tty(session) else [],
                "pid": _broker_pid(session),
            }

        if provider == "claude":
            session_id = _claude_native_session_id(raw_session)
            if not session_id:
                raise ValueError("session required")
            tty = self._lookup_terminal_tty(session_id)
            if not tty:
                raise FileNotFoundError("no terminal_tty for session")
            if not re.match(r'^/dev/ttys[0-9]{3,}$', tty):
                raise PermissionError("invalid terminal_tty")
            return {
                "provider": "claude",
                "source": "terminal_app_contents",
                "native_id": session_id,
                "session_id": _qualified_session_id("claude", session_id),
                "tty": tty,
                "tty_candidates": [tty],
                "pid": self._lookup_claude_pid(session_id) or 0,
            }

        if provider == "omp":
            raise PermissionError(
                "OMP terminal control requires a Pairling-owned PTY broker session"
            )

        if provider != "codex":
            raise ValueError(f"unsupported provider: {provider}")

        reg = _agent_registry_get("codex", native_id)
        if not reg:
            raise FileNotFoundError("no Codex control registry row for session")
        if reg.get("closed_at"):
            raise ProcessIdentityDriftError(
                "Codex session is closed; refresh before sending control"
            )
        reg = _agent_registry_promote_codex(
            native_id,
            str(reg.get("project") or ""),
            float(reg.get("started_at") or 0),
        ) or reg
        promoted_native_id = str(reg.get("native_id") or "")
        if promoted_native_id:
            native_id = promoted_native_id
        tty = reg.get("terminal_tty") or ""
        pid = int(reg.get("pid") or 0)
        if (
            not pid
            or not _process_alive(pid)
            or not _session_signal_target_is_verified(reg, "codex", pid)
        ):
            raise ProcessIdentityDriftError(
                "Codex process identity changed; refresh before sending control"
            )
        tty_candidates = _codex_terminal_tty_candidates(
            {**reg, "pid": pid, "terminal_tty": tty}
        )
        if not tty_candidates:
            raise ProcessIdentityDriftError(
                "Codex Terminal tab identity could not be verified"
            )
        tty = tty_candidates[0]
        if not re.match(r'^/dev/ttys[0-9]{3,}$', tty):
            raise PermissionError("invalid terminal_tty")
        return {
            "provider": "codex",
            "source": "terminal_app_contents",
            "native_id": native_id,
            "session_id": _qualified_session_id("codex", native_id),
            "tty": tty,
            "tty_candidates": tty_candidates,
            "pid": pid,
        }

    def _terminal_control_signal(self, target: dict, sig: int, sig_name: str) -> dict:
        provider = target["provider"]
        native_id = target["native_id"]
        expected_pid = int(target.get("pid") or 0)
        _row, pid, verification_error = _verified_session_signal_target(
            provider,
            native_id,
            expected_pid=expected_pid,
        )
        if verification_error == "process_identity_unverified":
            return {
                "ok": False,
                "error": f"{provider.title()} process identity changed; refresh before sending control",
                "error_code": "process_identity_unverified",
                "pid": pid or expected_pid or None,
                "status": 409,
            }
        if verification_error:
            return {"ok": False, "error": f"no {provider} pid for session", "status": 404}
        try:
            os.kill(pid, sig)
        except (ProcessLookupError, PermissionError, OSError) as e:
            return {"ok": False, "error": f"{type(e).__name__}: {e}", "pid": pid, "status": 502}
        if provider == "codex":
            _write_agent_turn_state("codex", native_id, "idle", event=sig_name.lower())
        return {"ok": True, "pid": pid, "signal": sig_name}

    def _terminal_control_run_in_terminal(self, target: dict, action: dict) -> dict:
        tty = str(target.get("tty") or "")
        if not re.fullmatch(r"/dev/ttys[0-9]{3,}", tty):
            return {
                "ok": False,
                "reason": "invalid terminal tty",
                "error_code": "invalid_tty",
                "status": 400,
                "mutation_outcome": "failed_before_mutation",
                "outcome_indeterminate": False,
            }
        try:
            helper = _automation_helper_client()
            if action["type"] == "choice":
                raw_result = _send_terminal_app_text_exact(
                    tty,
                    str(action["choice_id"]),
                )
            elif action["type"] == "text":
                raw_result = _send_terminal_app_text_exact(
                    tty,
                    str(action["text"]),
                )
            elif action["type"] == "key":
                raw_result = helper.send_special_key(
                    tty,
                    str(action["key"]),
                    timeout_ms=3_000,
                )
            else:
                return {
                    "ok": False,
                    "reason": "unsupported action",
                    "error_code": "unsupported_action",
                    "status": 400,
                    "mutation_outcome": "failed_before_mutation",
                    "outcome_indeterminate": False,
                }
        except (AutomationHelperMutationIndeterminate, AutomationHelperUnavailableError) as exc:
            return _automation_helper_failure(exc, mutation=True)
        return _automation_helper_response(raw_result, mutation=True)

    # ----- /terminal-input: type mode (SPEC-p4 §2.2) -----
    # Keystrokes stream to the broker PTY without steer's per-action
    # screen_hash gate. The guards that remain: explicit receipted mode entry,
    # a 10-minute idle expiry, the broker's generation guard (stale input is
    # dropped WITH a receipt), and bounded input size. Local echo is never
    # invented — echo is the real PTY roundtrip, and the response carries
    # received_at + generation so the client can measure it.
    def _handle_terminal_input(self, q):
        raw = self._read_body() or b""
        try:
            decoded_payload = json.loads(raw)
            payload = decoded_payload if isinstance(decoded_payload, dict) else {}
            payload_error = None if isinstance(decoded_payload, dict) else (
                "invalid_body",
                "body must be a JSON object",
            )
        except (TypeError, ValueError, json.JSONDecodeError) as exc:
            payload = {}
            payload_error = ("bad_json", str(exc)[:200] or "invalid JSON")
        raw_session = str(payload.get("session_id") or "").strip()
        provider, native_id = _parse_agent_session_ref(raw_session)
        action = str(payload.get("action") or "").strip().lower()
        action_kind = {
            "enter": "terminal_input_enter",
            "input": "terminal_input",
            "exit": "terminal_input_exit",
        }.get(action, "terminal_input_invalid")
        session_key = _qualified_session_id(provider, native_id) if native_id else raw_session
        receipt_scope = (
            _session_mutation_receipt_scope(self, raw_session)
            if ":" in raw_session and native_id
            else "terminal-input:request"
        )
        mutation = _begin_receipted_mutation(
            self,
            receipt_scope=receipt_scope,
            action_kind=action_kind,
            material=raw,
            action_label="terminal input",
        )
        if mutation is None:
            return

        device_id = mutation["device_id"]
        client_action_id = mutation["client_action_id"]
        now = _time.time()

        def mark_terminal_input_running(
            *,
            binding_id: str,
            capability_generation: int,
        ) -> None:
            _mark_receipted_mutation_running(
                mutation,
                provider_id=provider,
                provider_version="terminal-surface-v2",
                provider_channel="pty_broker",
                operation_id=action_kind,
                binding_id=binding_id,
                capability_generation=max(1, capability_generation),
                recovery_correlation={
                    "provider_operation_id": client_action_id,
                    "provider_cursor": None,
                },
            )

        def reject(
            code: str,
            message: str,
            status: int,
            *,
            state: str = "rejected",
        ) -> None:
            receipt = _make_action_receipt(
                client_action_id=client_action_id,
                state=state,
                idempotent=True,
                phases=_receipt_phases(
                    validated=False,
                    applied=False,
                    pty_written=None if state == "indeterminate" else False,
                ),
            )
            _receipt_attach_response(
                receipt,
                http_status=status,
                error_code=code,
                error_message=message,
                fields={
                    "session_id": raw_session or None,
                    "input_epoch": str(payload.get("input_epoch") or "").strip() or None,
                    "outcome_indeterminate": True if state == "indeterminate" else None,
                },
            )
            _store_action_receipt(
                device_id,
                mutation["receipt_scope"],
                client_action_id,
                mutation["body_hash"],
                receipt,
                action_kind=mutation["action_kind"],
                audit_action={"type": "terminal_input", "action": action, "error": code},
            )
            body = _terminal_control_error(code, message, status)
            body.update(receipt.get("response_fields") or {})
            body["receipt"] = receipt
            self._send_json(body, status=status)

        def terminal_target_or_reject() -> dict | None:
            try:
                return self._terminal_control_target(session_key)
            except ProcessIdentityDriftError as exc:
                reject("process_identity_unverified", str(exc), 409)
            except ValueError as exc:
                reject("bad_session", str(exc), 400)
            except PermissionError as exc:
                reject("invalid_tty", str(exc), 403)
            except FileNotFoundError as exc:
                reject("terminal_not_found", str(exc), 404)
            except Exception as exc:
                reject("surface_unavailable", str(exc)[:200], 502)
            return None

        if payload_error is not None:
            reject(payload_error[0], payload_error[1], 400)
            return
        if ":" not in raw_session:
            reject("provider_required", "session_id must be provider-qualified", 400)
            return
        if not native_id or not _valid_provider_filter(provider, allow_all=False):
            reject("bad_session", "session_id must be provider-qualified", 400)
            return
        if not _provider_supports(provider, "terminal_control"):
            reject(
                "unsupported_provider",
                f"{provider or 'unknown'} does not support terminal input",
                400,
            )
            return
        if action not in {"enter", "input", "exit"}:
            reject("bad_action", "action must be enter, input, or exit", 400)
            return

        if action == "exit":
            requested_epoch = str(payload.get("input_epoch") or "").strip()
            with _TYPE_MODE_LOCK:
                current = _TYPE_MODE_SESSIONS.get(session_key)
                existing = dict(current) if isinstance(current, dict) else None
            if isinstance(existing, dict) and existing.get("device_id") != device_id:
                reject(
                    "type_mode_identity_changed",
                    "Only the phone that entered type mode can exit it.",
                    409,
                )
                return
            if (
                isinstance(existing, dict)
                and requested_epoch != str(existing.get("input_epoch") or "")
            ):
                reject(
                    "input_epoch_changed",
                    "Type mode was replaced by a newer typing session.",
                    409,
                )
                return
            if PTY_BROKER is None:
                reject(
                    "broker_unavailable",
                    "The terminal broker is unavailable, so type mode was not cleared.",
                    503,
                )
                return
            broker_id = str((existing or {}).get("broker_id") or "")
            if not broker_id:
                exit_target = terminal_target_or_reject()
                if exit_target is None:
                    return
                if (
                    exit_target.get("source") != "broker_vt"
                    or not exit_target.get("broker_id")
                ):
                    reject(
                        "type_mode_unavailable",
                        "Type mode can only be cleared through the Pairling terminal broker.",
                        409,
                    )
                    return
                broker_id = str(exit_target.get("broker_id") or "")
                try:
                    broker_mode = PTY_BROKER.control(broker_id, {
                        "type": "input_mode_status",
                        "device_id": str(device_id or ""),
                    })
                except Exception as exc:
                    reject("broker_unavailable", str(exc)[:200], 503)
                    return
                if not broker_mode.get("ok"):
                    reason = str(broker_mode.get("reason") or "type_mode_not_active")
                    reject(
                        reason,
                        "The terminal broker does not have this phone's type-mode lease.",
                        409,
                    )
                    return
                if requested_epoch != str(broker_mode.get("input_epoch") or ""):
                    reject(
                        "input_epoch_changed",
                        "Type mode was replaced by a newer typing session.",
                        409,
                    )
                    return
            mark_terminal_input_running(
                binding_id=broker_id,
                capability_generation=(
                    int(payload.get("generation"))
                    if isinstance(payload.get("generation"), int)
                    and not isinstance(payload.get("generation"), bool)
                    else 1
                ),
            )
            try:
                broker_exit = PTY_BROKER.control(broker_id, {
                    "type": "input_mode_exit",
                    "input_epoch": requested_epoch,
                    "device_id": str(device_id or ""),
                })
            except PTYBrokerOutcomeUnknownError:
                reject(
                    "broker_apply_outcome_unknown",
                    "The broker response was lost. Check type mode before trying again.",
                    502,
                    state="indeterminate",
                )
                return
            except Exception as exc:
                reject("broker_unavailable", str(exc)[:200], 503)
                return
            if not broker_exit.get("ok"):
                reason = str(
                    broker_exit.get("reason") or "type_mode_exit_failed"
                )
                reject(
                    reason,
                    "The terminal broker did not confirm that type mode was cleared.",
                    409,
                )
                return
            with _TYPE_MODE_LOCK:
                current = _TYPE_MODE_SESSIONS.get(session_key)
                if (
                    isinstance(current, dict)
                    and current.get("device_id") == device_id
                    and str(current.get("input_epoch") or "") == requested_epoch
                    and str(current.get("broker_id") or "") == broker_id
                ):
                    _TYPE_MODE_SESSIONS.pop(session_key, None)
            _append_terminal_control_audit({
                "ts": now, "path": "/terminal-input", "session_id": session_key,
                "device_id": device_id, "action": "exit", "broker_id": broker_id,
                "ok": True,
            })
            response_fields = {
                "session_id": raw_session,
                "mode": "steer",
                "input_epoch": requested_epoch,
            }
            receipt = _make_action_receipt(
                client_action_id=client_action_id,
                state="applied",
                idempotent=True,
                phases=_receipt_phases(validated=True, applied=True, pty_written=False),
                backend="pty_broker",
            )
            _receipt_attach_response(receipt, http_status=200, fields=response_fields)
            _store_action_receipt(
                device_id,
                mutation["receipt_scope"],
                client_action_id,
                mutation["body_hash"],
                receipt,
                action_kind=mutation["action_kind"],
                audit_action={"type": "terminal_input", "action": "exit"},
            )
            self._send_json({"ok": True, **response_fields, "receipt": receipt})
            return

        target = terminal_target_or_reject()
        if target is None:
            return
        if target.get("source") != "broker_vt" or not target.get("broker_id"):
            reject("type_mode_unavailable", "Type mode needs a Pairling-owned PTY; this session runs in a Terminal window (steer stays available).", 409)
            return

        def current_atomic_context() -> dict | None:
            try:
                pair = self._broker_surface_pair_snapshot(session_key)
            except Exception:
                pair = None
            return _broker_atomic_control_context(
                pair,
                broker_id=str(target.get("broker_id") or ""),
            )

        if action == "enter":
            allowed, _retry = _inject_rate_check(f"terminal-input-enter:{session_key}", max_per_min=12)
            if not allowed:
                reject("rate_limited", "too many type-mode entries", 429)
                return
            context = current_atomic_context()
            if context is None:
                reject(
                    "type_mode_requires_current_broker",
                    "Type mode needs the current atomic terminal broker; update the helper and try again.",
                    409,
                )
                return
            _surface_schema_version, proof_version_error = (
                _terminal_control_surface_schema_version(payload)
            )
            if proof_version_error is not None:
                reject(
                    str(proof_version_error["error"]["code"]),
                    str(proof_version_error["error"]["message"]),
                    int(proof_version_error["status"]),
                )
                return
            proof_error = _terminal_control_v2_availability_error(context["v2"])
            if proof_error is None:
                proof_error = _terminal_control_validate_screen(
                    payload,
                    context["v2"],
                    {"type": "input_mode_enter"},
                )
            if proof_error is not None:
                reject(
                    str(proof_error["error"]["code"]),
                    str(proof_error["error"]["message"]),
                    int(proof_error["status"]),
                )
                return
            input_epoch = hashlib.sha256(
                f"{device_id or 'device'}\0{session_key}\0{client_action_id}".encode()
            ).hexdigest()[:32]
            mark_terminal_input_running(
                binding_id=str(target["broker_id"]),
                capability_generation=int(context["v2"]["generation"]),
            )
            try:
                broker_mode = PTY_BROKER.control(target["broker_id"], {
                    "type": "input_mode_enter",
                    "input_epoch": input_epoch,
                    "device_id": str(device_id or ""),
                    "control_proof": dict(context["control_proof"]),
                })
            except PTYBrokerOutcomeUnknownError:
                reject(
                    "broker_apply_outcome_unknown",
                    "The broker response was lost. Retry entering type mode.",
                    502,
                    state="indeterminate",
                )
                return
            except Exception as exc:
                reject("broker_unavailable", str(exc)[:200], 503)
                return
            if not broker_mode.get("ok"):
                reject(
                    str(broker_mode.get("reason") or "type_mode_unavailable"),
                    "The terminal broker could not start type mode.",
                    409,
                )
                return
            with _TYPE_MODE_LOCK:
                _TYPE_MODE_SESSIONS[session_key] = {
                    "device_id": device_id,
                    "broker_id": str(target.get("broker_id") or ""),
                    "broker_pid": int(target.get("pid") or 0),
                    "entered_at": now,
                    "last_input_at": now,
                    "input_epoch": input_epoch,
                    "next_sequence": int(broker_mode.get("next_sequence") or 1),
                }
            global LAST_HUMAN_ACTIVITY_AT
            LAST_HUMAN_ACTIVITY_AT = now
            receipt = _make_action_receipt(
                client_action_id=client_action_id,
                state="applied",
                idempotent=True,
                phases=_receipt_phases(validated=True, applied=True, pty_written=False),
                backend=target.get("source"),
                tty=target.get("tty"),
                pid=target.get("pid"),
            )
            response_fields = {
                "session_id": session_key,
                "mode": "type",
                "generation": context["v2"]["generation"],
                "input_epoch": input_epoch,
                "next_sequence": int(broker_mode.get("next_sequence") or 1),
                "received_at": now,
            }
            _receipt_attach_response(
                receipt,
                http_status=200,
                fields=response_fields,
            )
            _store_action_receipt(
                device_id,
                mutation["receipt_scope"],
                client_action_id,
                mutation["body_hash"],
                receipt,
                action_kind=mutation["action_kind"],
                audit_action={"type": "terminal_input", "action": "enter"},
            )
            self._send_json({
                "ok": True,
                **response_fields,
                "receipt": receipt,
            })
            return

        # action == "input"
        with _TYPE_MODE_LOCK:
            state = _TYPE_MODE_SESSIONS.get(session_key)
            if state is not None and now - float(state.get("last_input_at") or 0) > TYPE_MODE_IDLE_SECONDS:
                _TYPE_MODE_SESSIONS.pop(session_key, None)
                state = "expired"
        recovered_state = False
        requested_input_epoch = str(payload.get("input_epoch") or "").strip()
        if state is None and PTY_BROKER is not None:
            try:
                broker_mode = PTY_BROKER.control(target["broker_id"], {
                    "type": "input_mode_status",
                    "device_id": str(device_id or ""),
                })
            except Exception:
                broker_mode = None
            if (
                isinstance(broker_mode, dict)
                and broker_mode.get("ok") is True
                and requested_input_epoch
                == str(broker_mode.get("input_epoch") or "")
            ):
                state = {
                    "device_id": device_id,
                    "broker_id": str(target.get("broker_id") or ""),
                    "broker_pid": int(target.get("pid") or 0),
                    "entered_at": now,
                    "last_input_at": now,
                    "input_epoch": requested_input_epoch,
                    "next_sequence": int(broker_mode.get("next_sequence") or 1),
                }
                recovered_state = True
        if state is None:
            reject("type_mode_not_active", "Enter type mode before streaming input.", 409)
            return
        if state == "expired":
            reject("type_mode_expired", "Type mode expired after 10 idle minutes; enter it again.", 409)
            return
        state_device_id = state.get("device_id") if isinstance(state, dict) else None
        state_broker_id = str(state.get("broker_id") or "") if isinstance(state, dict) else ""
        state_broker_pid = int(state.get("broker_pid") or 0) if isinstance(state, dict) else 0
        state_input_epoch = str(state.get("input_epoch") or "") if isinstance(state, dict) else ""
        current_broker_id = str(target.get("broker_id") or "")
        current_broker_pid = int(target.get("pid") or 0)
        if (
            state_device_id != device_id
            or state_broker_id != current_broker_id
            or state_broker_pid != current_broker_pid
        ):
            with _TYPE_MODE_LOCK:
                _TYPE_MODE_SESSIONS.pop(session_key, None)
            reject(
                "type_mode_identity_changed",
                "Type mode belongs to a different phone or terminal process; enter it again.",
                409,
            )
            return
        b64 = str(payload.get("b64") or "")
        try:
            decoded = base64.b64decode(b64, validate=True)
        except Exception:
            reject("bad_input_encoding", "b64 must be valid base64", 400)
            return
        if not decoded or len(decoded) > 1024:
            reject("input_size", "input must be 1..1024 bytes", 400)
            return
        generation = payload.get("generation")
        if not isinstance(generation, int) or isinstance(generation, bool):
            reject(
                "bad_generation",
                "A current integer terminal generation is required for type input.",
                400,
            )
            return
        input_epoch = str(payload.get("input_epoch") or "").strip()
        input_sequence = payload.get("input_sequence")
        if input_epoch != state_input_epoch:
            reject(
                "input_epoch_changed",
                "Type mode was replaced. Enter it again before typing.",
                409,
            )
            return
        if (
            not isinstance(input_sequence, int)
            or isinstance(input_sequence, bool)
            or input_sequence < 1
        ):
            reject(
                "bad_input_sequence",
                "A positive input sequence is required for type input.",
                400,
            )
            return
        if PTY_BROKER is None:
            reject("broker_unavailable", "PTY broker is unavailable", 503)
            return
        input_control_context = current_atomic_context()
        if input_control_context is None:
            with _TYPE_MODE_LOCK:
                _TYPE_MODE_SESSIONS.pop(session_key, None)
            reject(
                "type_mode_requires_current_broker",
                "The terminal broker changed or cannot prove atomic control; enter type mode again.",
                409,
            )
            return
        mark_terminal_input_running(
            binding_id=str(target["broker_id"]),
            capability_generation=int(input_control_context["v2"]["generation"]),
        )
        try:
            result = PTY_BROKER.control(target["broker_id"], {
                "type": "input",
                "b64": b64,
                "input_epoch": input_epoch,
                "expected_generation": generation,
                "input_sequence": input_sequence,
                "device_id": str(device_id or ""),
            })
        except PTYBrokerOutcomeUnknownError as exc:
            receipt = _make_action_receipt(
                client_action_id=client_action_id,
                state="indeterminate",
                idempotent=True,
                phases=_receipt_phases(validated=True, applied=False, pty_written=None),
                backend=target.get("source"),
                tty=target.get("tty"),
                pid=target.get("pid"),
            )
            receipt["phases"]["pty_write_state"] = "unknown"
            body = _terminal_control_error(
                "broker_apply_outcome_unknown",
                "The broker response was lost. Pairling will retry this exact input sequence without typing it twice.",
                502,
            )
            body["outcome_indeterminate"] = True
            _receipt_attach_response(
                receipt,
                http_status=502,
                error_code="broker_apply_outcome_unknown",
                error_message="The broker response was lost. Pairling will retry this exact input sequence without typing it twice.",
                fields={
                    "session_id": raw_session,
                    "input_epoch": input_epoch,
                    "input_sequence": input_sequence,
                    "outcome_indeterminate": True,
                },
            )
            _store_action_receipt(
                device_id, mutation["receipt_scope"], client_action_id, mutation["body_hash"], receipt,
                action_kind=mutation["action_kind"],
                audit_action={"type": "terminal_input", "action": "input", "error": "broker_apply_outcome_unknown"},
            )
            body["receipt"] = receipt
            self._send_json(body, status=502)
            return
        except Exception as exc:
            reject("broker_unavailable", str(exc)[:200], 503)
            return
        if not result.get("ok"):
            reason = str(result.get("reason") or "terminal_input_failed")
            if reason == "stale_generation":
                receipt = _make_action_receipt(
                    client_action_id=client_action_id,
                    state="rejected",
                    idempotent=True,
                    phases=_receipt_phases(validated=True, applied=False, pty_written=False),
                    backend=target.get("source"),
                    tty=target.get("tty"),
                )
                body = _terminal_control_error("stale_generation", "The screen was replaced; input dropped.", 409)
                body["generation"] = result.get("generation")
                body["input_epoch"] = result.get("input_epoch")
                body["input_sequence"] = result.get("input_sequence")
                body["next_sequence"] = result.get("next_sequence")
                _receipt_attach_response(
                    receipt,
                    http_status=409,
                    error_code="stale_generation",
                    error_message="The screen was replaced; input dropped.",
                    fields={
                        "session_id": raw_session,
                        "generation": result.get("generation"),
                        "input_epoch": result.get("input_epoch"),
                        "input_sequence": result.get("input_sequence"),
                        "next_sequence": result.get("next_sequence"),
                    },
                )
                _store_action_receipt(
                    device_id, mutation["receipt_scope"], client_action_id, mutation["body_hash"], receipt,
                    action_kind=mutation["action_kind"],
                    audit_action={"type": "terminal_input", "action": "input", "error": "stale_generation"},
                )
                body["receipt"] = receipt
                self._send_json(body, status=409)
                return
            status = 400 if reason in {"bad_input_encoding", "input_size", "bad_generation"} else 502
            outcome_indeterminate = bool(result.get("outcome_indeterminate"))
            pty_written = (
                bool(result.get("pty_written"))
                if "pty_written" in result
                else (None if outcome_indeterminate else False)
            )
            receipt = _make_action_receipt(
                client_action_id=client_action_id,
                state="indeterminate" if outcome_indeterminate else "failed",
                idempotent=True,
                phases=_receipt_phases(validated=True, applied=False, pty_written=pty_written),
                backend=target.get("source"),
                tty=target.get("tty"),
                pid=target.get("pid"),
            )
            if result.get("write_outcome"):
                receipt["phases"]["pty_write_state"] = str(result["write_outcome"])
            body = _terminal_control_error(reason, reason.replace("_", " "), status)
            body["outcome_indeterminate"] = outcome_indeterminate
            body["bytes_written"] = result.get("bytes_written")
            body["bytes_expected"] = result.get("bytes_expected")
            body["input_epoch"] = result.get("input_epoch")
            body["input_sequence"] = result.get("input_sequence")
            body["next_sequence"] = result.get("next_sequence")
            _receipt_attach_response(
                receipt,
                http_status=status,
                error_code=reason,
                error_message=reason.replace("_", " "),
                fields={
                    "session_id": raw_session,
                    "outcome_indeterminate": outcome_indeterminate,
                    "bytes_written": result.get("bytes_written"),
                    "bytes_expected": result.get("bytes_expected"),
                    "input_epoch": result.get("input_epoch"),
                    "input_sequence": result.get("input_sequence"),
                    "next_sequence": result.get("next_sequence"),
                },
            )
            _store_action_receipt(
                device_id, mutation["receipt_scope"], client_action_id, mutation["body_hash"], receipt,
                action_kind=mutation["action_kind"],
                audit_action={"type": "terminal_input", "action": "input", "error": reason},
            )
            body["receipt"] = receipt
            self._send_json(body, status=status)
            return
        LAST_HUMAN_ACTIVITY_AT = now
        with _TYPE_MODE_LOCK:
            current_state = _TYPE_MODE_SESSIONS.get(session_key)
            if (
                isinstance(current_state, dict)
                and str(current_state.get("input_epoch") or "") == input_epoch
            ):
                current_state["last_input_at"] = now
                current_state["next_sequence"] = int(
                    result.get("next_sequence") or (input_sequence + 1)
                )
            elif (
                recovered_state
                and current_state is None
                and isinstance(state, dict)
                and state_input_epoch == input_epoch
            ):
                accepted_state = dict(state)
                accepted_state["entered_at"] = now
                accepted_state["last_input_at"] = now
                accepted_state["next_sequence"] = int(
                    result.get("next_sequence") or (input_sequence + 1)
                )
                _TYPE_MODE_SESSIONS[session_key] = accepted_state
        receipt = _make_action_receipt(
            client_action_id=client_action_id,
            state="applied",
            idempotent=True,
            deduped=bool(result.get("deduped")),
            phases=_receipt_phases(validated=True, applied=True, pty_written=True),
            backend=target.get("source"),
            tty=target.get("tty"),
            pid=target.get("pid"),
        )
        response_fields = {
            "session_id": raw_session,
            "generation": result.get("generation"),
            "input_epoch": input_epoch,
            "input_sequence": input_sequence,
            "next_sequence": result.get("next_sequence") or (input_sequence + 1),
            "deduped": bool(result.get("deduped")),
            "received_at": now,
        }
        _receipt_attach_response(receipt, http_status=200, fields=response_fields)
        _store_action_receipt(
            device_id,
            mutation["receipt_scope"],
            client_action_id,
            mutation["body_hash"],
            receipt,
            action_kind=mutation["action_kind"],
            audit_action={
                "type": "terminal_input",
                "action": "input",
                "input_epoch": input_epoch,
                "input_sequence": input_sequence,
                "bytes": len(decoded),
            },
        )
        self._send_json({
            "ok": True,
            **response_fields,
            "receipt": receipt,
        })

    def _handle_terminal_control(self, q):
        raw = self._read_body() or b""
        try:
            decoded_payload = json.loads(raw)
            payload = decoded_payload if isinstance(decoded_payload, dict) else {}
            payload_error = None if isinstance(decoded_payload, dict) else (
                "invalid_body",
                "body must be a JSON object",
            )
        except (TypeError, ValueError, json.JSONDecodeError) as exc:
            payload = {}
            payload_error = ("bad_json", str(exc)[:200] or "invalid JSON")

        body_session = str(payload.get("session_id") or "").strip()
        query_session = str((q.get("session", [""]) or [""])[0] or "").strip()
        claimed_session = body_session or query_session
        claimed_provider, claimed_native_id = _parse_agent_session_ref(claimed_session)
        receipt_session_id = (
            _session_mutation_receipt_scope(self, claimed_session)
            if ":" in claimed_session and claimed_native_id
            else "terminal-control:request"
        )
        mutation = _begin_receipted_mutation(
            self,
            receipt_scope=receipt_session_id,
            action_kind="terminal_control",
            material=raw + b"\0query-session=" + query_session.encode(),
            action_label="terminal control",
        )
        if mutation is None:
            return

        audit = {
            "ts": _time.time(),
            "path": "/terminal-control",
            "device_id": mutation["device_id"],
            "ok": False,
        }
        if body_session:
            audit["body_session_id"] = body_session
        if query_session:
            audit["query_session_id"] = query_session
        audit["session_id"] = claimed_session
        device_id = mutation["device_id"]
        client_action_id = mutation["client_action_id"]
        body_hash = mutation["body_hash"]
        action = None
        raw_session = claimed_session

        def reject_reserved_action(code: str, message: str, status: int) -> None:
            audit["error"] = code
            _append_terminal_control_audit(audit)
            receipt = _make_action_receipt(
                client_action_id=client_action_id or None,
                state="rejected",
                phases=_receipt_phases(validated=False, applied=False, pty_written=False),
            )
            _receipt_attach_response(
                receipt,
                http_status=status,
                error_code=code,
                error_message=message,
                fields={
                    "session_id": raw_session or None,
                    "action": action,
                },
            )
            _store_action_receipt(
                device_id,
                receipt_session_id,
                client_action_id or None,
                body_hash,
                receipt,
                action_kind=mutation["action_kind"],
                audit_action=audit.get("action"),
            )
            response = _terminal_control_error(code, message, status)
            response.update(receipt.get("response_fields") or {})
            response["receipt"] = receipt
            self._send_json(response, status=status)

        if payload_error is not None:
            reject_reserved_action(payload_error[0], payload_error[1], 400)
            return
        raw_session, session_err = _terminal_control_session_id(payload, q)
        if session_err:
            reject_reserved_action(
                str(session_err["error"]["code"]),
                str(session_err["error"]["message"]),
                int(session_err["status"]),
            )
            return
        if ":" not in raw_session:
            reject_reserved_action(
                "provider_required",
                "session_id must be provider-qualified",
                400,
            )
            return

        provider, native_id = _parse_agent_session_ref(raw_session)
        audit["provider"] = provider
        audit["native_id"] = native_id
        if (
            not native_id
            or not _valid_provider_filter(provider, allow_all=False)
            or not _safe_agent_native_id(native_id)
        ):
            reject_reserved_action(
                "bad_session",
                "session_id must be provider-qualified",
                400,
            )
            return
        if not _provider_supports(provider, "terminal_control"):
            reject_reserved_action(
                "unsupported_provider",
                f"{provider} does not support terminal control",
                400,
            )
            return

        action, err = _terminal_control_normalize_action(payload)
        audit["action"] = _terminal_control_audit_action(action)
        if err:
            reject_reserved_action(
                str(err["error"]["code"]),
                str(err["error"]["message"]),
                int(err["status"]),
            )
            return
        surface_schema_version, version_err = _terminal_control_surface_schema_version(payload)
        audit["surface_schema_version"] = surface_schema_version
        if version_err:
            reject_reserved_action(
                str(version_err["error"]["code"]),
                str(version_err["error"]["message"]),
                int(version_err["status"]),
            )
            return

        allowed, retry = _inject_rate_check(
            f"terminal-control:{_qualified_session_id(provider, native_id)}",
            max_per_min=60,
        )
        if not allowed:
            reject_reserved_action(
                "rate_limited",
                f"Too many terminal control requests. Retry in {retry}s.",
                429,
            )
            return

        broker_control_proof = None
        try:
            target = self._terminal_control_target(raw_session)
            audit["tty"] = target.get("tty")
            audit["terminal_source"] = target.get("source")
            audit["broker_id"] = target.get("broker_id")
            if target.get("source") == "broker_vt" and target.get("broker_id"):
                if surface_schema_version != 2:
                    reject_reserved_action(
                        "surface_schema_version_required",
                        "Broker terminal control requires a current version 2 screen proof.",
                        409,
                    )
                    return
                try:
                    pair = self._broker_surface_pair_snapshot(raw_session)
                except Exception:
                    pair = None
                context = _broker_atomic_control_context(
                    pair,
                    broker_id=str(target.get("broker_id") or ""),
                )
                if context is None:
                    reject_reserved_action(
                        "surface_not_controllable",
                        "Atomic terminal control proof is unavailable; refresh the helper before sending input.",
                        409,
                    )
                    return
                snapshot = context["v2"]
                broker_control_proof = context["control_proof"]
            else:
                reject_reserved_action(
                    "surface_not_controllable",
                    "Terminal control requires a Pairling-owned version 2 broker surface.",
                    409,
                )
                return
            audit["surface_source"] = snapshot.get("source")
            audit["surface_backend"] = snapshot.get("backend")
            audit["screen_hash"] = snapshot.get("screen_hash")
            audit["nonce"] = snapshot.get("nonce")
            audit["generation"] = snapshot.get("generation")
        except ProcessIdentityDriftError as e:
            reject_reserved_action("process_identity_unverified", str(e), 409)
            return
        except ValueError as e:
            reject_reserved_action("bad_session", str(e), 400)
            return
        except PermissionError as e:
            reject_reserved_action("invalid_tty", str(e), 403)
            return
        except FileNotFoundError as e:
            reject_reserved_action("terminal_not_found", str(e), 404)
            return
        except Exception as e:
            reject_reserved_action("surface_unavailable", str(e)[:200], 502)
            return

        stale = _terminal_control_v2_availability_error(snapshot)
        if stale is None:
            stale = _terminal_control_validate_screen(payload, snapshot, action)
        if stale:
            audit["error"] = stale["error"]["code"]
            _append_terminal_control_audit(audit)
            receipt = _make_action_receipt(
                client_action_id=client_action_id or None,
                state="rejected",
                phases=_receipt_phases(validated=False, applied=False, pty_written=False),
                backend=target.get("source"),
                tty=target.get("tty"),
                pid=target.get("pid"),
            )
            _receipt_attach_response(
                receipt,
                http_status=int(stale["status"]),
                error_code=str(stale["error"]["code"]),
                error_message=str(stale["error"]["message"]),
                fields={
                    "session_id": target["session_id"],
                    "action": action,
                    "current_screen_hash": stale.get("current_screen_hash"),
                    "current_nonce": stale.get("current_nonce"),
                    "current_generation": stale.get("current_generation"),
                },
            )
            stale["session_id"] = target["session_id"]
            stale["receipt"] = receipt
            _store_action_receipt(device_id, receipt_session_id, client_action_id or None, body_hash, receipt, action_kind="terminal_control", audit_action=audit.get("action"))
            self._send_json(stale, status=int(stale["status"]))
            return

        global LAST_HUMAN_ACTIVITY_AT
        LAST_HUMAN_ACTIVITY_AT = _time.time()
        _append_terminal_control_audit({**audit, "phase": "validated"})


        if target.get("source") == "broker_vt":
            broker_action = dict(action)
            if surface_schema_version == 2:
                broker_action.update({
                    "require_screen_proof": True,
                    "expected_screen_hash": broker_control_proof["screen_hash"],
                    "expected_nonce": broker_control_proof["nonce"],
                    "expected_generation": broker_control_proof["generation"],
                })
            if PTY_BROKER is None:
                result = {
                    "ok": False,
                    "reason": "broker_unavailable",
                    "error_code": "broker_unavailable",
                    "status": 503,
                    "pty_written": False,
                    "write_outcome": "none",
                }
            else:
                _mark_receipted_mutation_running(
                    mutation,
                    provider_id=provider,
                    provider_version="terminal-surface-v2",
                    provider_channel="pty_broker",
                    operation_id=f"terminal_control.{action['type']}",
                    binding_id=str(target["broker_id"]),
                    capability_generation=int(
                        broker_control_proof["generation"]
                    ),
                    recovery_correlation={
                        "provider_operation_id": client_action_id,
                        "provider_cursor": snapshot.get("screen_hash"),
                    },
                )
                try:
                    result = PTY_BROKER.control(target["broker_id"], broker_action)
                except PTYBrokerOutcomeUnknownError as exc:
                    # Once the request crossed the broker socket, a disconnect
                    # cannot prove whether zero, some, or all bytes reached the
                    # PTY. Finalize the action as indeterminate so idempotent
                    # replay never performs a second write.
                    result = {
                        "ok": False,
                        "reason": "broker_apply_outcome_unknown",
                        "error_code": "broker_apply_outcome_unknown",
                        "error": f"{type(exc).__name__}: {str(exc)[:160]}",
                        "status": 502,
                        "write_outcome": "unknown",
                        "outcome_indeterminate": True,
                    }
                except Exception as exc:
                    result = {
                        "ok": False,
                        "reason": "broker_unavailable",
                        "error_code": "broker_unavailable",
                        "error": f"{type(exc).__name__}: {str(exc)[:160]}",
                        "status": 503,
                        "pty_written": False,
                        "write_outcome": "none",
                        "outcome_indeterminate": False,
                    }
        elif action["type"] == "key" and action["key"] == "ctrl_c":
            _mark_receipted_mutation_running(
                mutation,
                provider_id=provider,
                provider_version="terminal-surface-v2",
                provider_channel=str(target.get("source") or "terminal"),
                operation_id="terminal_control.key",
                binding_id=str(target.get("broker_id") or target.get("tty")),
                capability_generation=int(snapshot["generation"]),
                recovery_correlation={
                    "provider_operation_id": client_action_id,
                    "provider_cursor": snapshot.get("screen_hash"),
                },
            )
            result = self._terminal_control_signal(target, signal.SIGINT, "SIGINT")
        else:
            _mark_receipted_mutation_running(
                mutation,
                provider_id=provider,
                provider_version="terminal-surface-v2",
                provider_channel=str(target.get("source") or "terminal"),
                operation_id=f"terminal_control.{action['type']}",
                binding_id=str(target.get("broker_id") or target.get("tty")),
                capability_generation=int(snapshot["generation"]),
                recovery_correlation={
                    "provider_operation_id": client_action_id,
                    "provider_cursor": snapshot.get("screen_hash"),
                },
            )
            result = self._terminal_control_run_in_terminal(target, action)

        ok = bool(result.get("ok"))
        public_current_proof = None
        if (
            not ok
            and result.get("reason") == "stale_screen"
            and target.get("source") == "broker_vt"
            and surface_schema_version == 2
        ):
            try:
                refreshed_pair = self._broker_surface_pair_snapshot(raw_session)
            except Exception:
                refreshed_pair = None
            refreshed_v2 = refreshed_pair.get("v2") if isinstance(refreshed_pair, dict) else None
            refreshed_generation = refreshed_v2.get("generation") if isinstance(refreshed_v2, dict) else None
            if (
                isinstance(refreshed_v2, dict)
                and str(refreshed_v2.get("screen_hash") or "")
                and str(refreshed_v2.get("nonce") or "")
                and isinstance(refreshed_generation, int)
                and not isinstance(refreshed_generation, bool)
            ):
                public_current_proof = {
                    "current_screen_hash": refreshed_v2["screen_hash"],
                    "current_nonce": refreshed_v2["nonce"],
                    "current_generation": refreshed_generation,
                }
        audit["ok"] = ok
        outcome_indeterminate = bool(result.get("outcome_indeterminate"))
        audit["phase"] = "applied" if ok else ("indeterminate" if outcome_indeterminate else "failed")
        if not ok:
            audit["error"] = result.get("error") or result.get("reason") or "terminal_control_failed"
        _append_terminal_control_audit(audit)
        status = 200 if ok else int(result.get("status") or 502)
        used_tty = result.get("stdout", "").split("\t", 1)[1] if str(result.get("stdout") or "").startswith("ok\t") else target.get("tty")
        source_offset_after = None
        source_offset_reason = None
        if ok and target.get("source") == "broker_vt" and PTY_BROKER:
            try:
                tail = PTY_BROKER.raw_tail(target.get("broker_id"), since=0)
            except Exception as exc:
                tail = None
                source_offset_reason = f"raw_tail_unavailable:{type(exc).__name__}"
            if tail:
                source_offset_after = tail[1]
            elif source_offset_reason is None:
                source_offset_reason = "no_broker_log"
        result_reports_pty_write = "pty_written" in result
        if result_reports_pty_write:
            pty_written: bool | None = bool(result.get("pty_written"))
        elif outcome_indeterminate:
            pty_written = None
        else:
            pty_written = bool(ok)
        receipt_phases = _receipt_phases(
            validated=True,
            applied=ok,
            pty_written=pty_written,
        )
        if result.get("write_outcome"):
            receipt_phases["pty_write_state"] = str(result["write_outcome"])
        receipt = _make_action_receipt(
            client_action_id=client_action_id or None,
            state="applied" if ok else ("indeterminate" if outcome_indeterminate else "failed"),
            phases=receipt_phases,
            backend=target.get("source"),
            tty=used_tty,
            pid=result.get("pid") or target.get("pid"),
            source_offset_after=source_offset_after,
            source_offset_reason=source_offset_reason,
        )
        response_code = str(
            result.get("error_code")
            or result.get("reason")
            or "terminal_control_failed"
        )
        response_message = (
            "The terminal screen advanced; refresh before sending control."
            if response_code == "stale_screen"
            else str(result.get("error") or result.get("reason") or "Terminal control failed.")
        )
        response_fields = {
            "session_id": target["session_id"],
            "action": action,
            "screen_hash": snapshot.get("screen_hash"),
            "nonce": snapshot.get("nonce"),
            "tty": used_tty,
            "pid": result.get("pid"),
            "reason": result.get("reason") or result.get("error"),
            "error_code": result.get("error_code"),
            "bytes_written": result.get("bytes_written"),
            "bytes_expected": result.get("bytes_expected"),
            "write_outcome": result.get("write_outcome"),
            "outcome_indeterminate": outcome_indeterminate,
            **(public_current_proof or {}),
        }
        _receipt_attach_response(
            receipt,
            http_status=status,
            error_code=response_code if not ok else None,
            error_message=response_message if not ok else None,
            fields=response_fields,
        )
        _store_action_receipt(
            device_id,
            receipt_session_id,
            client_action_id or None,
            body_hash,
            receipt,
            action_kind="terminal_control",
            audit_action=audit.get("action"),
        )
        response = {
            "ok": ok,
            **response_fields,
            "receipt": receipt,
        }
        response = {key: value for key, value in response.items() if value is not None}
        if not ok:
            response["error"] = {
                "code": response_code,
                "message": response_message,
            }
        if public_current_proof is not None:
            response.update(public_current_proof)
        self._send_json(response, status=status)

    def _resolve_transcript(self, session_id: str):
        """Resolve one exact Claude transcript without following path aliases."""
        native_id = _claude_native_session_id(session_id)
        if not native_id:
            return None
        session_id = _agent_registry_resolve_native_alias("claude", native_id)

        def accepted(candidate: Path) -> Path | None:
            try:
                with _open_session_transcript_file(candidate):
                    return candidate
            except (OSError, ValueError):
                return None

        if _safe_session_id(session_id) and session_id.startswith("s-"):
            claude_uuid = self._lookup_pg_field(session_id, "claude_uuid")
            project = self._lookup_pg_project(session_id)
            if claude_uuid and project:
                candidate = (
                    CLAUDE_PROJECTS_DIR
                    / _encode_project_dir(project)
                    / f"{claude_uuid}.jsonl"
                )
                return accepted(candidate)

        try:
            projects_fd = open_directory_fd(CLAUDE_PROJECTS_DIR, root=HOME)
        except (OSError, ValueError):
            return None
        try:
            for name in os.listdir(projects_fd):
                try:
                    project_fd = open_child_directory_fd(projects_fd, name)
                except (OSError, ValueError):
                    continue
                else:
                    os.close(project_fd)
                candidate = CLAUDE_PROJECTS_DIR / name / f"{session_id}.jsonl"
                if accepted(candidate) is not None:
                    return candidate
        finally:
            os.close(projects_fd)

        if not _safe_session_id(session_id):
            return None
        claude_uuid = self._lookup_pg_field(session_id, "claude_uuid")
        project = self._lookup_pg_project(session_id)
        if claude_uuid and project:
            candidate = (
                CLAUDE_PROJECTS_DIR
                / _encode_project_dir(project)
                / f"{claude_uuid}.jsonl"
            )
            return accepted(candidate)
        return None

    def _lookup_pg_project(self, session_id: str):
        """Query the continuous-claude PG for a session's project."""
        return self._lookup_pg_field(session_id, "project")

    def _lookup_pg_field(self, session_id: str, field: str):
        """Generic single-column read from the active claude session backend
        (name kept for grep-ability with the PG era; serves sqlite too)."""
        session_id = _claude_native_session_id(session_id)
        if not session_id or not field.replace("_", "").isalnum():
            return None
        return _claude_sessions_backend().lookup_field(session_id, field)

    # ----- /session-meta: effort, model, type, sentinel mode, working_on, size -----
    def _handle_session_meta(self, q):
        session_id = q.get("session", [""])[0]
        session_id = _claude_native_session_id(session_id)
        if not session_id:
            self.send_error(400, "session required")
            return

        meta = {
            "sessionId": _qualified_session_id("claude", session_id),
            "provider": "claude",
            "nativeId": session_id,
            "project": self._lookup_pg_project(session_id),
            "workingOn": self._lookup_pg_field(session_id, "working_on"),
            "transcriptFile": None,
            "transcriptSize": 0,
            "lineCount": 0,
            "kind": "main",
            "sentinelMode": None,
            "effort": None,
            "model": None,
        }

        path = self._resolve_transcript(session_id)
        if path:
            head = ""
            try:
                head_lines = []
                line_count = 0
                with _open_session_transcript_file(path) as f:
                    opened = os.fstat(f.fileno())
                    for raw_line in f:
                        if line_count < 120:
                            head_lines.append(raw_line.decode("utf-8", errors="replace"))
                        line_count += 1
                meta["transcriptFile"] = path.name
                meta["transcriptSize"] = opened.st_size
                meta["lineCount"] = line_count
                head = "".join(head_lines)
            except OSError:
                head = ""

            sm = re.search(r"\.claude/sentinel/modes/([A-Za-z0-9_-]+)/", head)
            if not sm:
                sm = re.search(r"forge-id:[A-Za-z0-9-]+[\s\S]{0,80}?mode:([A-Za-z0-9_-]+)", head)
            if sm:
                mode = sm.group(1).replace("_", "-")
                meta["sentinelMode"] = mode
                meta["kind"] = f"sentinel:{mode}"

            em = re.findall(
                r"<command-name>/effort</command-name>[\s\S]{0,200}?<command-args>(\w+)</command-args>",
                head,
            )
            if em:
                meta["effort"] = em[-1]

            mm = re.search(r"(claude-(?:opus|sonnet|haiku)-[\d.\-a-z]+)", head)
            if mm:
                meta["model"] = mm.group(1)

            if not meta["project"]:
                meta["project"] = _peek_cwd_from_transcript(path)

            # Last assistant text: streaming-tail the file to find the most recent
            # role==assistant message with a text content block. Verbatim — no
            # truncation up to the cap (any single Sonnet response well under).
            meta["lastAssistantText"] = _peek_last_assistant_text(path, max_chars=200_000)
            meta["firstPrompt"] = _peek_first_prompt(path)

        body = json.dumps(meta).encode()
        self.send_response(200)
        self.send_header("Content-Type", "application/json")
        self.send_header("Content-Length", str(len(body)))
        self.end_headers()
        self.wfile.write(body)

    # ----- /postures: user-authored prompt postures (SPEC-p6 §2.2) -----
    def _postures_root(self) -> Path:
        return HOME / ".pairling" / "postures"

    def _handle_deepfield_observation(self, q):
        """The voice telescope's file-drop: a verbatim transcript into
        deepfield's observations/inbox, mirroring bin/blurt exactly
        (YYYY-MM-DD-HHMMSS.md, one caught-header comment, then the text
        byte-for-byte). Verbatim into the user's layer; shaped copies stay in
        Pairling's layer. That covenant is the whole feature, so this
        endpoint never transforms the payload. Fail-closed when the
        observatory is absent."""
        raw = self._read_body() or b""
        mutation = _begin_receipted_mutation(
            self,
            receipt_scope="deepfield_observation",
            action_kind="deepfield_observation",
            material=raw,
            action_label="deepfield observations",
        )
        if mutation is None:
            return

        def finish(
            *,
            state: str,
            status: int,
            error_code: str | None = None,
            error_message: str | None = None,
            file_name: str | None = None,
        ) -> None:
            receipt = _finalize_receipted_mutation(
                mutation,
                state=state,
                http_status=status,
                backend="deepfield_inbox",
                error_code=error_code,
                error_message=error_message,
                fields={"file": file_name} if file_name else None,
                audit_action={"type": "deepfield_observation", "file": file_name},
            )
            body = {"ok": state == "applied", "receipt": receipt}
            if file_name:
                body["file"] = file_name
            if error_code:
                body["error"] = {
                    "code": error_code,
                    "message": error_message or error_code.replace("_", " "),
                }
            self._send_json(body, status=status)

        try:
            deepfield_root = _deepfield_repository_root()
            project_fd = open_directory_fd(deepfield_root, root=HOME)
        except FileNotFoundError:
            finish(
                state="rejected",
                status=404,
                error_code="no_observatory",
                error_message="deepfield is not present on this Mac",
            )
            return
        except (OSError, ValueError):
            finish(
                state="rejected",
                status=409,
                error_code="unsafe_observatory_path",
                error_message="deepfield repository path is unsafe",
            )
            return
        else:
            os.close(project_fd)
        if not raw.strip():
            finish(
                state="rejected",
                status=400,
                error_code="empty",
                error_message="empty observation",
            )
            return
        if len(raw) > 65536:
            finish(
                state="rejected",
                status=413,
                error_code="too_large",
                error_message="observation exceeds 64KB",
            )
            return
        published_path: Path | None = None
        directory_fd = -1
        temporary_name: str | None = None
        try:
            directory_fd = ensure_directory_fd(
                DEEPFIELD_INBOX_DIR,
                root=deepfield_root,
                mode=0o700,
            )
        except FileNotFoundError:
            finish(
                state="rejected",
                status=404,
                error_code="no_observatory",
                error_message="deepfield is not present on this Mac",
            )
            return
        except (OSError, ValueError):
            finish(
                state="rejected",
                status=409,
                error_code="unsafe_observatory_path",
                error_message="deepfield repository path is unsafe",
            )
            return
        try:
            stamp = _time.strftime("%Y-%m-%d-%H%M%S")
            header = f"<!-- caught {_time.strftime('%Y-%m-%d %H:%M:%S %Z')} via pairling-blurt, unprocessed -->\n\n".encode()
            payload = header + raw + (b"" if raw.endswith(b"\n") else b"\n")
            temporary_name = (
                f".{stamp}.{os.getpid()}.{secrets.token_hex(8)}.tmp"
            )
            flags = (
                os.O_CREAT
                | os.O_EXCL
                | os.O_WRONLY
                | getattr(os, "O_NOFOLLOW", 0)
            )
            fd = os.open(temporary_name, flags, 0o600, dir_fd=directory_fd)
            try:
                file_stat = os.fstat(fd)
                if not stat.S_ISREG(file_stat.st_mode) or file_stat.st_uid != os.getuid():
                    raise _UnsafeDeepfieldPathError("unsafe observation temporary file")
                view = memoryview(payload)
                written = 0
                while written < len(view):
                    count = os.write(fd, view[written:])
                    if count <= 0:
                        raise OSError("observation write made no progress")
                    written += count
                os.fsync(fd)
            finally:
                os.close(fd)

            # Publish the complete file relative to the already-validated inbox
            # descriptor. Neither source nor destination resolution can escape
            # through a replaced or symlinked pathname component.
            suffix = 1
            while True:
                name = f"{stamp}.md" if suffix == 1 else f"{stamp}-{suffix}.md"
                try:
                    os.link(
                        temporary_name,
                        name,
                        src_dir_fd=directory_fd,
                        dst_dir_fd=directory_fd,
                        follow_symlinks=False,
                    )
                    published_path = DEEPFIELD_INBOX_DIR / name
                    break
                except FileExistsError:
                    suffix += 1
                    if suffix > 100000:
                        raise
            os.fsync(directory_fd)
        except Exception as exc:
            finish(
                state="indeterminate" if published_path is not None else "failed",
                status=500,
                error_code=(
                    "observation_outcome_unknown"
                    if published_path is not None
                    else "write_failed"
                ),
                error_message=f"{type(exc).__name__}",
                file_name=published_path.name if published_path is not None else None,
            )
            return
        finally:
            if directory_fd >= 0:
                if temporary_name is not None:
                    try:
                        os.unlink(temporary_name, dir_fd=directory_fd)
                    except OSError:
                        pass
                os.close(directory_fd)
        finish(state="applied", status=200, file_name=published_path.name)

    def _handle_postures_list(self, q):
        try:
            rows = postures.list_postures(self._postures_root())
        except (postures.PostureIOError, OSError) as exc:
            self._send_json({
                "ok": False,
                "error": {
                    "code": getattr(exc, "code", "posture_io_failed"),
                    "message": "The posture files on this Mac could not be read.",
                },
            }, status=500)
            return
        self._send_json({"ok": True, "postures": rows})

    def _handle_posture_read(self, q, slug: str):
        try:
            row = postures.read_posture(self._postures_root(), slug)
        except (postures.PostureIOError, OSError) as exc:
            self._send_json({
                "ok": False,
                "error": {
                    "code": getattr(exc, "code", "posture_io_failed"),
                    "message": "This posture could not be read from the Mac.",
                },
            }, status=500)
            return
        if row is None:
            self._send_json({"ok": False, "error": {"code": "not_found", "message": "no such posture"}}, status=404)
            return
        self._send_json({"ok": True, "posture": row})

    def _handle_posture_write(self, q):
        raw = self._read_body() or b"{}"
        mutation = _begin_receipted_mutation(
            self,
            receipt_scope="posture_write",
            action_kind="posture_write",
            material=raw,
            action_label="posture changes",
        )
        if mutation is None:
            return

        def finish(
            *,
            state: str,
            status: int,
            code: str | None = None,
            message: str | None = None,
            fields: dict | None = None,
            audit: dict | None = None,
        ) -> None:
            receipt = _finalize_receipted_mutation(
                mutation,
                state=state,
                http_status=status,
                backend="posture_store",
                error_code=code,
                error_message=message,
                fields=fields,
                audit_action=audit,
            )
            response, response_status = _receipt_replay_response(
                receipt,
                {"ok": state == "applied"},
            )
            self._send_json(response, status=response_status)

        try:
            payload = json.loads(raw)
        except json.JSONDecodeError:
            finish(
                state="rejected",
                status=400,
                code="invalid_request",
                message="body must be JSON",
            )
            return
        if not isinstance(payload, dict):
            finish(
                state="rejected",
                status=400,
                code="invalid_request",
                message="body must be a JSON object",
            )
            return

        name = str(payload.get("name") or "").strip()
        description = str(payload.get("description") or "")
        body = str(payload.get("body") or "")
        mode = str(payload.get("mode") or "").strip().lower()
        original_slug = str(payload.get("original_slug") or "").strip() or None
        expected_revision = str(payload.get("expected_revision") or "").strip() or None
        audit_action = {
            "type": "posture_write",
            "name": name[:80],
            "mode": mode,
            "original_slug": original_slug,
        }
        if not name or not body.strip():
            finish(
                state="rejected",
                status=400,
                code="invalid_request",
                message="name and body are required",
                audit=audit_action,
            )
            return
        if not mode:
            finish(
                state="rejected",
                status=400,
                code="posture_mode_required",
                message="Choose create or edit explicitly.",
                audit=audit_action,
            )
            return
        if mode not in {"create", "edit"}:
            finish(
                state="rejected",
                status=400,
                code="invalid_request",
                message="mode must be create or edit",
                audit=audit_action,
            )
            return
        if mode == "create" and (original_slug is not None or expected_revision is not None):
            finish(
                state="rejected",
                status=400,
                code="invalid_request",
                message="create cannot include an original slug or expected revision",
                audit=audit_action,
            )
            return
        if mode == "edit" and (original_slug is None or expected_revision is None):
            finish(
                state="rejected",
                status=400,
                code="invalid_request",
                message="edit requires original_slug and expected_revision",
                audit=audit_action,
            )
            return
        try:
            written = postures.mutate_posture(
                self._postures_root(),
                name=name,
                description=description,
                body=body,
                original_slug=original_slug if mode == "edit" else None,
                expected_revision=expected_revision if mode == "edit" else None,
                create_only=mode == "create",
            )
        except postures.PostureTooLarge:
            message = f"posture body exceeds {postures.POSTURE_MAX_BYTES} bytes"
            finish(
                state="rejected",
                status=413,
                code="posture_too_large",
                message=message,
                fields={"error": {"code": "posture_too_large", "message": message}},
                audit={**audit_action, "error": "too_large"},
            )
            return
        except postures.PostureConflict as exc:
            current = exc.current if isinstance(exc.current, dict) else None
            current_summary = None
            if current is not None:
                current_summary = {
                    key: current.get(key)
                    for key in ("slug", "name", "description", "mtime", "revision")
                }
            error = {
                "code": "posture_conflict",
                "message": str(exc)[:200],
                "current": current_summary,
                "conflict_copies": exc.conflict_copies,
            }
            finish(
                state="rejected",
                status=409,
                code="posture_conflict",
                message=error["message"],
                fields={"error": error},
                audit={**audit_action, "error": "posture_conflict"},
            )
            return
        except ValueError as exc:
            finish(
                state="rejected",
                status=400,
                code="invalid_request",
                message=str(exc)[:200],
                audit={**audit_action, "error": "invalid_request"},
            )
            return
        except (postures.PostureIOError, OSError) as exc:
            code = getattr(exc, "code", "posture_io_failed")
            message = "The posture could not be saved on this Mac."
            finish(
                state="failed",
                status=500,
                code=code,
                message=message,
                fields={"error": {"code": code, "message": message}},
                audit={**audit_action, "error": type(exc).__name__},
            )
            return
        finish(
            state="applied",
            status=200,
            fields={"posture": written},
            audit={
                **audit_action,
                "slug": written["slug"],
                "overwrote": written["overwrote"],
                "renamed_from": written.get("renamed_from"),
                "revision": written.get("revision"),
            },
        )

    def _handle_posture_delete(self, q, slug: str):
        expected_revision = str((q.get("expected_revision", [""]) or [""])[0] or "").strip() or None
        audit_action = {"type": "posture_delete", "slug": slug[:80]}
        mutation = _begin_receipted_mutation(
            self,
            receipt_scope=f"posture_delete:{slug}",
            action_kind="posture_delete",
            material={"slug": slug, "expected_revision": expected_revision},
            action_label="posture deletion",
        )
        if mutation is None:
            return

        def finish(
            *,
            state: str,
            status: int,
            code: str | None = None,
            message: str | None = None,
            fields: dict | None = None,
            audit: dict | None = None,
        ) -> None:
            receipt = _finalize_receipted_mutation(
                mutation,
                state=state,
                http_status=status,
                backend="posture_store",
                error_code=code,
                error_message=message,
                fields=fields,
                audit_action=audit,
            )
            response, response_status = _receipt_replay_response(
                receipt,
                {"ok": state == "applied"},
            )
            self._send_json(response, status=response_status)

        if expected_revision is None:
            finish(
                state="rejected",
                status=400,
                code="posture_revision_required",
                message="Provide the posture revision when deleting.",
                audit=audit_action,
            )
            return
        try:
            removed = postures.delete_posture(
                self._postures_root(),
                slug,
                expected_revision=expected_revision,
            )
        except postures.PostureConflict as exc:
            message = str(exc)[:200]
            finish(
                state="rejected",
                status=409,
                code="posture_conflict",
                message=message,
                fields={"error": {"code": "posture_conflict", "message": message}},
                audit={**audit_action, "error": "posture_conflict"},
            )
            return
        except ValueError as exc:
            finish(
                state="rejected",
                status=400,
                code="invalid_request",
                message=str(exc)[:200],
                audit={**audit_action, "error": "invalid_request"},
            )
            return
        except (postures.PostureIOError, OSError) as exc:
            code = getattr(exc, "code", "posture_io_failed")
            message = "The posture could not be deleted from this Mac."
            finish(
                state="failed",
                status=500,
                code=code,
                message=message,
                fields={"error": {"code": code, "message": message}},
                audit={**audit_action, "error": type(exc).__name__},
            )
            return
        if not removed:
            finish(
                state="rejected",
                status=404,
                code="not_found",
                message="no such posture",
                audit={**audit_action, "removed": False},
            )
            return
        finish(
            state="applied",
            status=200,
            fields={"slug": slug},
            audit={**audit_action, "removed": True},
        )

    # ----- /personal-context: serve ~/.claude/personal-context.md -----
    def _handle_personal_context(self, q):
        path = HOME / ".claude" / "personal-context.md"
        if not path.exists():
            body = b'{"present": false, "content": ""}'
        else:
            try:
                content = path.read_text(encoding="utf-8")
            except Exception:
                content = ""
            body = json.dumps({
                "present": True,
                "content": content,
                "mtime": path.stat().st_mtime,
                "size": path.stat().st_size,
            }).encode()

        self.send_response(200)
        self.send_header("Content-Type", "application/json")
        self.send_header("Content-Length", str(len(body)))
        self.end_headers()
        self.wfile.write(body)

    @staticmethod
    def _llm_route_model_family(model: str) -> str | None:
        if llm_route_model_family is not None:
            return llm_route_model_family(model)
        return None


    # ----- /llm-route: filesystem-isolated one-shot prompt routing -----
    def _handle_llm_route(self, q):
        """Route an in-memory prompt without exposing a local agent process.

        Body: JSON {prompt, system?, max_chars?}
        Query: ?model=sonnet|haiku|opus|gpt-5.5|gpt-5.4|gpt-5.4-mini|gpt-5.3-codex
        """
        model = q.get("model", ["sonnet"])[0]
        family = self._llm_route_model_family(model)
        if family is None:
            self.send_error(400, "model must be sonnet|haiku|opus|gpt-5.5|gpt-5.4|gpt-5.4-mini|gpt-5.3-codex")
            return

        try:
            payload = json.loads(self._read_body() or b"{}")
        except json.JSONDecodeError:
            self.send_error(400, "body must be JSON")
            return

        prompt = (payload.get("prompt") or "").strip()
        system = (payload.get("system") or "").strip()
        max_chars = int(payload.get("max_chars") or 8000)
        if not prompt:
            self.send_error(400, "prompt required")
            return
        if len(prompt) > max_chars:
            prompt = prompt[:max_chars]

        if run_remote_llm is None:
            self.send_error(503, "remote LLM route helper unavailable")
            return

        try:
            content = run_remote_llm(model=model, prompt=prompt, system=system, timeout_seconds=120)
        except Exception as exc:
            status = int(getattr(exc, "status", 502) or 502)
            message = str(getattr(exc, "message", str(exc)) or str(exc))
            self.send_error(status, message)
            return

        body = json.dumps({
            "ok": True,
            "model": model,
            "content": content,
        }).encode()
        self.send_response(200)
        self.send_header("Content-Type", "application/json")
        self.send_header("Content-Length", str(len(body)))
        self.end_headers()
        self.wfile.write(body)

    # ----- /activity + /workers: operator surfaces for the phone -----
    _WORKER_PATTERNS = (
        "biotech-labs/synth-synth-",
        "biotech-labs/crohns-research/scripts",
        "biotech-research-",
    )

    def _send_json(
        self,
        payload: dict,
        status: int = 200,
        headers: dict[str, str] | None = None,
    ):
        body = json.dumps(payload).encode()
        try:
            self.send_response(status)
            self.send_header("Content-Type", "application/json")
            self.send_header("Content-Length", str(len(body)))
            for name, value in (headers or {}).items():
                self.send_header(name, value)
            self.end_headers()
            self.wfile.write(body)
        except (BrokenPipeError, ConnectionResetError) as exc:
            raise ClientDisconnected() from exc

    def _collect_session_rows_uncached(
        self,
        since_min: int = 360,
        live_only: bool = False,
        limit: int = 100,
        include_first_prompt: bool = True,
        live_terminal_rows: list[dict] | None = None,
        require_complete: bool = False,
    ) -> list[dict]:
        since_min = max(1, min(int(since_min), 60 * 24 * 14))
        limit = max(1, min(int(limit), 500))
        _claude_register_terminal_only_rows(set(), live_terminal_rows)
        backend = _claude_sessions_backend()
        if require_complete:
            backend_rows = backend.collect_rows(
                since_min,
                live_only,
                limit,
                strict=True,
            )
        else:
            backend_rows = backend.collect_rows(since_min, live_only, limit)
        rows: list[dict] = []
        try:
            _session_tombstone_keys()
        except SessionTombstoneStoreError:
            return []
        for raw in backend_rows:
            session_id, project = raw["id"], raw["project"]
            if _is_excluded_project(project):
                continue
            claude_uuid = raw.get("claude_uuid") or ""
            row = dict(raw)
            row["first_prompt"] = None
            row.update(self._turn_state_summary(claude_uuid))
            _refresh_claude_observed_activity(row, project, claude_uuid)
            if include_first_prompt and project and claude_uuid:
                transcript = (
                    HOME / ".claude" / "projects" / _encode_project_dir(project)
                    / f"{claude_uuid}.jsonl"
                )
                if transcript.is_file():
                    row["first_prompt"] = _peek_first_prompt(transcript)
            if project and claude_uuid:
                transcript = (
                    HOME / ".claude" / "projects" / _encode_project_dir(project)
                    / f"{claude_uuid}.jsonl"
                )
                stats = _session_transcript_stats(
                    transcript, "claude", session_id
                )
                row["turn_count"] = stats.get("turn_count")
                row["last_meaningful_turn_at"] = stats.get(
                    "last_meaningful_turn_at"
                )
            rows.append(row)
        return _filter_tombstoned_session_rows(rows)

    def _collect_session_rows(self, since_min: int = 360, live_only: bool = False, limit: int = 100, include_first_prompt: bool = True) -> list[dict]:
        since_min = max(1, min(int(since_min), 60 * 24 * 14))
        limit = max(1, min(int(limit), 500))
        cache_key = ("collect-session-rows", since_min, bool(live_only), limit, bool(include_first_prompt))

        return _cached_runtime_snapshot(
            cache_key,
            RUNTIME_SNAPSHOT_CACHE_SECONDS,
            lambda: self._collect_session_rows_uncached(
                since_min=since_min,
                live_only=live_only,
                limit=limit,
                include_first_prompt=include_first_prompt,
            ),
        )

    def _recent_session_signal(self, session_id: str, project: str | None = None, claude_uuid: str | None = None) -> dict:
        """Cheap parse of the tail of a transcript for Activity/Workers rows."""
        signal = {
            "anomaly": None,
            "latest_tool": None,
            "latest_command": None,
            "latest_edit": None,
            "latest_event_ts": None,
        }
        path = None
        if project and claude_uuid:
            candidate = HOME / ".claude" / "projects" / _encode_project_dir(project) / f"{claude_uuid}.jsonl"
            if candidate.exists():
                path = candidate
        if path is None:
            path = self._resolve_transcript(session_id)
        if not path or not path.exists():
            return signal
        try:
            lines = _tail_lines(path, max_lines=240, max_bytes=TRANSCRIPT_TAIL_SCAN_BYTES)
        except OSError:
            return signal
        for raw in reversed(lines):
            if not raw.strip():
                continue
            try:
                obj = json.loads(raw)
            except (ValueError, json.JSONDecodeError):
                continue
            ts = obj.get("timestamp")
            if signal["latest_event_ts"] is None and isinstance(ts, str):
                signal["latest_event_ts"] = ts
            msg = obj.get("message") or {}
            content = msg.get("content")
            if isinstance(content, list):
                for block in reversed(content):
                    if not isinstance(block, dict):
                        continue
                    if block.get("type") != "tool_use":
                        continue
                    name = block.get("name")
                    inp = block.get("input") if isinstance(block.get("input"), dict) else {}
                    if signal["latest_tool"] is None and isinstance(name, str):
                        signal["latest_tool"] = name
                    if signal["latest_command"] is None and name == "Bash":
                        cmd = inp.get("command")
                        if isinstance(cmd, str) and cmd:
                            signal["latest_command"] = cmd[:240]
                    if signal["latest_edit"] is None and name in ("Edit", "MultiEdit", "Write"):
                        fp = inp.get("file_path") or inp.get("path")
                        if isinstance(fp, str) and fp:
                            signal["latest_edit"] = fp
            if signal["anomaly"] is None:
                line_type = obj.get("type")
                subtype = obj.get("subtype")
                if line_type in ("error", "system") and subtype not in {"stop_hook_summary", "turn_duration", "compact_boundary"}:
                    signal["anomaly"] = {
                        "kind": line_type,
                        "title": f"{line_type}: {subtype or 'event'}",
                        "detail": (obj.get("content") or obj.get("text") or "")[:240],
                    }
                sr = msg.get("stop_reason")
                if isinstance(sr, str) and sr not in ("end_turn", "tool_use"):
                    signal["anomaly"] = {
                        "kind": "stop_reason",
                        "title": f"Stopped: {sr}",
                        "detail": json.dumps(msg.get("stop_details") or {})[:240],
                    }
            if signal["anomaly"] and signal["latest_tool"] and (signal["latest_command"] or signal["latest_edit"]):
                break
        return signal

    def _is_worker_project(self, project: str) -> bool:
        return any(p in project for p in self._WORKER_PATTERNS)

    def _worker_row_from_session(self, row: dict, now_epoch: int | None = None) -> dict:
        now_epoch = now_epoch or int(_time.time())
        native_id = row["id"]
        heartbeat = int(row.get("last_heartbeat") or 0)
        started = int(row.get("started_at") or 0)
        stale_seconds = max(0, now_epoch - heartbeat) if heartbeat else 0
        runtime_seconds = max(0, now_epoch - started) if started else 0
        active = stale_seconds < 300
        stale = stale_seconds >= 3600
        signal = self._recent_session_signal(
            row["id"],
            project=row.get("project"),
            claude_uuid=row.get("claude_uuid"),
        )
        context_pct = float(row.get("context_pct") or 0.0)
        risk = 0
        reasons: list[str] = []
        if active:
            risk += 1
        if stale:
            risk += 4; reasons.append("idle >60m")
        if context_pct >= 85:
            risk += 3; reasons.append("high context")
        elif context_pct >= 70:
            risk += 2; reasons.append("context pressure")
        state = row.get("state")
        if state in ("thinking", "tool"):
            turn_started = row.get("turn_started_at")
            if isinstance(turn_started, (int, float)) and now_epoch - turn_started > 900:
                risk += 2; reasons.append("long turn")
        if signal.get("anomaly"):
            risk += 3; reasons.append("recent anomaly")
        return {
            "id": _qualified_session_id("claude", native_id),
            "provider": "claude",
            "native_id": native_id,
            "project": row.get("project") or "",
            "working_on": row.get("working_on"),
            "first_prompt": row.get("first_prompt"),
            "started_at": started,
            "last_heartbeat": heartbeat,
            "stale_seconds": stale_seconds,
            "runtime_seconds": runtime_seconds,
            "active": active,
            "stale": stale,
            "stale_reason": "idle >60 minutes" if stale else None,
            "risk_score": risk,
            "risk_reasons": reasons,
            "state": state,
            "tool": row.get("tool"),
            "model": row.get("model"),
            "effort": row.get("effort"),
            "context_pct": context_pct,
            "turn_started_at": row.get("turn_started_at"),
            "latest_tool": signal.get("latest_tool"),
            "latest_command": signal.get("latest_command"),
            "latest_edit": signal.get("latest_edit"),
            "recent_anomaly": signal.get("anomaly"),
        }

    def _registry_metadata(self, row: dict) -> dict:
        try:
            obj = json.loads(row.get("metadata_json") or "{}")
            return obj if isinstance(obj, dict) else {}
        except Exception:
            return {}

    def _codex_worker_signal(self, metadata: dict) -> dict:
        signal = {
            "latest_tool": None,
            "latest_command": None,
            "latest_edit": None,
            "anomaly": None,
        }
        output_path = metadata.get("output_path")
        if isinstance(output_path, str):
            p = Path(output_path)
            if p.is_file():
                try:
                    lines = _tail_lines(p, max_lines=240, max_bytes=TRANSCRIPT_TAIL_SCAN_BYTES)
                except OSError:
                    lines = []
                for raw in reversed(lines):
                    for row in _normalize_codex_line(raw, metadata.get("native_id") or ""):
                        msg = row.get("message") or {}
                        for block in reversed(msg.get("content") or []):
                            if not isinstance(block, dict):
                                continue
                            if block.get("type") == "tool_use" and signal["latest_tool"] is None:
                                name = block.get("name")
                                inp = block.get("input") if isinstance(block.get("input"), dict) else {}
                                if isinstance(name, str):
                                    signal["latest_tool"] = name
                                command = inp.get("command") or inp.get("cmd")
                                if isinstance(command, str) and not signal["latest_command"]:
                                    signal["latest_command"] = command[:240]
                                fp = inp.get("file_path") or inp.get("path")
                                if isinstance(fp, str) and not signal["latest_edit"]:
                                    signal["latest_edit"] = fp
                    if signal["latest_tool"] and (signal["latest_command"] or signal["latest_edit"] or signal["anomaly"]):
                        break
        exit_code = metadata.get("exit_code")
        if signal["anomaly"] is None and isinstance(exit_code, int) and exit_code != 0:
            detail = ""
            stderr_path = metadata.get("stderr_path")
            if isinstance(stderr_path, str):
                try:
                    detail = Path(stderr_path).read_text(errors="replace")[-500:].strip()
                except OSError:
                    detail = ""
            signal["anomaly"] = {
                "kind": "exit_code",
                "title": f"Codex worker exited {exit_code}",
                "detail": detail[:240],
            }
        return signal

    def _codex_worker_row_from_registry(self, row: dict, now_epoch: int | None = None) -> dict | None:
        metadata = self._registry_metadata(row)
        if metadata.get("kind") not in {"worker", "orchestration_worker"}:
            return None
        now_epoch = now_epoch or int(_time.time())
        native_id = row.get("native_id") or metadata.get("native_id") or ""
        if not native_id:
            return None
        metadata.setdefault("native_id", native_id)
        heartbeat = int(row.get("last_heartbeat") or row.get("started_at") or 0)
        started = int(row.get("started_at") or heartbeat or now_epoch)
        pid = int(row.get("pid") or 0)
        closed_at = row.get("closed_at")
        process_alive = bool(pid and _process_alive(pid))
        if pid and not process_alive and not closed_at:
            _agent_registry_mark_closed("codex", native_id)
            closed_at = int(_time.time())
        stale_seconds = max(0, now_epoch - heartbeat) if heartbeat else 0
        runtime_seconds = max(0, now_epoch - started) if started else 0
        active = bool(process_alive and not closed_at)
        stale = bool(active and stale_seconds >= 3600)
        signal = self._codex_worker_signal(metadata)
        risk = 0
        reasons: list[str] = []
        if active:
            risk += 1
        if stale:
            risk += 4; reasons.append("idle >60m")
        if metadata.get("orchestration_id") and "orchestration" not in reasons:
            reasons.append("orchestration")
        if signal.get("anomaly"):
            risk += 3; reasons.append("recent anomaly")
        state = metadata.get("state") or row.get("state")
        if active:
            state = state or "running"
        elif metadata.get("exit_code") == 0:
            state = "idle"
        else:
            state = state or "terminated"
        return {
            "id": _qualified_session_id("codex", native_id),
            "provider": "codex",
            "native_id": native_id,
            "project": row.get("project") or metadata.get("project") or "",
            "working_on": metadata.get("title") or metadata.get("role") or metadata.get("prompt_preview"),
            "first_prompt": metadata.get("prompt_preview"),
            "started_at": started,
            "last_heartbeat": heartbeat,
            "stale_seconds": stale_seconds,
            "runtime_seconds": runtime_seconds,
            "active": active,
            "stale": stale,
            "stale_reason": "idle >60 minutes" if stale else None,
            "risk_score": risk,
            "risk_reasons": reasons,
            "state": state,
            "tool": metadata.get("tool"),
            "model": metadata.get("model"),
            "effort": metadata.get("effort"),
            "context_pct": None,
            "turn_started_at": None,
            "latest_tool": signal.get("latest_tool"),
            "latest_command": signal.get("latest_command"),
            "latest_edit": signal.get("latest_edit"),
            "recent_anomaly": signal.get("anomaly"),
        }

    def _orchestration_session_id_set(self) -> set[str]:
        ids: set[str] = set()
        for path in ORCHESTRATIONS_DIR.glob("orchestration-*.json"):
            try:
                run = json.loads(path.read_text())
            except Exception:
                continue
            for launch in run.get("launches") or []:
                sid = launch.get("session_id")
                if isinstance(sid, str) and sid:
                    ids.add(sid)
                    _, native = _parse_agent_session_ref(sid)
                    if native:
                        ids.add(native)
            for session in run.get("sessions") or []:
                sid = session.get("session_id")
                if isinstance(sid, str) and sid:
                    ids.add(sid)
                    _, native = _parse_agent_session_ref(sid)
                    if native:
                        ids.add(native)
        return ids

    def _collect_workers(self, since_min: int = 60 * 24, include_first_prompt: bool = True) -> list[dict]:
        now_epoch = int(_time.time())
        orchestration_ids = self._orchestration_session_id_set()
        workers = []
        for row in self._collect_session_rows(
            since_min=since_min,
            live_only=False,
            limit=300,
            include_first_prompt=include_first_prompt,
        ):
            first_prompt = row.get("first_prompt") or ""
            qualified_id = _qualified_session_id("claude", row.get("id") or "")
            is_orchestration = row.get("id") in orchestration_ids or qualified_id in orchestration_ids or "Pairling orchestration" in first_prompt
            if self._is_worker_project(row.get("project") or "") or is_orchestration:
                worker = self._worker_row_from_session(row, now_epoch)
                if is_orchestration and "orchestration" not in worker["risk_reasons"]:
                    worker["risk_reasons"].append("orchestration")
                workers.append(worker)
        return workers

    def _collect_codex_workers(self, since_min: int = 60 * 24) -> list[dict]:
        now_epoch = int(_time.time())
        workers: list[dict] = []
        for row in _agent_registry_recent("codex", since_min=since_min, limit=500):
            worker = self._codex_worker_row_from_registry(row, now_epoch)
            if worker:
                workers.append(worker)
        return workers

    @staticmethod
    def _activity_string_value(value) -> str:
        if value is None:
            return ""
        if isinstance(value, bool):
            return "Yes" if value else "No"
        if isinstance(value, (int, float)):
            return str(value)
        if isinstance(value, str):
            return value.strip()
        if isinstance(value, list):
            return ", ".join(Handler._activity_string_value(v) for v in value[:6] if Handler._activity_string_value(v))
        if isinstance(value, dict):
            try:
                return json.dumps(value, sort_keys=True)
            except (TypeError, ValueError):
                return str(value)
        return str(value)

    @staticmethod
    def _bounded_raw_details(value, limit: int = 4000) -> str:
        try:
            raw = json.dumps(value, sort_keys=True, indent=2, ensure_ascii=False)
        except (TypeError, ValueError):
            raw = str(value)
        if len(raw) > limit:
            return raw[:limit].rstrip() + "\n..."
        return raw

    @staticmethod
    def _first_nonempty_line(text: str, limit: int = 180) -> str:
        for line in str(text or "").splitlines():
            line = line.strip()
            if line:
                return line[:limit]
        return ""

    @staticmethod
    def _activity_tool_details(tool: str, inp: dict) -> dict[str, str]:
        labels = {
            "cmd": "Command",
            "command": "Command",
            "workdir": "Directory",
            "cwd": "Directory",
            "path": "Path",
            "file_path": "File",
            "files": "Files",
            "yield_time_ms": "Yield",
            "max_output_tokens": "Output cap",
            "timeout_ms": "Timeout",
            "session_id": "Session",
            "target": "Target",
            "chars": "Input",
        }
        details: dict[str, str] = {}
        for key, label in labels.items():
            if key not in inp:
                continue
            value = Handler._activity_string_value(inp.get(key))
            if value:
                details[label] = value[:240]
        if not details and inp:
            for key in sorted(inp.keys())[:4]:
                value = Handler._activity_string_value(inp.get(key))
                if value:
                    details[key.replace("_", " ").title()] = value[:240]
        if tool and "Tool" not in details:
            details = {"Tool": str(tool), **details}
        return details

    @staticmethod
    def _activity_tool_summary(tool: str, inp: dict) -> str:
        details = Handler._activity_tool_details(tool, inp)
        for key in ("Command", "File", "Path", "Directory", "Target"):
            if details.get(key):
                return f"{key}: {details[key]}"
        return "Tool call captured from session history."

    @staticmethod
    def _coerce_activity_tool(tool) -> tuple[str | None, dict]:
        if isinstance(tool, dict):
            name = tool.get("name") or tool.get("tool") or tool.get("type")
            return str(name) if name else None, tool
        if not isinstance(tool, str):
            return None, {}
        text = tool.strip()
        if not text:
            return None, {}
        if text.startswith("{"):
            try:
                obj = json.loads(text)
            except (TypeError, ValueError, json.JSONDecodeError):
                return text, {}
            if isinstance(obj, dict):
                name = obj.get("name") or obj.get("tool") or obj.get("type")
                if not name:
                    name = "exec_command" if "cmd" in obj else "tool"
                return str(name), obj
        return text, {}

    def _codex_activity_items(self, since_min: int = 360, limit: int = 80) -> list[dict]:
        cutoff = _time.time() - max(1, since_min) * 60
        items: list[dict] = []
        for path in _codex_rollout_paths()[:80]:
            try:
                st = path.stat()
            except OSError:
                continue
            if st.st_mtime < cutoff:
                continue
            meta = _codex_rollout_meta(path)
            if not meta:
                continue
            native_id = meta["id"]
            project = meta["cwd"]
            project_name = os.path.basename(project.rstrip("/")) or project
            try:
                lines = _tail_lines(path, max_lines=240, max_bytes=TRANSCRIPT_TAIL_SCAN_BYTES)
            except OSError:
                continue
            for raw in reversed(lines):
                for row in _normalize_codex_line(raw, native_id):
                    ts = _iso_to_epoch(row.get("timestamp")) or st.st_mtime
                    if ts < cutoff:
                        continue
                    msg = row.get("message") or {}
                    for block in msg.get("content") or []:
                        if not isinstance(block, dict):
                            continue
                        btype = block.get("type")
                        if btype == "tool_use":
                            tool = block.get("name") or "tool"
                            inp = block.get("input") if isinstance(block.get("input"), dict) else {}
                            details = self._activity_tool_details(str(tool), inp)
                            raw_details = self._bounded_raw_details(inp)
                            event_type = "running_tool"
                            title = f"{project_name}: {tool}"
                            if str(tool).lower() in {"apply_patch", "edit", "write", "multi_edit"}:
                                event_type = "file_edit"
                                title = f"{project_name}: edited file"
                            items.append({
                                "id": f"codex-tool-{row.get('uuid')}-{hashlib.sha256((str(tool) + raw_details).encode()).hexdigest()[:8]}",
                                "provider": "codex",
                                "type": event_type,
                                "severity": "info",
                                "timestamp": int(ts),
                                "session_id": _qualified_session_id("codex", native_id),
                                "project": project,
                                "title": title,
                                "subtitle": self._activity_tool_summary(str(tool), inp),
                                "details": details,
                                "raw_details": raw_details,
                                "state": None,
                                "tool": tool,
                                "context_pct": None,
                                "entry_id": row.get("uuid"),
                            })
                        elif btype == "tool_result":
                            content = block.get("content")
                            if isinstance(content, str) and ("error" in content.lower() or "traceback" in content.lower()):
                                summary = self._first_nonempty_line(content) or "Diagnostic output captured from Codex."
                                items.append({
                                    "id": f"codex-diagnostic-{row.get('uuid')}",
                                    "provider": "codex",
                                    "type": "diagnostic",
                                    "severity": "info",
                                    "timestamp": int(ts),
                                    "session_id": _qualified_session_id("codex", native_id),
                                    "project": project,
                                    "title": f"{project_name}: diagnostic tool output",
                                    "subtitle": summary,
                                    "details": {
                                        "Output": summary,
                                    },
                                    "raw_details": content[:4000] + ("\n..." if len(content) > 4000 else ""),
                                    "state": None,
                                    "tool": None,
                                    "context_pct": None,
                                    "entry_id": row.get("uuid"),
                                })
                if len(items) >= limit:
                    break
            if len(items) >= limit:
                break
        return items[:limit]

    @staticmethod
    def _terminal_source_diagnostic_event(provider: str, rows: list[dict], now_epoch: int) -> dict | None:
        if not rows:
            return None
        sources: dict[str, int] = {}
        unavailable = 0
        surface_count = 0
        control_count = 0
        needs_input = 0
        for row in rows:
            capabilities = set(row.get("capabilities") or [])
            has_surface = "terminal_surface" in capabilities
            has_control = "terminal_control" in capabilities
            surface_count += 1 if has_surface else 0
            control_count += 1 if has_control else 0
            if isinstance(row.get("terminal_attention"), dict) and row["terminal_attention"].get("needs_input"):
                needs_input += 1

            source = "unavailable"
            if provider == "codex":
                source_info = _terminal_surface_source(row.get("id") or "")
                source = str(source_info.get("source") or "unavailable")
            elif has_surface:
                source = "terminal_app_contents"
            sources[source] = sources.get(source, 0) + 1
            if source == "unavailable":
                unavailable += 1

        provider_label = "Codex" if provider == "codex" else "Claude"
        details = {
            "Live sessions": str(len(rows)),
            "Terminal surface": str(surface_count),
            "Terminal control": str(control_count),
            "Broker VT": str(sources.get("broker_vt", 0)),
            "Terminal.app": str(sources.get("terminal_app_contents", 0)),
            "Unavailable": str(unavailable),
            "Needs input": str(needs_input),
            "Raw screen rows": "Not included",
        }
        raw_details = {
            "provider": provider,
            "live_sessions": len(rows),
            "terminal_surface": surface_count,
            "terminal_control": control_count,
            "needs_input": needs_input,
            "sources": sources,
            "screen_rows_included": False,
        }
        return {
            "id": f"terminal-source-{provider}",
            "provider": provider,
            "type": "diagnostic",
            "severity": "warning" if unavailable and surface_count == 0 else "info",
            "timestamp": now_epoch,
            "session_id": f"{provider}:terminal-source-diagnostics",
            "project": "Pairling terminal diagnostics",
            "title": f"Terminal source diagnostics: {provider_label}",
            "subtitle": f"{surface_count}/{len(rows)} live sessions expose terminal surface; {control_count}/{len(rows)} expose safe controls.",
            "details": details,
            "raw_details": Handler._bounded_raw_details(raw_details),
            "state": None,
            "tool": None,
            "context_pct": None,
            "entry_id": None,
        }

    def _terminal_source_diagnostic_items(self, since_min: int, now_epoch: int) -> list[dict]:
        items: list[dict] = []
        try:
            claude_rows = self._collect_session_rows(
                since_min=since_min,
                live_only=True,
                limit=100,
                include_first_prompt=False,
            )
            claude_event = self._terminal_source_diagnostic_event("claude", claude_rows, now_epoch)
            if claude_event:
                items.append(claude_event)
        except Exception:
            pass
        try:
            codex_rows = _list_codex_sessions(live_only=True, active_within_min=since_min)
            codex_event = self._terminal_source_diagnostic_event("codex", codex_rows, now_epoch)
            if codex_event:
                items.append(codex_event)
        except Exception:
            pass
        return items

    def _activity_items(self, since_min: int = 360, limit: int = 120) -> list[dict]:
        now_epoch = int(_time.time())
        items: list[dict] = []
        for row in self._collect_session_rows(since_min=since_min, live_only=True, limit=100):
            sid = row["id"]
            project = row.get("project") or ""
            project_name = os.path.basename(project) or project
            state = row.get("state")
            turn_started = row.get("turn_started_at")
            ts = int(turn_started) if isinstance(turn_started, (int, float)) else int(row.get("last_heartbeat") or now_epoch)
            if state in ("thinking", "tool"):
                tool = row.get("tool")
                tool_name, tool_input = self._coerce_activity_tool(tool)
                tool_details = self._activity_tool_details(tool_name or "", tool_input) if tool_input else None
                tool_raw_details = self._bounded_raw_details(tool_input) if tool_input else None
                elapsed = max(0, now_epoch - ts)
                items.append({
                    "id": f"active-{sid}-{state}",
                    "provider": "claude",
                    "type": "running_tool" if state == "tool" else "thinking",
                    "severity": "warning" if elapsed > 900 else "info",
                    "timestamp": ts,
                    "session_id": sid,
                    "project": project,
                    "title": f"{project_name}: {tool_name or state}",
                    "subtitle": self._activity_tool_summary(tool_name or "", tool_input) if tool_input else (f"Running for {elapsed // 60}m {elapsed % 60}s" if elapsed >= 60 else f"Running for {elapsed}s"),
                    "details": tool_details,
                    "raw_details": tool_raw_details,
                    "state": state,
                    "tool": tool_name or tool,
                    "context_pct": row.get("context_pct"),
                    "entry_id": None,
                })
            context_pct = float(row.get("context_pct") or 0.0)
            if context_pct >= 70:
                items.append({
                    "id": f"context-{sid}",
                    "provider": "claude",
                    "type": "context_pressure",
                    "severity": "critical" if context_pct >= 95 else ("warning" if context_pct >= 85 else "info"),
                    "timestamp": int(row.get("last_heartbeat") or now_epoch),
                    "session_id": sid,
                    "project": project,
                    "title": f"{project_name}: {context_pct:.0f}% context",
                    "subtitle": "Consider summarizing, compacting, or starting a fresh session.",
                    "state": state,
                    "tool": row.get("tool"),
                    "context_pct": context_pct,
                    "entry_id": None,
                })
            sig = self._recent_session_signal(
                sid,
                project=row.get("project"),
                claude_uuid=row.get("claude_uuid"),
            )
            if sig.get("anomaly"):
                an = sig["anomaly"]
                items.append({
                    "id": f"anomaly-{sid}-{an.get('kind')}",
                    "provider": "claude",
                    "type": "anomaly",
                    "severity": "critical" if an.get("kind") == "error" else "warning",
                    "timestamp": int(row.get("last_heartbeat") or now_epoch),
                    "session_id": sid,
                    "project": project,
                    "title": f"{project_name}: {an.get('title')}",
                    "subtitle": an.get("detail") or "Open the transcript for details.",
                    "state": state,
                    "tool": row.get("tool"),
                    "context_pct": context_pct,
                    "entry_id": None,
                })
            if sig.get("latest_edit"):
                items.append({
                    "id": f"edit-{sid}-{hashlib.sha256(sig['latest_edit'].encode()).hexdigest()[:8]}",
                    "provider": "claude",
                    "type": "file_edit",
                    "severity": "info",
                    "timestamp": int(row.get("last_heartbeat") or now_epoch),
                    "session_id": sid,
                    "project": project,
                    "title": f"{project_name}: edited file",
                    "subtitle": sig["latest_edit"],
                    "state": state,
                    "tool": row.get("tool"),
                    "context_pct": context_pct,
                    "entry_id": None,
                })
        activity_workers = self._collect_workers(since_min=min(since_min, 360), include_first_prompt=False)
        activity_workers.extend(self._collect_codex_workers(since_min=min(since_min, 360)))
        for worker in activity_workers:
            if worker["stale"] or worker["risk_score"] >= 5:
                items.append({
                    "id": f"worker-{worker['id']}",
                    "provider": worker.get("provider") or "claude",
                    "type": "worker",
                    "severity": "critical" if worker["stale"] else "warning",
                    "timestamp": int(worker["last_heartbeat"] or now_epoch),
                    "session_id": worker["id"],
                    "project": worker["project"],
                    "title": f"Worker risk: {os.path.basename(worker['project'])}",
                    "subtitle": ", ".join(worker["risk_reasons"]) or "Worker needs review.",
                    "state": worker["state"],
                    "tool": worker["tool"],
                    "context_pct": worker["context_pct"],
                    "entry_id": None,
                })
        items.extend(self._codex_activity_items(since_min=since_min, limit=max(20, limit // 2)))
        items.extend(self._terminal_source_diagnostic_items(since_min=since_min, now_epoch=now_epoch))
        items.extend(self._safety_activity_items(limit=max(20, limit // 3)))
        items.sort(key=lambda x: (x.get("severity") == "critical", x.get("timestamp") or 0), reverse=True)
        return items[: max(1, min(limit, 300))]

    def _safety_activity_items(self, limit: int = 40) -> list[dict]:
        if SAFETY_MONITOR is None:
            return []
        items: list[dict] = []
        for event in SAFETY_MONITOR.events(limit=limit):
            severity = event.get("severity") or "info"
            if severity == "watch":
                severity = "warning"
            items.append({
                "id": f"safety-{event.get('id')}",
                "type": "safety",
                "severity": "critical" if severity == "critical" else ("warning" if severity == "warning" else "info"),
                "timestamp": int(event.get("timestamp") or _time.time()),
                "session_id": event.get("session_id") or "safety-monitor",
                "project": event.get("project") or "Pairling Safety Monitor",
                "title": event.get("title") or "Safety event",
                "subtitle": event.get("subtitle"),
                "state": event.get("state"),
                "tool": event.get("tool"),
                "context_pct": None,
                "entry_id": event.get("entry_id"),
            })
        return items

    def _send_race_mutation_result(self, context: dict, result: dict) -> None:
        response = dict(result)
        status = int(response.pop("status", 200 if response.get("ok") else 500))
        ok = bool(response.get("ok"))
        error_code = str(response.pop("code", "") or "")
        error_message = str(response.pop("message", "") or "")
        outcome_indeterminate = bool(response.get("outcome_indeterminate"))
        if not ok:
            error_code = error_code or (
                "race_action_outcome_unknown"
                if outcome_indeterminate
                else "race_action_failed"
            )
            error_message = error_message or error_code.replace("_", " ")
            response["error"] = {
                "code": error_code,
                "message": error_message,
            }
            response["error_code"] = error_code

        state = (
            "applied"
            if ok
            else (
                "indeterminate"
                if outcome_indeterminate
                else ("rejected" if 400 <= status < 500 else "failed")
            )
        )
        receipt = _finalize_receipted_mutation(
            context,
            state=state,
            http_status=status,
            backend="git_worktree",
            error_code=error_code if not ok else None,
            error_message=error_message if not ok else None,
            fields=response,
            audit_action={
                "type": context["action_kind"],
                "race_id": response.get("race_id"),
                "state": state,
                "error_code": error_code or None,
            },
        )
        response["receipt"] = receipt
        response["deduped"] = False
        self._send_json(response, status=status)

    def _handle_race_prepare(self, q):
        try:
            payload = self._read_json_object()
        except Exception:
            self._send_json({"ok": False, "error": {"code": "bad_json", "message": "invalid JSON"}}, status=400)
            return
        project_input = str(payload.get("project") or "").strip()
        try:
            project = _canonical_user_directory(project_input, allow_tmp=False)
        except ValueError:
            self._send_json({"ok": False, "error": {"code": "bad_project", "message": "absolute project path required"}}, status=400)
            return
        except (FileNotFoundError, NotADirectoryError):
            self._send_json({"ok": False, "error": {"code": "missing_project", "message": "project directory does not exist"}}, status=404)
            return
        except (PermissionError, RuntimeError, OSError):
            self._send_json({"ok": False, "error": {"code": "path_not_allowed", "message": "project must resolve under the home directory"}}, status=400)
            return
        context = _begin_receipted_mutation(
            self,
            receipt_scope="race:prepare",
            action_kind="race_prepare",
            material={"project": project},
            action_label="race preparation",
        )
        if context is None:
            return
        try:
            result = _race_prepare(project)
        except Exception as exc:
            result = {
                "ok": False,
                "status": 500,
                "code": "race_prepare_outcome_unknown",
                "message": f"race preparation stopped unexpectedly: {type(exc).__name__}",
                "outcome_indeterminate": True,
            }
        self._send_race_mutation_result(context, result)

    def _handle_race_status(self, q, race_id: str):
        result = _race_status(race_id)
        status = result.pop("status", 200 if result.get("ok") else 500)
        self._send_json(result, status=status)

    def _handle_race_finish(self, q, race_id: str):
        try:
            payload = self._read_json_object()
        except Exception:
            self._send_json({"ok": False, "error": {"code": "bad_json", "message": "invalid JSON"}}, status=400)
            return
        raw_force = payload.get("force", False)
        if not isinstance(raw_force, bool):
            self._send_json({
                "ok": False,
                "error": {
                    "code": "bad_force",
                    "message": "force must be a JSON boolean",
                },
            }, status=400)
            return
        force = raw_force
        context = _begin_receipted_mutation(
            self,
            receipt_scope=f"race:{race_id}:finish",
            action_kind="race_finish",
            material={"race_id": race_id, "force": force},
            action_label="race finish",
        )
        if context is None:
            return
        try:
            result = _race_finish(race_id, force=force)
        except Exception as exc:
            result = {
                "ok": False,
                "status": 500,
                "code": "race_finish_outcome_unknown",
                "message": f"race finish stopped unexpectedly: {type(exc).__name__}",
                "race_id": race_id,
                "outcome_indeterminate": True,
            }
        self._send_race_mutation_result(context, result)

    def _handle_fleet_digest(self, q):
        try:
            since_hours = min(168.0, max(1.0, float(q.get("since_hours", ["24"])[0])))
        except ValueError:
            since_hours = 24.0
        until = _time.time()
        self._send_json(_fleet_digest_payload(until - since_hours * 3600.0, until))

    def _handle_activity(self, q):
        try:
            since_min = int(q.get("since_min", ["360"])[0])
            limit = int(q.get("limit", ["120"])[0])
        except ValueError:
            since_min, limit = 360, 120
        items = self._activity_items(since_min=since_min, limit=limit)
        self._send_json({"count": len(items), "items": items, "ts": _time.time()})

    def _handle_activity_stream(self, q):
        try:
            since_min = int(q.get("since_min", ["360"])[0])
        except ValueError:
            since_min = 360
        self.send_response(200)
        self.send_header("Content-Type", "text/event-stream")
        self.send_header("Cache-Control", "no-store")
        self.send_header("Connection", "keep-alive")
        self.end_headers()
        deadline = _time.time() + 10 * 60
        last_hash = None
        while _time.time() < deadline:
            if not self._stream_authorization_is_current():
                return
            items = self._activity_items(since_min=since_min, limit=120)
            digest = hashlib.sha256(json.dumps(items, sort_keys=True).encode()).hexdigest()
            if digest != last_hash:
                payload = json.dumps({"items": items, "ts": _time.time()}).encode()
                try:
                    self.wfile.write(b"event: snapshot\ndata: " + payload + b"\n\n")
                    self.wfile.flush()
                except (BrokenPipeError, ConnectionResetError):
                    return
                last_hash = digest
            _time.sleep(2.0)
        try:
            self.wfile.write(b"event: done\ndata: {}\n\n")
            self.wfile.flush()
        except (BrokenPipeError, ConnectionResetError):
            return

    def _handle_safety_status(self, q):
        if SAFETY_MONITOR is None:
            self._send_json({
                "ok": False,
                "error": {
                    "code": "safety_unavailable",
                    "message": "Safety monitor bridge is unavailable",
                },
            }, status=503)
            return
        self._send_json({"ok": True, "safety": SAFETY_MONITOR.status(), "ts": _time.time()})

    def _handle_push_status(self, q):
        if PUSH_DISPATCHER is None:
            self._send_json({
                "ok": False,
                "error": {
                    "code": "push_unavailable",
                    "message": "Push dispatcher is unavailable",
                },
            }, status=503)
            return
        device_id = self._resolve_self_device_target(q.get("device_id", [None])[0])
        if device_id is None:
            return
        self._send_json(PUSH_DISPATCHER.status(device_id=device_id))

    def _handle_push_preferences(self, q):
        if PUSH_DISPATCHER is None:
            self._send_json({
                "ok": False,
                "error": {
                    "code": "push_unavailable",
                    "message": "Push dispatcher is unavailable",
                },
            }, status=503)
            return
        try:
            payload = self._read_json_object()
            device_id = self._resolve_self_device_target(payload.get("device_id"))
            if device_id is None:
                return
            result = PUSH_DISPATCHER.update_preferences(device_id=device_id, payload=payload)
        except (ValueError, json.JSONDecodeError) as exc:
            self._send_json({"ok": False, "error": {"code": "bad_request", "message": str(exc)}}, status=400)
            return
        except PushDispatcherError as exc:
            self._send_json({"ok": False, "error": {"code": exc.code, "message": exc.message}}, status=exc.status)
            return
        self._send_json(result)

    def _handle_push_permission_allow(self, q):
        # "Allow" from the phone's Lock-Screen card: answer the waiting permission
        # dialog by injecting Enter into the broker PTY (the same key path
        # /terminal-control uses). Idempotent on request_nonce (duplicate Allow is a
        # no-op). NO timeout / NO auto-decision.
        Handler._handle_push_permission_decision(self, decision="allow")

    def _handle_push_permission_deny(self, q):
        # "Deny" from the phone's Lock-Screen card: reject the waiting permission
        # dialog by injecting Escape (both providers treat Escape at an approval
        # prompt as rejection). Same nonce lifecycle, CAS discipline, and
        # idempotency as allow; the two verbs cannot both win one nonce.
        Handler._handle_push_permission_decision(self, decision="deny")

    def _handle_push_permission_decision(self, *, decision):
        spec = _PERMISSION_DECISIONS[decision]
        try:
            payload = self._read_json_object()
        except Exception:
            self._send_json({"ok": False, "error": {"code": "bad_json", "message": "invalid JSON"}}, status=400)
            return
        request_nonce = str(payload.get("request_nonce") or "").strip()
        if not request_nonce:
            self._send_json({"ok": False, "error": {"code": "bad_request", "message": "request_nonce required"}}, status=400)
            return
        row = _pending_approval_get(request_nonce)
        if not row:
            self._send_json({"ok": False, "error": {"code": "not_found", "message": "unknown request_nonce"}}, status=404)
            return
        current_state = str(row.get("state") or "")

        def send_terminal_state(state: str) -> None:
            if state == "outcome_unknown":
                self._send_json({
                    "ok": False,
                    "state": state,
                    "broker_id": str(row.get("broker_id") or ""),
                    "already_resolved": False,
                    "error": {
                        "code": "approval_apply_outcome_unknown",
                        "message": "Pairling still cannot confirm whether this permission decision reached the terminal. Inspect the session on the Mac before acting again.",
                    },
                }, status=502)
                return
            if state in {"screen_proof_unavailable", "screen_state_unknown"}:
                self._send_json({
                    "ok": False,
                    "state": state,
                    "broker_id": str(row.get("broker_id") or ""),
                    "already_resolved": False,
                    "error": {
                        "code": "approval_screen_unverified",
                        "message": "Pairling cannot prove the current permission screen. Decide on the Mac.",
                    },
                }, status=409)
                return
            self._send_json({"ok": True, "state": state, "already_resolved": True})

        if current_state in _PERMISSION_IN_FLIGHT_NOUNS:
            self._send_json(_permission_in_flight_response(current_state), status=409)
            return
        if current_state not in {"pending", "attention"}:
            # Already resolved (double-tap / re-delivery) — safe idempotent no-op.
            send_terminal_state(current_state)
            return
        if not _pending_approval_cas(request_nonce, current_state, spec["in_flight"]):
            latest = _pending_approval_get(request_nonce) or {}
            latest_state = str(latest.get("state") or "")
            if latest_state in _PERMISSION_IN_FLIGHT_NOUNS:
                self._send_json(_permission_in_flight_response(latest_state), status=409)
            else:
                send_terminal_state(latest_state)
            return
        provider = str(row.get("provider") or "claude")
        expected_proof = _approval_row_screen_proof(row)
        broker_id = str(row.get("broker_id") or "")

        def reject_stale(snapshot, *, fallback_code="approval_screen_changed"):
            current_proof = _approval_snapshot_proof(snapshot)
            if not isinstance(snapshot, dict) or not isinstance(snapshot.get("pending_input"), dict):
                final_state = "resolved_local"
                code = "approval_no_longer_pending"
                message = "the permission dialog was already resolved on the Mac"
                _pending_approval_cas(request_nonce, spec["in_flight"], final_state)
            elif not _approval_snapshot_matches_request(row, snapshot):
                final_state = "superseded"
                code = "approval_replaced"
                message = "a different terminal prompt replaced this permission dialog"
                _pending_approval_cas(request_nonce, spec["in_flight"], final_state)
            elif _pending_approval_refresh_screen(
                request_nonce,
                expected_state=spec["in_flight"],
                restored_state=current_state,
                snapshot=snapshot,
            ):
                final_state = current_state
                code = fallback_code
                message = "the permission dialog changed; review the refreshed card before deciding"
            else:
                final_state = "screen_state_unknown"
                code = "approval_screen_state_unknown"
                message = "the current permission dialog could not be proven"
                _pending_approval_cas(request_nonce, spec["in_flight"], final_state)
            self._send_json(_permission_stale_screen_response(
                state=final_state,
                broker_id=broker_id,
                code=code,
                message=message,
                current_proof=current_proof,
            ), status=409)

        if not expected_proof:
            _pending_approval_cas(request_nonce, spec["in_flight"], "screen_proof_unavailable")
            self._send_json(_permission_stale_screen_response(
                state="screen_proof_unavailable",
                broker_id=broker_id,
                code="approval_screen_unverified",
                message="this permission card has no exact terminal screen proof; decide on the Mac",
            ), status=409)
            return

        # The hook-captured broker id is authoritative. The registry lookup is
        # only a fallback for older rows which predate that field.
        if not broker_id:
            native_id = str(row.get("native_id") or "")
            if not native_id:
                native_id, _resolved_broker, _tty = _approval_resolve_session(
                    provider, str(row.get("session_id") or "")
                )
            if native_id and PTY_BROKER is not None:
                try:
                    broker_id = str(
                        self._terminal_control_target(_qualified_session_id(provider, native_id)).get("broker_id")
                        or ""
                    )
                except Exception:
                    broker_id = ""

        if not broker_id or PTY_BROKER is None:
            _pending_approval_cas(request_nonce, spec["in_flight"], current_state)
            self._send_json({
                "ok": False,
                "state": current_state,
                "broker_id": broker_id,
                "injected": {"ok": False, "reason": "no broker session", "pty_written": False},
                "error": {
                    "code": "injection_failed",
                    "message": f"permission {spec['noun']} could not be delivered to the broker PTY",
                },
            }, status=409)
            return

        context = _broker_atomic_control_context_for_id(
            broker_id,
            public_session_id=str(row.get("session_id") or broker_id),
        )
        if context is None:
            _pending_approval_cas(request_nonce, spec["in_flight"], current_state)
            self._send_json({
                "ok": False,
                "state": current_state,
                "broker_id": broker_id,
                "injected": {
                    "ok": False,
                    "reason": "approval_requires_current_broker",
                    "pty_written": False,
                },
                "error": {
                    "code": "approval_requires_current_broker",
                    "message": "This permission decision needs the current atomic terminal broker; decide on the Mac or update the helper.",
                },
            }, status=409)
            return
        current_snapshot = context["v2"]
        current_proof = _approval_snapshot_proof(current_snapshot)
        if not _approval_proof_matches(expected_proof, current_proof):
            reject_stale(current_snapshot)
            return
        if not _approval_snapshot_matches_request(row, current_snapshot):
            reject_stale(current_snapshot)
            return

        action = {
            "type": "key",
            "key": spec["key"],
            "require_screen_proof": True,
            "expected_screen_hash": context["control_proof"]["screen_hash"],
            "expected_generation": context["control_proof"]["generation"],
            "expected_nonce": context["control_proof"]["nonce"],
        }
        try:
            injected = PTY_BROKER.control(broker_id, action)
        except PTYBrokerOutcomeUnknownError as exc:
            _pending_approval_cas(request_nonce, spec["in_flight"], "outcome_unknown")
            self._send_json({
                "ok": False,
                "state": "outcome_unknown",
                "broker_id": broker_id,
                "injected": {
                    "ok": False,
                    "reason": "approval_apply_outcome_unknown",
                    "pty_written": None,
                    "write_outcome": "unknown",
                    "outcome_indeterminate": True,
                },
                "error": {
                    "code": "approval_apply_outcome_unknown",
                    "message": "The broker response was lost, so Pairling cannot confirm whether the permission decision reached the terminal.",
                    "detail": f"{type(exc).__name__}: {str(exc)[:120]}",
                },
            }, status=502)
            return
        except Exception as exc:
            injected = {
                "ok": False,
                "reason": f"{type(exc).__name__}: {str(exc)[:120]}",
                "pty_written": False,
                "write_outcome": "none",
            }

        if not injected.get("ok") and injected.get("reason") == "stale_screen":
            latest_context = _broker_atomic_control_context_for_id(
                broker_id,
                public_session_id=str(row.get("session_id") or broker_id),
            )
            latest_snapshot = latest_context.get("v2") if latest_context is not None else None
            reject_stale(latest_snapshot)
            return
        if not injected.get("ok"):
            if injected.get("outcome_indeterminate"):
                _pending_approval_cas(request_nonce, spec["in_flight"], "outcome_unknown")
                self._send_json({
                    "ok": False,
                    "state": "outcome_unknown",
                    "broker_id": broker_id,
                    "injected": injected,
                    "error": {
                        "code": "approval_apply_outcome_unknown",
                        "message": "Pairling cannot confirm how much of the permission decision reached the terminal.",
                    },
                }, status=502)
                return
            _pending_approval_cas(request_nonce, spec["in_flight"], current_state)
            latest = _pending_approval_get(request_nonce) or {}
            self._send_json({
                "ok": False,
                "state": str(latest.get("state") or current_state),
                "broker_id": broker_id,
                "injected": injected,
                "error": {
                    "code": "injection_failed",
                    "message": f"permission {spec['noun']} could not be delivered to the broker PTY",
                },
            }, status=409)
            return
        if not _pending_approval_cas(request_nonce, spec["in_flight"], spec["final"]):
            latest = _pending_approval_get(request_nonce) or {}
            latest_state = str(latest.get("state") or "")
            if latest_state == spec["final"]:
                self._send_json({"ok": True, "state": spec["final"], "broker_id": broker_id, "injected": injected})
            else:
                self._send_json({
                    "ok": False,
                    "state": latest_state or spec["in_flight"],
                    "broker_id": broker_id,
                    "injected": injected,
                    "error": {
                        "code": "release_state_failed",
                        "message": f"permission {spec['noun']} was injected but the state transition did not complete",
                    },
                }, status=409)
            return
        self._send_json({"ok": True, "state": spec["final"], "broker_id": broker_id, "injected": injected})

    def _handle_push_test(self, q):
        if PUSH_DISPATCHER is None:
            self._send_json({
                "ok": False,
                "error": {
                    "code": "push_unavailable",
                    "message": "Push dispatcher is unavailable",
                },
            }, status=503)
            return
        try:
            payload = self._read_json_object()
            device_id = self._resolve_self_device_target(payload.get("device_id"))
            if device_id is None:
                return
            result = PUSH_DISPATCHER.record_test(device_id=device_id, payload=payload)
        except (ValueError, json.JSONDecodeError) as exc:
            self._send_json({"ok": False, "error": {"code": "bad_request", "message": str(exc)}}, status=400)
            return
        except PushDispatcherError as exc:
            self._send_json({"ok": False, "error": {"code": exc.code, "message": exc.message}}, status=exc.status)
            return
        self._send_json(result, status=200 if result.get("ok") else 202)

    def _handle_push_live_activity_token(self, q):
        if PUSH_DISPATCHER is None:
            self._send_json({
                "ok": False,
                "error": {
                    "code": "push_unavailable",
                    "message": "Push dispatcher is unavailable",
                },
            }, status=503)
            return
        try:
            payload = self._read_json_object()
            device_id = self._resolve_self_device_target(payload.get("device_id"))
            if device_id is None:
                return
            result = PUSH_DISPATCHER.record_live_activity_token(device_id=device_id, payload=payload)
        except (ValueError, json.JSONDecodeError) as exc:
            self._send_json({"ok": False, "error": {"code": "bad_request", "message": str(exc)}}, status=400)
            return
        except PushDispatcherError as exc:
            self._send_json({"ok": False, "error": {"code": exc.code, "message": exc.message}}, status=exc.status)
            return
        self._send_json(result)

    def _handle_push_live_activity_test(self, q):
        if PUSH_DISPATCHER is None:
            self._send_json({
                "ok": False,
                "error": {
                    "code": "push_unavailable",
                    "message": "Push dispatcher is unavailable",
                },
            }, status=503)
            return
        try:
            payload = self._read_json_object()
            device_id = self._resolve_self_device_target(payload.get("device_id"))
            if device_id is None:
                return
            result = PUSH_DISPATCHER.record_live_activity_test(device_id=device_id, payload=payload)
        except (ValueError, json.JSONDecodeError) as exc:
            self._send_json({"ok": False, "error": {"code": "bad_request", "message": str(exc)}}, status=400)
            return
        except PushDispatcherError as exc:
            self._send_json({"ok": False, "error": {"code": exc.code, "message": exc.message}}, status=exc.status)
            return
        self._send_json(result, status=200 if result.get("ok") else 202)

    def _handle_sentinel_status(self, q):
        if SENTINEL_NOTIFICATIONS is None:
            self._send_json({
                "ok": False,
                "error": {
                    "code": "sentinel_unavailable",
                    "message": "Sentinel notification center is unavailable",
                },
            }, status=503)
            return
        try:
            since_min = int(q.get("since_min", ["60"])[0])
            human_idle = q.get("human_idle_minutes", [None])[0]
            human_idle_minutes = float(human_idle) if human_idle not in (None, "") else None
            worker_stats = self._worker_stats_payload(since_min)
        except ValueError:
            self._send_json({"ok": False, "error": {"code": "bad_request", "message": "numeric query is invalid"}}, status=400)
            return
        except RuntimeError as exc:
            self._send_json({"ok": False, "error": {"code": "worker_stats_unavailable", "message": str(exc)}}, status=502)
            return
        self._send_json(SENTINEL_NOTIFICATIONS.status(
            worker_stats=worker_stats,
            token_sessions=[],
            human_idle_minutes=human_idle_minutes,
        ))

    def _handle_sentinel_preferences(self, q):
        if SENTINEL_NOTIFICATIONS is None:
            self._send_json({
                "ok": False,
                "error": {
                    "code": "sentinel_unavailable",
                    "message": "Sentinel notification center is unavailable",
                },
            }, status=503)
            return
        if self.command == "GET":
            self._send_json(SENTINEL_NOTIFICATIONS.preferences())
            return
        try:
            result = SENTINEL_NOTIFICATIONS.update_preferences(self._read_json_object())
        except (ValueError, json.JSONDecodeError) as exc:
            self._send_json({"ok": False, "error": {"code": "bad_request", "message": str(exc)}}, status=400)
            return
        except Exception as exc:
            code = getattr(exc, "code", "sentinel_preferences_failed")
            message = getattr(exc, "message", str(exc))
            status = getattr(exc, "status", 400)
            self._send_json({"ok": False, "error": {"code": code, "message": message}}, status=status)
            return
        self._send_json(result)

    def _handle_sentinel_snooze(self, q):
        if SENTINEL_NOTIFICATIONS is None:
            self._send_json({
                "ok": False,
                "error": {
                    "code": "sentinel_unavailable",
                    "message": "Sentinel notification center is unavailable",
                },
            }, status=503)
            return
        try:
            payload = self._read_json_object()
            result = SENTINEL_NOTIFICATIONS.snooze(
                key=str(payload.get("key") or "*"),
                minutes=int(payload.get("minutes") or 60),
            )
        except (ValueError, json.JSONDecodeError) as exc:
            self._send_json({"ok": False, "error": {"code": "bad_request", "message": str(exc)}}, status=400)
            return
        self._send_json(result)

    def _handle_sentinel_evaluate_now(self, q):
        if SENTINEL_NOTIFICATIONS is None:
            self._send_json({
                "ok": False,
                "error": {
                    "code": "sentinel_unavailable",
                    "message": "Sentinel notification center is unavailable",
                },
            }, status=503)
            return
        try:
            payload = self._read_json_object()
            since_min = int(payload.get("since_min") or q.get("since_min", ["60"])[0])
            worker_stats = payload.get("worker_stats")
            if not isinstance(worker_stats, dict):
                worker_stats = self._worker_stats_payload(since_min)
            token_sessions = payload.get("token_sessions")
            if not isinstance(token_sessions, list):
                token_sessions = []
            human_idle = payload.get("human_idle_minutes")
            human_idle_minutes = float(human_idle) if human_idle not in (None, "") else None
            device_id = self._resolve_self_device_target(payload.get("device_id"))
            if device_id is None:
                return
            result = SENTINEL_NOTIFICATIONS.evaluate_now(
                worker_stats=worker_stats,
                token_sessions=token_sessions,
                human_idle_minutes=human_idle_minutes,
                device_id=device_id or None,
                force=bool(payload.get("force")),
            )
        except (ValueError, json.JSONDecodeError) as exc:
            self._send_json({"ok": False, "error": {"code": "bad_request", "message": str(exc)}}, status=400)
            return
        except RuntimeError as exc:
            self._send_json({"ok": False, "error": {"code": "worker_stats_unavailable", "message": str(exc)}}, status=502)
            return
        self._send_json(result)

    def _handle_sentinel_events(self, q):
        if SENTINEL_NOTIFICATIONS is None:
            self._send_json({
                "ok": False,
                "error": {
                    "code": "sentinel_unavailable",
                    "message": "Sentinel notification center is unavailable",
                },
            }, status=503)
            return
        try:
            since = float(q.get("since", ["0"])[0] or 0)
            limit = int(q.get("limit", ["100"])[0])
        except ValueError:
            self._send_json({"ok": False, "error": {"code": "bad_request", "message": "since/limit must be numeric"}}, status=400)
            return
        events = SENTINEL_NOTIFICATIONS.events(since=since, limit=limit)
        self._send_json({"ok": True, "count": len(events), "items": events, "ts": _time.time()})

    def _handle_safety_events(self, q):
        if SAFETY_MONITOR is None:
            self._send_json({
                "ok": False,
                "error": {
                    "code": "safety_unavailable",
                    "message": "Safety monitor bridge is unavailable",
                },
            }, status=503)
            return
        since = q.get("since", [""])[0]
        try:
            limit = int(q.get("limit", ["100"])[0])
        except ValueError:
            limit = 100
        events = SAFETY_MONITOR.events(since=since, limit=limit)
        self._send_json({"ok": True, "count": len(events), "items": events, "ts": _time.time()})

    def _handle_safety_ack(self, q):
        if SAFETY_MONITOR is None:
            self._send_json(
                {"ok": False, "error": {"code": "safety_unavailable", "message": "Safety Monitor is unavailable."}},
                status=503,
            )
            return
        try:
            payload = self._read_json_object()
        except (ValueError, TypeError, json.JSONDecodeError) as exc:
            self._send_json(
                {"ok": False, "error": {"code": "bad_request", "message": str(exc)}},
                status=400,
            )
            return
        ids = payload.get("ids")
        if not isinstance(ids, list) or not ids:
            self._send_json(
                {"ok": False, "error": {"code": "bad_request", "message": "ids must be a non-empty list."}},
                status=400,
            )
            return
        if len(ids) > MAX_SAFETY_ACK_IDS:
            self._send_json(
                {
                    "ok": False,
                    "error": {
                        "code": "too_many_ids",
                        "message": f"At most {MAX_SAFETY_ACK_IDS} safety event IDs may be acknowledged at once.",
                    },
                },
                status=400,
            )
            return
        normalized: list[str] = []
        for value in ids:
            if not isinstance(value, str):
                self._send_json(
                    {"ok": False, "error": {"code": "bad_request", "message": "Every safety event ID must be a string."}},
                    status=400,
                )
                return
            event_id = value.strip()
            if not event_id or len(event_id.encode("utf-8")) > MAX_SAFETY_ACK_ID_BYTES:
                self._send_json(
                    {"ok": False, "error": {"code": "bad_request", "message": "A safety event ID is empty or too large."}},
                    status=400,
                )
                return
            normalized.append(event_id)
        if len(set(normalized)) != len(normalized):
            self._send_json(
                {"ok": False, "error": {"code": "duplicate_ids", "message": "Safety event IDs must be unique."}},
                status=400,
            )
            return
        visible_ids = {
            str(event.get("id") or "")
            for event in SAFETY_MONITOR.events(limit=MAX_SAFETY_ACK_IDS * 3)
            if isinstance(event, dict) and event.get("id")
        }
        if any(event_id not in visible_ids for event_id in normalized):
            self._send_json(
                {
                    "ok": False,
                    "error": {
                        "code": "unknown_safety_event",
                        "message": "One or more safety events are no longer visible.",
                    },
                },
                status=409,
            )
            return
        result = SAFETY_MONITOR.ack(normalized)
        self._send_json(result, status=200 if result.get("ok") else 400)

    def _handle_safety_request_activation(self, q):
        if SAFETY_MONITOR is None:
            self._send_json({
                "ok": False,
                "error": {
                    "code": "safety_unavailable",
                    "message": "Safety monitor bridge is unavailable",
                },
            }, status=503)
            return
        result = SAFETY_MONITOR.request_activation()
        self._send_json(result, status=200 if result.get("ok") else 404)

    def _handle_safety_open_full_disk_access(self, q):
        if SAFETY_MONITOR is None:
            self._send_json({
                "ok": False,
                "error": {
                    "code": "safety_unavailable",
                    "message": "Safety monitor bridge is unavailable",
                },
            }, status=503)
            return
        result = SAFETY_MONITOR.open_full_disk_access()
        self._send_json(result, status=200 if result.get("ok") else 502)

    def _handle_safety_evidence_test(self, q):
        if SAFETY_MONITOR is None:
            self._send_json({
                "ok": False,
                "error": {
                    "code": "safety_unavailable",
                    "message": "Safety monitor bridge is unavailable",
                },
            }, status=503)
            return
        try:
            payload = self._read_json_object()
            wait_seconds = float(payload.get("wait_seconds", 8))
        except (ValueError, TypeError, json.JSONDecodeError) as exc:
            self._send_json({"ok": False, "error": {"code": "bad_request", "message": str(exc)}}, status=400)
            return
        result = SAFETY_MONITOR.run_evidence_test(wait_seconds=wait_seconds)
        self._send_json(result, status=200 if result.get("ok") else 202)

    def _handle_aperture_cli_status(self, q):
        if _aperture_cli_status_payload is None:
            self._send_json({
                "ok": False,
                "error": {
                    "code": "aperture_cli_integration_unavailable",
                    "message": "Aperture CLI integration is unavailable",
                },
            }, status=503)
            return
        self._send_json(_aperture_cli_status_payload(home=HOME, env=os.environ))

    def _handle_aperture_cli_providers(self, q):
        if _aperture_cli_provider_payload is None:
            self._send_json({
                "ok": False,
                "error": {
                    "code": "aperture_cli_integration_unavailable",
                    "message": "Aperture CLI integration is unavailable",
                },
            }, status=503)
            return
        self._send_json(_aperture_cli_provider_payload(home=HOME, env=os.environ))

    def _handle_aperture_cli_launch_contexts(self, q):
        if _aperture_cli_contexts_payload is None:
            self._send_json({
                "ok": False,
                "error": {
                    "code": "aperture_cli_integration_unavailable",
                    "message": "Aperture CLI integration is unavailable",
                },
            }, status=503)
            return
        self._send_json(_aperture_cli_contexts_payload(home=HOME, env=os.environ))

    def _handle_aperture_cli_open(self, q):
        receipt_context = _begin_receipted_mutation(
            self,
            receipt_scope="aperture:open",
            action_kind="aperture_cli_open",
            material={"operation": "open_aperture_cli"},
            action_label="Aperture CLI launch",
        )
        if receipt_context is None:
            return

        if _aperture_cli_status_payload is None:
            message = "Aperture CLI integration is unavailable"
            receipt = _finalize_receipted_mutation(
                receipt_context,
                state="failed",
                http_status=503,
                backend="terminal_app",
                error_code="aperture_cli_integration_unavailable",
                error_message=message,
                audit_action={"type": "aperture_cli_open"},
            )
            self._send_json({
                "ok": False,
                "error": {
                    "code": "aperture_cli_integration_unavailable",
                    "message": message,
                },
                "receipt": receipt,
            }, status=503)
            return

        allowed, retry = _inject_rate_check("__aperture_cli_open__")
        if not allowed:
            message = f"retry in {retry}s"
            receipt = _finalize_receipted_mutation(
                receipt_context,
                state="rejected",
                http_status=429,
                backend="terminal_app",
                error_code="rate_limited",
                error_message=message,
                fields={"retry_after": retry},
                audit_action={"type": "aperture_cli_open"},
            )
            self._send_json({
                "ok": False,
                "error": {"code": "rate_limited", "message": message},
                "retry_after": retry,
                "receipt": receipt,
            }, status=429)
            return

        status_payload = _aperture_cli_status_payload(home=HOME, env=os.environ)
        if status_payload.get("binary_trusted") is not True:
            message = (
                "Aperture CLI launch is disabled because this build has no "
                "independently authenticated Aperture release artifact."
            )
            receipt = _finalize_receipted_mutation(
                receipt_context,
                state="rejected",
                http_status=503,
                backend="terminal_app",
                error_code="aperture_cli_launch_untrusted",
                error_message=message,
                fields={
                    "trust_policy": status_payload.get("binary_trust_policy")
                },
                audit_action={"type": "aperture_cli_open"},
            )
            self._send_json({
                "ok": False,
                "error": {
                    "code": "aperture_cli_launch_untrusted",
                    "message": message,
                },
                "receipt": receipt,
            }, status=503)
            return
        binary = str(status_payload.get("binary_path") or "").strip()
        if not binary or not os.path.exists(binary) or not os.access(binary, os.X_OK):
            message = "Aperture CLI binary was not found on this Mac."
            receipt = _finalize_receipted_mutation(
                receipt_context,
                state="failed",
                http_status=503,
                backend="terminal_app",
                error_code="aperture_cli_not_installed",
                error_message=message,
                audit_action={"type": "aperture_cli_open"},
            )
            self._send_json({
                "ok": False,
                "error": {
                    "code": "aperture_cli_not_installed",
                    "message": message,
                },
                "receipt": receipt,
            }, status=503)
            return

        shell_cmd = f"cd {shlex.quote(str(HOME))} && exec {shlex.quote(binary)}"
        result = _start_pairling_terminal_session(shell_cmd, "Aperture CLI")
        if not result.get("ok"):
            outcome_indeterminate = bool(result.get("outcome_indeterminate"))
            message = str(result.get("reason") or "Terminal could not open Aperture CLI.")
            receipt = _finalize_receipted_mutation(
                receipt_context,
                state="indeterminate" if outcome_indeterminate else "failed",
                http_status=502,
                backend="terminal_app",
                error_code=(
                    "aperture_cli_launch_outcome_unknown"
                    if outcome_indeterminate
                    else "terminal_open_failed"
                ),
                error_message=message,
                fields={"outcome_indeterminate": outcome_indeterminate},
                audit_action={"type": "aperture_cli_open"},
                pty_written=None if outcome_indeterminate else False,
            )
            self._send_json({
                "ok": False,
                "error": {
                    "code": (
                        "aperture_cli_launch_outcome_unknown"
                        if outcome_indeterminate
                        else "terminal_open_failed"
                    ),
                    "message": message,
                },
                "outcome_indeterminate": outcome_indeterminate,
                "receipt": receipt,
            }, status=502)
            return

        tty = str(result.get("tty") or "").strip()
        if re.fullmatch(r"/dev/ttys[0-9]{3,}", tty) is None:
            message = "Terminal accepted the launch, but Pairling could not identify the new tab."
            receipt = _finalize_receipted_mutation(
                receipt_context,
                state="indeterminate",
                http_status=502,
                backend="terminal_app",
                error_code="aperture_cli_launch_outcome_unknown",
                error_message=message,
                fields={"outcome_indeterminate": True},
                audit_action={"type": "aperture_cli_open"},
                pty_written=None,
            )
            self._send_json({
                "ok": False,
                "error": {
                    "code": "aperture_cli_launch_outcome_unknown",
                    "message": message,
                },
                "outcome_indeterminate": True,
                "receipt": receipt,
            }, status=502)
            return
        try:
            audit_path = HOME / ".claude" / "audit" / "aperture-cli-open.jsonl"
            audit_path.parent.mkdir(parents=True, exist_ok=True)
            with open(audit_path, "a", encoding="utf-8") as f:
                f.write(json.dumps({
                    "ts": _time.time(),
                    "action": "aperture_cli_open",
                    "tty": tty or None,
                    "version": status_payload.get("version"),
                    "binary_path_source": status_payload.get("binary_path_source"),
                    "endpoint": (status_payload.get("settings") or {}).get("active_endpoint"),
                }, ensure_ascii=False) + "\n")
        except Exception:
            pass

        response = {
            "ok": True,
            "tty": tty or None,
            "version": status_payload.get("version"),
            "endpoint": (status_payload.get("settings") or {}).get("active_endpoint"),
            "message": "Aperture CLI opened on Mac.",
        }
        response["receipt"] = _finalize_receipted_mutation(
            receipt_context,
            state="applied",
            http_status=200,
            backend="terminal_app",
            fields=response,
            audit_action={"type": "aperture_cli_open", "tty": tty},
        )
        self._send_json(response)

    def _handle_workers(self, q):
        try:
            since_min = int(q.get("since_min", ["1440"])[0])
        except ValueError:
            since_min = 1440
        provider_filter = q.get("provider", ["all"])[0].lower()
        if not _valid_provider_filter(provider_filter):
            _send_unknown_provider(self, provider_filter)
            return
        workers: list[dict] = []
        if provider_filter in ("all", "claude"):
            workers.extend(self._collect_workers(since_min=since_min))
        if provider_filter in ("all", "codex"):
            workers.extend(self._collect_codex_workers(since_min=since_min))
        workers.sort(key=lambda w: (w["risk_score"], w["last_heartbeat"]), reverse=True)
        active = sum(1 for w in workers if w["active"])
        stale = sum(1 for w in workers if w["stale"])
        self._send_json({
            "count": len(workers),
            "active": active,
            "stale": stale,
            "items": workers[:300],
            "ts": _time.time(),
        })

    # ----- /orchestrations: bounded multi-agent orchestration -----
    _ORCHESTRATION_MODES = {"research", "debug", "scaffold", "decide", "draft", "remember", "extend"}
    _ORCHESTRATION_PERMISSIONS = {"default", "accept_edits", "plan"}
    _ORCHESTRATION_STOP_CONDITIONS = {"manual_stop"}
    _ORCHESTRATION_ACTIVE_HEARTBEAT_SECONDS = 180

    @staticmethod
    def _orchestration_permission_args(provider: str, permission_profile: str) -> list[str]:
        """Translate the user-visible profile into enforced provider flags."""
        if permission_profile not in Handler._ORCHESTRATION_PERMISSIONS:
            raise ValueError("invalid permission profile")
        if provider == "claude":
            mode = {
                "default": "manual",
                "accept_edits": "acceptEdits",
                "plan": "plan",
            }[permission_profile]
            return ["--permission-mode", mode]
        if provider == "codex":
            sandbox = "read-only" if permission_profile == "plan" else "workspace-write"
            return ["--sandbox", sandbox, "--ask-for-approval", "on-request"]
        raise ValueError(f"unsupported orchestration provider: {provider}")

    @staticmethod
    def _orchestration_wait_for_provider_pid(
        tty: str,
        provider: str,
        timeout_seconds: float = 3.0,
    ) -> int:
        deadline = _time.monotonic() + max(0.0, timeout_seconds)
        while True:
            pid = _pid_for_tty_command(tty, provider)
            if pid:
                return pid
            remaining = deadline - _time.monotonic()
            if remaining <= 0:
                return 0
            _time.sleep(min(0.1, remaining))

    def _route_orchestration_path(self, path: str, q):
        parts = [p for p in path.split("/") if p]
        if len(parts) < 2:
            self.send_error(404, "unknown orchestration path")
            return
        orchestration_id = parts[1]
        if not _safe_session_id(orchestration_id):
            self.send_error(400, "bad orchestration id")
            return
        if len(parts) == 2 and self.command == "GET":
            self._handle_orchestration_detail(orchestration_id)
        elif len(parts) == 3 and parts[2] == "stream" and self.command == "GET":
            self._handle_orchestration_stream(orchestration_id)
        elif len(parts) == 3 and parts[2] == "stop" and self.command == "POST":
            self._handle_orchestration_stop(orchestration_id)
        else:
            self.send_error(404, "unknown orchestration path")

    def _orchestration_path(self, orchestration_id: str) -> Path:
        return ORCHESTRATIONS_DIR / f"{orchestration_id}.json"

    def _orchestration_read(self, orchestration_id: str) -> dict | None:
        path = self._orchestration_path(orchestration_id)
        if not path.exists():
            return None
        try:
            return json.loads(path.read_text())
        except Exception:
            return None

    def _orchestration_write(self, run: dict) -> None:
        run["updated_at"] = _time.time()
        path = self._orchestration_path(run["id"])
        tmp = path.with_name(
            f"{path.name}.tmp.{os.getpid()}.{threading.get_ident()}"
        )
        fd = os.open(tmp, os.O_WRONLY | os.O_CREAT | os.O_EXCL, 0o600)
        with os.fdopen(fd, "w", encoding="utf-8") as file:
            file.write(json.dumps(run, indent=2, sort_keys=True))
            file.flush()
            os.fsync(file.fileno())
        tmp.replace(path)
        path.chmod(0o600)

    def _orchestration_event(self, run: dict, kind: str, title: str, detail: str | None = None) -> None:
        events = run.setdefault("events", [])
        events.append({
            "id": secrets.token_hex(6),
            "ts": _time.time(),
            "kind": kind,
            "title": title,
            "detail": detail,
        })
        del events[:-80]

    def _orchestration_validate_project(self, project: str) -> tuple[str | None, str | None]:
        project = (project or "").strip()
        if not project:
            return None, "project required"
        try:
            return _canonical_user_directory(project, allow_tmp=True), None
        except ValueError as error:
            return None, str(error)
        except FileNotFoundError:
            return None, f"directory not found: {project}"
        except NotADirectoryError:
            return None, f"not a directory: {project}"
        except (PermissionError, RuntimeError, OSError) as error:
            return None, str(error)

    def _orchestration_project_dirty(self, project: str) -> bool:
        try:
            project = _revalidate_canonical_user_directory(project, allow_tmp=True)
            proc = subprocess.run(
                ["git", "-C", project, "status", "--porcelain"],
                capture_output=True, text=True, timeout=4,
            )
            return proc.returncode == 0 and bool(proc.stdout.strip())
        except Exception:
            return True

    def _orchestration_claude_bin(self) -> Path | None:
        for candidate in (
            HOME / ".local" / "bin" / "claude",
            Path("/opt/homebrew/bin/claude"),
            Path("/usr/local/bin/claude"),
        ):
            if candidate.exists():
                return candidate
        return None

    def _orchestration_codex_bin(self) -> Path | None:
        for candidate in (
            Path("/usr/local/bin/codex"),
            Path("/opt/homebrew/bin/codex"),
            HOME / ".local" / "bin" / "codex",
        ):
            if candidate.exists():
                return candidate
        for prefix in os.environ.get("PATH", "").split(":"):
            p = Path(prefix) / "codex"
            if p.exists() and os.access(p, os.X_OK):
                return p
        return None

    def _orchestration_shell_quote(self, value: str) -> str:
        return "'" + value.replace("'", "'\\''") + "'"

    def _codex_worker_append_jsonl(self, path: Path, obj: dict) -> None:
        try:
            path.parent.mkdir(parents=True, exist_ok=True)
            with path.open("a", encoding="utf-8") as f:
                f.write(json.dumps(obj, ensure_ascii=False, sort_keys=True) + "\n")
        except OSError:
            pass

    def _codex_worker_timestamp(self) -> str:
        return datetime.now(timezone.utc).isoformat().replace("+00:00", "Z")

    def _codex_worker_metadata(self, run: dict, role: str, prompt_path: Path,
                               output_path: Path, stderr_path: Path, last_path: Path,
                               title: str, prompt_preview: str, pid: int | None = None,
                               extra: dict | None = None) -> dict:
        metadata = {
            "kind": "orchestration_worker",
            "provider": "codex",
            "native_id": f"worker-{run['id']}-{role}",
            "orchestration_id": run["id"],
            "role": role,
            "title": title,
            "project": run["project"],
            "prompt_path": str(prompt_path),
            "output_path": str(output_path),
            "stderr_path": str(stderr_path),
            "last_message_path": str(last_path),
            "prompt_preview": prompt_preview[:500],
            "state": "running",
            "model": run.get("model"),
        }
        if pid:
            metadata["pid"] = pid
        if extra:
            metadata.update(extra)
        return metadata

    def _orchestration_watch_codex_worker(self, run_id: str, native_id: str, proc: subprocess.Popen,
                                 output_path: Path, last_path: Path, stderr_path: Path) -> None:
        exit_code = None
        try:
            exit_code = proc.wait()
        except Exception:
            exit_code = -1
        reg = _agent_registry_get("codex", native_id) or {}
        metadata = self._registry_metadata(reg) if reg else {}
        metadata["exit_code"] = int(exit_code or 0)
        metadata["completed_at"] = _time.time()
        metadata["state"] = "idle" if exit_code == 0 else "error"
        last_text = ""
        try:
            last_text = last_path.read_text(errors="replace").strip()
        except OSError:
            last_text = ""
        if last_text:
            self._codex_worker_append_jsonl(output_path, {
                "type": "event_msg",
                "timestamp": self._codex_worker_timestamp(),
                "payload": {
                    "type": "agent_message",
                    "message": last_text,
                },
            })
        elif exit_code != 0:
            try:
                last_text = stderr_path.read_text(errors="replace")[-1000:].strip()
            except OSError:
                last_text = ""
            if last_text:
                self._codex_worker_append_jsonl(output_path, {
                    "type": "event_msg",
                    "timestamp": self._codex_worker_timestamp(),
                    "payload": {
                        "type": "agent_message",
                        "message": f"Codex worker exited {exit_code}:\n{last_text}",
                    },
                })
        self._codex_worker_append_jsonl(output_path, {
            "type": "event_msg",
            "timestamp": self._codex_worker_timestamp(),
            "payload": {
                "type": "worker_stop",
                "exit_code": exit_code,
            },
        })
        _agent_registry_upsert(
            "codex",
            native_id,
            metadata.get("project") or str(HOME),
            pid=int(metadata.get("pid") or proc.pid or 0),
            state=metadata["state"],
            metadata=metadata,
        )
        _agent_registry_mark_closed("codex", native_id)
        run = self._orchestration_read(run_id)
        if run:
            self._orchestration_event(
                run,
                "worker_finished",
                f"{metadata.get('role') or native_id} finished",
                f"exit {exit_code}",
            )
            self._orchestration_write(self._orchestration_refresh(run))

    def _orchestration_launch_role(self, run: dict, role: str, prompt_path: Path, title_suffix: str) -> dict:
        try:
            project = _revalidate_canonical_user_directory(run["project"], allow_tmp=True)
        except (FileNotFoundError, NotADirectoryError, PermissionError, RuntimeError, OSError, ValueError) as error:
            return {"provider": "claude", "role": role, "ok": False, "error": f"project path is no longer safe: {error}"}
        claude_bin = self._orchestration_claude_bin()
        if not claude_bin:
            return {"role": role, "ok": False, "error": "claude CLI not found"}
        orchestration_id = run["id"]
        title = f"orchestration-{role}-{orchestration_id[:6]}"
        launch_script = prompt_path.with_suffix(".launch.sh")
        permission_args = self._orchestration_permission_args(
            "claude", str(run.get("permission_profile") or "default")
        )
        permission_flags = " ".join(
            self._orchestration_shell_quote(arg) for arg in permission_args
        )
        launch_script.write_text(
            "#!/bin/zsh\n"
            "set -e\n"
            f"cd {self._orchestration_shell_quote(project)}\n"
            f"export PAIRLING_ORCHESTRATION_ID={self._orchestration_shell_quote(orchestration_id)}\n"
            f"export PAIRLING_ORCHESTRATION_ROLE={self._orchestration_shell_quote(role)}\n"
            f"prompt=$(cat {self._orchestration_shell_quote(str(prompt_path))})\n"
            f"{_claude_interactive_exec_prefix()} "
            f"{self._orchestration_shell_quote(str(claude_bin))} {permission_flags} \"$prompt\"\n",
            encoding="utf-8",
        )
        launch_script.chmod(0o700)
        shell_cmd = (
            f"/bin/zsh {self._orchestration_shell_quote(str(launch_script))}"
        )
        result = _start_pairling_terminal_session(shell_cmd, title)
        tty = str(result.get("tty") or "").strip() if result.get("ok") else ""
        pid = self._orchestration_wait_for_provider_pid(tty, "claude") if tty else 0
        outcome_indeterminate = bool(result.get("outcome_indeterminate"))
        launch_confirmed = bool(result.get("ok") and tty and pid)
        if result.get("ok") and not launch_confirmed:
            outcome_indeterminate = True
        return {
            "provider": "claude",
            "role": role,
            "ok": launch_confirmed,
            "error": (
                result.get("reason")
                if not result.get("ok")
                else (None if launch_confirmed else "Claude launch could not be confirmed from the Terminal process.")
            ),
            "outcome_indeterminate": outcome_indeterminate,
            "title": title,
            "prompt_path": str(prompt_path),
            "launch_script": str(launch_script),
            "title_suffix": title_suffix,
            "tty": tty,
            "pid": pid,
            "session_id": None,
        }

    def _orchestration_launch_codex_role(self, run: dict, role: str, prompt_path: Path, title_suffix: str) -> dict:
        try:
            project = _revalidate_canonical_user_directory(run["project"], allow_tmp=True)
        except (FileNotFoundError, NotADirectoryError, PermissionError, RuntimeError, OSError, ValueError) as error:
            return {"provider": "codex", "role": role, "ok": False, "error": f"project path is no longer safe: {error}"}
        codex_bin = self._orchestration_codex_bin()
        if not codex_bin:
            return {"provider": "codex", "role": role, "ok": False, "error": "codex CLI not found"}
        orchestration_id = run["id"]
        native_id = f"worker-{orchestration_id}-{role}"
        title = f"codex-orchestration-{role}-{orchestration_id[:6]}"
        output_path = prompt_path.with_suffix(".codex.jsonl")
        stderr_path = prompt_path.with_suffix(".stderr.log")
        last_path = prompt_path.with_suffix(".last.txt")
        prompt_text = ""
        try:
            prompt_text = prompt_path.read_text(errors="replace")
        except OSError:
            prompt_text = ""
        self._codex_worker_append_jsonl(output_path, {
            "type": "session_meta",
            "timestamp": self._codex_worker_timestamp(),
            "payload": {
                "id": native_id,
                "cwd": project,
                "model": run.get("model"),
                "source": "Pairling Orchestration",
            },
        })
        self._codex_worker_append_jsonl(output_path, {
            "type": "event_msg",
            "timestamp": self._codex_worker_timestamp(),
            "payload": {
                "type": "user_message",
                "message": prompt_text,
            },
        })
        cmd = [
            str(codex_bin),
            *self._orchestration_permission_args(
                "codex", str(run.get("permission_profile") or "default")
            ),
            "exec",
            "--json",
            "-C",
            project,
            "-o",
            str(last_path),
            "-",
        ]
        try:
            stdin_f = prompt_path.open("rb")
            stdout_f = output_path.open("ab")
            stderr_f = stderr_path.open("ab")
            proc = subprocess.Popen(
                cmd,
                cwd=project,
                stdin=stdin_f,
                stdout=stdout_f,
                stderr=stderr_f,
                start_new_session=True,
                env=_provider_child_environment(),
            )
            stdin_f.close()
            stdout_f.close()
            stderr_f.close()
        except Exception as e:
            return {
                "provider": "codex",
                "role": role,
                "ok": False,
                "error": f"{type(e).__name__}: {e}",
                "title": title,
                "prompt_path": str(prompt_path),
                "output_path": str(output_path),
            }
        if proc.poll() is not None:
            try:
                startup_error = stderr_path.read_text(errors="replace")[-1000:].strip()
            except OSError:
                startup_error = ""
            return {
                "provider": "codex",
                "role": role,
                "ok": False,
                "error": startup_error or f"Codex exited during launch with status {proc.returncode}",
                "outcome_indeterminate": False,
                "title": title,
                "prompt_path": str(prompt_path),
                "output_path": str(output_path),
            }
        metadata = self._codex_worker_metadata(
            run,
            role,
            prompt_path,
            output_path,
            stderr_path,
            last_path,
            title,
            prompt_text,
            pid=proc.pid,
        )
        _agent_registry_upsert(
            "codex",
            native_id,
            project,
            pid=proc.pid,
            state="running",
            metadata=metadata,
        )
        threading.Thread(
            target=self._orchestration_watch_codex_worker,
            args=(orchestration_id, native_id, proc, output_path, last_path, stderr_path),
            daemon=True,
        ).start()
        return {
            "provider": "codex",
            "role": role,
            "ok": True,
            "error": None,
            "title": title,
            "prompt_path": str(prompt_path),
            "output_path": str(output_path),
            "stderr_path": str(stderr_path),
            "last_message_path": str(last_path),
            "session_id": _qualified_session_id("codex", native_id),
            "native_id": native_id,
            "pid": proc.pid,
        }

    def _orchestration_prompt(self, run: dict, role: str, worker_index: int | None = None) -> str:
        handoff_path = run.get("handoff_path")
        common = f"""You are part of a Pairling orchestration launched from Pairling.

Orchestration id: {run['id']}
Role: {role}
Project: {run['project']}
Mode: {run['mode']}
Permission profile: {run['permission_profile']}
Source handoff file: {handoff_path or 'none'}

Objective:
{run['objective']}

Safety rules:
- Stay inside the stated project unless the task explicitly requires reading the handoff file.
- Do not spawn extra agents or background work beyond this role.
- Do not use bypass permissions unless already configured by the user outside this orchestration.
- Prefer evidence, file paths, and concrete commands over broad claims.
- Finish with a concise status block: outcome, changed files, tests run, open risks, next action.
"""
        if role == "planner":
            return common + """
Planner/Judge instructions:
- Inspect the repository and handoff context.
- Produce a bounded plan suitable for the worker count.
- Identify disjoint write scopes and verification gates.
- If workers are already running, judge their output and summarize convergence.
"""
        return common + f"""
Worker instructions:
- You are worker {worker_index or 1} of {run['max_workers']}.
- Take one bounded slice of the objective and execute it end to end.
- Avoid overlapping files with other workers where possible.
- Run the most relevant local verification available.
- Stop cleanly when the assigned slice is done or blocked.
"""

    def _orchestration_launch_background(self, run_id: str) -> None:
        run = self._orchestration_read(run_id)
        if not run:
            return
        try:
            run_dir = ORCHESTRATIONS_DIR / run_id
            run_dir.mkdir(parents=True, exist_ok=True)
            provider = run.get("provider") or "claude"
            provider_mode = run.get("provider_mode") or provider

            def launch_for_role(role_name: str):
                if provider_mode == "all":
                    return "claude" if role_name == "planner" else ("codex" if role_name.endswith("-1") else "claude")
                return provider

            def launch_role_for(provider_name: str):
                return self._orchestration_launch_codex_role if provider_name == "codex" else self._orchestration_launch_role

            planner_prompt = run_dir / "planner.md"
            planner_prompt.write_text(self._orchestration_prompt(run, "planner"))
            planner_prompt.chmod(0o600)
            planner_provider = launch_for_role("planner")
            run["launches"].append(launch_role_for(planner_provider)(run, "planner", planner_prompt, "planner"))
            run["launches"][-1]["provider"] = planner_provider
            for idx in range(1, int(run.get("max_workers") or 1) + 1):
                worker_prompt = run_dir / f"worker-{idx}.md"
                role = f"worker-{idx}"
                worker_prompt.write_text(self._orchestration_prompt(run, "worker", idx))
                worker_prompt.chmod(0o600)
                role_provider = launch_for_role(role)
                run["launches"].append(launch_role_for(role_provider)(run, role, worker_prompt, f"worker {idx}"))
                run["launches"][-1]["provider"] = role_provider

            indeterminate = [
                launch for launch in run["launches"]
                if launch.get("outcome_indeterminate")
            ]
            failed = [
                launch for launch in run["launches"]
                if not launch.get("ok") and not launch.get("outcome_indeterminate")
            ]
            run["failed_launch_count"] = len(failed)
            run["indeterminate_launch_count"] = len(indeterminate)
            if indeterminate:
                run["status"] = "launch_indeterminate"
                run["status_detail"] = (
                    f"Pairling could not confirm {len(indeterminate)} role launch outcome(s). "
                    "It will not label this orchestration as running."
                )
                self._orchestration_event(
                    run,
                    "error",
                    "One or more role launch outcomes are unknown",
                    "; ".join((launch.get("error") or "unknown") for launch in indeterminate)[:500],
                )
            elif failed:
                run["status"] = "launch_error"
                run["status_detail"] = f"{len(failed)} role(s) failed to launch."
                self._orchestration_event(run, "error", "One or more roles failed to launch", "; ".join((f.get("error") or "unknown") for f in failed)[:500])
            else:
                run["status"] = "running"
                surface = "mixed provider role(s)" if provider_mode == "all" else ("Codex exec job(s)" if provider == "codex" else "Terminal role(s)")
                self._orchestration_event(run, "launched", "Planner and workers launched", f"{len(run['launches'])} {surface} opened.")
        except Exception as e:
            run["status"] = "launch_error"
            run["status_detail"] = f"Orchestration launcher failed: {type(e).__name__}: {e}"
            self._orchestration_event(run, "error", "Orchestration launcher crashed", f"{type(e).__name__}: {e}")
        self._orchestration_write(run)

    def _orchestration_find_sessions(self, run: dict, rows: list[dict] | None = None) -> list[dict]:
        started = float(run.get("created_at") or 0)
        run_project_real = os.path.realpath(run.get("project") or "")
        provider = run.get("provider") or "claude"
        if provider == "codex":
            matches: list[dict] = []
            now_epoch = int(_time.time())
            for launch in run.get("launches") or []:
                native_id = launch.get("native_id")
                session_id = launch.get("session_id")
                if not native_id and isinstance(session_id, str):
                    _, native_id = _parse_agent_session_ref(session_id)
                if not native_id:
                    continue
                native_id = _agent_registry_resolve_native_alias("codex", native_id)
                reg = _agent_registry_get("codex", native_id) or {}
                metadata = self._registry_metadata(reg) if reg else {}
                pid = int((reg or {}).get("pid") or launch.get("pid") or 0)
                process_alive = bool(pid and _process_alive(pid))
                closed_at = reg.get("closed_at")
                heartbeat = int(reg.get("last_heartbeat") or reg.get("started_at") or run.get("updated_at") or run.get("created_at") or 0)
                idle_seconds = max(0, now_epoch - heartbeat) if heartbeat else None
                if pid and not process_alive and not closed_at:
                    _agent_registry_mark_closed("codex", native_id)
                    closed_at = int(_time.time())
                is_active = bool(process_alive and not closed_at)
                state = metadata.get("state")
                if is_active:
                    state = state or "running"
                elif metadata.get("exit_code") == 0:
                    state = "idle"
                else:
                    state = state or "terminated"
                matches.append({
                    "provider": "codex",
                    "session_id": _qualified_session_id("codex", native_id),
                    "native_id": native_id,
                    "role": launch.get("role") or metadata.get("role"),
                    "title": launch.get("title") or metadata.get("title"),
                    "state": state,
                    "tool": metadata.get("tool"),
                    "last_heartbeat": heartbeat,
                    "started_at": int(reg.get("started_at") or run.get("created_at") or 0),
                    "closed_at": int(closed_at) if closed_at else None,
                    "is_active": is_active,
                    "idle_seconds": idle_seconds,
                    "process_alive": process_alive,
                    "context_pct": None,
                    "effort": metadata.get("effort"),
                    "model": metadata.get("model"),
                })
            return matches
        if rows is None:
            rows = self._collect_session_rows(since_min=60 * 24, live_only=False, limit=300, include_first_prompt=False)
        matches = []
        now_epoch = int(_time.time())
        launch_ids: set[str] = set()
        for launch in run.get("launches") or []:
            sid = launch.get("session_id")
            if isinstance(sid, str) and sid:
                launch_ids.add(sid)
                launch_ids.add(_claude_native_session_id(sid) or sid)
        for row in rows:
            if launch_ids:
                if row.get("id") not in launch_ids and _qualified_session_id("claude", row.get("id") or "") not in launch_ids:
                    continue
            else:
                if os.path.realpath(row.get("project") or "") != run_project_real:
                    continue
                if float(row.get("started_at") or 0) + 120 < started:
                    continue
            title = None
            role = None
            for launch in run.get("launches") or []:
                launch_sid = launch.get("session_id")
                launch_native = _claude_native_session_id(launch_sid) if isinstance(launch_sid, str) else ""
                if launch_sid == row.get("id") or launch_sid == _qualified_session_id("claude", row.get("id") or "") or launch_native == row.get("id"):
                    role = launch.get("role")
                    title = launch.get("title")
                    break
            heartbeat = int(row.get("last_heartbeat") or 0)
            idle_seconds = max(0, now_epoch - heartbeat) if heartbeat else None
            closed_at = row.get("closed_at")
            pid = row.get("claude_pid")
            process_alive = None
            if pid:
                try:
                    os.kill(int(pid), 0)
                    process_alive = True
                except ProcessLookupError:
                    process_alive = False
                    self._mark_session_closed(row.get("id") or "")
                    closed_at = closed_at or now_epoch
                except PermissionError:
                    process_alive = True
                except OSError:
                    process_alive = False
            is_active = bool(
                heartbeat and
                idle_seconds is not None and
                idle_seconds < self._ORCHESTRATION_ACTIVE_HEARTBEAT_SECONDS and
                not closed_at and
                process_alive is not False
            )
            matches.append({
                "provider": "claude",
                "session_id": _qualified_session_id("claude", row.get("id") or ""),
                "native_id": row.get("id"),
                "role": role,
                "title": title,
                "state": row.get("state") if is_active or not closed_at else "terminated",
                "tool": row.get("tool"),
                "last_heartbeat": row.get("last_heartbeat"),
                "started_at": row.get("started_at"),
                "closed_at": closed_at,
                "is_active": is_active,
                "idle_seconds": idle_seconds,
                "process_alive": process_alive,
                "context_pct": row.get("context_pct"),
                "effort": row.get("effort"),
                "model": row.get("model"),
            })
        if (run.get("provider_mode") or run.get("provider")) == "all":
            for launch in run.get("launches") or []:
                if launch.get("provider") != "codex":
                    continue
                native_id = launch.get("native_id")
                session_id = launch.get("session_id")
                if not native_id and isinstance(session_id, str):
                    _, native_id = _parse_agent_session_ref(session_id)
                if not native_id:
                    continue
                native_id = _agent_registry_resolve_native_alias("codex", native_id)
                reg = _agent_registry_get("codex", native_id) or {}
                metadata = self._registry_metadata(reg) if reg else {}
                pid = int((reg or {}).get("pid") or launch.get("pid") or 0)
                process_alive = bool(pid and _process_alive(pid))
                closed_at = reg.get("closed_at")
                heartbeat = int(reg.get("last_heartbeat") or reg.get("started_at") or run.get("updated_at") or run.get("created_at") or 0)
                idle_seconds = max(0, now_epoch - heartbeat) if heartbeat else None
                if pid and not process_alive and not closed_at:
                    _agent_registry_mark_closed("codex", native_id)
                    closed_at = int(_time.time())
                is_active = bool(process_alive and not closed_at)
                state = metadata.get("state")
                if is_active:
                    state = state or "running"
                elif metadata.get("exit_code") == 0:
                    state = "idle"
                else:
                    state = state or "terminated"
                matches.append({
                    "provider": "codex",
                    "session_id": _qualified_session_id("codex", native_id),
                    "native_id": native_id,
                    "role": launch.get("role") or metadata.get("role"),
                    "title": launch.get("title") or metadata.get("title"),
                    "state": state,
                    "tool": metadata.get("tool"),
                    "last_heartbeat": heartbeat,
                    "started_at": int(reg.get("started_at") or run.get("created_at") or 0),
                    "closed_at": int(closed_at) if closed_at else None,
                    "is_active": is_active,
                    "idle_seconds": idle_seconds,
                    "process_alive": process_alive,
                    "context_pct": None,
                    "effort": metadata.get("effort"),
                    "model": metadata.get("model"),
                })
        return matches

    def _orchestration_refresh(self, run: dict, rows: list[dict] | None = None) -> dict:
        sessions = self._orchestration_find_sessions(run, rows=rows)
        known = {s["session_id"] for s in sessions if s.get("session_id")}
        run["sessions"] = sessions
        for launch in run.get("launches") or []:
            if launch.get("session_id"):
                continue
            for s in sessions:
                if s.get("role") is None:
                    launch["session_id"] = s.get("session_id")
                    s["role"] = launch.get("role")
                    s["title"] = launch.get("title")
                    break
        now = _time.time()
        active = [s for s in sessions if s.get("is_active")]
        idle = [s for s in sessions if s.get("session_id") and not s.get("is_active")]
        run["active_session_count"] = len(active)
        run["idle_session_count"] = len(idle)
        run["registered_session_count"] = len(known)
        run["stop_status"] = self._orchestration_stop_status(run, sessions)
        if run.get("status") == "running":
            created = float(run.get("created_at") or now)
            if not active and known and now - created > 60:
                run["status"] = "quiet"
                run["finished_reason"] = "quiet"
                run["finished_at"] = now
                run["status_detail"] = "All registered orchestration sessions are idle; no explicit stop condition fired."
                self._orchestration_event(run, "status", "Orchestration finished quietly", run["status_detail"])
        elif run.get("status") in {"quiet", "stopped"} and not run.get("status_detail"):
            run["finished_reason"] = run.get("finished_reason") or run.get("status")
            run["status_detail"] = self._orchestration_status_detail(run.get("status"), run)
            run["finished_at"] = run.get("finished_at") or run.get("updated_at") or now
        run["stop_status"] = self._orchestration_stop_status(run, sessions)
        return run

    def _orchestration_status_detail(self, status: str, run: dict) -> str:
        if status == "quiet":
            return "All registered orchestration sessions are idle; no explicit stop condition fired."
        if status == "stopped":
            return "Stopped manually from the phone."
        return ""

    def _orchestration_stop_status(self, run: dict, sessions: list[dict]) -> list[dict]:
        status = run.get("status")
        finished_reason = run.get("finished_reason") or status
        labels = {"manual_stop": "Manual stop"}
        details = {
            "manual_stop": "Reached only when active orchestration sessions are stopped from the phone.",
        }
        items = []
        if finished_reason == "quiet" or status == "quiet":
            items.append({
                "id": "quiet",
                "label": "Idle / complete",
                "state": "reached",
                "detail": "All registered orchestration sessions are idle. No configured stop condition was triggered.",
            })
        for condition in ["manual_stop"]:
            state = "armed"
            if condition == finished_reason or (condition == "manual_stop" and status == "stopped"):
                state = "reached"
            elif status in {"quiet", "stopped", "launch_error", "launch_indeterminate"}:
                state = "not_reached"
            items.append({
                "id": condition,
                "label": labels[condition],
                "state": state,
                "detail": details[condition],
            })
        return items

    def _handle_orchestrations_create(self, q):
        client_action_id = str(
            (getattr(self, "headers", {}) or {}).get("X-Pairling-Action-Id") or ""
        ).strip()
        if not _valid_client_action_id(client_action_id):
            self._send_json({
                "ok": False,
                "error": {
                    "code": "action_id_required",
                    "message": "A valid X-Pairling-Action-Id is required to create an orchestration.",
                },
            }, status=400)
            return
        raw_body = self._read_body() or b"{}"
        try:
            payload = json.loads(raw_body)
        except json.JSONDecodeError:
            self.send_error(400, "body must be JSON")
            return
        device_id = getattr(getattr(self, "pairling_auth", None), "device_id", None)
        if not isinstance(device_id, str) or not device_id.strip():
            self._send_json({
                "ok": False,
                "error": {
                    "code": "authenticated_device_required",
                    "message": "A paired phone identity is required to create an orchestration.",
                },
            }, status=401)
            return
        device_id = device_id.strip()
        orchestration_id = "orchestration-" + hashlib.sha256(
            f"{device_id}\0{client_action_id}".encode()
        ).hexdigest()[:12]
        mutation = _begin_receipted_mutation(
            self,
            receipt_scope=orchestration_id,
            action_kind="orchestration_create",
            material=raw_body,
            action_label="orchestration creation",
        )
        if mutation is None:
            return

        def reject_create(
            status: int,
            code: str,
            message: str,
            *,
            error_details: dict | None = None,
        ) -> None:
            error = {"code": code, "message": message, **(error_details or {})}
            receipt = _finalize_receipted_mutation(
                mutation,
                state="rejected",
                http_status=status,
                backend="orchestration_launcher",
                error_code=code,
                error_message=message,
                fields={
                    "orchestration_id": orchestration_id,
                    "error": error,
                },
                audit_action={
                    "type": "orchestration_create",
                    "orchestration_id": orchestration_id,
                    "state": "rejected",
                    "error_code": code,
                },
            )
            body, response_status = _receipt_replay_response(receipt, {"ok": False})
            self._send_json(body, status=response_status)

        existing_run = self._orchestration_read(orchestration_id)
        if existing_run is not None:
            receipt = _finalize_receipted_mutation(
                mutation,
                state="indeterminate",
                http_status=409,
                backend="orchestration_launcher",
                error_code="orchestration_create_outcome_unknown",
                error_message=(
                    "This action already has an orchestration record, but its launch outcome "
                    "cannot be reconstructed. Pairling did not launch another fleet."
                ),
                fields={
                    "orchestration": existing_run,
                    "ts": _time.time(),
                    "outcome_indeterminate": True,
                },
                audit_action={
                    "type": "orchestration_create",
                    "orchestration_id": orchestration_id,
                    "state": "indeterminate",
                },
            )
            body, status = _receipt_replay_response(receipt, {"ok": False})
            self._send_json(body, status=status)
            return

        if not isinstance(payload, dict):
            reject_create(400, "invalid_body", "body must be a JSON object")
            return
        project_input = (payload.get("project") or "").strip()
        project, project_error = self._orchestration_validate_project(project_input)
        if project_error or project is None:
            reject_create(400, "invalid_project", project_error or "project required")
            return
        objective = (payload.get("objective") or "").strip()
        if not objective:
            reject_create(400, "objective_required", "objective required")
            return
        mode = payload.get("mode") or "research"
        permission_profile = payload.get("permission_profile") or "default"
        provider_mode = (payload.get("provider") or "claude").lower()
        if provider_mode == "mixed":
            provider_mode = "all"
        if not _valid_provider_filter(provider_mode):
            error = _unknown_provider_payload(provider_mode)["error"]
            reject_create(
                400,
                str(error["code"]),
                str(error["message"]),
                error_details={
                    "known_providers": error["known_providers"],
                    "known_future_providers": error["known_future_providers"],
                },
            )
            return
        if provider_mode == "all":
            provider = None
        elif _provider_supports(provider_mode, "orchestration_launch"):
            provider = provider_mode
        else:
            error = _unsupported_provider_payload(provider_mode, "orchestration_launch")["error"]
            reject_create(
                400,
                str(error["code"]),
                str(error["message"]),
                error_details={
                    "provider": provider_mode,
                    "capability": "orchestration_launch",
                },
            )
            return
        if provider is not None and not _provider_visible(provider):
            error = _provider_hidden_payload(provider)["error"]
            reject_create(
                409,
                str(error["code"]),
                str(error["message"]),
                error_details={"provider": provider},
            )
            return
        if mode not in self._ORCHESTRATION_MODES:
            reject_create(400, "invalid_orchestration_mode", "invalid orchestration mode")
            return
        if permission_profile not in self._ORCHESTRATION_PERMISSIONS:
            reject_create(400, "invalid_permission_profile", "invalid permission profile")
            return
        if provider_mode in {"codex", "all"} and permission_profile == "accept_edits":
            reject_create(
                400,
                "unsupported_permission_profile",
                "accept edits is not a distinct Codex permission profile; choose default or plan",
            )
            return
        try:
            max_workers = max(1, min(int(payload.get("max_workers") or 1), 4))
        except (TypeError, ValueError):
            reject_create(
                400,
                "invalid_orchestration_limits",
                "max_workers must be an integer",
            )
            return
        stop_conditions = payload.get("stop_conditions") or ["manual_stop"]
        if (
            not isinstance(stop_conditions, list)
            or any(s not in self._ORCHESTRATION_STOP_CONDITIONS for s in stop_conditions)
        ):
            reject_create(
                400,
                "invalid_stop_conditions",
                "only manual_stop is currently enforced",
            )
            return
        stop_conditions = ["manual_stop"]
        if self._orchestration_project_dirty(project) and not payload.get("allow_dirty_project"):
            reject_create(
                409,
                "dirty_project",
                "project has uncommitted changes; set allow_dirty_project to continue",
            )
            return

        health = _health_payload()
        coordinator_meta, preflight_meta = _orchestration_preflight_from_health(health)
        if isinstance(payload.get("coordinator"), dict):
            coordinator_meta.update(payload["coordinator"])
        if isinstance(payload.get("preflight"), dict):
            preflight_meta.update(payload["preflight"])
        placement_meta = payload.get("placement") if isinstance(payload.get("placement"), dict) else None
        if not placement_meta:
            placement_meta = {
                "planner": "local",
                "workers": [
                    {"index": idx + 1, "target": "local"}
                    for idx in range(max_workers)
                ],
            }

        allowed, retry = _inject_rate_check("__orchestrations__")
        if not allowed:
            receipt = _finalize_receipted_mutation(
                mutation,
                state="failed",
                http_status=429,
                backend="orchestration_launcher",
                error_code="rate_limited",
                error_message=f"Orchestration creation is rate limited. Retry in {retry}s.",
                fields={"retry_after_seconds": retry},
                audit_action={
                    "type": "orchestration_create",
                    "orchestration_id": orchestration_id,
                    "state": "rate_limited",
                },
            )
            body, status = _receipt_replay_response(receipt, {"ok": False})
            self._send_json(body, status=status)
            return

        try:
            orchestration_dir = ORCHESTRATIONS_DIR / orchestration_id
            orchestration_dir.mkdir(parents=True, exist_ok=False, mode=0o700)
            orchestration_dir.chmod(0o700)
            handoff_text = payload.get("handoff_text") or ""
            handoff_title = (payload.get("handoff_title") or "Manual Orchestration brief").strip()[:120]
            handoff_path = None
            if handoff_text.strip():
                handoff = {
                    "schemaVersion": 1,
                    "source": payload.get("handoff_source") or "Pairling",
                    "title": handoff_title,
                    "generatedAt": _time.time(),
                    "workflowHint": mode,
                    "suggestedPrompt": objective,
                    "transcriptText": handoff_text,
                }
                handoff_path = HANDOFFS_DIR / f"{orchestration_id}.json"
                handoff_path.write_text(json.dumps(handoff, indent=2, sort_keys=True))
                handoff_path.chmod(0o600)

            run = {
                "id": orchestration_id,
                "status": "launching",
                "created_at": _time.time(),
                "updated_at": _time.time(),
                "create_action_id": client_action_id,
                "create_body_hash": mutation["body_hash"],
                "provider": provider,
                "provider_mode": provider_mode,
                "providers": ["claude", "codex"] if provider_mode == "all" else [provider_mode],
                "project": project,
                "objective": objective[:8000],
                "mode": mode,
                "permission_profile": permission_profile,
                "max_workers": max_workers,
                "stop_conditions": stop_conditions,
                "handoff_title": handoff_title,
                "handoff_path": str(handoff_path) if handoff_path else None,
                "coordinator": coordinator_meta,
                "preflight": preflight_meta,
                "placement": placement_meta,
                "launches": [],
                "sessions": [],
                "events": [],
            }
            self._orchestration_event(run, "created", "Orchestration created", f"{provider_mode} · {mode} · {max_workers} worker(s)")
            self._orchestration_event(run, "preflight", "Coordinator preflight captured", f"{preflight_meta.get('posture', 'unknown')} · {preflight_meta.get('route', 'unknown')} · {preflight_meta.get('summary') or 'no summary'}")
            self._orchestration_write(run)
        except Exception as error:
            receipt = _finalize_receipted_mutation(
                mutation,
                state="failed",
                http_status=500,
                backend="orchestration_launcher",
                error_code="orchestration_create_failed",
                error_message=f"{type(error).__name__}: {error}",
                fields={"orchestration_id": orchestration_id},
                audit_action={
                    "type": "orchestration_create",
                    "orchestration_id": orchestration_id,
                    "state": "failed",
                },
            )
            body, status = _receipt_replay_response(receipt, {"ok": False})
            self._send_json(body, status=status)
            return

        try:
            threading.Thread(
                target=self._orchestration_launch_background,
                args=(orchestration_id,),
                daemon=True,
            ).start()
        except Exception as error:
            run["status"] = "launch_error"
            run["status_detail"] = f"Orchestration launcher could not start: {type(error).__name__}: {error}"
            self._orchestration_event(run, "error", "Orchestration launcher could not start", run["status_detail"])
            self._orchestration_write(run)
            receipt = _finalize_receipted_mutation(
                mutation,
                state="failed",
                http_status=500,
                backend="orchestration_launcher",
                error_code="orchestration_launcher_failed",
                error_message=run["status_detail"],
                fields={"orchestration": run, "ts": _time.time()},
                audit_action={
                    "type": "orchestration_create",
                    "orchestration_id": orchestration_id,
                    "state": "failed",
                },
            )
            body, status = _receipt_replay_response(receipt, {"ok": False})
            self._send_json(body, status=status)
            return

        response_ts = _time.time()
        receipt = _finalize_receipted_mutation(
            mutation,
            state="applied",
            http_status=200,
            backend="orchestration_launcher",
            fields={"orchestration": run, "ts": response_ts},
            audit_action={
                "type": "orchestration_create",
                "orchestration_id": orchestration_id,
                "state": "launching",
            },
        )
        body, status = _receipt_replay_response(receipt, {"ok": True})
        self._send_json(body, status=status)

    def _handle_orchestrations_list(self, q):
        try:
            limit = max(1, min(int(q.get("limit", ["30"])[0]), 500))
        except ValueError:
            limit = 30
        orchestrations = []
        rows = self._collect_session_rows(since_min=60 * 24, live_only=False, limit=500, include_first_prompt=False)
        for path in sorted(ORCHESTRATIONS_DIR.glob("orchestration-*.json"), key=lambda p: p.stat().st_mtime, reverse=True)[:limit]:
            try:
                run = json.loads(path.read_text())
                orchestrations.append(self._orchestration_refresh(run, rows=rows))
            except Exception:
                continue
        self._send_json({"count": len(orchestrations), "items": orchestrations, "ts": _time.time()})

    def _handle_orchestration_detail(self, orchestration_id: str):
        run = self._orchestration_read(orchestration_id)
        if not run:
            self.send_error(404, "orchestration not found")
            return
        run = self._orchestration_refresh(run)
        self._orchestration_write(run)
        self._send_json({"ok": True, "orchestration": run, "ts": _time.time()})

    def _handle_orchestration_stream(self, orchestration_id: str):
        run = self._orchestration_read(orchestration_id)
        if not run:
            self.send_error(404, "orchestration not found")
            return
        self.send_response(200)
        self.send_header("Content-Type", "text/event-stream")
        self.send_header("Cache-Control", "no-store")
        self.send_header("Connection", "keep-alive")
        self.send_header("X-Accel-Buffering", "no")
        self.end_headers()
        last_hash = None
        deadline = _time.time() + 10 * 60
        while _time.time() < deadline:
            if not self._stream_authorization_is_current():
                return
            run = self._orchestration_read(orchestration_id)
            if not run:
                break
            run = self._orchestration_refresh(run)
            self._orchestration_write(run)
            payload_core = {"ok": True, "orchestration": run}
            payload = {**payload_core, "ts": _time.time()}
            digest = hashlib.sha256(json.dumps(payload_core, sort_keys=True).encode()).hexdigest()
            if digest != last_hash:
                try:
                    self.wfile.write(b"event: snapshot\ndata: " + json.dumps(payload).encode() + b"\n\n")
                    self.wfile.flush()
                except (BrokenPipeError, ConnectionResetError):
                    return
                last_hash = digest
            _time.sleep(2.0)
        try:
            self.wfile.write(b"event: done\ndata: {}\n\n")
            self.wfile.flush()
        except (BrokenPipeError, ConnectionResetError):
            return

    def _handle_orchestration_stop(self, orchestration_id: str):
        mutation = _begin_receipted_mutation(
            self,
            receipt_scope=f"orchestration:{orchestration_id}:stop",
            action_kind="orchestration_stop",
            material={
                "orchestration_id": orchestration_id,
                "action": "stop_active_sessions",
            },
            action_label="orchestration stop",
        )
        if mutation is None:
            return

        client_action_id = mutation["client_action_id"]
        device_id = mutation["device_id"]
        receipt_session_id = mutation["receipt_scope"]
        body_hash = mutation["body_hash"]
        run = self._orchestration_read(orchestration_id)
        if not run:
            message = "orchestration not found"
            receipt = _finalize_receipted_mutation(
                mutation,
                state="rejected",
                http_status=404,
                backend="orchestration_launcher",
                error_code="orchestration_not_found",
                error_message=message,
                fields={
                    "stopped": [],
                    "errors": [message],
                    "unknown_outcomes": [],
                    "orchestration": None,
                },
                audit_action={"type": "stop_orchestration", "state": "rejected"},
            )
            body, status = _receipt_replay_response(receipt, {"ok": False})
            self._send_json(body, status=status)
            return
        run = self._orchestration_refresh(run)
        stopped = []
        errors = []
        unknown_outcomes = []
        identity_drift = False
        broker_runtime_mismatch = False
        broker_unavailable = False
        represented_session_targets: set[tuple[str, str]] = set()
        processed_session_targets: set[tuple[str, str]] = set()
        active_target_count = 0

        def durable_broker_id(provider: str, native_id: str) -> str | None:
            row = _agent_registry_get(provider, native_id)
            if row is None:
                row = _agent_registry_row_for_broker_id(
                    provider,
                    _qualified_session_id(provider, native_id),
                )
            return _durable_broker_id_from_registry_row(
                row,
                provider=provider,
                native_id=native_id,
            )

        for s in run.get("sessions") or []:
            sid = str(s.get("session_id") or "").strip()
            if not sid:
                if s.get("is_active"):
                    errors.append("active orchestration session is missing its session_id")
                continue
            session_provider = str(
                s.get("provider") or run.get("provider") or "claude"
            ).strip().lower()
            _, native_id = _parse_agent_session_ref(sid)
            if not native_id:
                if s.get("is_active"):
                    errors.append(f"{sid}: active orchestration session has no native session id")
                continue
            if session_provider == "codex":
                native_id = _agent_registry_resolve_native_alias(
                    "codex", native_id
                )
                if not native_id:
                    if s.get("is_active"):
                        errors.append(
                            f"{sid}: active orchestration session has no canonical session id"
                        )
                    continue
            target_key = (session_provider, native_id)
            represented_session_targets.add(target_key)
            if not s.get("is_active"):
                continue
            if target_key in processed_session_targets:
                continue
            processed_session_targets.add(target_key)
            active_target_count += 1
            qualified = _qualified_session_id(session_provider, native_id)
            broker_found = self._broker_session_for(qualified)
            if broker_found and PTY_BROKER:
                _, broker_session = broker_found
                if not _broker_session_owns_identity(broker_session, session_provider, native_id):
                    identity_drift = True
                    errors.append(f"{sid}: broker ownership changed; refresh before stopping")
                    continue
                if not _broker_is_current_runtime():
                    broker_runtime_mismatch = True
                    errors.append(f"{sid}: current terminal broker required before stopping")
                    continue
                try:
                    result = PTY_BROKER.terminate(_broker_session_id(broker_session), signal.SIGTERM)
                except PTYBrokerOutcomeUnknownError as exc:
                    unknown_outcomes.append(f"{sid}: {str(exc)[:160]}")
                    continue
                except Exception as exc:
                    errors.append(f"{sid}: {type(exc).__name__}: {exc}")
                    continue
                if result.get("outcome_indeterminate"):
                    unknown_outcomes.append(
                        f"{sid}: {result.get('error') or result.get('reason') or 'termination outcome unknown'}"
                    )
                    continue
                if result.get("ok"):
                    stopped.append(sid)
                    if session_provider == "codex":
                        _agent_registry_mark_closed("codex", native_id)
                    else:
                        self._mark_session_closed(native_id)
                else:
                    errors.append(f"{sid}: {result.get('error') or result.get('reason') or 'broker termination failed'}")
                continue
            known_broker_id = durable_broker_id(session_provider, native_id)
            if known_broker_id:
                broker_unavailable = True
                errors.append(f"{sid}: terminal broker is temporarily unavailable")
                continue
            verified_row, pid, verification_error = _verified_session_signal_target(session_provider, native_id)
            if verification_error == "process_identity_unverified":
                identity_drift = True
                errors.append(f"{sid}: process identity changed; refresh before stopping")
                continue
            if verification_error:
                errors.append(
                    f"{sid}: target verification failed ({str(verification_error)[:160]})"
                )
                continue
            termination = _terminate_direct_session_process(
                verified_row or {}, session_provider, pid
            )
            if not termination.get("ok"):
                detail = str(termination.get("error") or "termination failed")[:160]
                if termination.get("outcome_indeterminate"):
                    unknown_outcomes.append(f"{sid}: {detail}")
                else:
                    errors.append(f"{sid}: {detail}")
                continue
            stopped.append(sid)
            if session_provider == "codex":
                _agent_registry_mark_closed("codex", native_id)
            else:
                self._mark_session_closed(native_id)
        stopped_set = set(stopped)
        for launch in run.get("launches") or []:
            launch_provider = str(
                launch.get("provider") or run.get("provider") or "claude"
            ).strip().lower()
            if launch_provider != "claude":
                continue
            sid = str(
                launch.get("session_id")
                or f"claude:{launch.get('role') or launch.get('title') or 'launch'}"
            ).strip()
            _, native_id = _parse_agent_session_ref(sid)
            if not native_id:
                errors.append(f"{sid or 'orchestration launch'}: launch has no native session id")
                continue
            target_key = ("claude", native_id)
            # run.sessions is the authoritative live/idle view. Launches only
            # fill a missing old record; they never retry or override it.
            if target_key in represented_session_targets:
                continue
            represented_session_targets.add(target_key)
            active_target_count += 1
            broker_found = self._broker_session_for(_qualified_session_id("claude", native_id))
            if broker_found and PTY_BROKER:
                _, broker_session = broker_found
                if not _broker_session_owns_identity(broker_session, "claude", native_id):
                    identity_drift = True
                    errors.append(f"{sid}: broker ownership changed; refresh before stopping")
                    continue
                if not _broker_is_current_runtime():
                    broker_runtime_mismatch = True
                    errors.append(f"{sid}: current terminal broker required before stopping")
                    continue
                try:
                    result = PTY_BROKER.terminate(_broker_session_id(broker_session), signal.SIGTERM)
                except PTYBrokerOutcomeUnknownError as exc:
                    unknown_outcomes.append(f"{sid}: {str(exc)[:160]}")
                    continue
                except Exception as exc:
                    errors.append(f"{sid}: {type(exc).__name__}: {exc}")
                    continue
                if result.get("outcome_indeterminate"):
                    unknown_outcomes.append(
                        f"{sid}: {result.get('error') or result.get('reason') or 'termination outcome unknown'}"
                    )
                    continue
                if result.get("ok"):
                    stopped.append(sid)
                    stopped_set.add(sid)
                    self._mark_session_closed(native_id)
                else:
                    errors.append(f"{sid}: {result.get('error') or result.get('reason') or 'broker termination failed'}")
                continue
            known_broker_id = durable_broker_id("claude", native_id)
            if known_broker_id:
                broker_unavailable = True
                errors.append(f"{sid}: terminal broker is temporarily unavailable")
                continue
            verified_row, pid, verification_error = _verified_session_signal_target("claude", native_id)
            if verification_error == "process_identity_unverified":
                identity_drift = True
                errors.append(f"{sid}: process identity changed; refresh before stopping")
                continue
            if verification_error:
                errors.append(
                    f"{sid}: target verification failed ({str(verification_error)[:160]})"
                )
                continue
            termination = _terminate_direct_session_process(
                verified_row or {}, "claude", pid
            )
            if not termination.get("ok"):
                detail = str(termination.get("error") or "termination failed")[:160]
                if termination.get("outcome_indeterminate"):
                    unknown_outcomes.append(f"{sid}: {detail}")
                else:
                    errors.append(f"{sid}: {detail}")
                continue
            stopped.append(sid)
            stopped_set.add(sid)
            self._mark_session_closed(native_id)
        if active_target_count > 0 and len(stopped) != active_target_count and not errors and not unknown_outcomes:
            errors.append("not every active session produced a confirmed stop outcome")

        if active_target_count > 0 and not errors and not unknown_outcomes:
            run["status"] = "stopped"
            run["finished_reason"] = "manual_stop"
            run["finished_at"] = _time.time()
            run["status_detail"] = f"Stopped {len(stopped)} active session(s). Idle sessions were left untouched."
            self._orchestration_event(run, "stop", "Active orchestration sessions stopped from phone", run["status_detail"])
        elif errors or unknown_outcomes:
            run["status"] = run.get("status") or "quiet"
            run["status_detail"] = (
                f"Stopped {len(stopped)} of {active_target_count} active session(s). "
                "One or more stop outcomes were not confirmed."
            )
            self._orchestration_event(
                run,
                "stop_failed",
                "Orchestration stop was not fully confirmed",
                run["status_detail"],
            )
        else:
            run["status"] = run.get("status") or "quiet"
            run["status_detail"] = "No active orchestration sessions were running; idle sessions were left untouched."
            self._orchestration_event(run, "status", "No active orchestration sessions to stop", run["status_detail"])
        self._orchestration_write(run)
        receipt = _make_action_receipt(
            client_action_id=client_action_id or None,
            state="indeterminate" if unknown_outcomes else ("applied" if not errors else "failed"),
            phases=_receipt_phases(
                validated=True,
                applied=not errors and not unknown_outcomes,
                pty_written=None if unknown_outcomes else False,
            ),
            backend="process_signal",
        )
        final_status = (
            409
            if identity_drift or broker_runtime_mismatch
            else (
                503
                if broker_unavailable
                else (502 if unknown_outcomes or errors else 200)
            )
        )
        final_error_code = (
            "process_identity_unverified"
            if identity_drift
            else (
                "broker_requires_current_runtime"
                if broker_runtime_mismatch
                else (
                    "broker_unavailable"
                    if broker_unavailable
                    else (
                        "broker_termination_outcome_unknown"
                        if unknown_outcomes
                        else ("orchestration_stop_failed" if errors else None)
                    )
                )
            )
        )
        _receipt_attach_response(
            receipt,
            http_status=final_status,
            error_code=(
                final_error_code
            ),
            error_message=(
                "One or more session stop outcomes could not be confirmed."
                if unknown_outcomes
                else (
                    "One or more active sessions could not be stopped."
                    if errors
                    else None
                )
            ),
            fields={
                "stopped": stopped,
                "errors": errors,
                "unknown_outcomes": unknown_outcomes,
                "orchestration": run,
            },
        )
        _store_action_receipt(
            device_id,
            receipt_session_id,
            client_action_id or None,
            body_hash,
            receipt,
            action_kind="orchestration_stop",
            audit_action={
                "type": "stop_orchestration",
                "stopped_count": len(stopped),
                "error_count": len(errors),
                "unknown_count": len(unknown_outcomes),
            },
        )
        response, response_status = _receipt_replay_response(
            receipt,
            {"ok": not errors and not unknown_outcomes},
        )
        self._send_json(response, status=response_status)

    # ----- /workstate-feed: read-only substrate feed for native context surfaces -----
    def _handle_workstate_feed(self, q):
        run = q.get("run", [""])[0].strip()
        if not run:
            self.send_error(400, "run is required")
            return
        since = q.get("since", [WORKSTATE_FEED_DEFAULT_SINCE])[0]
        try:
            limit = int(q.get("limit", ["50"])[0])
        except ValueError:
            self.send_error(400, "limit must be an integer")
            return
        event_types: list[str] = []
        for raw_value in q.get("type", []):
            event_types.extend(part.strip() for part in raw_value.split(",") if part.strip())
        try:
            payload = _fetch_workstate_feed(run, since=since, limit=limit, event_types=event_types)
        except WorkstateFeedError as exc:
            self.send_error(502, str(exc))
            return
        self._send_json(payload)

    # ----- /model-status: read-only substrate model arbiter status -----
    def _handle_model_status(self, q):
        run = q.get("run", [""])[0].strip()
        if not run:
            self.send_error(400, "run is required")
            return
        since = q.get("since", [MODEL_STATUS_DEFAULT_SINCE])[0]
        try:
            limit = int(q.get("limit", ["50"])[0])
        except ValueError:
            self.send_error(400, "limit must be an integer")
            return
        try:
            payload = _fetch_model_status(run, since=since, limit=limit)
        except ModelStatusError as exc:
            self.send_error(502, str(exc))
            return
        self._send_json(payload)

    # ----- /substrate-status and /substrate-feed: read-only operational substrate -----
    def _handle_substrate_status(self, q):
        run = q.get("run", [""])[0].strip()
        if not run:
            self.send_error(400, "run is required")
            return
        since = q.get("since", [SUBSTRATE_STATUS_DEFAULT_SINCE])[0]
        try:
            limit = int(q.get("limit", ["50"])[0])
        except ValueError:
            self.send_error(400, "limit must be an integer")
            return
        try:
            payload = _fetch_substrate_status(run, since=since, limit=limit)
        except SubstrateStatusError as exc:
            self.send_error(502, str(exc))
            return
        self._send_json(payload)

    def _handle_substrate_feed(self, q):
        run = q.get("run", [""])[0].strip()
        if not run:
            self.send_error(400, "run is required")
            return
        since = q.get("since", [SUBSTRATE_STATUS_DEFAULT_SINCE])[0]
        try:
            limit = int(q.get("limit", ["50"])[0])
        except ValueError:
            self.send_error(400, "limit must be an integer")
            return
        event_types: list[str] = []
        for raw_value in q.get("type", []):
            event_types.extend(part.strip() for part in raw_value.split(",") if part.strip())
        try:
            payload = _fetch_substrate_feed(run, since=since, limit=limit, event_types=event_types)
        except SubstrateStatusError as exc:
            self.send_error(502, str(exc))
            return
        self._send_json(payload)

    def _worker_stats_payload(self, since_min: int = 60) -> dict:
        return _worker_stats_payload(since_min)

    # ----- /worker-stats: count automated worker sessions -----
    def _handle_worker_stats(self, q):
        try:
            since_min = int(q.get("since_min", ["60"])[0])
            payload = self._worker_stats_payload(since_min)
        except ValueError:
            self.send_error(400, "since_min must be an integer")
            return
        except RuntimeError as exc:
            self.send_error(502, str(exc))
            return

        body = json.dumps(payload).encode()

        self.send_response(200)
        self.send_header("Content-Type", "application/json")
        self.send_header("Content-Length", str(len(body)))
        self.end_headers()
        self.wfile.write(body)

    # ----- /worker-kill: SIGTERM workers, audit log -----
    def _handle_worker_kill(self, q):
        try:
            payload = json.loads(self._read_body() or b"{}")
        except json.JSONDecodeError:
            self.send_error(400, "body must be JSON")
            return

        target_ids: list[str] = payload.get("session_ids") or []
        kill_filter = payload.get("filter")
        provider_filter = str(payload.get("provider") or "claude").lower()
        if not _valid_provider_filter(provider_filter):
            _send_unknown_provider(self, provider_filter)
            return
        client_action_id = str(self.headers.get("X-Pairling-Action-Id") or "").strip()
        if not _valid_client_action_id(client_action_id):
            self._send_json({
                "ok": False,
                "error": {
                    "code": "action_id_required",
                    "message": "A valid X-Pairling-Action-Id is required to stop workers.",
                },
                "error_code": "action_id_required",
            }, status=400)
            return
        device_id = getattr(getattr(self, "pairling_auth", None), "device_id", None)
        receipt_session_id = f"worker-kill:{provider_filter}:{kill_filter or 'ids'}"
        body_hash = _receipt_body_hash({
            "session_ids": sorted(str(item) for item in target_ids),
            "filter": kill_filter,
            "provider": provider_filter,
        })
        deduped_receipt, conflict = _receipt_duplicate_response(
            device_id,
            receipt_session_id,
            client_action_id,
            body_hash,
            action_kind="worker_kill",
        )
        if conflict:
            _store_action_receipt(
                device_id,
                receipt_session_id,
                client_action_id,
                body_hash,
                conflict["receipt"],
                action_kind="worker_kill",
                audit_action={"type": "idempotency_conflict"},
                persist=False,
            )
            self._send_json({
                "ok": False,
                "killed": [],
                "skipped": [],
                "errors": [conflict["error"]["message"]],
                "receipt": conflict["receipt"],
                "deduped": True,
                "error_code": conflict["error"]["code"],
            }, status=int(conflict["status"]))
            return
        if deduped_receipt:
            replay, replay_status = _receipt_replay_response(deduped_receipt, {
                "ok": deduped_receipt.get("state") == "applied",
                "killed": [],
                "skipped": [],
                "errors": [],
                "deduped": True,
            })
            if isinstance(replay.get("error"), dict):
                replay["error"] = replay["error"].get("message")
            self._send_json(replay, status=replay_status)
            return

        # If filter=stale, bind the kill set to a freshly recomputed stale
        # set. Explicit session_ids are the user-confirmed upper bound: kill
        # exactly the intersection and skip anything that recovered or was
        # never requested, even if it is stale now.
        stale_intersection_skips: list[str] = []
        if kill_filter == "stale":
            fresh_stale_ids: list[str] = []
            if provider_filter in ("all", "claude"):
                worker_patterns = [
                    "biotech-labs/synth-synth-",
                    "biotech-labs/crohns-research/scripts",
                    "biotech-research-",
                ]
                for sid in _claude_sessions_backend().stale_session_ids():
                    sid = sid.strip()
                    if not sid:
                        continue
                    project = self._lookup_pg_project(sid) or ""
                    if any(p in project for p in worker_patterns):
                        fresh_stale_ids.append(sid)
            if provider_filter in ("all", "codex"):
                for worker in self._collect_codex_workers(since_min=60 * 24):
                    if worker.get("stale"):
                        fresh_stale_ids.append(worker.get("id") or "")
            if target_ids:
                requested_ids = [str(item) for item in target_ids]
                fresh_stale_set = {
                    _parse_agent_session_ref(str(item))
                    for item in fresh_stale_ids
                    if str(item)
                }
                still_stale: list[str] = []
                for rid in requested_ids:
                    if _parse_agent_session_ref(rid) in fresh_stale_set:
                        still_stale.append(rid)
                    else:
                        stale_intersection_skips.append(f"{rid} (no longer stale)")
                target_ids = still_stale
            else:
                target_ids = fresh_stale_ids

        # SAFETY: never kill anything with a recent heartbeat (<5 min)
        # SAFETY: refuse mass kills > 100 to avoid runaway
        if len(target_ids) > 100:
            too_many_message = f"too many ids ({len(target_ids)}); max 100"
            receipt = _make_action_receipt(
                client_action_id=client_action_id or None,
                state="rejected",
                phases=_receipt_phases(validated=False, applied=False, pty_written=False),
                backend="worker_kill",
            )
            _receipt_attach_response(
                receipt,
                http_status=400,
                error_code="too_many_targets",
                error_message=too_many_message,
                fields={
                    "killed": [],
                    "skipped": [],
                    "errors": [too_many_message],
                    "outcome_indeterminate": False,
                },
            )
            _store_action_receipt(
                device_id,
                receipt_session_id,
                client_action_id or None,
                body_hash,
                receipt,
                action_kind="worker_kill",
                audit_action={"type": "worker_kill_rejected", "reason": "too_many_ids"},
            )
            self._send_json({
                "ok": False,
                "killed": [],
                "skipped": [],
                "errors": [too_many_message],
                "error_code": "too_many_targets",
                "receipt": receipt,
                "deduped": False,
            }, status=400)
            return

        killed: list[str] = []
        skipped: list[str] = list(stale_intersection_skips)
        errors: list[str] = []
        identity_drift = False
        broker_runtime_mismatch = False
        broker_unavailable = False
        outcome_indeterminate = False
        terminal_error_code: str | None = None

        for raw_sid in target_ids:
            provider, sid = _parse_agent_session_ref(str(raw_sid or ""))
            if provider_filter != "all" and provider != provider_filter:
                skipped.append(f"{raw_sid} (provider mismatch)")
                continue

            if provider == "codex":
                sid = _agent_registry_resolve_native_alias("codex", sid)
                if not _safe_agent_native_id(sid):
                    skipped.append(str(raw_sid))
                    continue
                reg = _agent_registry_get("codex", sid)
                if not reg:
                    skipped.append(f"{raw_sid} (no Codex registry row)")
                    continue
                idle_seconds = int(max(0, _time.time() - float(reg.get("last_heartbeat") or 0)))
                if idle_seconds < 300:
                    skipped.append(f"{raw_sid} (active <5min)")
                    continue
                _current, pid, verification_error = _verified_session_signal_target("codex", sid)
                if verification_error == "process_identity_unverified":
                    identity_drift = True
                    terminal_error_code = terminal_error_code or "process_identity_unverified"
                    errors.append(f"{raw_sid}: process identity changed; refresh before stopping")
                    continue
                if verification_error:
                    _agent_registry_mark_closed("codex", sid)
                    killed.append(f"{raw_sid} (no live process; registry closed)")
                    continue
                current_idle_seconds = int(max(0, _time.time() - float((_current or {}).get("last_heartbeat") or 0)))
                if current_idle_seconds < 300:
                    skipped.append(f"{raw_sid} (active <5min)")
                    continue

                broker_found = self._broker_session_for(_qualified_session_id("codex", sid))
                durable_broker_id = _durable_broker_id_from_registry_row(
                    reg,
                    provider="codex",
                    native_id=sid,
                )
                if broker_found and PTY_BROKER:
                    _public_id, broker_session = broker_found
                    broker_id = _broker_session_id(broker_session)
                    if not _broker_session_owns_identity(broker_session, "codex", sid):
                        identity_drift = True
                        terminal_error_code = terminal_error_code or "process_identity_unverified"
                        errors.append(f"{raw_sid}: broker ownership changed; refresh before stopping")
                        continue
                    if not _broker_is_current_runtime():
                        broker_runtime_mismatch = True
                        terminal_error_code = terminal_error_code or "broker_requires_current_runtime"
                        errors.append(f"{raw_sid}: termination requires the current terminal broker")
                        continue
                    try:
                        result = PTY_BROKER.terminate(broker_id, signal.SIGTERM)
                    except PTYBrokerOutcomeUnknownError as exc:
                        outcome_indeterminate = True
                        terminal_error_code = "worker_kill_outcome_unknown"
                        errors.append(f"{raw_sid}: termination outcome is unknown: {str(exc)[:100]}")
                        continue
                    except Exception as exc:
                        broker_unavailable = True
                        terminal_error_code = terminal_error_code or "broker_unavailable"
                        errors.append(f"{raw_sid}: terminal broker unavailable: {str(exc)[:100]}")
                        continue
                    if not bool(result.get("ok")):
                        if result.get("outcome_indeterminate"):
                            outcome_indeterminate = True
                            terminal_error_code = "worker_kill_outcome_unknown"
                        else:
                            terminal_error_code = terminal_error_code or str(
                                result.get("error_code") or "worker_kill_failed"
                            )
                        errors.append(
                            f"{raw_sid}: {str(result.get('error') or result.get('reason') or 'termination failed')[:120]}"
                        )
                        continue
                    _agent_registry_mark_closed("codex", sid)
                    killed.append(str(raw_sid))
                    continue
                if durable_broker_id:
                    broker_unavailable = True
                    terminal_error_code = terminal_error_code or "broker_unavailable"
                    errors.append(f"{raw_sid}: terminal broker is unavailable; no direct signal was sent")
                    continue

                termination = _terminate_direct_session_process(
                    _current or reg,
                    "codex",
                    pid,
                )
                if not termination.get("ok"):
                    if termination.get("outcome_indeterminate"):
                        outcome_indeterminate = True
                        terminal_error_code = "worker_kill_outcome_unknown"
                    terminal_error_code = terminal_error_code or str(
                        termination.get("error_code") or "worker_kill_failed"
                    )
                    errors.append(
                        f"{raw_sid}: {str(termination.get('error') or 'termination failed')[:120]}"
                    )
                    continue
                _agent_registry_mark_closed("codex", sid)
                killed.append(str(raw_sid))
                continue

            if provider != "claude" or not _safe_session_id(sid):
                skipped.append(str(raw_sid))
                continue

            record = _claude_sessions_backend().session_record(sid)
            if not record:
                skipped.append(f"{raw_sid} (no Claude registry row)")
                continue
            idle_seconds = int(max(0, _time.time() - float(record.get("last_heartbeat") or 0)))

            if idle_seconds < 300:
                skipped.append(f"{sid} (active <5min)")
                continue

            _current, pid, verification_error = _verified_session_signal_target("claude", sid)
            if verification_error == "process_identity_unverified":
                identity_drift = True
                terminal_error_code = terminal_error_code or "process_identity_unverified"
                errors.append(f"{raw_sid}: process identity changed; refresh before stopping")
                continue
            if verification_error:
                killed.append(f"{raw_sid} (no live process; row remains)")
                continue
            current_idle_seconds = int(max(0, _time.time() - float((_current or {}).get("last_heartbeat") or 0)))
            if current_idle_seconds < 300:
                skipped.append(f"{sid} (active <5min)")
                continue

            broker_registry_row = _agent_registry_get("claude", sid)
            if broker_registry_row is None:
                broker_registry_row = _agent_registry_row_for_broker_id(
                    "claude",
                    _qualified_session_id("claude", sid),
                )
            broker_found = self._broker_session_for(_qualified_session_id("claude", sid))
            durable_broker_id = _durable_broker_id_from_registry_row(
                broker_registry_row,
                provider="claude",
                native_id=sid,
            )
            if broker_found and PTY_BROKER:
                _public_id, broker_session = broker_found
                broker_id = _broker_session_id(broker_session)
                if not _broker_session_owns_identity(broker_session, "claude", sid):
                    identity_drift = True
                    terminal_error_code = terminal_error_code or "process_identity_unverified"
                    errors.append(f"{raw_sid}: broker ownership changed; refresh before stopping")
                    continue
                if not _broker_is_current_runtime():
                    broker_runtime_mismatch = True
                    terminal_error_code = terminal_error_code or "broker_requires_current_runtime"
                    errors.append(f"{raw_sid}: termination requires the current terminal broker")
                    continue
                try:
                    result = PTY_BROKER.terminate(broker_id, signal.SIGTERM)
                except PTYBrokerOutcomeUnknownError as exc:
                    outcome_indeterminate = True
                    terminal_error_code = "worker_kill_outcome_unknown"
                    errors.append(f"{raw_sid}: termination outcome is unknown: {str(exc)[:100]}")
                    continue
                except Exception as exc:
                    broker_unavailable = True
                    terminal_error_code = terminal_error_code or "broker_unavailable"
                    errors.append(f"{raw_sid}: terminal broker unavailable: {str(exc)[:100]}")
                    continue
                if not bool(result.get("ok")):
                    if result.get("outcome_indeterminate"):
                        outcome_indeterminate = True
                        terminal_error_code = "worker_kill_outcome_unknown"
                    else:
                        terminal_error_code = terminal_error_code or str(
                            result.get("error_code") or "worker_kill_failed"
                        )
                    errors.append(
                        f"{raw_sid}: {str(result.get('error') or result.get('reason') or 'termination failed')[:120]}"
                    )
                    continue
                self._mark_session_closed(sid)
                killed.append(str(raw_sid))
                continue
            if durable_broker_id:
                broker_unavailable = True
                terminal_error_code = terminal_error_code or "broker_unavailable"
                errors.append(f"{raw_sid}: terminal broker is unavailable; no direct signal was sent")
                continue

            termination = _terminate_direct_session_process(
                _current or record,
                "claude",
                pid,
            )
            if not termination.get("ok"):
                if termination.get("outcome_indeterminate"):
                    outcome_indeterminate = True
                    terminal_error_code = "worker_kill_outcome_unknown"
                terminal_error_code = terminal_error_code or str(
                    termination.get("error_code") or "worker_kill_failed"
                )
                errors.append(
                    f"{raw_sid}: {str(termination.get('error') or 'termination failed')[:120]}"
                )
                continue
            self._mark_session_closed(sid)
            killed.append(str(raw_sid))

        # Audit log
        audit_dir = HOME / ".claude" / "audit"
        audit_dir.mkdir(parents=True, exist_ok=True)
        audit_file = audit_dir / "worker-kills.jsonl"
        with open(audit_file, "a") as f:
            f.write(json.dumps({
                "timestamp": _time.time(),
                "killer": "phone-companion",
                "filter": kill_filter,
                "provider": provider_filter,
                "target_count": len(target_ids),
                "killed": killed,
                "skipped": skipped,
                "errors": errors,
            }) + "\n")

        if outcome_indeterminate:
            response_status = 502
            terminal_error_code = "worker_kill_outcome_unknown"
        elif identity_drift or broker_runtime_mismatch:
            response_status = 409
        elif broker_unavailable:
            response_status = 503
        elif errors:
            response_status = 502
        else:
            response_status = 200

        receipt = _make_action_receipt(
            client_action_id=client_action_id or None,
            state=(
                "indeterminate"
                if outcome_indeterminate
                else ("applied" if not errors else "failed")
            ),
            phases=_receipt_phases(validated=True, applied=not errors, pty_written=False),
            backend="worker_kill",
        )
        _receipt_attach_response(
            receipt,
            http_status=response_status,
            error_code=terminal_error_code if errors else None,
            error_message=errors[0] if errors else None,
            fields={
                "killed": killed,
                "skipped": skipped,
                "errors": errors,
                "outcome_indeterminate": outcome_indeterminate,
            },
        )
        _store_action_receipt(
            device_id,
            receipt_session_id,
            client_action_id or None,
            body_hash,
            receipt,
            action_kind="worker_kill",
            audit_action={
                "type": "worker_kill",
                "filter": kill_filter,
                "provider": provider_filter,
                "target_count": len(target_ids),
                "killed_count": len(killed),
                "skipped_count": len(skipped),
                "error_count": len(errors),
            },
        )
        response = {
            "ok": receipt.get("state") == "applied",
            "killed": killed,
            "skipped": skipped,
            "errors": errors,
            "receipt": receipt,
            "deduped": False,
            "outcome_indeterminate": outcome_indeterminate,
            **({"error_code": terminal_error_code} if terminal_error_code else {}),
        }
        self._send_json(response, status=response_status)

    def _handle_spawn_session_broker(
        self,
        project: str,
        provider: str,
        launch_context: dict | None = None,
        native_id_override: str | None = None,
        first_prompt: str = "",
        spawn_action_id: str = "",
        spawn_body_hash: str = "",
        requested_session_mode: str = "terminal",
        structured_fallback_reason: str | None = None,
    ) -> None:
        spawn_device_id = getattr(getattr(self, "pairling_auth", None), "device_id", None)
        if PTY_BROKER is None:
            message = "PTY broker unavailable"
            receipt = _finalize_spawn_action(
                device_id=spawn_device_id,
                provider=provider,
                client_action_id=spawn_action_id or None,
                body_hash=spawn_body_hash,
                state="failed",
                http_status=503,
                backend="pty_broker",
                error_code="broker_unavailable",
                error_message=message,
                fields={"outcome_indeterminate": False},
            )
            self._send_json({
                "ok": False,
                "error": {"code": "broker_unavailable", "message": message},
                "error_code": "broker_unavailable",
                "outcome_indeterminate": False,
                "receipt": receipt,
            }, status=503)
            return
        if not _broker_is_current_runtime():
            message = "New sessions require the current terminal broker. Control remains unavailable for a session owned by the previous runtime until it finishes."
            receipt = _finalize_spawn_action(
                device_id=spawn_device_id,
                provider=provider,
                client_action_id=spawn_action_id or None,
                body_hash=spawn_body_hash,
                state="rejected",
                http_status=409,
                backend="pty_broker",
                error_code="broker_requires_current_runtime",
                error_message=message,
                fields={"outcome_indeterminate": False},
            )
            self._send_json({
                "ok": False,
                "error": {
                    "code": "broker_requires_current_runtime",
                    "message": message,
                },
                "error_code": "broker_requires_current_runtime",
                "outcome_indeterminate": False,
                "receipt": receipt,
            }, status=409)
            return

        capture_id = secrets.token_hex(12)
        native_id = native_id_override or ("pending-" + secrets.token_hex(8))
        published_native_id = native_id
        omp_session_identity: dict | None = None
        broker_session_id = _qualified_session_id(provider, native_id)
        broker_env = None
        if launch_context is not None:
            generated = launch_context.get("generated") if isinstance(launch_context.get("generated"), dict) else {}
            broker_env = generated.get("env") if isinstance(generated.get("env"), dict) else None
            command = _aperture_cli_command_for_context(launch_context, project) if _aperture_cli_command_for_context else ""
            unavailable_code = "aperture_cli_launch_unavailable"
            unavailable_message = "Aperture CLI launch command unavailable"
        else:
            try:
                command, _interactive = _reviewed_provider_launch_command(
                    provider,
                    project,
                    "broker",
                )
            except ValueError:
                command = ""
            unavailable_code = "provider_spawn_backend_unavailable"
            unavailable_message = (
                f"{provider} has no reviewed broker launch command"
            )
        if not command:
            message = unavailable_message
            receipt = _finalize_spawn_action(
                device_id=spawn_device_id,
                provider=provider,
                client_action_id=spawn_action_id or None,
                body_hash=spawn_body_hash,
                state="failed",
                http_status=503,
                backend="pty_broker",
                error_code=unavailable_code,
                error_message=message,
                fields={"outcome_indeterminate": False},
            )
            self._send_json({
                "ok": False,
                "error": {"code": unavailable_code, "message": message},
                "error_code": unavailable_code,
                "outcome_indeterminate": False,
                "receipt": receipt,
            }, status=503)
            return

        if provider == "claude":
            # Headless PTY: nobody can answer the folder-trust prompt, so
            # accept it up front (the phone user's spawn IS the trust gesture).
            try:
                _pretrust_claude_project(project)
            except ClaudeProjectTrustError as error:
                receipt = _finalize_spawn_action(
                    device_id=spawn_device_id,
                    provider=provider,
                    client_action_id=spawn_action_id or None,
                    body_hash=spawn_body_hash,
                    state="rejected" if error.status == 409 else "failed",
                    http_status=error.status,
                    backend="claude_config",
                    error_code=error.code,
                    error_message=str(error),
                    fields={"outcome_indeterminate": False},
                )
                self._send_json({
                    "ok": False,
                    "error": {"code": error.code, "message": str(error)},
                    "error_code": error.code,
                    "outcome_indeterminate": False,
                    "receipt": receipt,
                }, status=error.status)
                return

        ok = False
        reason = None
        outcome_indeterminate = False
        session = None
        provider_identity = None
        reconciled_existing = False
        try:
            session = PTY_BROKER.get(broker_session_id)
            if session is not None:
                if not _broker_session_matches_spawn_request(
                    session,
                    broker_id=broker_session_id,
                    provider=provider,
                    native_id=native_id,
                ):
                    raise ProcessIdentityDriftError("existing broker session identity does not match spawn action")
                ok = True
                reconciled_existing = True
                reason = "existing spawn action reconciled by broker session id"
            else:
                session = PTY_BROKER.spawn(
                    session_id=broker_session_id,
                    provider=provider,
                    native_id=native_id,
                    project=project,
                    command=command,
                    rows=30,
                    columns=120,
                    # Mark phone-spawned sessions so the global PermissionRequest hook
                    # self-enables ONLY here (no-op for the user's own claude sessions).
                    env={**(broker_env or {}), "PAIRLING_PHONE_SESSION": "1",
                         "PAIRLING_BROKER_SESSION_ID": broker_session_id},
                )
                if not _broker_session_matches_spawn_request(
                    session,
                    broker_id=broker_session_id,
                    provider=provider,
                    native_id=native_id,
                ):
                    raise ProcessIdentityDriftError(
                        "spawned broker session identity does not match spawn action"
                    )
                ok = True
        except PTYBrokerOutcomeUnknownError as exc:
            session = _broker_reconcile_session_after_unknown(
                broker_session_id,
                provider=provider,
                native_id=native_id,
            )
            if session is not None:
                reconciled_existing = True
                ok = True
                reason = "spawn response lost; reconciled by broker session id"
            else:
                outcome_indeterminate = True
                reason = f"spawn outcome unknown: {str(exc)[:180]}"
        except Exception as e:
            reason = f"{type(e).__name__}: {e}"

        if ok and session is not None:
            provider_identity = _broker_spawn_provider_identity(
                session,
                broker_id=broker_session_id,
                provider=provider,
                native_id=native_id,
                project=project,
            )
            if provider_identity is None:
                ok = False
                reason = "broker launch did not produce one live exact provider process"
                if not reconciled_existing:
                    try:
                        cleanup = PTY_BROKER.terminate(broker_session_id)
                        if not isinstance(cleanup, dict) or not cleanup.get("ok"):
                            outcome_indeterminate = True
                            reason += "; broker cleanup could not be confirmed"
                    except Exception as error:
                        outcome_indeterminate = True
                        reason += (
                            "; broker cleanup failed: "
                            + f"{type(error).__name__}: {str(error)[:120]}"
                        )

        if ok and session is not None and provider == "omp":
            omp_session_identity = _wait_for_omp_spawn_terminal_identity(
                provider_identity,
                canonical_project=project,
            )
            identity_probe_state = str(
                (omp_session_identity or {}).get("identity_probe_state") or ""
            )
            adopted_native_id = str(
                (omp_session_identity or {}).get("native_id") or ""
            )
            if identity_probe_state == "pairling_pending_process":
                published_native_id = native_id
            elif not _safe_agent_native_id(adopted_native_id):
                ok = False
                reason = "broker launch did not produce one exact OMP session identity"
                if not reconciled_existing:
                    try:
                        cleanup = PTY_BROKER.terminate(broker_session_id)
                        if not isinstance(cleanup, dict) or not cleanup.get("ok"):
                            outcome_indeterminate = True
                            reason += "; broker cleanup could not be confirmed"
                    except Exception as error:
                        outcome_indeterminate = True
                        reason += (
                            "; broker cleanup failed: "
                            + f"{type(error).__name__}: {str(error)[:120]}"
                        )
            else:
                published_native_id = adopted_native_id

        if ok and session is not None:
            session_tty = _broker_slave_tty(session)
            session_log = _broker_raw_log_path(session)
            session_pid = int(provider_identity.get("pid") or 0)
            if launch_context is not None:
                launch_meta = {
                    "spawned_by": "pairling",
                    "launch_strategy": "aperture_cli",
                    "client_id": provider,
                    "aperture_endpoint_url": (launch_context.get("endpoint") or {}).get("url"),
                    "aperture_endpoint_mode": (launch_context.get("endpoint") or {}).get("mode"),
                    "aperture_provider_id": (launch_context.get("provider") or {}).get("id"),
                    "aperture_backend_id": (launch_context.get("backend") or {}).get("id"),
                    "aperture_model": (launch_context.get("model") or {}).get("fqn") if launch_context.get("model") else None,
                    "aperture_cli_version": launch_context.get("aperture_cli_version"),
                    "danger_mode": bool((launch_context.get("danger_mode") or {}).get("enabled")),
                    "generated_env_redacted": (launch_context.get("generated") or {}).get("env_redacted"),
                    "generated_args": (launch_context.get("generated") or {}).get("args"),
                    "config_writes": (launch_context.get("generated") or {}).get("config_writes"),
                }
            else:
                launch_meta = {
                    "spawned_by": "pairling",
                    "launch_strategy": "direct_pairling",
                    "danger_mode": True,
                }
            omp_metadata = {}
            if omp_session_identity is not None:
                omp_metadata = {
                    "pending_native_id": native_id,
                    "broker_native_id": native_id,
                    "identity_probe_state": str(
                        omp_session_identity.get("identity_probe_state") or ""
                    ),
                    "provider_tty": str(
                        omp_session_identity.get("provider_tty")
                        or provider_identity.get("provider_tty")
                        or provider_identity.get("tty")
                        or session_tty
                    ),
                    "process_started_at": float(
                        omp_session_identity.get("process_started_at") or 0
                    ),
                    "executable_path": str(
                        omp_session_identity.get("executable_path") or ""
                    ),
                    "source": str(
                        omp_session_identity.get("source") or ""
                    ),
                    "output_path": str(
                        omp_session_identity.get("output_path") or ""
                    ),
                    "session_path": str(
                        omp_session_identity.get("session_path") or ""
                    ),
                    "record_mtime": float(
                        omp_session_identity.get("record_mtime") or 0
                    ),
                }
            registry_ok = _agent_registry_upsert(
                provider,
                published_native_id,
                project,
                pid=session_pid,
                terminal_tty=session_tty,
                metadata={
                    "terminal_log": str(session_log) if session_log else None,
                    "capture_backend": "pty_broker",
                    "capture_id": capture_id,
                    "broker_id": broker_session_id,
                    "send_scope_id": broker_session_id,
                    "broker_socket": str(PTY_BROKER_SOCKET),
                    "spawn_action_id": spawn_action_id or None,
                    "spawn_body_hash": spawn_body_hash or None,
                    **omp_metadata,
                    **launch_meta,
                    "broker_owner_pid": _broker_pid(session),
                },
            )
            if not registry_ok:
                ok = False
                reason = "Spawned broker ownership could not be stored durably."
                if not reconciled_existing:
                    try:
                        cleanup = PTY_BROKER.terminate(broker_session_id)
                        if not isinstance(cleanup, dict) or not cleanup.get("ok"):
                            outcome_indeterminate = True
                            reason += "; broker cleanup could not be confirmed"
                    except Exception as error:
                        outcome_indeterminate = True
                        reason += (
                            "; broker cleanup failed: "
                            + f"{type(error).__name__}: {str(error)[:120]}"
                        )
            else:
                if session_tty and session_log:
                    _write_terminal_capture_mapping(
                        session_tty,
                        session_log,
                        provider=provider,
                        project=project,
                        capture_id=capture_id,
                    )
                if provider == "codex":
                    _write_agent_turn_state(
                        "codex",
                        native_id,
                        "idle",
                        event="spawn",
                    )
                elif provider == "omp":
                    try:
                        PTY_BROKER.register_alias(
                            _qualified_session_id("omp", published_native_id),
                            broker_session_id,
                        )
                    except Exception:
                        pass

        try:
            audit_path = HOME / ".claude" / "audit" / "spawn-sessions.jsonl"
            audit_path.parent.mkdir(parents=True, exist_ok=True)
            with open(audit_path, "a") as f:
                f.write(json.dumps({
                    "ts": _time.time(),
                    "project": project,
                    "provider": provider,
                    "native_id": published_native_id,
                    "tty": _broker_slave_tty(session) if session else "",
                    "pid": int(provider_identity.get("pid") or 0) if provider_identity else 0,
                    "terminal_log": str(_broker_raw_log_path(session)) if session and _broker_raw_log_path(session) else None,
                    "capture_backend": "pty_broker",
                    "broker_id": broker_session_id,
                    "broker_socket": str(PTY_BROKER_SOCKET),
                    "ok": ok,
                    "reason": reason,
                    "via": "pairling" if launch_context is not None else "phone-companion",
                    "launch_strategy": "aperture_cli" if launch_context is not None else "direct_pairling",
                    "aperture": {
                        "endpoint": (launch_context or {}).get("endpoint"),
                        "provider": (launch_context or {}).get("provider"),
                        "backend": (launch_context or {}).get("backend"),
                        "model": (launch_context or {}).get("model"),
                        "danger_mode": (launch_context or {}).get("danger_mode"),
                    } if launch_context is not None else None,
                }) + "\n")
        except Exception:
            pass

        if not ok or session is None:
            error_code = "broker_spawn_outcome_unknown" if outcome_indeterminate else "broker_spawn_failed"
            message = reason or "PTY broker spawn failed"
            receipt = _finalize_spawn_action(
                device_id=spawn_device_id,
                provider=provider,
                client_action_id=spawn_action_id or None,
                body_hash=spawn_body_hash,
                state="indeterminate" if outcome_indeterminate else "failed",
                http_status=502,
                backend="pty_broker",
                error_code=error_code,
                error_message=message,
                fields={
                    "session_id": broker_session_id,
                    "outcome_indeterminate": outcome_indeterminate,
                },
            )
            self._send_json({
                "ok": False,
                "error": {
                    "code": error_code,
                    "message": message,
                },
                "error_code": error_code,
                "session_id": broker_session_id,
                "outcome_indeterminate": outcome_indeterminate,
                "receipt": receipt,
            }, status=502)
            return

        first_prompt_scheduled = False
        if first_prompt:
            first_prompt_scheduled = _schedule_first_prompt_delivery(
                provider=provider,
                native_id=published_native_id,
                text=first_prompt,
                client_action_id=spawn_action_id or None,
                device_id=spawn_device_id,
            )
        first_prompt_delivery = (
            _read_first_prompt_delivery(provider, published_native_id)
            if first_prompt else None
        )
        response = {
            "ok": True,
            "deduped": reconciled_existing,
            "first_prompt_scheduled": first_prompt_scheduled,
            "first_prompt_delivery_state": (
                first_prompt_delivery.get("state")
                if isinstance(first_prompt_delivery, dict)
                else None
            ),
            "project": project,
            "provider": provider,
            "native_id": published_native_id,
            "session_id": _qualified_session_id(provider, published_native_id),
            "send_scope_id": broker_session_id,
            "session_mode": "terminal",
            "requested_session_mode": requested_session_mode,
            "structured_fallback_reason": structured_fallback_reason,
            "terminal_backed": True,
            "tty": _broker_slave_tty(session),
            "pid": int(provider_identity.get("pid") or 0),
            "terminal_log": str(_broker_raw_log_path(session)) if _broker_raw_log_path(session) else None,
            "capture_backend": "pty_broker",
            "terminal_source": "broker_vt",
            "broker_id": broker_session_id,
            "broker_socket": str(PTY_BROKER_SOCKET),
            "launch_strategy": "aperture_cli" if launch_context is not None else "direct_pairling",
            "aperture": {
                "endpoint": (launch_context or {}).get("endpoint"),
                "provider": (launch_context or {}).get("provider"),
                "backend": (launch_context or {}).get("backend"),
                "model": (launch_context or {}).get("model"),
                "danger_mode": (launch_context or {}).get("danger_mode"),
                "generated": {"env_redacted": ((launch_context or {}).get("generated") or {}).get("env_redacted")},
            } if launch_context is not None else None,
            "attach_command": f"pairling attach {broker_session_id}",
        }
        receipt = _finalize_spawn_action(
            device_id=spawn_device_id,
            provider=provider,
            client_action_id=spawn_action_id or None,
            body_hash=spawn_body_hash,
            state="applied",
            http_status=200,
            backend="pty_broker",
            fields={key: value for key, value in response.items() if key != "deduped"},
        )
        response["receipt"] = receipt
        self._send_json(response)

    # ----- /spawn-session: open a new broker-owned agent CLI session -----
    def _handle_onestream_handoff(self, q):
        """OneStream -> Pairling handoff ingestion (W1b).

        POST validates the schema-version-1 envelope and writes one bounded,
        owner-only record without following storage symlinks. GET returns only
        a bounded projection of pending records. PUT/DELETE are rejected by the
        route dispatcher before this method is reached.
        """
        if self.command == "POST":
            try:
                payload = json.loads(self._read_body() or b"{}")
            except (UnicodeDecodeError, json.JSONDecodeError, RecursionError):
                self._send_error(400, "invalid_json", "Invalid JSON body")
                return
            if not isinstance(payload, dict):
                self._send_error(400, "invalid_payload", "Request body must be an object")
                return
            if payload.get("schemaVersion") != 1:
                self._send_error(
                    400,
                    "unsupported_schema",
                    "Unsupported or missing handoff schemaVersion",
                )
                return
            transcript_value = payload.get("transcriptText")
            if transcript_value is not None and not isinstance(transcript_value, str):
                self._send_error(
                    400,
                    "invalid_transcript",
                    "transcriptText must be a string",
                )
                return

            try:
                source = _bounded_utf8_text(
                    payload.get("source") or "OneStream",
                    "source",
                    ONESTREAM_HANDOFF_MAX_METADATA_BYTES,
                    required=True,
                )
                suggested_prompt = _bounded_utf8_text(
                    payload.get("suggestedPrompt"),
                    "suggestedPrompt",
                    ONESTREAM_HANDOFF_MAX_PROMPT_BYTES,
                )
                transcript_text = _bounded_utf8_text(
                    payload.get("transcriptText"),
                    "transcriptText",
                    ONESTREAM_HANDOFF_MAX_TRANSCRIPT_BYTES,
                )
                workflow_hint = _bounded_utf8_text(
                    payload.get("workflowHint"),
                    "workflowHint",
                    ONESTREAM_HANDOFF_MAX_METADATA_BYTES,
                ) or None
                generated_at = _bounded_utf8_text(
                    payload.get("generatedAt"),
                    "generatedAt",
                    ONESTREAM_HANDOFF_MAX_METADATA_BYTES,
                ) or None
            except (TypeError, ValueError, UnicodeError) as exc:
                self._send_error(
                    400,
                    "invalid_handoff_fields",
                    str(exc)[:300] or "Handoff contains invalid field values",
                )
                return
            segments = payload.get("segments", [])
            if not isinstance(segments, list):
                self._send_error(400, "invalid_segments", "segments must be an array")
                return
            if not suggested_prompt and not transcript_text:
                self._send_error(
                    400,
                    "empty_handoff",
                    "Handoff contains no prompt or transcript",
                )
                return
            compose_parts = [
                part
                for part in (suggested_prompt, transcript_text)
                if part
            ]
            compose_draft = "\n\n---\n\n".join(compose_parts)
            handoff_id = f"onestream-{secrets.token_hex(6)}"
            record = {
                "handoff_id": handoff_id,
                "schemaVersion": 1,
                "source": source,
                "generatedAt": generated_at,
                "workflowHint": workflow_hint,
                "suggestedPrompt": suggested_prompt,
                "transcriptText": transcript_text,
                "received_at": int(_time.time()),
                "consumed": False,
            }
            try:
                record_body = json.dumps(
                    record,
                    sort_keys=True,
                    separators=(",", ":"),
                    allow_nan=False,
                ).encode("utf-8")
            except (TypeError, ValueError, RecursionError):
                self._send_error(
                    400,
                    "invalid_handoff_fields",
                    "Handoff contains invalid field values",
                )
                return
            if len(record_body) > ONESTREAM_HANDOFF_MAX_STORED_BYTES:
                self._send_error(413, "handoff_too_large", "Handoff record is too large")
                return
            try:
                _write_onestream_handoff_record(f"{handoff_id}.json", record_body)
            except OSError as exc:
                if exc.errno == errno.ENOSPC:
                    self._send_error(
                        507,
                        "handoff_quota_exceeded",
                        "Pending OneStream handoffs exceed their storage quota",
                    )
                else:
                    self._send_error(
                        503,
                        "handoff_storage_unavailable",
                        "Handoff storage is unavailable",
                    )
                return
            self._send_json(
                {
                    "ok": True,
                    "handoff_id": handoff_id,
                    "composeDraft": compose_draft,
                },
                status=200,
            )
            return

        try:
            directory_fd = _open_handoffs_directory_fd()
        except OSError:
            self._send_error(
                503,
                "handoff_storage_unavailable",
                "Handoff storage is unavailable",
            )
            return
        try:
            records = _onestream_handoff_records(directory_fd, cleanup=False)
            items = []
            response_size = len(json.dumps({"ok": True, "handoffs": []}).encode())
            for filename, record, _byte_count, _created_at in records:
                suggested = record.get(
                    "suggestedPrompt",
                    record.get("suggested_prompt", ""),
                )
                if not isinstance(suggested, str):
                    suggested = ""
                transcript = record.get(
                    "transcriptText",
                    record.get("transcript_text", ""),
                )
                if not isinstance(transcript, str):
                    transcript = ""
                compose_draft = "\n\n---\n\n".join(
                    part for part in (suggested, transcript) if part
                )
                item = {
                    "handoff_id": filename[:-5],
                    "source": (
                        record.get("source")
                        if isinstance(record.get("source"), str)
                        else "OneStream"
                    ),
                    "generatedAt": (
                        record.get("generatedAt", record.get("generated_at"))
                        if isinstance(
                            record.get("generatedAt", record.get("generated_at")),
                            str,
                        )
                        else None
                    ),
                    "workflowHint": (
                        record.get("workflowHint", record.get("workflow_hint"))
                        if isinstance(
                            record.get("workflowHint", record.get("workflow_hint")),
                            str,
                        )
                        else None
                    ),
                    "suggestedPrompt": suggested,
                    "transcriptText": transcript,
                    "composeDraft": compose_draft,
                    "received_at": (
                        record.get("received_at")
                        if (
                            isinstance(record.get("received_at"), int)
                            and not isinstance(record.get("received_at"), bool)
                        )
                        else None
                    ),
                }
                item_size = len(json.dumps(item).encode("utf-8"))
                separator_size = 2 if items else 0
                if (
                    response_size + separator_size + item_size
                    > ONESTREAM_HANDOFF_MAX_RESPONSE_BYTES
                ):
                    break
                items.append(item)
                response_size += separator_size + item_size
        finally:
            os.close(directory_fd)
        self._send_json({"ok": True, "handoffs": items})

    def _handle_spawn_session(self, q):
        """Spawn a reviewed provider session through an allowed launch backend.

        Pairling PTY sessions use the owned broker. Reviewed providers may also
        use the signed Pairling.app helper for a visible Terminal.app session.

        Security:
        - Project path must be absolute and exist on disk.
        - Path must be under one of the allowed prefixes (no arbitrary fs).
        - Global rate limit reuses _inject_rate_check with a special key.
        - Every spawn (success or failure) appended to ~/.claude/audit/.
        """
        headers = getattr(self, "headers", {}) or {}
        header_content_type = headers.get("Content-Type") if hasattr(headers, "get") else ""
        content_type = (header_content_type or "").lower()
        raw_body = (
            self._read_body() or b"{}"
            if "application/json" in content_type
            else b"{}"
        )
        payload: dict = {}
        payload_error: tuple[str, str] | None = None
        if "application/json" in content_type:
            try:
                decoded_payload = json.loads(raw_body)
                if isinstance(decoded_payload, dict):
                    payload = decoded_payload
                else:
                    payload_error = ("invalid_body", "body must be a JSON object")
            except json.JSONDecodeError as exc:
                payload_error = ("bad_json", str(exc)[:200] or "body must be JSON")

        query_material = {
            key: list(q.get(key, []))
            for key in (
                "project", "provider", "provider_id", "launch_strategy",
                "spawn_backend", "provider_profile_id",
            )
            if q.get(key)
        }
        mutation = _begin_receipted_mutation(
            self,
            receipt_scope="spawn_session",
            action_kind="spawn_session",
            material={
                "body_sha256": hashlib.sha256(raw_body).hexdigest(),
                "query": query_material,
            },
            action_label="session launch",
        )
        if mutation is None:
            return

        aperture_payload = payload.get("aperture") if isinstance(payload.get("aperture"), dict) else {}
        launch_strategy = str(payload.get("launch_strategy") or q.get("launch_strategy", ["direct_pairling"])[0] or "direct_pairling").strip().lower()
        session_mode = str(
            payload.get("session_mode")
            or q.get("session_mode", ["terminal"])[0]
            or "terminal"
        ).strip().lower()
        requested_spawn_backend = str(
            payload.get("spawn_backend") or ""
        ).strip().lower()
        provider_profile_id = str(
            payload.get("provider_profile_id") or ""
        ).strip()
        requested_native_id = str(payload.get("native_id") or "").strip()
        structured_fallback_reason = None
        project = str(
            payload.get("project") or q.get("project", [""])[0]
        ).strip()
        body_provider = str(payload.get("provider") or "").strip().lower()
        body_provider_id = str(
            payload.get("provider_id") or ""
        ).strip().lower()
        provider = (
            body_provider_id
            or body_provider
            or str(aperture_payload.get("client_id") or "").lower()
            or str(q.get("provider", ["claude"])[0]).lower()
        )
        client_action_id = mutation["client_action_id"]
        spawn_body_hash = mutation["body_hash"]
        device_id = str(mutation["device_id"])

        def reject_spawn(
            status: int,
            code: str,
            message: str,
            *,
            fields: dict | None = None,
            state: str = "rejected",
        ) -> None:
            response_fields = {
                "provider": provider or None,
                "project": project or None,
                "launch_strategy": launch_strategy or None,
                "spawn_backend": requested_spawn_backend or None,
                "provider_profile_id": provider_profile_id or None,
                "outcome_indeterminate": state == "indeterminate",
                **(fields or {}),
            }
            receipt = _finalize_spawn_action(
                device_id=device_id,
                provider=provider or "unknown",
                client_action_id=client_action_id,
                body_hash=spawn_body_hash,
                state=state,
                http_status=status,
                backend="session_launcher",
                error_code=code,
                error_message=message,
                fields=response_fields,
            )
            body, response_status = _receipt_replay_response(
                receipt,
                {"ok": False, "deduped": False},
            )
            self._send_json(body, status=response_status)

        if payload_error is not None:
            reject_spawn(400, payload_error[0], payload_error[1])
            return

        # Thick new-session (field report item 6): an optional first prompt
        # rides the spawn and is delivered once the session is ready, using
        # the same readiness event and send discipline the phone's manual
        # flow uses. Sanitized like every terminal-bound text.
        first_prompt = str(payload.get("first_prompt") or "").strip()
        if first_prompt:
            first_prompt, _fp_err = _sanitize_terminal_text_input(
                first_prompt, allow_newline=True, max_chars=4000,
            )
            if _fp_err:
                reject_spawn(
                    int(_fp_err["status"]),
                    str(_fp_err["code"]),
                    str(_fp_err["message"]),
                )
                return
        if launch_strategy not in {"direct_pairling", "aperture_cli"}:
            reject_spawn(
                400,
                "invalid_launch_strategy",
                "launch_strategy must be direct_pairling or aperture_cli",
            )
            return
        if session_mode != "terminal":
            reject_spawn(
                400,
                "invalid_session_mode",
                "session_mode is terminal-only; use spawn_backend=managed_provider",
            )
            return
        if (
            body_provider
            and body_provider_id
            and body_provider != body_provider_id
        ):
            reject_spawn(
                409,
                "provider_mismatch",
                "provider_id does not match provider",
            )
            return
        if requested_spawn_backend not in {
            "", "terminal_app", "broker", "managed_provider",
        }:
            reject_spawn(
                400,
                "invalid_spawn_backend",
                (
                    "spawn_backend must be terminal_app, broker, "
                    "or managed_provider"
                ),
            )
            return
        managed_spawn = requested_spawn_backend == "managed_provider"
        if managed_spawn and launch_strategy != "direct_pairling":
            reject_spawn(
                400,
                "managed_provider_launch_strategy_conflict",
                "managed_provider requires direct_pairling launch_strategy",
            )
            return
        if managed_spawn and requested_native_id:
            reject_spawn(
                400,
                "managed_provider_native_id_rejected",
                "managed_provider owns the native session identity",
            )
            return
        if managed_spawn and not provider_profile_id:
            reject_spawn(
                400,
                "managed_provider_profile_required",
                "provider_profile_id is required for managed_provider",
            )
            return
        if not managed_spawn and provider_profile_id:
            reject_spawn(
                400,
                "provider_profile_backend_mismatch",
                "provider_profile_id is supported only by managed_provider",
            )
            return
        forbidden_managed_fields = {
            "cwd", "profile", "provider_version", "provider_channel",
            "argv", "command", "env", "credentials",
        }
        if managed_spawn and forbidden_managed_fields.intersection(payload):
            reject_spawn(
                400,
                "managed_provider_unsafe_override_rejected",
                "managed provider runtime identity is server-owned",
            )
            return
        if requested_native_id and re.fullmatch(r"pending-[a-f0-9]{16}", requested_native_id) is None:
            reject_spawn(
                400,
                "invalid_native_id",
                "native_id must be pending- followed by 16 lowercase hex characters",
            )
            return
        if requested_native_id and launch_strategy != "direct_pairling":
            reject_spawn(
                400,
                "native_id_not_supported",
                "native_id is supported only for direct_pairling launches",
            )
            return
        if not _valid_provider_filter(provider, allow_all=False):
            error = _unknown_provider_payload(provider or "empty")["error"]
            reject_spawn(
                400,
                str(error["code"]),
                str(error["message"]),
                fields={"error": error},
            )
            return
        if not managed_spawn and not _provider_supports(provider, "spawn"):
            error = _unsupported_provider_payload(provider, "spawn")["error"]
            reject_spawn(
                400,
                str(error["code"]),
                str(error["message"]),
                fields={"error": error},
            )
            return
        if not _provider_visible(provider):
            reject_spawn(409, "provider_hidden", f"{provider} is hidden in Pairling")
            return
        if managed_spawn:
            spawn_backend = "managed_provider"
        elif launch_strategy == "aperture_cli":
            if requested_spawn_backend not in {"", "broker"}:
                reject_spawn(
                    409,
                    "aperture_spawn_backend_mismatch",
                    "aperture_cli launches require the broker backend",
                )
                return
            spawn_backend = "broker"
        else:
            spawn_backend = (
                requested_spawn_backend
                or os.environ.get("PAIRLING_SPAWN_BACKEND", "terminal_app")
            ).lower()
            if spawn_backend not in {"terminal_app", "broker"}:
                reject_spawn(
                    400,
                    "invalid_spawn_backend",
                    "spawn_backend must be terminal_app or broker",
                )
                return
            launch_contract = _reviewed_terminal_launch_contract(provider)
            if (
                launch_contract is None
                or spawn_backend not in launch_contract.backends
            ):
                reject_spawn(
                    409,
                    "provider_spawn_backend_unavailable",
                    (
                        f"{provider} has no reviewed {spawn_backend} "
                        "launch command"
                    ),
                )
                return
        if not project:
            reject_spawn(400, "project_required", "project required")
            return
        if not project.startswith("/"):
            reject_spawn(400, "invalid_project", "project must be absolute path")
            return
        if ".." in project.split("/"):
            reject_spawn(400, "path_traversal_rejected", "path traversal rejected")
            return

        try:
            canonical_project = _canonical_user_directory(project, allow_tmp=True)
        except ValueError:
            reject_spawn(400, "invalid_project", "project path is invalid")
            return
        except (FileNotFoundError, NotADirectoryError):
            reject_spawn(
                404, "project_not_found", f"directory not found: {project}"
            )
            return
        except (PermissionError, OSError):
            reject_spawn(
                403,
                "project_not_allowed",
                f"project path must be a real directory under $HOME or /tmp: {project}",
            )
            return
        project = canonical_project

        deterministic_native_id = requested_native_id or (
            "pending-"
            + hashlib.sha256(f"{device_id}\0{client_action_id}".encode()).hexdigest()[:16]
        )
        existing_native_id = deterministic_native_id
        existing_row = _agent_registry_get(provider, deterministic_native_id)
        if existing_row is None and provider == "omp":
            existing_native_id = _agent_registry_resolve_native_alias(
                "omp", deterministic_native_id
            )
            existing_row = _agent_registry_get("omp", existing_native_id)
        if existing_row is not None:
            existing_metadata = _registry_metadata_from_row(existing_row)
            if (
                existing_metadata.get("spawn_action_id") != client_action_id
                or existing_metadata.get("spawn_body_hash") != spawn_body_hash
            ):
                reject_spawn(
                    409,
                    "idempotency_conflict",
                    "This launch action ID is already bound to different session data.",
                    fields={
                        "native_id": deterministic_native_id,
                        "session_id": _qualified_session_id(provider, deterministic_native_id),
                    },
                )
                return
            existing_broker_id = str(existing_metadata.get("broker_id") or "")
            first_prompt_scheduled = False
            if first_prompt:
                first_prompt_scheduled = _schedule_first_prompt_delivery(
                    provider=provider,
                    native_id=existing_native_id,
                    text=first_prompt,
                    client_action_id=client_action_id,
                    device_id=device_id,
                )
            first_prompt_delivery = (
                _read_first_prompt_delivery(provider, existing_native_id)
                if first_prompt
                else None
            )
            response = {
                "ok": True,
                "deduped": True,
                "first_prompt_scheduled": first_prompt_scheduled,
                "first_prompt_delivery_state": (
                    first_prompt_delivery.get("state")
                    if isinstance(first_prompt_delivery, dict)
                    else None
                ),
                "project": project,
                "provider": provider,
                "native_id": existing_native_id,
                "session_id": _qualified_session_id(provider, existing_native_id),
                "send_scope_id": (
                    _durable_send_scope_id_from_registry_row(
                        existing_row,
                        provider=provider,
                        native_id=existing_native_id,
                    )
                    or _qualified_session_id(provider, existing_native_id)
                ),
                "tty": existing_row.get("terminal_tty") or "",
                "pid": int(existing_row.get("pid") or 0),
                "terminal_log": existing_metadata.get("terminal_log"),
                "capture_backend": existing_metadata.get("capture_backend"),
                "terminal_source": existing_metadata.get("terminal_source") or (
                    "broker_vt" if existing_broker_id else "terminal_app_contents"
                ),
                "broker_id": existing_broker_id or None,
                "broker_socket": existing_metadata.get("broker_socket"),
                "launch_strategy": existing_metadata.get("launch_strategy") or launch_strategy,
                "launch_visibility": existing_metadata.get("launch_visibility"),
                "attach_command": f"pairling attach {existing_broker_id}" if existing_broker_id else None,
            }
            response["receipt"] = _finalize_spawn_action(
                device_id=device_id,
                provider=provider,
                client_action_id=client_action_id,
                body_hash=spawn_body_hash,
                state="applied",
                http_status=200,
                backend="pty_broker" if existing_broker_id else "terminal_app",
                fields={key: value for key, value in response.items() if key != "deduped"},
            )
            self._send_json(response)
            return
        reviewed_terminal_command = ""
        reviewed_terminal_interactive_shell = False
        if not managed_spawn and launch_strategy == "direct_pairling":
            try:
                (
                    reviewed_terminal_command,
                    reviewed_terminal_interactive_shell,
                ) = _reviewed_provider_launch_command(
                    provider,
                    project,
                    spawn_backend,
                )
            except ValueError:
                reject_spawn(
                    503,
                    "provider_spawn_backend_unavailable",
                    (
                        f"{provider} has no available reviewed "
                        f"{spawn_backend} launch command"
                    ),
                    state="failed",
                )
                return
        # Rate limit: single global key. _inject_rate_check enforces 30/min
        # AND a 1-second cooldown between consecutive calls. For spawn, that's
        # plenty — actual launch takes ~2-3s anyway.
        allowed, retry = _inject_rate_check("__spawn_session__")
        if not allowed:
            reject_spawn(
                429,
                "rate_limited",
                f"rate limited, retry in {retry}s",
                fields={"retry_after": retry},
            )
            return
        if managed_spawn:
            managed_store = _ensure_managed_provider_session_store()
            manager = _ensure_managed_provider_session_manager()
            try:
                existing_managed = (
                    managed_store.find_launch(
                        client_action_id,
                        spawn_body_hash,
                    )
                    if managed_store is not None
                    else None
                )
            except _ManagedProviderSessionCollision as exc:
                reject_spawn(
                    409,
                    "managed_launch_idempotency_conflict",
                    str(exc)[:200],
                )
                return
            if existing_managed is not None:
                response = {
                    "ok": True,
                    "deduped": True,
                    "project": existing_managed["project"],
                    "provider": existing_managed["provider"],
                    "native_id": existing_managed["native_id"],
                    "session_id": existing_managed["id"],
                    "send_scope_id": existing_managed["id"],
                    "spawn_backend": "managed_provider",
                    "provider_profile_id": existing_managed["provider_profile_id"],
                    "terminal_backed": False,
                    "binding_id": existing_managed["binding_id"],
                    "capability_generation": int(
                        existing_managed["capability_generation"]
                    ),
                    "capabilities": existing_managed["capabilities"],
                    "control_state": existing_managed["control_state"],
                }
                response["receipt"] = _finalize_spawn_action(
                    device_id=device_id,
                    provider=provider,
                    client_action_id=client_action_id,
                    body_hash=spawn_body_hash,
                    state="applied",
                    http_status=200,
                    backend="managed_provider",
                    fields={
                        key: value
                        for key, value in response.items()
                        if key != "deduped"
                    },
                )
                self._send_json(response)
                return
            try:
                if manager is None:
                    raise _ManagedProviderDriverUnavailable(
                        "managed provider session runtime is unavailable"
                    )
                auth_result = getattr(self, "pairling_auth", None)
                source_install_id = str(
                    getattr(auth_result, "install_id", None) or device_id
                )
                title = str(
                    payload.get("title")
                    or Path(project).name
                    or f"{provider} session"
                ).strip()[:500]
                def commit_managed_first_prompt(proof: dict) -> None:
                    _mark_receipted_mutation_running(
                        mutation,
                        provider_id=str(proof["provider_id"]),
                        provider_version=str(proof["provider_version"]),
                        provider_channel=str(proof["provider_channel"]),
                        operation_id=str(proof["operation_id"]),
                        binding_id=str(proof["binding_id"]),
                        capability_generation=int(
                            proof["capability_generation"]
                        ),
                        recovery_correlation={
                            "provider_operation_id": str(
                                proof["provider_operation_id"]
                            ),
                            "provider_cursor": proof.get("provider_cursor"),
                        },
                    )
                managed_row = manager.launch(
                    provider=provider,
                    project=project,
                    title=title,
                    source_install_id=source_install_id,
                    provider_profile_id=provider_profile_id,
                    first_prompt=first_prompt or "",
                    launch_action_id=client_action_id,
                    launch_body_hash=spawn_body_hash,
                    before_first_prompt=commit_managed_first_prompt,
                )
            except _ManagedProviderSessionCollision as exc:
                reject_spawn(
                    409,
                    "managed_session_id_collision",
                    str(exc)[:200],
                    state="failed",
                )
                return
            except Exception as exc:
                error_code = str(
                    getattr(exc, "code", None)
                    or "managed_provider_unavailable"
                )
                outcome_indeterminate = bool(
                    getattr(exc, "outcome_indeterminate", False)
                )
                session_id = str(
                    getattr(exc, "session_id", None) or ""
                ).strip()
                reject_spawn(
                    409 if outcome_indeterminate else 503,
                    error_code,
                    str(exc)[:200]
                    or "Managed provider launch is unavailable.",
                    state=(
                        "indeterminate"
                        if outcome_indeterminate
                        else "failed"
                    ),
                    fields={"session_id": session_id or None},
                )
                return
            else:
                _bump_catalog_epoch()
                if SESSION_EVENT_HUB is not None:
                    SESSION_EVENT_HUB.publish(SESSION_SUMMARIES_TOPIC, {
                        "type": "managed_session_registered",
                        "session_id": managed_row["id"],
                        "provider": provider,
                    })
                response = {
                    "ok": True,
                    "deduped": False,
                    "project": managed_row["project"],
                    "provider": managed_row["provider"],
                    "native_id": managed_row["native_id"],
                    "session_id": managed_row["id"],
                    "send_scope_id": managed_row["id"],
                    "spawn_backend": "managed_provider",
                    "provider_profile_id": managed_row["provider_profile_id"],
                    "terminal_backed": False,
                    "binding_id": managed_row["binding_id"],
                    "capability_generation": int(
                        managed_row["capability_generation"]
                    ),
                    "capabilities": managed_row["capabilities"],
                    "control_state": managed_row["control_state"],
                    "first_prompt_scheduled": bool(first_prompt),
                    "first_prompt_delivery_state": (
                        "provider_submitted" if first_prompt else None
                    ),
                }
                response["receipt"] = _finalize_spawn_action(
                    device_id=device_id,
                    provider=provider,
                    client_action_id=client_action_id,
                    body_hash=spawn_body_hash,
                    state="applied",
                    http_status=200,
                    backend="managed_provider",
                    fields={
                        key: value
                        for key, value in response.items()
                        if key != "deduped"
                    },
                )
                self._send_json(response)
                return

        aperture_launch_context = None
        if launch_strategy == "aperture_cli":
            if _aperture_cli_validate_launch_context is None:
                reject_spawn(
                    503,
                    "aperture_cli_integration_unavailable",
                    "Aperture CLI launch integration is unavailable",
                    state="failed",
                )
                return
            try:
                preview_native_id = deterministic_native_id
                aperture_launch_context = _aperture_cli_validate_launch_context(
                    aperture_payload,
                    preview_native_id,
                    home=HOME,
                    env=os.environ,
                    write_config=True,
                )
            except Exception as exc:
                reject_spawn(
                    400,
                    "invalid_aperture_launch_context",
                    str(exc)[:200],
                )
                return

        if requested_native_id and spawn_backend != "broker":
            reject_spawn(
                400,
                "native_id_backend_mismatch",
                "native_id is supported only for broker launches",
            )
            return


        # A real new launch changes the composer catalogs. The durable action
        # reservation above must exist before this global epoch mutation.
        _bump_catalog_epoch()

        if launch_strategy == "aperture_cli" or spawn_backend == "broker":
            self._handle_spawn_session_broker(
                project,
                provider,
                launch_context=aperture_launch_context,
                native_id_override=(
                    preview_native_id
                    if launch_strategy == "aperture_cli"
                    else deterministic_native_id
                ),
                first_prompt=first_prompt,
                spawn_action_id=client_action_id,
                spawn_body_hash=spawn_body_hash,
                requested_session_mode=session_mode,
                structured_fallback_reason=structured_fallback_reason,
            )
            return

        capture_id = hashlib.sha256(
            f"{device_id}\0{client_action_id}\0{provider}".encode()
        ).hexdigest()[:24]
        capture_log_path: Path | None = (
            TERMINAL_CAPTURE_DIR / f"{provider}-{capture_id}.log"
        )
        shell_cmd = _terminal_script_command(
            capture_log_path,
            reviewed_terminal_command,
            interactive_shell=reviewed_terminal_interactive_shell,
        )

        # The title is the helper's Pairling-owned session marker. Session
        # identity itself remains the exact TTY and verified provider process.
        basename = os.path.basename(project.rstrip("/")) or provider
        title = f"{provider}:{basename}" if provider == "codex" else basename
        result = _start_pairling_terminal_session(shell_cmd, title)
        tty = str(result.get("tty") or "").strip() if result.get("ok") else ""
        pid = 0
        terminal_identity: dict | None = None
        omp_session_identity: dict | None = None
        registry_written = False
        native_id = deterministic_native_id
        if result.get("ok"):
            terminal_identity = _wait_for_provider_terminal_identity(
                tty, provider
            ) if tty else None
            pid = int((terminal_identity or {}).get("pid") or 0)
            if pid <= 0:
                result = {
                    "ok": False,
                    "reason": "Terminal opened, but the provider process identity could not be verified.",
                    "outcome_indeterminate": True,
                    "pty_written": None,
                    "write_outcome": "unknown",
                }
            elif provider == "omp":
                omp_session_identity = _wait_for_omp_spawn_terminal_identity(
                    terminal_identity,
                    canonical_project=project,
                )
                identity_probe_state = str(
                    (omp_session_identity or {}).get("identity_probe_state") or ""
                )
                adopted_native_id = str(
                    (omp_session_identity or {}).get("native_id") or ""
                )
                if identity_probe_state == "pairling_pending_process":
                    native_id = deterministic_native_id
                elif not _safe_agent_native_id(adopted_native_id):
                    result = {
                        "ok": False,
                        "reason": (
                            "Terminal opened, but OMP's exact session identity "
                            "could not be verified."
                        ),
                        "outcome_indeterminate": True,
                        "pty_written": None,
                        "write_outcome": "unknown",
                    }
                else:
                    native_id = adopted_native_id
        if result.get("ok"):
            if tty and capture_log_path is not None:
                _write_terminal_capture_mapping(
                    tty,
                    capture_log_path,
                    provider=provider,
                    project=project,
                    capture_id=capture_id,
                )
            send_scope_id = _qualified_session_id(
                provider,
                deterministic_native_id if provider == "omp" else native_id,
            )
            omp_metadata = {}
            if omp_session_identity is not None:
                omp_metadata = {
                    "pending_native_id": deterministic_native_id,
                    "identity_probe_state": str(
                        omp_session_identity.get("identity_probe_state") or ""
                    ),
                    "provider_tty": str(
                        omp_session_identity.get("provider_tty")
                        or (terminal_identity or {}).get("provider_tty")
                        or ""
                    ),
                    "process_started_at": float(
                        omp_session_identity.get("process_started_at") or 0
                    ),
                    "executable_path": str(
                        omp_session_identity.get("executable_path") or ""
                    ),
                    "source": str(
                        omp_session_identity.get("source") or ""
                    ),
                    "output_path": str(
                        omp_session_identity.get("output_path") or ""
                    ),
                    "session_path": str(
                        omp_session_identity.get("session_path") or ""
                    ),
                    "record_mtime": float(
                        omp_session_identity.get("record_mtime") or 0
                    ),
                }
            registry_written = _agent_registry_upsert(
                provider,
                native_id,
                project,
                pid=pid,
                terminal_tty=tty,
                metadata={
                    "spawned_by": "pairling",
                    "launch_strategy": "direct_pairling",
                    "launch_visibility": "visible_terminal",
                    "terminal_title": title,
                    "terminal_log": str(capture_log_path) if capture_log_path else None,
                    "capture_backend": "script" if capture_log_path else None,
                    "terminal_source": "terminal_app_contents",
                    "capture_id": capture_id or None,
                    "send_scope_id": send_scope_id,
                    "spawn_action_id": client_action_id,
                    "spawn_body_hash": spawn_body_hash,
                    **_provider_terminal_identity_metadata(terminal_identity),
                    **omp_metadata,
                },
                working_on=f"New {provider.title()} session",
            )
            if not registry_written:
                result = {
                    "ok": False,
                    "reason": (
                        "Terminal opened, but Pairling could not store its "
                        "control identity. Do not launch it again."
                    ),
                    "outcome_indeterminate": True,
                    "registry_unavailable": True,
                    "pty_written": None,
                    "write_outcome": "unknown",
                }
            elif provider == "codex":
                _write_agent_turn_state("codex", native_id, "idle", event="spawn")

        # Audit log — append-only, JSONL, includes failures.
        try:
            audit_path = HOME / ".claude" / "audit" / "spawn-sessions.jsonl"
            audit_path.parent.mkdir(parents=True, exist_ok=True)
            with open(audit_path, "a") as f:
                f.write(json.dumps({
                    "ts": _time.time(),
                    "project": project,
                    "provider": provider,
                    "native_id": native_id,
                    "tty": tty,
                    "pid": pid,
                    "terminal_log": str(capture_log_path) if capture_log_path else None,
                    "capture_backend": "script" if capture_log_path else None,
                    "ok": result.get("ok", False),
                    "reason": result.get("reason"),
                    "via": "phone-companion",
                }) + "\n")
        except Exception:
            pass  # audit failure shouldn't break the spawn

        if not result.get("ok"):
            outcome_indeterminate = bool(result.get("outcome_indeterminate"))
            if result.get("registry_unavailable"):
                error_code = "terminal_spawn_registry_unavailable"
            elif outcome_indeterminate:
                error_code = "terminal_spawn_outcome_unknown"
            else:
                error_code = "terminal_spawn_failed"
            message = str(result.get("reason") or "Terminal session launch failed.")
            receipt = _finalize_spawn_action(
                device_id=device_id,
                provider=provider,
                client_action_id=client_action_id,
                body_hash=spawn_body_hash,
                state="indeterminate" if outcome_indeterminate else "failed",
                http_status=502,
                backend="terminal_app",
                error_code=error_code,
                error_message=message,
                fields={
                    "native_id": native_id,
                    "session_id": _qualified_session_id(provider, native_id),
                    "outcome_indeterminate": outcome_indeterminate,
                },
            )
            self._send_json({
                "ok": False,
                "error": {"code": error_code, "message": message},
                "error_code": error_code,
                "native_id": native_id,
                "session_id": _qualified_session_id(provider, native_id),
                "outcome_indeterminate": outcome_indeterminate,
                "receipt": receipt,
            }, status=502)
            return

        first_prompt_scheduled = False
        if first_prompt:
            first_prompt_scheduled = _schedule_first_prompt_delivery(
                provider=provider,
                native_id=native_id,
                text=first_prompt,
                client_action_id=client_action_id,
                device_id=device_id,
            )
        first_prompt_delivery = (
            _read_first_prompt_delivery(provider, native_id) if first_prompt else None
        )
        response = {
            "ok": True,
            "deduped": bool(result.get("reconciled_after_unknown")),
            "first_prompt_scheduled": first_prompt_scheduled,
            "first_prompt_delivery_state": (
                first_prompt_delivery.get("state")
                if isinstance(first_prompt_delivery, dict)
                else None
            ),
            "project": project,
            "provider": provider,
            "native_id": native_id,
            "session_id": _qualified_session_id(provider, native_id),
            "send_scope_id": (
                _qualified_session_id(provider, deterministic_native_id)
                if provider == "omp"
                else _qualified_session_id(provider, native_id)
            ),
            "session_mode": "terminal",
            "requested_session_mode": session_mode,
            "structured_fallback_reason": structured_fallback_reason,
            "terminal_backed": True,
            "tty": tty,
            "pid": pid,
            "terminal_log": str(capture_log_path) if capture_log_path else None,
            "capture_backend": "script" if capture_log_path else None,
            "terminal_source": "terminal_app_contents",
            "launch_strategy": "direct_pairling",
            "launch_visibility": "visible_terminal",
            "attach_command": None,
        }
        receipt = _finalize_spawn_action(
            device_id=device_id,
            provider=provider,
            client_action_id=client_action_id,
            body_hash=spawn_body_hash,
            state="applied",
            http_status=200,
            backend="terminal_app",
            fields={key: value for key, value in response.items() if key != "deduped"},
        )
        response["receipt"] = receipt
        self._send_json(response)

    def _session_context_for_workflow(self, raw_session: str) -> dict | None:
        provider, native_id = _parse_agent_session_ref(raw_session)
        if provider == "codex":
            path = _resolve_codex_transcript(native_id)
            project = _codex_project_for_session(native_id)
            if not path or not project:
                return None
            history = _codex_history_map()
            first_prompt = _codex_first_prompt(path, native_id, history) or ""
            assistant_chunks: list[str] = []
            try:
                lines = _tail_lines(path, max_lines=400, max_bytes=TRANSCRIPT_TAIL_SCAN_BYTES)
                for raw in lines:
                    for row in _normalize_codex_line(raw, native_id):
                        msg = row.get("message") or {}
                        if msg.get("role") != "assistant":
                            continue
                        for block in msg.get("content") or []:
                            if isinstance(block, dict) and block.get("type") == "text":
                                text = block.get("text")
                                if isinstance(text, str) and text.strip():
                                    assistant_chunks.append(text.strip())
            except OSError:
                pass
            return {
                "provider": provider,
                "native_id": native_id,
                "session_id": _qualified_session_id(provider, native_id),
                "project": project,
                "first_prompt": first_prompt,
                "last_assistant": "\n\n".join(assistant_chunks[-2:])[-6000:],
                "transcript_path": str(path),
            }

        native_id = _claude_native_session_id(raw_session)
        if not native_id:
            return None
        path = self._resolve_transcript(native_id)
        project = self._lookup_pg_project(native_id) or (_peek_cwd_from_transcript(path) if path else "")
        if not path or not project:
            return None
        return {
            "provider": "claude",
            "native_id": native_id,
            "session_id": _qualified_session_id("claude", native_id),
            "project": project,
            "first_prompt": _peek_first_prompt(path) or "",
            "last_assistant": _peek_last_assistant_text(path, max_chars=6000) or "",
            "transcript_path": str(path),
        }




    def _handle_resume_session_broker(
        self,
        *,
        provider: str,
        project: str,
        native_id: str,
        prompt: str,
        receipt_context: dict,
    ) -> None:
        if PTY_BROKER is None:
            message = "PTY broker unavailable"
            receipt = _finalize_receipted_mutation(
                receipt_context,
                state="failed",
                http_status=503,
                backend="pty_broker",
                error_code="broker_unavailable",
                error_message=message,
                audit_action={"type": "resume_session", "provider": provider},
            )
            self._send_json({
                "ok": False,
                "error": {"code": "broker_unavailable", "message": message},
                "receipt": receipt,
            }, status=503)
            return
        if not _broker_is_current_runtime():
            message = "Resume requires the current terminal broker. Control remains unavailable for a session owned by the previous runtime until it finishes."
            receipt = _finalize_receipted_mutation(
                receipt_context,
                state="rejected",
                http_status=409,
                backend="pty_broker",
                error_code="broker_requires_current_runtime",
                error_message=message,
                audit_action={"type": "resume_session", "provider": provider},
            )
            self._send_json({
                "ok": False,
                "error": {
                    "code": "broker_requires_current_runtime",
                    "message": message,
                },
                "receipt": receipt,
            }, status=409)
            return
        broker_session_id = _qualified_session_id(provider, native_id)
        resume_running = False

        def mark_resume_running() -> None:
            nonlocal resume_running
            if resume_running:
                raise RuntimeError(
                    "resume action entered its execution boundary twice"
                )
            _mark_receipted_mutation_running(
                receipt_context,
                provider_id=provider,
                provider_version="terminal-surface-v2",
                provider_channel="pty_broker",
                operation_id="session.resume",
                binding_id=f"pty-broker:{broker_session_id}",
                capability_generation=1,
                recovery_correlation={
                    "provider_operation_id": str(
                        receipt_context["client_action_id"]
                    ),
                    "provider_cursor": broker_session_id,
                },
            )
            resume_running = True
        omp_path = ""
        omp_resolved_binary: Path | None = None
        if provider == "omp":
            adapter = _provider_get("omp") if _provider_get is not None else None
            omp_path = str(adapter.probe().diagnostics.cli_path or "") if adapter else ""
            try:
                omp_resolved_binary = Path(omp_path).resolve(strict=True) if omp_path else None
            except OSError:
                omp_resolved_binary = None
        existing = PTY_BROKER.get(broker_session_id)
        if existing is not None:
            if not _broker_session_owns_identity(existing, provider, native_id):
                message = "Existing broker session identity does not match the requested resume."
                receipt = _finalize_receipted_mutation(
                    receipt_context,
                    state="rejected",
                    http_status=409,
                    backend="pty_broker",
                    error_code="process_identity_unverified",
                    error_message=message,
                    fields={"session_id": broker_session_id},
                    audit_action={"type": "resume_session", "provider": provider},
                )
                self._send_json({
                    "ok": False,
                    "error": {
                        "code": "process_identity_unverified",
                        "message": message,
                    },
                    "session_id": broker_session_id,
                    "receipt": receipt,
                }, status=409)
                return
            if provider == "omp":
                identity = (
                    _wait_for_omp_resume_terminal_identity(
                        native_id,
                        terminal_tty=_broker_slave_tty(existing),
                        canonical_project=project,
                        resolved_binary=omp_resolved_binary,
                    )
                    if omp_resolved_binary is not None
                    else None
                )
            else:
                identity = _broker_spawn_provider_identity(
                    existing,
                    broker_id=broker_session_id,
                    provider=provider,
                    native_id=native_id,
                    project=project,
                )
            if identity is None:
                message = (
                    f"Existing {provider} broker session has no exact "
                    "provider process identity proof."
                )
                receipt = _finalize_receipted_mutation(
                    receipt_context,
                    state="rejected",
                    http_status=409,
                    backend="pty_broker",
                    error_code="process_identity_unverified",
                    error_message=message,
                    fields={"session_id": broker_session_id},
                    audit_action={"type": "resume_session", "provider": provider},
                )
                self._send_json({
                    "ok": False,
                    "error": {
                        "code": "process_identity_unverified",
                        "message": message,
                    },
                    "session_id": broker_session_id,
                    "receipt": receipt,
                }, status=409)
                return
            mark_resume_running()
            existing_tty = _broker_slave_tty(existing)
            existing_log = _broker_raw_log_path(existing)
            existing_pid = int(identity.get("pid") or 0)
            capture_id = secrets.token_hex(12)
            registry_ok = _agent_registry_upsert(
                provider,
                native_id,
                project,
                pid=existing_pid,
                terminal_tty=existing_tty,
                metadata={
                    "spawned_by": "phone-companion",
                    "resume_target": native_id,
                    "terminal_log": (
                        str(existing_log) if existing_log else None
                    ),
                    "capture_backend": "pty_broker",
                    "capture_id": capture_id,
                    "terminal_source": "broker_vt",
                    "broker_id": broker_session_id,
                    "send_scope_id": broker_session_id,
                    "broker_socket": str(PTY_BROKER_SOCKET),
                    "resume_identity_verified": True,
                    "broker_owner_pid": _broker_pid(existing),
                },
            )
            if not registry_ok:
                message = (
                    "Existing broker ownership could not be stored durably."
                )
                receipt = _finalize_receipted_mutation(
                    receipt_context,
                    state="failed",
                    http_status=502,
                    backend="pty_broker",
                    error_code="broker_resume_registry_failed",
                    error_message=message,
                    fields={
                        "session_id": broker_session_id,
                        "outcome_indeterminate": False,
                    },
                    audit_action={
                        "type": "resume_session",
                        "provider": provider,
                    },
                    pty_written=False,
                )
                self._send_json({
                    "ok": False,
                    "error": {
                        "code": "broker_resume_registry_failed",
                        "message": message,
                    },
                    "session_id": broker_session_id,
                    "outcome_indeterminate": False,
                    "receipt": receipt,
                }, status=502)
                return
            if existing_tty and existing_log:
                _write_terminal_capture_mapping(
                    existing_tty,
                    existing_log,
                    provider=provider,
                    project=project,
                    capture_id=capture_id,
                )
            response = {
                "ok": True,
                "provider": provider,
                "native_id": native_id,
                "session_id": broker_session_id,
                "send_scope_id": broker_session_id,
                "project": project,
                "tty": existing_tty,
                "pid": existing_pid,
                "terminal_log": (
                    str(existing_log) if existing_log else None
                ),
                "capture_backend": "pty_broker",
                "terminal_source": "broker_vt",
                "broker_id": _broker_session_id(existing),
                "broker_socket": str(PTY_BROKER_SOCKET),
                "attach_command": f"pairling attach {broker_session_id}",
            }
            response["receipt"] = _finalize_receipted_mutation(
                receipt_context,
                state="applied",
                http_status=200,
                backend="pty_broker",
                fields=response,
                audit_action={"type": "resume_session", "provider": provider},
            )
            self._send_json(response)
            return

        if provider == "omp":
            command = (
                f"exec {shlex.quote(omp_path)} "
                f"--cwd {shlex.quote(project)} --resume {shlex.quote(native_id)}"
            )
        else:
            command = (
                f"exec codex resume "
                f"-C {shlex.quote(project)} --add-dir {shlex.quote(project)} "
                f"{shlex.quote(native_id)}"
            )
            if prompt:
                command += f" {shlex.quote(prompt)}"
        session = None
        ok = False
        reason = None
        outcome_indeterminate = False
        reconciled_after_unknown = False
        mark_resume_running()
        try:
            session = PTY_BROKER.spawn(
                session_id=broker_session_id,
                provider=provider,
                native_id=native_id,
                project=project,
                command=command,
                rows=30,
                columns=120,
                env={"PAIRLING_PHONE_SESSION": "1",
                     "PAIRLING_BROKER_SESSION_ID": broker_session_id},
            )
            if not _broker_session_matches_spawn_request(
                session,
                broker_id=broker_session_id,
                provider=provider,
                native_id=native_id,
            ):
                raise ProcessIdentityDriftError(
                    "spawned broker session identity does not match resume action"
                )
            ok = True
        except PTYBrokerOutcomeUnknownError as exc:
            session = _broker_reconcile_session_after_unknown(
                broker_session_id,
                provider=provider,
                native_id=native_id,
            )
            if session is not None:
                reconciled_after_unknown = True
                ok = True
                reason = "resume response lost; reconciled by broker session id"
            else:
                outcome_indeterminate = True
                reason = f"resume outcome unknown: {str(exc)[:180]}"
        except Exception as e:
            reason = f"{type(e).__name__}: {e}"

        if ok and session is not None:
            capture_id = secrets.token_hex(12)
            session_tty = _broker_slave_tty(session)
            session_log = _broker_raw_log_path(session)
            identity = (
                _wait_for_omp_resume_terminal_identity(
                    native_id,
                    terminal_tty=session_tty,
                    canonical_project=project,
                    resolved_binary=omp_resolved_binary,
                )
                if provider == "omp"
                and omp_resolved_binary is not None
                and session_tty
                else _broker_spawn_provider_identity(
                    session,
                    broker_id=broker_session_id,
                    provider=provider,
                    native_id=native_id,
                    project=project,
                )
                if provider != "omp"
                else None
            )
            session_pid = int(identity.get("pid") or 0) if identity else 0
            if identity is None:
                ok = False
                reason = (
                    f"{provider} resume could not prove one live exact "
                    "provider process identity."
                )
                outcome_indeterminate = reconciled_after_unknown
            if ok:
                registry_ok = _agent_registry_upsert(
                    provider,
                    native_id,
                    project,
                    pid=session_pid,
                    terminal_tty=session_tty,
                    metadata={
                        "spawned_by": "phone-companion",
                        "resume_target": native_id,
                        "terminal_log": str(session_log) if session_log else None,
                        "capture_backend": "pty_broker",
                        "capture_id": capture_id,
                        "terminal_source": "broker_vt",
                        "broker_id": broker_session_id,
                        "send_scope_id": broker_session_id,
                        "broker_socket": str(PTY_BROKER_SOCKET),
                        "resume_identity_verified": True,
                    },
                )
                if not registry_ok:
                    ok = False
                    reason = (
                        "Resumed broker ownership could not be stored durably."
                    )
                    outcome_indeterminate = reconciled_after_unknown

            if not ok:
                if not reconciled_after_unknown:
                    try:
                        termination = PTY_BROKER.terminate(
                            broker_session_id,
                            signal.SIGTERM,
                        )
                        if termination.get("outcome_indeterminate"):
                            outcome_indeterminate = True
                            reason = str(
                                termination.get("error")
                                or termination.get("reason")
                                or reason
                                or "resume cleanup outcome unknown"
                            )
                    except PTYBrokerOutcomeUnknownError as exc:
                        outcome_indeterminate = True
                        reason = (
                            "resume cleanup outcome unknown: "
                            f"{str(exc)[:180]}"
                        )
                    except Exception as exc:
                        outcome_indeterminate = True
                        reason = (
                            f"{reason or 'resume verification failed'}; cleanup "
                            f"failed: {type(exc).__name__}: {exc}"
                        )
            else:
                if session_tty and session_log:
                    _write_terminal_capture_mapping(
                        session_tty,
                        session_log,
                        provider=provider,
                        project=project,
                        capture_id=capture_id,
                    )
                _write_agent_turn_state(
                    provider,
                    native_id,
                    "idle",
                    event="resume",
                )

        try:
            audit_path = HOME / ".claude" / "audit" / "resume-sessions.jsonl"
            audit_path.parent.mkdir(parents=True, exist_ok=True)
            with open(audit_path, "a") as f:
                f.write(json.dumps({
                    "ts": _time.time(),
                    "provider": provider,
                    "project": project,
                    "native_id": native_id,
                    "tty": _broker_slave_tty(session) if session else "",
                    "pid": _broker_pid(session) if session else 0,
                    "terminal_log": str(_broker_raw_log_path(session)) if session and _broker_raw_log_path(session) else None,
                    "capture_backend": "pty_broker",
                    "terminal_source": "broker_vt",
                    "broker_id": broker_session_id,
                    "broker_socket": str(PTY_BROKER_SOCKET),
                    "ok": ok,
                    "reason": reason,
                    "via": "phone-companion",
                }) + "\n")
        except Exception:
            pass

        if not ok or session is None:
            error_code = "broker_resume_outcome_unknown" if outcome_indeterminate else "broker_resume_failed"
            receipt = _finalize_receipted_mutation(
                receipt_context,
                state="indeterminate" if outcome_indeterminate else "failed",
                http_status=502,
                backend="pty_broker",
                error_code=error_code,
                error_message=reason or "PTY broker resume failed",
                fields={
                    "session_id": broker_session_id,
                    "outcome_indeterminate": outcome_indeterminate,
                },
                audit_action={"type": "resume_session", "provider": provider},
                pty_written=None if outcome_indeterminate else False,
            )
            self._send_json({
                "ok": False,
                "error": {
                    "code": error_code,
                    "message": reason or "PTY broker resume failed",
                },
                "session_id": broker_session_id,
                "outcome_indeterminate": outcome_indeterminate,
                "receipt": receipt,
            }, status=502)
            return

        response = {
            "ok": True,
            "provider": provider,
            "native_id": native_id,
            "session_id": broker_session_id,
            "send_scope_id": broker_session_id,
            "project": project,
            "tty": _broker_slave_tty(session),
            "pid": _broker_pid(session),
            "terminal_log": str(_broker_raw_log_path(session)) if _broker_raw_log_path(session) else None,
            "capture_backend": "pty_broker",
            "terminal_source": "broker_vt",
            "broker_id": broker_session_id,
            "broker_socket": str(PTY_BROKER_SOCKET),
            "attach_command": f"pairling attach {broker_session_id}",
        }
        response["receipt"] = _finalize_receipted_mutation(
            receipt_context,
            state="applied",
            http_status=200,
            backend="pty_broker",
            fields=response,
            audit_action={"type": "resume_session", "provider": provider},
        )
        self._send_json(response)

    def _handle_resume_omp(
        self,
        *,
        project: str,
        native_id: str,
        prompt: str,
    ) -> None:
        """Resume one saved OMP UUID through the owned PTY broker."""
        try:
            canonical_project = _canonical_user_directory(project, allow_tmp=True)
        except ValueError as exc:
            self.send_error(400, str(exc))
            return
        except (FileNotFoundError, NotADirectoryError):
            self.send_error(404, f"directory not found: {project}")
            return
        except PermissionError as exc:
            self.send_error(403, str(exc))
            return
        except OSError as exc:
            self.send_error(400, str(exc))
            return
        if not _safe_agent_native_id(native_id):
            self.send_error(400, "bad OMP session id")
            return
        if prompt:
            _send_unsupported_provider(self, "omp", "send_text")
            return
        source_record = next(
            (
                record
                for record in (
                    _omp_saved_sessions(
                        project=canonical_project,
                        limit=200,
                    )
                    if _omp_saved_sessions is not None
                    else []
                )
                if record.session_id == native_id
            ),
            None,
        )
        if source_record is None:
            self.send_error(404, "No OMP session exists for this project")
            return
        if not _provider_visible("omp"):
            self.send_error(409, "OMP is hidden in Pairling settings.")
            return
        if not str(_provider_get("omp").probe().diagnostics.cli_path or ""):
            _send_unsupported_provider(self, "omp", "resume")
            return
        receipt_context = _begin_receipted_mutation(
            self,
            receipt_scope=f"resume:{_qualified_session_id('omp', native_id)}",
            action_kind="resume_session",
            material={
                "provider": "omp",
                "project": canonical_project,
                "native_id": native_id,
                "prompt": "",
            },
            action_label="OMP session resume",
        )
        if receipt_context is None:
            return
        self._handle_resume_session_broker(
            provider="omp",
            project=canonical_project,
            native_id=native_id,
            prompt="",
            receipt_context=receipt_context,
        )


    def _handle_resume_session(self, q):
        """Resume Codex once and bind the new terminal to a durable send scope."""
        try:
            payload = json.loads(self._read_body() or b"{}")
        except json.JSONDecodeError:
            self.send_error(400, "body must be JSON")
            return
        provider = str(payload.get("provider") or "").lower()
        project = str(payload.get("project") or "").strip()
        native_id = str(payload.get("session_id") or payload.get("native_id") or "").strip()
        prompt = str(payload.get("prompt") or "").strip()
        if not _valid_provider_filter(provider, allow_all=False):
            _send_unknown_provider(self, provider)
            return
        if not _provider_supports(provider, "resume"):
            _send_unsupported_provider(self, provider, "resume")
            return
        if provider == "omp":
            self._handle_resume_omp(
                project=project,
                native_id=native_id,
                prompt=prompt,
            )
            return
        if provider != "codex":
            self.send_error(400, "Claude resume uses /send-text with /resume <id>")
            return
        try:
            project = _canonical_user_directory(project, allow_tmp=True)
        except ValueError as exc:
            self.send_error(400, str(exc))
            return
        except (FileNotFoundError, NotADirectoryError):
            self.send_error(404, f"directory not found: {project}")
            return
        except PermissionError as exc:
            self.send_error(403, str(exc))
            return
        except OSError as exc:
            self.send_error(400, str(exc))
            return
        if not _safe_agent_native_id(native_id):
            self.send_error(400, "bad Codex session id")
            return
        if len(prompt) > 4000:
            self.send_error(413, "prompt too long")
            return

        receipt_context = _begin_receipted_mutation(
            self,
            receipt_scope=f"resume:{_qualified_session_id(provider, native_id)}",
            action_kind="resume_session",
            material={
                "provider": provider,
                "project": project,
                "native_id": native_id,
                "prompt": prompt,
            },
            action_label="session resume",
        )
        if receipt_context is None:
            return

        if not _provider_visible(provider):
            body = _provider_hidden_payload(provider)
            receipt = _finalize_receipted_mutation(
                receipt_context,
                state="rejected",
                http_status=409,
                backend="session_resume",
                error_code="provider_hidden",
                error_message=str(body["error"]["message"]),
                fields={"provider": provider},
                audit_action={"type": "resume_session", "provider": provider},
            )
            body["receipt"] = receipt
            self._send_json(body, status=409)
            return
        if not os.path.isdir(project):
            message = "The project directory is no longer available."
            receipt = _finalize_receipted_mutation(
                receipt_context,
                state="rejected",
                http_status=400,
                backend="session_resume",
                error_code="project_unavailable",
                error_message=message,
                fields={"project": project},
                audit_action={"type": "resume_session", "provider": provider},
            )
            self._send_json({
                "ok": False,
                "error": {"code": "project_unavailable", "message": message},
                "project": project,
                "receipt": receipt,
            }, status=400)
            return
        transcript_path = _resolve_codex_transcript(native_id)
        if not transcript_path:
            message = "No Codex transcript exists for this session."
            receipt = _finalize_receipted_mutation(
                receipt_context,
                state="rejected",
                http_status=404,
                backend="session_resume",
                error_code="transcript_not_found",
                error_message=message,
                fields={"session_id": _qualified_session_id(provider, native_id)},
                audit_action={"type": "resume_session", "provider": provider},
            )
            self._send_json({
                "ok": False,
                "error": {"code": "transcript_not_found", "message": message},
                "session_id": _qualified_session_id(provider, native_id),
                "receipt": receipt,
            }, status=404)
            return
        transcript_metadata = _codex_rollout_meta(transcript_path) or {}
        recorded_project = str(transcript_metadata.get("cwd") or "").strip()
        if (
            not recorded_project
            or os.path.realpath(recorded_project) != os.path.realpath(project)
        ):
            message = (
                "The requested project does not match this Codex session's "
                "recorded workspace."
            )
            receipt = _finalize_receipted_mutation(
                receipt_context,
                state="rejected",
                http_status=409,
                backend="session_resume",
                error_code="project_mismatch",
                error_message=message,
                fields={
                    "session_id": _qualified_session_id(provider, native_id),
                    "project": project,
                },
                audit_action={"type": "resume_session", "provider": provider},
            )
            self._send_json({
                "ok": False,
                "error": {"code": "project_mismatch", "message": message},
                "session_id": _qualified_session_id(provider, native_id),
                "project": project,
                "receipt": receipt,
            }, status=409)
            return


        allowed, retry = _inject_rate_check("__resume_session__")
        if not allowed:
            message = f"rate limited, retry in {retry}s"
            receipt = _finalize_receipted_mutation(
                receipt_context,
                state="rejected",
                http_status=429,
                backend="session_resume",
                error_code="rate_limited",
                error_message=message,
                fields={"retry_after": retry},
                audit_action={"type": "resume_session", "provider": provider},
            )
            self._send_json({
                "ok": False,
                "error": {"code": "rate_limited", "message": message},
                "retry_after": retry,
                "receipt": receipt,
            }, status=429)
            return

        self._handle_resume_session_broker(
            provider=provider,
            project=project,
            native_id=native_id,
            prompt=prompt,
            receipt_context=receipt_context,
        )

    def _finish_send_text_failure(
        self,
        receipt_context: dict,
        text: str,
        *,
        status: int,
        reason: str,
        state: str = "rejected",
        validated: bool = False,
        backend: str | None = None,
        tty: str | None = None,
        pid: int | None = None,
        error_code: str | None = None,
        extra: dict | None = None,
    ) -> None:
        receipt = _make_send_text_receipt(
            receipt_context,
            client_action_id=receipt_context.get("client_action_id"),
            state=state,
            phases=_receipt_phases(validated=validated, applied=False, pty_written=False),
            backend=backend,
            tty=tty,
            pid=pid,
        )
        _receipt_attach_response(
            receipt,
            http_status=status,
            error_code=error_code or "send_text_failed",
            error_message=reason,
            fields=extra,
        )
        _store_action_receipt(
            receipt_context.get("device_id"),
            str(receipt_context.get("session_id") or ""),
            receipt_context.get("client_action_id"),
            str(receipt_context.get("body_hash") or ""),
            receipt,
            action_kind="send_text",
            audit_action={"type": "send_text", "chars": len(text), "error": error_code or reason[:120]},
        )
        body = {"ok": False, "error": reason, "reason": reason, "receipt": receipt}
        if error_code:
            body["error_code"] = error_code
        if extra:
            body.update(extra)
        self._send_json(body, status=status)

    def _send_text_to_codex_registry(self, native_id: str, text: str, receipt_context: dict | None = None) -> None:
        # Precondition: callers pass text through _sanitize_terminal_text_input.
        receipt_context = receipt_context or {}
        requested_native_id = native_id
        native_id = _agent_registry_resolve_native_alias("codex", native_id)
        client_action_id = receipt_context.get("client_action_id")
        device_id = receipt_context.get("device_id")
        body_hash = receipt_context.get("body_hash") or _receipt_body_hash(text)
        receipt_session_id = receipt_context.get("session_id") or _qualified_session_id("codex", native_id)
        public_session_id = receipt_context.get("public_session_id") or _qualified_session_id("codex", native_id)
        if (
            "registry_row" in receipt_context
            and str((receipt_context.get("registry_row") or {}).get("native_id") or "")
            == native_id
        ):
            reg = receipt_context.get("registry_row")
        else:
            reg = _agent_registry_get("codex", native_id)
        if not reg:
            reason = "no Codex control registry row for session"
            self._finish_send_text_failure(
                receipt_context, text, status=404, reason=reason,
            )
            return

        if reg.get("closed_at") is not None:
            self._finish_send_text_failure(
                receipt_context,
                text,
                status=409,
                reason="Codex session is closed and its process identity is no longer verified.",
                backend="terminal_app",
                tty=str(reg.get("terminal_tty") or "") or None,
                pid=int(reg.get("pid") or 0) or None,
                error_code="process_identity_unverified",
            )
            return

        durable_broker_id = _durable_broker_id_from_registry_row(
            reg,
            provider="codex",
            native_id=native_id,
        )

        broker_found = self._broker_session_for(
            _qualified_session_id("codex", requested_native_id)
        )
        if broker_found and PTY_BROKER:
            _public_id, session = broker_found
            broker_id = _broker_session_id(session)
            if not _broker_session_owns_identity(session, "codex", native_id):
                self._finish_send_text_failure(
                    receipt_context,
                    text,
                    status=409,
                    reason="Codex broker ownership changed; refresh before sending text",
                    backend="pty_broker",
                    tty=_broker_slave_tty(session),
                    pid=_broker_pid(session),
                    error_code="process_identity_unverified",
                    extra={"broker_id": _broker_session_id(session)},
                )
                return
            _mark_send_text_running(
                receipt_context,
                provider_id="codex",
                binding_id=f"pty_broker:{broker_id}",
            )
            result, source_offset_after, source_offset_reason = _broker_send_text_with_truth(
                broker_id,
                text,
                public_session_id=str(public_session_id),
            )
            if result.get("ok"):
                _agent_registry_update_control(
                    "codex",
                    native_id,
                    pid=_broker_pid(session),
                    terminal_tty=_broker_slave_tty(session),
                    state="running",
                    reopen=True,
                )
                _write_agent_turn_state("codex", native_id, "thinking", started_at=_time.time(), event="send_text")
            outcome_indeterminate = bool(result.get("outcome_indeterminate"))
            pty_written = (
                result.get("pty_written")
                if "pty_written" in result
                else (None if outcome_indeterminate else bool(result.get("ok")))
            )
            receipt = _make_send_text_receipt(
                receipt_context,
                client_action_id=client_action_id,
                state="applied" if result.get("ok") else ("indeterminate" if outcome_indeterminate else "failed"),
                phases=_receipt_phases(validated=True, applied=bool(result.get("ok")), pty_written=pty_written),
                backend="pty_broker",
                tty=_broker_slave_tty(session),
                pid=_broker_pid(session),
                source_offset_after=source_offset_after,
                source_offset_reason=source_offset_reason,
            )
            if result.get("write_outcome"):
                receipt["phases"]["pty_write_state"] = str(result["write_outcome"])
            if not result.get("ok"):
                _receipt_attach_response(
                    receipt,
                    http_status=int(result.get("status") or 502),
                    error_code=str(result.get("error_code") or result.get("reason") or "send_text_failed"),
                    error_message=str(result.get("error") or result.get("reason") or "Send failed."),
                    fields={
                        "reason": result.get("reason"),
                        "bytes_written": result.get("bytes_written"),
                        "bytes_expected": result.get("bytes_expected"),
                        "write_outcome": result.get("write_outcome"),
                        "outcome_indeterminate": outcome_indeterminate,
                    },
                )
            _store_action_receipt(device_id, receipt_session_id, client_action_id, body_hash, receipt, action_kind="send_text", audit_action={"type": "send_text", "chars": len(text)})
            body = json.dumps({
                "ok": bool(result.get("ok")),
                "session_id": public_session_id,
                "tty": _broker_slave_tty(session),
                "pid": _broker_pid(session),
                "broker_id": _broker_session_id(session),
                "reason": result.get("reason"),
                "error_code": result.get("error_code"),
                "bytes_written": result.get("bytes_written"),
                "bytes_expected": result.get("bytes_expected"),
                "write_outcome": result.get("write_outcome"),
                "outcome_indeterminate": outcome_indeterminate,
                "receipt": receipt,
            }).encode()
            self.send_response(200 if result.get("ok") else int(result.get("status") or 502))
            self.send_header("Content-Type", "application/json")
            self.send_header("Content-Length", str(len(body)))
            self.end_headers()
            self.wfile.write(body)
            return

        if durable_broker_id:
            self._finish_send_text_failure(
                receipt_context,
                text,
                status=503,
                reason="Codex terminal broker is temporarily unavailable. No text was sent.",
                state="failed",
                validated=True,
                backend="pty_broker",
                tty=str(reg.get("terminal_tty") or "") or None,
                pid=int(reg.get("pid") or 0) or None,
                error_code="broker_unavailable",
                extra={"broker_id": durable_broker_id},
            )
            return

        reg = _agent_registry_promote_codex(
            native_id,
            str(reg.get("project") or ""),
            float(reg.get("started_at") or 0),
        ) or reg
        tty = reg.get("terminal_tty") or ""
        if not tty:
            reason = "no terminal_tty for Codex session"
            receipt = _make_send_text_receipt(
                receipt_context,
                client_action_id=client_action_id,
                state="rejected",
                phases=_receipt_phases(validated=False, applied=False, pty_written=False),
            )
            _store_action_receipt(device_id, receipt_session_id, client_action_id, body_hash, receipt, action_kind="send_text", audit_action={"type": "send_text", "chars": len(text)})
            body = json.dumps({"ok": False, "error": reason, "reason": reason, "receipt": receipt}).encode()
            self.send_response(404)
            self.send_header("Content-Type", "application/json")
            self.send_header("Content-Length", str(len(body)))
            self.end_headers()
            self.wfile.write(body)
            return
        if not re.match(r'^/dev/ttys[0-9]{3,}$', tty):
            self._finish_send_text_failure(
                receipt_context,
                text,
                status=500,
                reason=f"invalid tty in registry: {tty[:40]}",
                tty=tty,
                pid=int(reg.get("pid") or 0) or None,
            )
            return

        pid = int(reg.get("pid") or 0)
        if (
            not pid
            or not _process_alive(pid)
            or not _session_signal_target_is_verified(reg, "codex", pid)
        ):
            self._finish_send_text_failure(
                receipt_context,
                text,
                status=409,
                reason="Codex process identity changed; refresh before sending text.",
                backend="terminal_app",
                tty=tty,
                pid=pid or None,
                error_code="process_identity_unverified",
            )
            return

        tty_candidates = _codex_terminal_tty_candidates(
            {**reg, "pid": pid, "terminal_tty": tty}
        )
        if not tty_candidates:
            self._finish_send_text_failure(
                receipt_context,
                text,
                status=409,
                reason="Codex Terminal tab identity changed; refresh before sending text.",
                backend="terminal_app",
                tty=tty,
                pid=pid,
                error_code="process_identity_unverified",
            )
            return
        _mark_send_text_running(
            receipt_context,
            provider_id="codex",
            binding_id=f"terminal_tty:{tty}",
        )
        # The registry binding is re-proved above. A helper request names one
        # exact Terminal TTY; retrying is safe only when the helper confirms
        # that a candidate tab did not exist before any mutation.
        result: dict = {
            "ok": False,
            "reason": "Terminal tab not found.",
            "error_code": "terminal_tab_not_found",
            "mutation_outcome": "failed_before_mutation",
            "outcome_indeterminate": False,
        }
        for candidate_tty in tty_candidates:
            result = _send_terminal_app_text_exact(candidate_tty, text)
            if result.get("ok"):
                tty = candidate_tty
                break
            if result.get("error_code") != "terminal_tab_not_found":
                break
        if (not result.get("ok")) and result.get("error_code") == "terminal_tab_not_found":
            if pid and _process_alive(pid):
                self._finish_send_text_failure(
                    receipt_context,
                    text,
                    status=502,
                    reason="Terminal tab not found, but Codex process is still alive.",
                    state="failed",
                    validated=True,
                    backend="terminal_app",
                    tty=tty,
                    pid=pid,
                    extra={"gone": False, "tty_candidates": tty_candidates},
                )
                return
            _agent_registry_mark_closed("codex", native_id)
            self._finish_send_text_failure(
                receipt_context,
                text,
                status=410,
                reason="Terminal tab is gone — Codex session marked closed.",
                validated=True,
                backend="terminal_app",
                tty=tty,
                pid=pid or None,
                extra={"gone": True},
            )
            return
        if result.get("ok"):
            stdout = str(result.get("stdout") or "")
            used_tty = stdout.split("\t", 1)[1].strip() if stdout.startswith("ok\t") else tty
            tty = used_tty or tty
            _agent_registry_update_control(
                "codex", native_id, state="running"
            )
            _write_agent_turn_state("codex", native_id, "thinking", started_at=_time.time(), event="send_text")
        capture_path = _terminal_capture_for_tty(tty, reg.get("project")) if tty else None
        source_offset_after = None
        source_offset_reason = "no_capture_log"
        try:
            if capture_path and capture_path.is_file():
                source_offset_after = capture_path.stat().st_size
                source_offset_reason = None
        except OSError:
            pass
        outcome_indeterminate = bool(result.get("outcome_indeterminate"))
        pty_written = (
            result.get("pty_written")
            if "pty_written" in result
            else (None if outcome_indeterminate else bool(result.get("ok")))
        )
        receipt = _make_send_text_receipt(
            receipt_context,
            client_action_id=client_action_id,
            state=(
                "applied"
                if result.get("ok")
                else ("indeterminate" if outcome_indeterminate else "failed")
            ),
            phases=_receipt_phases(
                validated=True,
                applied=bool(result.get("ok")),
                pty_written=pty_written,
            ),
            backend="terminal_app",
            tty=tty,
            pid=pid,
            source_offset_after=source_offset_after,
            source_offset_reason=source_offset_reason,
        )
        if result.get("write_outcome"):
            receipt["phases"]["pty_write_state"] = str(result["write_outcome"])
        if not result.get("ok"):
            _receipt_attach_response(
                receipt,
                http_status=502,
                error_code=(
                    "terminal_write_outcome_unknown"
                    if outcome_indeterminate
                    else "send_text_failed"
                ),
                error_message=str(result.get("reason") or "Send failed."),
                fields={
                    "reason": result.get("reason"),
                    "write_outcome": result.get("write_outcome"),
                    "outcome_indeterminate": outcome_indeterminate,
                },
            )
        _store_action_receipt(device_id, receipt_session_id, client_action_id, body_hash, receipt, action_kind="send_text", audit_action={"type": "send_text", "chars": len(text)})
        body = json.dumps({
            "ok": result.get("ok", False),
            "session_id": public_session_id,
            "tty": tty,
            "pid": pid,
            "reason": result.get("reason"),
            "error_code": (
                "terminal_write_outcome_unknown"
                if outcome_indeterminate
                else ("send_text_failed" if not result.get("ok") else None)
            ),
            "write_outcome": result.get("write_outcome"),
            "outcome_indeterminate": outcome_indeterminate,
            "receipt": receipt,
        }).encode()
        self.send_response(200 if result.get("ok") else 502)
        self.send_header("Content-Type", "application/json")
        self.send_header("Content-Length", str(len(body)))
        self.end_headers()
        self.wfile.write(body)

    def _send_text_to_omp_registry(
        self,
        native_id: str,
        text: str,
        receipt_context: dict | None = None,
    ) -> None:
        """Send through an owned OMP broker or an exact Terminal.app binding."""
        receipt_context = receipt_context or {}
        reg = _agent_registry_get("omp", native_id)
        if not reg:
            self._finish_send_text_failure(
                receipt_context,
                text,
                status=404,
                reason="No OMP control record exists for this session.",
                error_code="session_not_found",
            )
            return
        if reg.get("closed_at") is not None:
            self._finish_send_text_failure(
                receipt_context,
                text,
                status=409,
                reason="OMP session is closed and cannot receive text.",
                backend="pty_broker",
                error_code="process_identity_unverified",
            )
            return

        public_session_id = str(
            receipt_context.get("public_session_id")
            or _qualified_session_id("omp", native_id)
        )
        durable_broker_id = _durable_broker_id_from_registry_row(
            reg,
            provider="omp",
            native_id=native_id,
        )
        broker_session = _registry_owned_broker_session("omp", native_id, reg)
        if broker_session is None and durable_broker_id:
            self._finish_send_text_failure(
                receipt_context,
                text,
                status=503,
                reason="OMP terminal broker is temporarily unavailable. No text was sent.",
                state="failed",
                validated=True,
                backend="pty_broker",
                tty=str(reg.get("terminal_tty") or "") or None,
                pid=int(reg.get("pid") or 0) or None,
                error_code="broker_unavailable",
                extra={"broker_id": durable_broker_id},
            )
            return
        if broker_session is None:
            inventory = _capture_sessions_provider_inventory("omp")
            live_terminals = list(inventory.get("terminals") or [])
            tty = str(reg.get("terminal_tty") or "")
            pid = int(reg.get("pid") or 0)
            identity_matches = (
                _omp_pairling_pending_terminal(reg, live_terminals) is not None
                if native_id.startswith("pending-")
                else _omp_inventory_registry_process_matches(
                    reg,
                    live_terminals,
                    require_direct_control=True,
                )
            )
            if (
                inventory.get("probe_state") != "exact"
                or not bool(inventory.get("membership_complete"))
                or not identity_matches
            ):
                self._finish_send_text_failure(
                    receipt_context,
                    text,
                    status=409,
                    reason="OMP process identity changed; refresh before sending text.",
                    backend="terminal_app",
                    tty=tty or None,
                    pid=pid or None,
                    error_code="process_identity_unverified",
                )
                return

            if native_id.startswith("pending-"):
                try:
                    snapshot = self._terminal_app_surface_snapshot(
                        public_session_id,
                        automation_timeout=3.0,
                    )
                except (FileNotFoundError, PermissionError, RuntimeError):
                    snapshot = None
                if not _first_prompt_surface_is_ready("omp", snapshot):
                    self._finish_send_text_failure(
                        receipt_context,
                        text,
                        status=409,
                        reason="OMP is still starting. No text was sent.",
                        backend="terminal_app",
                        tty=tty or None,
                        pid=pid or None,
                        error_code="provider_composer_not_ready",
                    )
                    return

            _mark_send_text_running(
                receipt_context,
                provider_id="omp",
                binding_id=f"terminal_tty:{tty}",
            )
            result = _send_terminal_app_text_exact(tty, text)
            if result.get("ok"):
                _agent_registry_update_control(
                    "omp", native_id, pid=pid, terminal_tty=tty,
                    state="running", reopen=True,
                )
                _write_agent_turn_state(
                    "omp", native_id, "thinking",
                    started_at=_time.time(), event="send_text",
                )
            outcome_indeterminate = bool(result.get("outcome_indeterminate"))
            pty_written = (
                result.get("pty_written")
                if "pty_written" in result
                else (None if outcome_indeterminate else bool(result.get("ok")))
            )
            receipt = _make_send_text_receipt(
                receipt_context,
                client_action_id=receipt_context.get("client_action_id"),
                state=(
                    "applied"
                    if result.get("ok")
                    else ("indeterminate" if outcome_indeterminate else "failed")
                ),
                phases=_receipt_phases(
                    validated=True,
                    applied=bool(result.get("ok")),
                    pty_written=pty_written,
                ),
                backend="terminal_app",
                tty=tty,
                pid=pid,
                source_offset_reason="omp_transcript_confirmation",
            )
            if result.get("write_outcome"):
                receipt["phases"]["pty_write_state"] = str(result["write_outcome"])
            if not result.get("ok"):
                _receipt_attach_response(
                    receipt,
                    http_status=int(result.get("status") or 502),
                    error_code=str(
                        result.get("error_code")
                        or (
                            "terminal_write_outcome_unknown"
                            if outcome_indeterminate
                            else "send_text_failed"
                        )
                    ),
                    error_message=str(result.get("reason") or "Send failed."),
                    fields={
                        "reason": result.get("reason"),
                        "write_outcome": result.get("write_outcome"),
                        "outcome_indeterminate": outcome_indeterminate,
                    },
                )
            _store_action_receipt(
                receipt_context.get("device_id"),
                str(
                    receipt_context.get("session_id")
                    or _qualified_session_id("omp", native_id)
                ),
                receipt_context.get("client_action_id"),
                str(receipt_context.get("body_hash") or _receipt_body_hash(text)),
                receipt,
                action_kind="send_text",
                audit_action={"type": "send_text", "chars": len(text)},
            )
            self._send_json(
                {
                    "ok": bool(result.get("ok")),
                    "session_id": public_session_id,
                    "tty": tty,
                    "pid": pid,
                    "reason": result.get("reason"),
                    "error_code": result.get("error_code"),
                    "write_outcome": result.get("write_outcome"),
                    "outcome_indeterminate": outcome_indeterminate,
                    "receipt": receipt,
                },
                status=200 if result.get("ok") else int(result.get("status") or 502),
            )
            return

        broker_id = _broker_session_id(broker_session)
        if _broker_runtime_relation() != "current":
            self._finish_send_text_failure(
                receipt_context,
                text,
                status=409,
                reason="OMP control requires the current terminal broker.",
                backend="pty_broker",
                tty=_broker_slave_tty(broker_session) or None,
                pid=_broker_pid(broker_session) or None,
                error_code="broker_requires_current_runtime",
                extra={"broker_id": broker_id},
            )
            return

        if native_id.startswith("pending-"):
            try:
                snapshot = self._broker_surface_snapshot(public_session_id)
            except (FileNotFoundError, PermissionError, RuntimeError):
                snapshot = None
            if not _first_prompt_surface_is_ready("omp", snapshot):
                self._finish_send_text_failure(
                    receipt_context,
                    text,
                    status=409,
                    reason="OMP is still starting. No text was sent.",
                    backend="pty_broker",
                    tty=_broker_slave_tty(broker_session) or None,
                    pid=_broker_pid(broker_session) or None,
                    error_code="provider_composer_not_ready",
                    extra={"broker_id": broker_id},
                )
                return

        _mark_send_text_running(
            receipt_context,
            provider_id="omp",
            binding_id=f"pty_broker:{broker_id}",
        )
        result, source_offset_after, source_offset_reason = _broker_send_text_with_truth(
            broker_id,
            text,
            public_session_id=public_session_id,
        )
        if result.get("ok"):
            _agent_registry_update_control(
                "omp",
                native_id,
                pid=_broker_pid(broker_session),
                terminal_tty=_broker_slave_tty(broker_session),
                state="running",
                reopen=True,
            )
            _write_agent_turn_state(
                "omp",
                native_id,
                "thinking",
                started_at=_time.time(),
                event="send_text",
            )

        outcome_indeterminate = bool(result.get("outcome_indeterminate"))
        pty_written = (
            result.get("pty_written")
            if "pty_written" in result
            else (None if outcome_indeterminate else bool(result.get("ok")))
        )
        receipt = _make_send_text_receipt(
            receipt_context,
            client_action_id=receipt_context.get("client_action_id"),
            state=(
                "applied"
                if result.get("ok")
                else ("indeterminate" if outcome_indeterminate else "failed")
            ),
            phases=_receipt_phases(
                validated=True,
                applied=bool(result.get("ok")),
                pty_written=pty_written,
            ),
            backend="pty_broker",
            tty=_broker_slave_tty(broker_session),
            pid=_broker_pid(broker_session),
            source_offset_after=source_offset_after,
            source_offset_reason=source_offset_reason,
        )
        if result.get("write_outcome"):
            receipt["phases"]["pty_write_state"] = str(result["write_outcome"])
        if not result.get("ok"):
            _receipt_attach_response(
                receipt,
                http_status=int(result.get("status") or 502),
                error_code=str(
                    result.get("error_code")
                    or result.get("reason")
                    or "send_text_failed"
                ),
                error_message=str(
                    result.get("error")
                    or result.get("reason")
                    or "Send failed."
                ),
                fields={
                    "reason": result.get("reason"),
                    "bytes_written": result.get("bytes_written"),
                    "bytes_expected": result.get("bytes_expected"),
                    "write_outcome": result.get("write_outcome"),
                    "outcome_indeterminate": outcome_indeterminate,
                },
            )
        _store_action_receipt(
            receipt_context.get("device_id"),
            str(
                receipt_context.get("session_id")
                or _qualified_session_id("omp", native_id)
            ),
            receipt_context.get("client_action_id"),
            str(receipt_context.get("body_hash") or _receipt_body_hash(text)),
            receipt,
            action_kind="send_text",
            audit_action={"type": "send_text", "chars": len(text)},
        )
        self._send_json(
            {
                "ok": bool(result.get("ok")),
                "session_id": public_session_id,
                "tty": _broker_slave_tty(broker_session),
                "pid": _broker_pid(broker_session),
                "broker_id": broker_id,
                "reason": result.get("reason"),
                "error_code": result.get("error_code"),
                "bytes_written": result.get("bytes_written"),
                "bytes_expected": result.get("bytes_expected"),
                "write_outcome": result.get("write_outcome"),
                "outcome_indeterminate": outcome_indeterminate,
                "receipt": receipt,
            },
            status=200 if result.get("ok") else int(result.get("status") or 502),
        )

    def _send_text_confirmation_boundary(
        self,
        provider: str,
        native_id: str,
        raw_session: str,
    ) -> tuple[dict | None, str | None]:
        session_key = _qualified_session_id(provider, native_id)
        log = _ensure_session_event_log()
        ingestor = _ensure_session_log_ingestor()
        if log is None or ingestor is None:
            return None, "session_log_unavailable"
        try:
            transcript_path = self._resolve_session_transcript_path(
                provider,
                native_id,
                raw_session,
            )
        except Exception:
            return None, "transcript_resolution_failed"
        if transcript_path is None:
            if provider == "omp" and native_id.startswith("pending-"):
                inventory = _capture_sessions_provider_inventory("omp")
                terminals = list(inventory.get("terminals") or [])
                row = _agent_registry_get("omp", native_id)
                if (
                    inventory.get("probe_state") == "exact"
                    and bool(inventory.get("membership_complete"))
                    and _omp_pairling_pending_terminal(row, terminals) is not None
                ):
                    try:
                        transcript_offset = int(
                            log.prepare_ingest(session_key, _OMP_PARSER_VERSION)
                        )
                        log_seq = int(log.last_seq(session_key))
                        log_generation = int(log.get_generation(session_key))
                    except Exception:
                        return None, "session_log_boundary_failed"
                    if transcript_offset == 0 and log_seq == 0 and log_generation > 0:
                        return {
                            "transcript_offset": 0,
                            "log_seq": 0,
                            "log_generation": log_generation,
                        }, None
                    return None, "pending_session_log_not_empty"
            return None, "transcript_source_unavailable"
        if not ingestor.ensure(session_key, provider, native_id, transcript_path):
            return None, "session_log_registration_failed"
        drained = ingestor.drain_now(session_key)
        if drained.get("ok") is not True:
            return None, str(drained.get("reason") or "session_log_boundary_failed")
        log_generation = int(drained.get("log_generation") or 0)
        if log_generation <= 0:
            return None, "session_log_generation_unavailable"
        return {
            "transcript_offset": max(0, int(drained.get("transcript_offset") or 0)),
            "log_seq": max(0, int(drained.get("log_seq") or 0)),
            "log_generation": log_generation,
        }, None

    # ----- /send-text: write directly to a Terminal tab's pty (no keystrokes) -----
    def _handle_send_text(self, q):
        """Write text plus Enter to the exact provider session's PTY.

        Terminal.app sessions are matched by their recorded tty. Broker sessions
        are matched by their provider-qualified broker identity.

        terminal_tty is populated for any session that has fired at least one
        hook event since the schema migration. Sessions started before then
        get backfilled on next hook fire (heartbeat opportunistically writes
        terminal_tty when it's NULL).
        """
        raw_session = q.get("session", [""])[0]
        if ":" not in raw_session:
            self._send_json({
                "ok": False,
                "error": {
                    "code": "provider_required",
                    "message": "session must be provider-qualified",
                },
                "error_code": "provider_required",
            }, status=400)
            return
        provider, native_id = _parse_agent_session_ref(raw_session)
        if not native_id or not _valid_provider_filter(provider, allow_all=False):
            self._send_json({
                "ok": False,
                "error": {
                    "code": "bad_session",
                    "message": "session must be provider-qualified",
                },
                "error_code": "bad_session",
            }, status=400)
            return
        if not _provider_supports(provider, "send_text"):
            _send_unsupported_provider(self, provider, "send_text")
            return

        attachment_records: list[dict] = []
        raw_attachment_records = q.get("attachment", [])
        if len(raw_attachment_records) > 8:
            self._send_json({
                "ok": False,
                "error": {"code": "too_many_attachments", "message": "At most 8 attachments are allowed."},
                "error_code": "too_many_attachments",
            }, status=400)
            return
        try:
            for raw_record in raw_attachment_records:
                decoded = json.loads(raw_record)
                if not isinstance(decoded, dict):
                    raise ValueError("attachment must be an object")
                attachment_records.append(decoded)
        except (TypeError, ValueError, json.JSONDecodeError):
            self._send_json({
                "ok": False,
                "error": {"code": "bad_attachment_records", "message": "Attachment metadata is invalid."},
                "error_code": "bad_attachment_records",
            }, status=400)
            return
        raw = self._read_body()
        text = raw.decode("utf-8", errors="replace")
        if not text:
            self.send_error(400, "empty body")
            return

        # Embedded newlines are preserved for bracketed paste; client-supplied
        # terminal control bytes and paste delimiters are rejected centrally.
        text, sanitize_err = _sanitize_terminal_text_input(
            text,
            allow_newline=True,
            max_chars=TERMINAL_TEXT_MAX_CHARS,
        )
        if sanitize_err:
            self.send_error(int(sanitize_err["status"]), str(sanitize_err["message"]))
            return

        public_session_id = _qualified_session_id(provider, native_id)
        receipt_session_id, registry_row = _session_mutation_receipt_identity(
            self,
            public_session_id,
        )
        client_action_id = str(self.headers.get("X-Pairling-Action-Id") or "").strip()
        if not _valid_client_action_id(client_action_id):
            self._send_json({
                "ok": False,
                "error": {
                    "code": "action_id_required",
                    "message": "A valid X-Pairling-Action-Id is required for terminal text.",
                },
                "error_code": "action_id_required",
            }, status=400)
            return
        receipt_context = {
            "client_action_id": client_action_id or None,
            "device_id": getattr(getattr(self, "pairling_auth", None), "device_id", None),
            "session_id": receipt_session_id,
            "receipt_scope": receipt_session_id,
            "action_kind": "send_text",
            "public_session_id": public_session_id,
            "registry_row": registry_row,
            "body_hash": _receipt_body_hash({
                "session_id": receipt_session_id,
                "text": text,
                "attachments": attachment_records,
            }),
        }
        deduped_receipt, conflict = _receipt_duplicate_response(
            receipt_context["device_id"],
            receipt_session_id,
            client_action_id,
            receipt_context["body_hash"],
            action_kind="send_text",
        )
        if conflict:
            _store_action_receipt(
                receipt_context["device_id"],
                receipt_session_id,
                client_action_id,
                receipt_context["body_hash"],
                conflict["receipt"],
                action_kind="send_text",
                audit_action={"type": "send_text", "chars": len(text)},
                persist=False,
            )
            self._send_json(conflict, status=int(conflict["status"]))
            return
        if deduped_receipt:
            replay, replay_status = _receipt_replay_response(deduped_receipt, {
                "ok": deduped_receipt.get("state") == "applied",
                "session_id": public_session_id,
            })
            self._send_json(replay, status=replay_status)
            return

        # Replays are resolved above before the limiter. A new action that is
        # rate-limited finalizes its reservation so later retries return the
        # same rejection instead of remaining stuck in progress.
        allowed, retry = _inject_rate_check(_qualified_session_id(provider, native_id))
        if not allowed:
            reason = f"rate limited, retry in {retry}s"
            receipt = _make_action_receipt(
                client_action_id=client_action_id,
                state="rejected",
                phases=_receipt_phases(validated=False, applied=False, pty_written=False),
            )
            _receipt_attach_response(
                receipt,
                http_status=429,
                error_code="rate_limited",
                error_message=reason,
                fields={"retry_after": retry},
            )
            _store_action_receipt(
                receipt_context["device_id"],
                receipt_session_id,
                client_action_id,
                receipt_context["body_hash"],
                receipt,
                action_kind="send_text",
                audit_action={"type": "send_text", "chars": len(text), "error": "rate_limited"},
            )
            self._send_json({
                "ok": False,
                "error": {"code": "rate_limited", "message": reason},
                "error_code": "rate_limited",
                "retry_after": retry,
                "receipt": receipt,
            }, status=429)
            return

        if attachment_records:
            auth = getattr(self, "pairling_auth", None)
            try:
                prepared_attachments = self._pairdrop_store().prepare_attachment_handles(
                    attachment_records,
                    session_id=receipt_session_id,
                    source_device_id=str(getattr(auth, "device_id", "") or ""),
                    source_install_id=str(getattr(auth, "install_id", "") or ""),
                    binding_id=f"send-text:{receipt_session_id}:{client_action_id}",
                    client_action_id=client_action_id,
                )
                attachment_lines: list[str] = []
                for attachment in prepared_attachments:
                    local_path = attachment.materialize_local_path_for_send()
                    attachment_lines.append(
                        "Attached file "
                        + json.dumps(attachment.display_name or "attachment")
                        + " is available to this local provider at "
                        + json.dumps(str(local_path))
                        + "."
                    )
                text += "\n\n" + "\n".join(attachment_lines)
            except PairDropStoreError as exc:
                code = str(getattr(exc, "code", "") or "attachment_unavailable")
                status = 404 if code in {
                    "attachment_not_found",
                    "not_found",
                    "deleted",
                    "missing_object",
                } else 409
                self._finish_send_text_failure(
                    receipt_context,
                    text,
                    status=status,
                    reason="The attachment is no longer available for this session.",
                    state="rejected",
                    validated=False,
                    error_code=code,
                )
                return

        confirmation_boundary, boundary_error = self._send_text_confirmation_boundary(
            provider,
            native_id,
            raw_session,
        )
        if confirmation_boundary is None:
            self._finish_send_text_failure(
                receipt_context,
                text,
                status=503,
                reason="Pairling could not establish the transcript proof boundary. No text was sent.",
                state="failed",
                validated=True,
                error_code="confirmation_boundary_unavailable",
                extra={"boundary_reason": boundary_error},
            )
            return
        receipt_context["confirmation_boundary"] = confirmation_boundary

        global LAST_HUMAN_ACTIVITY_AT
        LAST_HUMAN_ACTIVITY_AT = _time.time()

        if provider == "codex":
            self._send_text_to_codex_registry(native_id, text, receipt_context)
            return
        if provider == "omp":
            self._send_text_to_omp_registry(native_id, text, receipt_context)
            return
        if provider != "claude":
            _send_unsupported_provider(self, provider, "send_text")
            return

        session_id = _claude_native_session_id(raw_session)
        if not session_id:
            self._finish_send_text_failure(
                receipt_context,
                text,
                status=400,
                reason="session required",
            )
            return

        broker_registry_row = receipt_context.get("registry_row")
        if broker_registry_row is None:
            broker_registry_row = _agent_registry_row_for_broker_id(
                "claude",
                _qualified_session_id("claude", session_id),
            )
        claude_record = _claude_sessions_backend().session_record(session_id)
        if (
            (broker_registry_row or {}).get("closed_at") is not None
            or (claude_record or {}).get("closed_at") is not None
        ):
            self._finish_send_text_failure(
                receipt_context,
                text,
                status=409,
                reason="Claude session is closed and its process identity is no longer verified.",
                backend="pty_broker" if broker_registry_row else "terminal_app",
                tty=str((broker_registry_row or {}).get("terminal_tty") or "") or None,
                pid=int((broker_registry_row or {}).get("pid") or 0) or None,
                error_code="process_identity_unverified",
            )
            return
        durable_broker_id = _durable_broker_id_from_registry_row(
            broker_registry_row,
            provider="claude",
            native_id=session_id,
        )
        broker_found = self._broker_session_for(
            _qualified_session_id("claude", session_id)
        )
        if not broker_found and durable_broker_id:
            self._finish_send_text_failure(
                receipt_context,
                text,
                status=503,
                reason="Claude terminal broker is temporarily unavailable. No text was sent.",
                state="failed",
                validated=True,
                backend="pty_broker",
                tty=str((broker_registry_row or {}).get("terminal_tty") or "") or None,
                pid=int((broker_registry_row or {}).get("pid") or 0) or None,
                error_code="broker_unavailable",
                extra={"broker_id": durable_broker_id},
            )
            return

        if broker_found and PTY_BROKER:
            _public_id, broker_session = broker_found
            broker_id = _broker_session_id(broker_session)
            if not _broker_session_owns_identity(broker_session, "claude", session_id):
                self._finish_send_text_failure(
                    receipt_context,
                    text,
                    status=409,
                    reason="Claude broker ownership changed; refresh before sending text",
                    backend="pty_broker",
                    tty=_broker_slave_tty(broker_session),
                    pid=_broker_pid(broker_session),
                    error_code="process_identity_unverified",
                    extra={"broker_id": _broker_session_id(broker_session)},
                )
                return
            _mark_send_text_running(
                receipt_context,
                provider_id="claude",
                binding_id=f"pty_broker:{broker_id}",
            )
            result, source_offset_after, source_offset_reason = _broker_send_text_with_truth(
                broker_id,
                text,
                public_session_id=public_session_id,
            )
            outcome_indeterminate = bool(result.get("outcome_indeterminate"))
            pty_written = (
                result.get("pty_written")
                if "pty_written" in result
                else (None if outcome_indeterminate else bool(result.get("ok")))
            )
            receipt = _make_send_text_receipt(
                receipt_context,
                client_action_id=receipt_context["client_action_id"],
                state="applied" if result.get("ok") else ("indeterminate" if outcome_indeterminate else "failed"),
                phases=_receipt_phases(validated=True, applied=bool(result.get("ok")), pty_written=pty_written),
                backend="pty_broker",
                tty=_broker_slave_tty(broker_session),
                pid=_broker_pid(broker_session),
                source_offset_after=source_offset_after,
                source_offset_reason=source_offset_reason,
            )
            if result.get("write_outcome"):
                receipt["phases"]["pty_write_state"] = str(result["write_outcome"])
            if not result.get("ok"):
                _receipt_attach_response(
                    receipt,
                    http_status=int(result.get("status") or 502),
                    error_code=str(result.get("error_code") or result.get("reason") or "send_text_failed"),
                    error_message=str(result.get("error") or result.get("reason") or "Send failed."),
                    fields={
                        "reason": result.get("reason"),
                        "bytes_written": result.get("bytes_written"),
                        "bytes_expected": result.get("bytes_expected"),
                        "write_outcome": result.get("write_outcome"),
                        "outcome_indeterminate": outcome_indeterminate,
                    },
                )
            _store_action_receipt(receipt_context["device_id"], receipt_session_id, receipt_context["client_action_id"], receipt_context["body_hash"], receipt, action_kind="send_text", audit_action={"type": "send_text", "chars": len(text)})
            body = json.dumps({
                "ok": bool(result.get("ok")),
                "session_id": public_session_id,
                "tty": _broker_slave_tty(broker_session),
                "pid": _broker_pid(broker_session),
                "broker_id": _broker_session_id(broker_session),
                "reason": result.get("reason"),
                "error_code": result.get("error_code"),
                "bytes_written": result.get("bytes_written"),
                "bytes_expected": result.get("bytes_expected"),
                "write_outcome": result.get("write_outcome"),
                "outcome_indeterminate": outcome_indeterminate,
                "receipt": receipt,
            }).encode()
            self.send_response(200 if result.get("ok") else int(result.get("status") or 502))
            self.send_header("Content-Type", "application/json")
            self.send_header("Content-Length", str(len(body)))
            self.end_headers()
            self.wfile.write(body)
            return

        # Freshness gate: prompt_toolkit needs ~1-3s after claude bin start to
        # enable bracketed paste mode (DECSET 2004) and attach to the pty as
        # the input handler. Writing earlier lands bytes in cooked-mode buffer;
        # the bracketed-paste markers don't get interpreted, the trailing
        # newline may be eaten, and the user sees text appear without
        # submitting. Block until the row is at least MIN_AGE old.
        MIN_AGE_S = 3.0
        try:
            age = self._lookup_session_age_seconds(session_id)
            if age is not None and age < MIN_AGE_S:
                _time.sleep(MIN_AGE_S - age)
        except Exception:
            pass  # best effort — proceed even if the lookup fails

        direct_native_id = _agent_registry_resolve_native_alias(
            "claude",
            str((broker_registry_row or {}).get("native_id") or session_id),
        )
        direct_registry_row = _agent_registry_get("claude", direct_native_id)
        direct_pid = int((direct_registry_row or {}).get("pid") or 0)
        tty = str((direct_registry_row or {}).get("terminal_tty") or "")
        if (
            not direct_registry_row
            or direct_registry_row.get("closed_at") is not None
            or direct_pid <= 0
            or not _process_alive(direct_pid)
            or not _registry_process_birth_matches(direct_registry_row, direct_pid)
            or not _session_signal_target_is_verified(
                direct_registry_row, "claude", direct_pid
            )
            or not _direct_terminal_binding_is_verified(
                direct_registry_row, "claude", direct_pid
            )
        ):
            self._finish_send_text_failure(
                receipt_context,
                text,
                status=409,
                reason=(
                    "Claude terminal process or Terminal binding changed before "
                    "text delivery. No text was sent."
                ),
                backend="terminal_app",
                tty=tty or None,
                pid=direct_pid or None,
                error_code="process_identity_unverified",
            )
            return
        receipt_context["registry_row"] = direct_registry_row

        _mark_send_text_running(
            receipt_context,
            provider_id="claude",
            binding_id=f"terminal_tty:{tty}",
        )
        result = _send_terminal_app_text_exact(tty, text)

        # If no Terminal tab matches the recorded tty, the session is a zombie:
        # the user closed that tab. Auto-tombstone and tell the iPhone with a
        # 410 Gone so the bucket disappears on next /sessions?live=true poll.
        if (not result.get("ok")) and result.get("error_code") == "terminal_tab_not_found":
            self._mark_session_closed(session_id)
            self._finish_send_text_failure(
                receipt_context,
                text,
                status=410,
                reason="Terminal tab is gone — session marked closed.",
                validated=True,
                backend="terminal_app",
                tty=tty,
                extra={"gone": True},
            )
            return

        capture_path = _terminal_capture_for_tty(tty, self._lookup_pg_project(session_id)) if tty else None
        source_offset_after = None
        source_offset_reason = "no_capture_log"
        try:
            if capture_path and capture_path.is_file():
                source_offset_after = capture_path.stat().st_size
                source_offset_reason = None
        except OSError:
            pass
        outcome_indeterminate = bool(result.get("outcome_indeterminate"))
        pty_written = (
            result.get("pty_written")
            if "pty_written" in result
            else (None if outcome_indeterminate else bool(result.get("ok")))
        )
        receipt = _make_send_text_receipt(
            receipt_context,
            client_action_id=receipt_context["client_action_id"],
            state=(
                "applied"
                if result.get("ok")
                else ("indeterminate" if outcome_indeterminate else "failed")
            ),
            phases=_receipt_phases(
                validated=True,
                applied=bool(result.get("ok")),
                pty_written=pty_written,
            ),
            backend="terminal_app",
            tty=tty,
            source_offset_after=source_offset_after,
            source_offset_reason=source_offset_reason,
        )
        if result.get("write_outcome"):
            receipt["phases"]["pty_write_state"] = str(result["write_outcome"])
        if not result.get("ok"):
            error_code = (
                "terminal_write_outcome_unknown"
                if outcome_indeterminate
                else str(result.get("error_code") or "send_text_failed")
            )
            status = int(result.get("status") or 502)
            _receipt_attach_response(
                receipt,
                http_status=status,
                error_code=error_code,
                error_message=str(result.get("reason") or "Send failed."),
                fields={
                    "reason": result.get("reason"),
                    "write_outcome": result.get("write_outcome"),
                    "outcome_indeterminate": outcome_indeterminate,
                },
            )
        _store_action_receipt(receipt_context["device_id"], receipt_session_id, receipt_context["client_action_id"], receipt_context["body_hash"], receipt, action_kind="send_text", audit_action={"type": "send_text", "chars": len(text)})
        error_code = (
            "terminal_write_outcome_unknown"
            if outcome_indeterminate
            else (str(result.get("error_code") or "send_text_failed") if not result.get("ok") else None)
        )
        status = int(result.get("status") or 502)
        body = json.dumps({
            "ok": result.get("ok", False),
            "tty": tty,
            "reason": result.get("reason"),
            "error_code": error_code,
            "write_outcome": result.get("write_outcome"),
            "outcome_indeterminate": outcome_indeterminate,
            "receipt": receipt,
        }).encode()
        self.send_response(200 if result.get("ok") else status)
        self.send_header("Content-Type", "application/json")
        self.send_header("Content-Length", str(len(body)))
        self.end_headers()
        self.wfile.write(body)

    def _mark_session_closed(self, session_id: str) -> None:
        """Set closed_at for the given claude session id. Best effort —
        GC of dead sessions, called from /send-text and /sessions zombie scan."""
        session_id = _claude_native_session_id(session_id)
        if not session_id:
            return
        _claude_sessions_backend().tombstone_sessions([session_id])
        try:
            self._pairdrop_store().revoke_attachments_for_session(
                _qualified_session_id("claude", session_id)
            )
        except Exception:
            pass

    # ----- /sigint: send SIGINT to the session's claude process (cancel turn) -----
    def _handle_sigint(self, q):
        """Send SIGINT to claude_pid — cancels the current turn (analogous to
        the user pressing Ctrl+C in the terminal). Session stays alive.
        """
        self._send_signal_to_session(q, signal.SIGINT, "SIGINT")

    # ----- /sigterm: terminate the session's claude process -----
    def _handle_sigterm(self, q):
        """Send SIGTERM — the session ends. claude exits cleanly, the user
        gets their shell back. The SessionEnd hook fires, writing closed_at.
        """
        self._send_signal_to_session(q, signal.SIGTERM, "SIGTERM")

    def _send_signal_to_session(self, q, sig: int, sig_name: str) -> None:
        raw_session = q.get("session", [""])[0]
        if ":" not in raw_session:
            self._send_json({
                "ok": False,
                "signal": sig_name,
                "error": "session must be provider-qualified",
                "error_code": "provider_required",
            }, status=400)
            return
        provider, native_id = _parse_agent_session_ref(raw_session)
        if not native_id or not _valid_provider_filter(provider, allow_all=False):
            self._send_json({
                "ok": False,
                "signal": sig_name,
                "error": "session must be provider-qualified",
                "error_code": "bad_session",
            }, status=400)
            return
        capability = "terminate" if sig == signal.SIGTERM else "interrupt"
        if not _provider_supports(provider, capability):
            _send_unsupported_provider(self, provider, capability)
            return
        public_session_id = _qualified_session_id(provider, native_id)
        receipt_session_id = _session_mutation_receipt_scope(self, public_session_id)
        requested_native_id = native_id
        control_native_id = _agent_registry_resolve_native_alias(
            provider, native_id
        )
        signal_action_kind = "sigterm" if sig == signal.SIGTERM else "sigint"
        client_action_id = str(self.headers.get("X-Pairling-Action-Id") or "").strip()
        if not _valid_client_action_id(client_action_id):
            self._send_json({
                "ok": False,
                "session_id": public_session_id,
                "signal": sig_name,
                "error": "A valid X-Pairling-Action-Id is required for session control.",
                "error_code": "action_id_required",
            }, status=400)
            return
        device_id = getattr(getattr(self, "pairling_auth", None), "device_id", None)
        body_hash = _receipt_body_hash({"session_id": receipt_session_id, "signal": sig_name})
        deduped_receipt, conflict = _receipt_duplicate_response(
            device_id,
            receipt_session_id,
            client_action_id,
            body_hash,
            action_kind=signal_action_kind,
        )
        if conflict:
            _store_action_receipt(
                device_id,
                receipt_session_id,
                client_action_id,
                body_hash,
                conflict["receipt"],
                action_kind=signal_action_kind,
                audit_action={"type": "idempotency_conflict", "signal": sig_name},
                persist=False,
            )
            self._send_json({
                "ok": False,
                "session_id": public_session_id,
                "pid": None,
                "signal": sig_name,
                "error": conflict["error"]["message"],
                "error_code": conflict["error"]["code"],
                "receipt": conflict["receipt"],
            }, status=int(conflict["status"]))
            return
        if deduped_receipt:
            replay, replay_status = _receipt_replay_response(deduped_receipt, {
                "ok": deduped_receipt.get("state") == "applied",
                "session_id": public_session_id,
                "pid": deduped_receipt.get("pid"),
                "signal": sig_name,
                "error": None,
            })
            if isinstance(replay.get("error"), dict):
                replay["error"] = replay["error"].get("message")
            self._send_json(replay, status=replay_status)
            return

        mutation = {
            "device_id": device_id,
            "receipt_scope": receipt_session_id,
            "client_action_id": client_action_id,
            "body_hash": body_hash,
            "action_kind": signal_action_kind,
            "execution_state": "queued",
        }
        signal_running = False

        def mark_signal_running() -> None:
            nonlocal signal_running
            if signal_running:
                raise RuntimeError("signal action entered its execution boundary twice")
            _mark_receipted_mutation_running(
                mutation,
                provider_id=provider,
                provider_version="terminal-surface-v2",
                provider_channel="terminal",
                operation_id=signal_action_kind,
                binding_id=(
                    f"{provider}:terminal-signal:{receipt_session_id}"
                ),
                capability_generation=1,
                recovery_correlation={
                    "provider_operation_id": client_action_id,
                    "provider_cursor": None,
                },
            )
            signal_running = True

        def send_signal_result(
            ok: bool,
            pid: int | None,
            err: str | None,
            status: int,
            broker_id: str | None = None,
            error_code: str | None = None,
            already_closed: bool = False,
            pty_written: bool | None = False,
            write_outcome: str | None = None,
            outcome_indeterminate: bool = False,
        ) -> None:
            if (ok or outcome_indeterminate) and not already_closed and not signal_running:
                raise RuntimeError("signal outcome recorded before its execution boundary")
            receipt = _make_action_receipt(
                client_action_id=client_action_id or None,
                state="applied" if ok else ("indeterminate" if outcome_indeterminate else "failed"),
                phases=_receipt_phases(validated=True, applied=ok, pty_written=pty_written),
                backend="pty_broker" if broker_id else "process_signal",
                pid=pid,
            )
            if write_outcome:
                receipt["phases"]["pty_write_state"] = write_outcome
            if not ok:
                _receipt_attach_response(
                    receipt,
                    http_status=status,
                    error_code=error_code or "session_signal_failed",
                    error_message=err or "Session signal failed.",
                    fields={
                        "signal": sig_name,
                        "pid": pid,
                        "broker_id": broker_id,
                        "outcome_indeterminate": outcome_indeterminate,
                    },
                )
            _store_action_receipt(
                device_id,
                receipt_session_id,
                client_action_id or None,
                body_hash,
                receipt,
                action_kind=signal_action_kind,
                audit_action={"type": sig_name.lower(), "provider": provider, "ok": ok},
            )
            body = {
                "ok": ok,
                "session_id": public_session_id,
                "pid": pid,
                "signal": sig_name,
                "error": err,
                "outcome_indeterminate": outcome_indeterminate,
                "receipt": receipt,
            }
            if broker_id:
                body["broker_id"] = broker_id
            if error_code:
                body["error_code"] = error_code
            if already_closed:
                body["already_closed"] = True
            self._send_json(body, status=status)

        if provider == "codex":
            native_id = control_native_id
            reg = _agent_registry_get("codex", native_id)
            if reg and reg.get("closed_at") is None:
                reg = _agent_registry_promote_codex(
                    native_id,
                    str(reg.get("project") or ""),
                    float(reg.get("started_at") or 0),
                ) or reg
                promoted_native_id = str(reg.get("native_id") or "")
                if promoted_native_id:
                    native_id = promoted_native_id
            durable_broker_id = _durable_broker_id_from_registry_row(
                reg,
                provider="codex",
                native_id=native_id,
            )
            if reg and reg.get("closed_at") is not None:
                if sig == signal.SIGTERM:
                    send_signal_result(True, None, None, 200, already_closed=True)
                else:
                    send_signal_result(
                        False,
                        None,
                        "Codex session is closed and cannot be interrupted.",
                        409,
                        error_code="process_identity_unverified",
                    )
                return
            broker_found = self._broker_session_for(
                _qualified_session_id("codex", requested_native_id)
            )
            if broker_found and PTY_BROKER:
                _, broker_session = broker_found
                broker_id = _broker_session_id(broker_session)
                if not _broker_session_owns_identity(broker_session, "codex", native_id):
                    send_signal_result(
                        False,
                        _broker_pid(broker_session) or None,
                        "Codex broker ownership changed; refresh before sending control",
                        409,
                        broker_id=broker_id,
                        error_code="process_identity_unverified",
                    )
                    return
                broker_relation = _broker_runtime_relation()
                if sig == signal.SIGINT and broker_relation not in {"current", "stale_deferred"}:
                    send_signal_result(
                        False,
                        _broker_pid(broker_session) or None,
                        "Interrupt requires an exactly identified current or draining terminal broker.",
                        409,
                        broker_id=broker_id,
                        error_code="broker_runtime_identity_unverified",
                        pty_written=False,
                        write_outcome="none",
                    )
                    return
                if sig != signal.SIGINT and broker_relation != "current":
                    send_signal_result(
                        False,
                        _broker_pid(broker_session) or None,
                        "Termination requires the current terminal broker.",
                        409,
                        broker_id=broker_id,
                        error_code="broker_requires_current_runtime",
                        pty_written=False,
                        write_outcome="none",
                    )
                    return
                try:
                    mark_signal_running()
                    if sig == signal.SIGINT:
                        result = _broker_interrupt_for_draining_runtime(broker_id)
                    else:
                        result = PTY_BROKER.terminate(broker_id, sig)
                except PTYBrokerOutcomeUnknownError as exc:
                    send_signal_result(
                        False,
                        _broker_pid(broker_session) or None,
                        str(exc)[:200],
                        502,
                        broker_id=broker_id,
                        error_code="broker_signal_outcome_unknown",
                        pty_written=None,
                        write_outcome="unknown",
                        outcome_indeterminate=True,
                    )
                    return
                except Exception as exc:
                    send_signal_result(
                        False,
                        _broker_pid(broker_session) or None,
                        str(exc)[:200],
                        503,
                        broker_id=broker_id,
                        error_code="broker_unavailable",
                        pty_written=False,
                        write_outcome="none",
                    )
                    return
                ok = bool(result.get("ok"))
                if ok:
                    _write_agent_turn_state("codex", native_id, "idle", event=sig_name.lower())
                if ok and sig == signal.SIGTERM:
                    _agent_registry_mark_closed("codex", native_id)
                send_signal_result(
                    ok,
                    result.get("pid") or _broker_pid(broker_session),
                    result.get("error") or result.get("reason"),
                    200 if ok else int(result.get("status") or 502),
                    broker_id=broker_id,
                    pty_written=(
                        bool(result.get("pty_written"))
                        if "pty_written" in result
                        else bool(ok and sig == signal.SIGINT)
                    ),
                    write_outcome=result.get("write_outcome"),
                    outcome_indeterminate=bool(result.get("outcome_indeterminate")),
                )
                return

            if durable_broker_id:
                send_signal_result(
                    False,
                    int(reg.get("pid") or 0) or None,
                    "Codex terminal broker is temporarily unavailable.",
                    503,
                    broker_id=durable_broker_id,
                    error_code="broker_unavailable",
                    pty_written=False,
                    write_outcome="none",
                )
                return

            if not reg:
                send_signal_result(False, None, "no Codex control registry row for session", 404)
                return
            pid = int(reg.get("pid") or 0)
            if not pid or not _process_alive(pid):
                send_signal_result(
                    False,
                    pid or None,
                    "Codex process identity changed; refresh before sending control",
                    409,
                    error_code="process_identity_unverified",
                )
                return
            if not _session_signal_target_is_verified(reg, "codex", pid):
                send_signal_result(
                    False,
                    pid,
                    "Codex process identity changed; refresh before sending control",
                    409,
                    error_code="process_identity_unverified",
                )
                return
            ok = True
            err: str | None = None
            error_code: str | None = None
            if sig == signal.SIGTERM:
                mark_signal_running()
                termination = _terminate_direct_session_process(reg, "codex", pid)
                ok = bool(termination.get("ok"))
                err = termination.get("error")
                error_code = termination.get("error_code")
                outcome_indeterminate = bool(termination.get("outcome_indeterminate"))
            else:
                outcome_indeterminate = False
                try:
                    mark_signal_running()
                    os.kill(pid, sig)
                except (ProcessLookupError, PermissionError, OSError) as e:
                    ok = False
                    err = f"{type(e).__name__}: {e}"
            if ok:
                _write_agent_turn_state("codex", native_id, "idle", event=sig_name.lower())
            if ok and sig == signal.SIGTERM:
                _agent_registry_mark_closed("codex", native_id)
            status = 409 if error_code == "process_identity_unverified" else (200 if ok else 502)
            send_signal_result(
                ok,
                pid,
                err,
                status,
                error_code=error_code,
                outcome_indeterminate=outcome_indeterminate,
            )
            return

        if provider == "omp":
            native_id = control_native_id
            reg = _agent_registry_get("omp", native_id)
            if reg and reg.get("closed_at") is not None:
                if sig == signal.SIGTERM:
                    send_signal_result(True, None, None, 200, already_closed=True)
                else:
                    send_signal_result(
                        False,
                        None,
                        "OMP session is closed and cannot be interrupted.",
                        409,
                        error_code="process_identity_unverified",
                    )
                return
            if not reg:
                send_signal_result(
                    False,
                    None,
                    "No OMP control record exists for this session.",
                    404,
                    error_code="session_not_found",
                )
                return

            durable_broker_id = _durable_broker_id_from_registry_row(
                reg,
                provider="omp",
                native_id=native_id,
            )
            broker_session = _registry_owned_broker_session("omp", native_id, reg)
            if broker_session is None:
                if durable_broker_id:
                    send_signal_result(
                        False,
                        int(reg.get("pid") or 0) or None,
                        "OMP terminal broker is temporarily unavailable.",
                        503,
                        broker_id=durable_broker_id,
                        error_code="broker_unavailable",
                        pty_written=False,
                        write_outcome="none",
                    )
                    return

                current, pid, verification_error = _verified_session_signal_target(
                    "omp", native_id
                )
                if verification_error:
                    send_signal_result(
                        False,
                        pid or None,
                        "OMP process identity changed; refresh before sending control.",
                        409,
                        error_code="process_identity_unverified",
                    )
                    return

                ok = True
                err = None
                error_code = None
                outcome_indeterminate = False
                if sig == signal.SIGTERM:
                    mark_signal_running()
                    termination = _terminate_direct_session_process(
                        current or reg,
                        "omp",
                        pid,
                    )
                    ok = bool(termination.get("ok"))
                    err = termination.get("error")
                    error_code = termination.get("error_code")
                    outcome_indeterminate = bool(
                        termination.get("outcome_indeterminate")
                    )
                else:
                    try:
                        mark_signal_running()
                        os.kill(pid, sig)
                    except (ProcessLookupError, PermissionError, OSError) as exc:
                        ok = False
                        err = f"{type(exc).__name__}: {exc}"
                if ok:
                    _write_agent_turn_state(
                        "omp", native_id, "idle", event=sig_name.lower()
                    )
                if ok and sig == signal.SIGTERM:
                    _agent_registry_mark_closed("omp", native_id)
                send_signal_result(
                    ok,
                    pid,
                    err,
                    409
                    if error_code == "process_identity_unverified"
                    else (200 if ok else 502),
                    error_code=error_code,
                    outcome_indeterminate=outcome_indeterminate,
                )
                return

            broker_id = _broker_session_id(broker_session)
            if _broker_runtime_relation() != "current":
                send_signal_result(
                    False,
                    _broker_pid(broker_session) or None,
                    "OMP control requires the current terminal broker.",
                    409,
                    broker_id=broker_id,
                    error_code="broker_requires_current_runtime",
                    pty_written=False,
                    write_outcome="none",
                )
                return
            try:
                mark_signal_running()
                if sig == signal.SIGINT:
                    result = _broker_interrupt_for_draining_runtime(broker_id)
                else:
                    result = PTY_BROKER.terminate(broker_id, sig)
            except PTYBrokerOutcomeUnknownError as exc:
                send_signal_result(
                    False,
                    _broker_pid(broker_session) or None,
                    str(exc)[:200],
                    502,
                    broker_id=broker_id,
                    error_code="broker_signal_outcome_unknown",
                    pty_written=None,
                    write_outcome="unknown",
                    outcome_indeterminate=True,
                )
                return
            except Exception as exc:
                send_signal_result(
                    False,
                    _broker_pid(broker_session) or None,
                    str(exc)[:200],
                    503,
                    broker_id=broker_id,
                    error_code="broker_unavailable",
                    pty_written=False,
                    write_outcome="none",
                )
                return

            ok = bool(result.get("ok"))
            if ok:
                _write_agent_turn_state(
                    "omp",
                    native_id,
                    "idle",
                    event=sig_name.lower(),
                )
            if ok and sig == signal.SIGTERM:
                _agent_registry_mark_closed("omp", native_id)
            send_signal_result(
                ok,
                result.get("pid") or _broker_pid(broker_session),
                result.get("error") or result.get("reason"),
                200 if ok else int(result.get("status") or 502),
                broker_id=broker_id,
                error_code=result.get("error_code"),
                pty_written=(
                    bool(result.get("pty_written"))
                    if "pty_written" in result
                    else bool(ok and sig == signal.SIGINT)
                ),
                write_outcome=result.get("write_outcome"),
                outcome_indeterminate=bool(result.get("outcome_indeterminate")),
            )
            return

        if provider != "claude":
            _send_unsupported_provider(self, provider, sig_name.lower())
            return

        session_id = control_native_id
        if not session_id:
            self.send_error(400, "session required")
            return

        record = _claude_sessions_backend().session_record(session_id)
        broker_registry_row = _agent_registry_get("claude", session_id)
        if broker_registry_row is None:
            broker_registry_row = _agent_registry_row_for_broker_id(
                "claude",
                _qualified_session_id("claude", session_id),
            )
        durable_broker_id = _durable_broker_id_from_registry_row(
            broker_registry_row,
            provider="claude",
            native_id=session_id,
        )
        session_is_closed = bool(
            (record and record.get("closed_at") is not None)
            or (
                broker_registry_row
                and broker_registry_row.get("closed_at") is not None
            )
        )
        if session_is_closed:
            if sig == signal.SIGTERM:
                send_signal_result(True, None, None, 200, already_closed=True)
            else:
                send_signal_result(
                    False,
                    None,
                    "Claude session is closed and cannot be interrupted.",
                    409,
                    error_code="process_identity_unverified",
                )
            return
        broker_found = self._broker_session_for(_qualified_session_id("claude", session_id))
        if broker_found and PTY_BROKER:
            _, broker_session = broker_found
            broker_id = _broker_session_id(broker_session)
            if not _broker_session_owns_identity(broker_session, "claude", session_id):
                send_signal_result(
                    False,
                    _broker_pid(broker_session) or None,
                    "Claude broker ownership changed; refresh before sending control",
                    409,
                    broker_id=broker_id,
                    error_code="process_identity_unverified",
                )
                return
            broker_relation = _broker_runtime_relation()
            if sig == signal.SIGINT and broker_relation not in {"current", "stale_deferred"}:
                send_signal_result(
                    False,
                    _broker_pid(broker_session) or None,
                    "Interrupt requires an exactly identified current or draining terminal broker.",
                    409,
                    broker_id=broker_id,
                    error_code="broker_runtime_identity_unverified",
                    pty_written=False,
                    write_outcome="none",
                )
                return
            if sig != signal.SIGINT and broker_relation != "current":
                send_signal_result(
                    False,
                    _broker_pid(broker_session) or None,
                    "Termination requires the current terminal broker.",
                    409,
                    broker_id=broker_id,
                    error_code="broker_requires_current_runtime",
                    pty_written=False,
                    write_outcome="none",
                )
                return
            try:
                mark_signal_running()
                if sig == signal.SIGINT:
                    result = _broker_interrupt_for_draining_runtime(broker_id)
                else:
                    result = PTY_BROKER.terminate(broker_id, sig)
            except PTYBrokerOutcomeUnknownError as exc:
                send_signal_result(
                    False,
                    _broker_pid(broker_session) or None,
                    str(exc)[:200],
                    502,
                    broker_id=broker_id,
                    error_code="broker_signal_outcome_unknown",
                    pty_written=None,
                    write_outcome="unknown",
                    outcome_indeterminate=True,
                )
                return
            except Exception as exc:
                send_signal_result(
                    False,
                    _broker_pid(broker_session) or None,
                    str(exc)[:200],
                    503,
                    broker_id=broker_id,
                    error_code="broker_unavailable",
                    pty_written=False,
                    write_outcome="none",
                )
                return
            ok = bool(result.get("ok"))
            if ok and sig == signal.SIGTERM:
                self._mark_session_closed(session_id)
            send_signal_result(
                ok,
                result.get("pid") or _broker_pid(broker_session),
                result.get("error") or result.get("reason"),
                200 if ok else int(result.get("status") or 502),
                broker_id=broker_id,
                pty_written=(
                    bool(result.get("pty_written"))
                    if "pty_written" in result
                    else bool(ok and sig == signal.SIGINT)
                ),
                write_outcome=result.get("write_outcome"),
                outcome_indeterminate=bool(result.get("outcome_indeterminate")),
            )
            return

        if durable_broker_id:
            send_signal_result(
                False,
                int((broker_registry_row or {}).get("pid") or 0) or None,
                "Claude terminal broker is temporarily unavailable.",
                503,
                broker_id=durable_broker_id,
                error_code="broker_unavailable",
                pty_written=False,
                write_outcome="none",
            )
            return

        if not record:
            send_signal_result(False, None, "no claude_pid for session", 404)
            return
        pid = int(record.get("pid") or record.get("claude_pid") or 0)
        if not pid:
            send_signal_result(False, None, "no claude_pid for session", 404)
            return
        if not _session_signal_target_is_verified(record, "claude", pid):
            send_signal_result(
                False,
                pid,
                "Claude process identity changed; refresh before sending control",
                409,
                error_code="process_identity_unverified",
            )
            return

        ok = True
        err: str | None = None
        error_code: str | None = None
        if sig == signal.SIGTERM:
            mark_signal_running()
            termination = _terminate_direct_session_process(record, "claude", pid)
            ok = bool(termination.get("ok"))
            err = termination.get("error")
            error_code = termination.get("error_code")
            outcome_indeterminate = bool(termination.get("outcome_indeterminate"))
        else:
            outcome_indeterminate = False
            try:
                mark_signal_running()
                os.kill(pid, sig)
            except (ProcessLookupError, PermissionError, OSError) as e:
                ok = False
                err = f"{type(e).__name__}: {e}"
        if ok and sig == signal.SIGTERM:
            self._mark_session_closed(session_id)

        status = 409 if error_code == "process_identity_unverified" else (200 if ok else 502)
        send_signal_result(
            ok,
            pid,
            err,
            status,
            error_code=error_code,
            outcome_indeterminate=outcome_indeterminate,
        )

    # ----- /commands: snapshot catalog of slash commands across all sources -----
    def _handle_commands(self, q):
        """Returns the merged catalog of slash commands available to claude:
        built-ins (hardcoded) + ~/.claude/commands + <cwd>/.claude/commands +
        ~/.claude/plugins/.../commands + ~/.claude/skills/<n>/SKILL.md (where
        user-invocable is not explicitly false).

        iOS caches this catalog locally and filters on `/` keystroke. Pass
        `?cwd=<absolute-path>` to also include project-scoped commands.

        Future: SSE delta stream when files change. For v1 the phone fetches
        on session entry and pull-to-refresh.
        """
        cwd = q.get("cwd", [""])[0].strip()
        provider = q.get("provider", ["claude"])[0].lower()
        if not _valid_provider_filter(provider, allow_all=False):
            _send_unknown_provider(self, provider)
            return
        items = _build_command_catalog(cwd=cwd, provider=provider) if provider in _visible_agent_provider_ids() else []
        items, extras = _catalog_payload_extras(provider, items, _commands_signature(cwd, provider=provider))
        body = json.dumps({"count": len(items), "items": items, **extras}).encode()
        self.send_response(200)
        self.send_header("Content-Type", "application/json")
        self.send_header("Content-Length", str(len(body)))
        self.end_headers()
        self.wfile.write(body)

    # ----- /invocations: snapshot catalog of slash commands and dollar skills -----
    def _handle_invocations(self, q):
        cwd = q.get("cwd", [""])[0].strip()
        provider = q.get("provider", ["claude"])[0].lower()
        trigger = q.get("trigger", [""])[0].strip() or None
        if not _valid_provider_filter(provider, allow_all=False):
            _send_unknown_provider(self, provider)
            return
        if trigger is not None and trigger not in {"/", "$"}:
            self.send_error(400, "trigger must be / or $")
            return
        items = _build_invocation_catalog(cwd=cwd, provider=provider, trigger=trigger) if provider in _visible_agent_provider_ids() else []
        items, extras = _catalog_payload_extras(
            provider, items, _invocations_signature(cwd=cwd, provider=provider, trigger=trigger)
        )
        body = json.dumps({
            "schema_version": _INVOCATION_SCHEMA_VERSION,
            "provider": provider,
            "cwd": cwd,
            "count": len(items),
            "items": items,
            **extras,
        }).encode()
        self.send_response(200)
        self.send_header("Content-Type", "application/json")
        self.send_header("Content-Length", str(len(body)))
        self.end_headers()
        self.wfile.write(body)

    # ----- /tokens: aggregate input + output tokens from the session transcript -----
    def _handle_tokens(self, q):
        """Sum `usage.input_tokens` and `usage.output_tokens` across every
        assistant message in the transcript JSONL. iOS spinner polls this
        every ~8s while a turn is in flight to display the running token
        total Claude Code shows in its terminal status line.
        """
        session_id = q.get("session", [""])[0]
        session_id = _claude_native_session_id(session_id)
        if not session_id:
            self.send_error(400, "session required")
            return

        path = self._resolve_transcript(session_id)
        if path is None or not path.exists():
            self.send_error(404, "no transcript")
            return

        # Walk the JSONL backwards: sum tokens for the CURRENT TURN only —
        # everything since the most recent user prompt. Mirrors what Claude
        # Code shows in its terminal status line. Whole-session totals
        # ballooned numbers misleadingly (60k vs 14k for the actual turn).
        out_total = 0
        in_total = 0
        try:
            lines = _tail_lines(path, max_lines=1000, max_bytes=TRANSCRIPT_STATS_MAX_SCAN_BYTES)
        except OSError:
            lines = []
        for raw in reversed(lines):
            if not raw.strip():
                continue
            try:
                obj = json.loads(raw)
            except (ValueError, json.JSONDecodeError):
                continue
            msg = obj.get("message") or {}
            role = msg.get("role")
            usage = msg.get("usage") or obj.get("usage") or {}
            # Stop at the most recent user prompt — that boundary is "turn start".
            if role == "user" and obj.get("type") == "user":
                break
            if not isinstance(usage, dict):
                continue
            out_total += int(usage.get("output_tokens") or 0)
            in_total += int(usage.get("input_tokens") or 0)

        body = json.dumps({
            "ok": True,
            "input_tokens": in_total,
            "output_tokens": out_total,
            "total": in_total + out_total,
        }).encode()
        self.send_response(200)
        self.send_header("Content-Type", "application/json")
        self.send_header("Content-Length", str(len(body)))
        self.end_headers()
        self.wfile.write(body)

    # ----- /provider-status: provider-level health for Tools tab -----
    def _handle_provider_status(self, q):
        provider = q.get("provider", ["all"])[0].lower()
        registered_ids = set(_provider_registry_ids() if _provider_registry_ids else AGENT_PROVIDERS)
        known_ids = set(_provider_known_ids() if _provider_known_ids else registered_ids)
        if provider != "all" and provider not in registered_ids:
            self._send_json({
                "ok": False,
                "error": {
                    "code": "unknown_provider",
                    "message": f"Unknown provider: {provider}",
                    "known_providers": sorted(registered_ids),
                    "known_future_providers": sorted(known_ids - registered_ids),
                },
            }, status=400)
            return

        def config_default_model(path: Path) -> str | None:
            if not path.is_file():
                return None
            try:
                text = path.read_text(errors="replace")
            except OSError:
                return None
            # Handles JSON-ish and TOML-ish config without adding a parser dependency.
            for key in ("model", "default_model", "MODEL"):
                m = re.search(rf'(?m)^\s*["\']?{re.escape(key)}["\']?\s*[:=]\s*["\']([^"\']+)["\']', text)
                if m:
                    return m.group(1).strip()[:80]
            return None

        def default_model_payload(path: Path) -> tuple[str | None, bool | None, str | None]:
            model = config_default_model(path)
            if not model:
                return None, None, None
            shorthand = model.lower() in {"opus", "sonnet", "haiku"}
            return model, not shorthand, "config"

        def exact_model_from_claude_sessions(family: str | None) -> str | None:
            if not family:
                return None
            wanted = family.lower()
            for state_path in sorted((HOME / ".claude" / "turn-state").glob("*.json"), key=lambda p: p.stat().st_mtime if p.exists() else 0, reverse=True):
                try:
                    obj = json.loads(state_path.read_text(errors="replace"))
                except Exception:
                    continue
                model = obj.get("model")
                if isinstance(model, str) and model and wanted in model.lower() and model.lower() != wanted:
                    return model[:120]
            for row in self._collect_session_rows(since_min=60 * 24 * 7, live_only=False, limit=100, include_first_prompt=False):
                sid = row.get("id")
                if not sid:
                    continue
                path = self._resolve_transcript(sid)
                if not path or not path.exists():
                    continue
                try:
                    lines = _tail_lines(path, max_lines=400, max_bytes=TRANSCRIPT_TAIL_SCAN_BYTES)
                except OSError:
                    continue
                for raw in reversed(lines):
                    try:
                        obj = json.loads(raw)
                    except Exception:
                        continue
                    msg = obj.get("message") or {}
                    model = msg.get("model")
                    if isinstance(model, str) and model and wanted in model.lower() and model.lower() != wanted:
                        return model[:120]
            aliases = {
                "opus": "claude-opus-4-7",
                "sonnet": "claude-sonnet-4-6",
                "haiku": "claude-haiku-4-5",
            }
            return aliases.get(wanted)

        def resolve_default_model_payload(provider_name: str, path: Path) -> tuple[str | None, bool | None, str | None]:
            model, is_exact, source = default_model_payload(path)
            if provider_name == "claude" and model and is_exact is False:
                exact = exact_model_from_claude_sessions(model)
                if exact:
                    return exact, True, "observed-session+config"
            return model, is_exact, source

        def registry_total(provider_name: str) -> int:
            try:
                with _agent_registry_conn() as conn:
                    cur = conn.execute("SELECT COUNT(*) FROM agent_sessions WHERE provider = ?", (provider_name,))
                    return int(cur.fetchone()[0] or 0)
            except Exception:
                return 0

        if _provider_probe_all is None or provider_detail_payload is None or provider_snapshot_payload is None:
            self._send_json({
                "ok": False,
                "error": {
                    "code": "provider_registry_unavailable",
                    "message": "Provider registry is unavailable",
                },
            }, status=503)
            return

        cache_key = ("provider-status", str(HOME), provider)
        def load_provider_status() -> dict:
            results = _cached_runtime_snapshot(
                ("provider-probe-all", str(HOME), provider),
                PROVIDER_STATUS_CACHE_SECONDS,
                lambda: _provider_probe_all(provider_filter=provider, home=HOME),
            )
            enriched_results = []
            default_models: dict[str, tuple[str | None, bool | None, str | None]] = {}
            for result in results:
                provider_name = result.availability.provider_id
                if provider_name == "claude":
                    rows = self._collect_session_rows(since_min=60 * 24, live_only=True, limit=200, include_first_prompt=False)
                    readable_rows = self._collect_session_rows(since_min=60 * 24, live_only=False, limit=200, include_first_prompt=False)
                    config_path = HOME / ".claude" / "settings.json"
                    default_model, default_model_is_exact, default_model_source = resolve_default_model_payload("claude", config_path)
                    default_models[provider_name] = (default_model, default_model_is_exact, default_model_source)
                    result = result.with_availability(
                        readable_sessions=len(readable_rows),
                        live_sessions=len(rows),
                        controllable_sessions=sum(1 for r in rows if r.get("claude_pid")),
                    ).with_diagnostics(
                        registry_count=None,
                        registry_live_count=None,
                    )
                elif provider_name == "codex":
                    config_path = HOME / ".codex" / "config.toml"
                    codex_rows = _list_codex_sessions(live_only=False, active_within_min=60 * 24)
                    live_codex_rows = _list_codex_sessions(live_only=True, active_within_min=60 * 24)
                    live_registry = _agent_registry_live("codex")
                    default_model, default_model_is_exact, default_model_source = resolve_default_model_payload("codex", config_path)
                    default_models[provider_name] = (default_model, default_model_is_exact, default_model_source)
                    result = result.with_availability(
                        readable_sessions=len(codex_rows),
                        live_sessions=len(live_codex_rows),
                        controllable_sessions=sum(1 for r in codex_rows if (r.get("controllability") or {}).get("can_send_text")),
                    ).with_diagnostics(
                        registry_count=registry_total("codex"),
                        registry_live_count=len(live_registry),
                    )
                enriched_results.append(result)

            spawn_contract_by_id = {
                result.availability.provider_id:
                    _provider_spawn_contract(result)
                for result in enriched_results
            }
            providers: list[dict] = []
            for result in enriched_results:
                payload = provider_detail_payload(result)
                default_model, default_model_is_exact, default_model_source = default_models.get(result.availability.provider_id, (None, None, None))
                payload["default_model"] = default_model
                payload["default_model_is_exact"] = default_model_is_exact
                payload["default_model_source"] = default_model_source
                (
                    spawn_backends,
                    spawn_profiles,
                    spawn_setup_diagnostics,
                ) = spawn_contract_by_id.get(
                    result.availability.provider_id, ([], [], [])
                )
                payload["spawn_backends"] = list(spawn_backends)
                payload["spawn_profiles"] = list(spawn_profiles)
                payload["spawn_setup_diagnostics"] = list(
                    spawn_setup_diagnostics
                )
                providers.append(payload)

            ts = _time.time()
            payload = {
                "ok": True,
                "schema_version": 2,
                "providers": providers,
                "snapshot": provider_snapshot_payload(enriched_results, observed_at=ts),
                "ts": ts,
            }
            # Visibility + depth annotation (SPEC-p1 §2.2/§2.3). Excluded
            # providers STAY in the payload — the Settings screen needs the row
            # to offer the toggle back on; exclusion hides sessions, not truth.
            excluded_set = _excluded_provider_ids()
            depth_by_id = {
                result.availability.provider_id: getattr(result.descriptor, "adapter_depth", "deep")
                for result in enriched_results
            }
            for row in list(payload["providers"]) + list(payload["snapshot"].get("providers") or []):
                row_id = str(row.get("provider_id") or row.get("provider") or "")
                row["included"] = row_id not in excluded_set
                (
                    spawn_backends,
                    spawn_profiles,
                    spawn_setup_diagnostics,
                ) = spawn_contract_by_id.get(row_id, ([], [], []))
                row["spawn_backends"] = list(spawn_backends)
                row["spawn_profiles"] = list(spawn_profiles)
                row["spawn_setup_diagnostics"] = list(
                    spawn_setup_diagnostics
                )
                row["adapter_depth"] = depth_by_id.get(row_id, "deep")
            payload["excluded"] = sorted(excluded_set)
            return payload

        payload = _cached_runtime_snapshot(
            cache_key,
            PROVIDER_STATUS_CACHE_SECONDS,
            load_provider_status,
        )
        self._send_json(payload)

    # ----- /power-state: the keep-awake truth (SPEC-p7 §2.3) -----
    def _handle_power_state(self, q):
        manager = _KEEP_AWAKE
        keep_awake = manager.status() if manager is not None else {
            "enabled": False,
            "active": False,
            "reasons": {},
            "since": None,
            "caffeinate_pid": None,
            "linger_seconds": None,
            "trace": [],
        }
        self._send_json({
            "ok": True,
            "schema_version": 1,
            "keep_awake": keep_awake,
            "ts": _time.time(),
        })

    # ----- /provider-controls/*: reviewed structured provider controls -----
    def _provider_control_target(self, raw_session: str) -> dict | None:
        try:
            target = _PROVIDER_CONTROL_TARGET_RESOLVER(self, raw_session)
        except _ProviderControlRouteError as exc:
            _provider_control_send_error(self, exc)
            return None
        if not isinstance(target, dict):
            _provider_control_send_error(
                self,
                _ProviderControlRouteError(
                    "provider_target_invalid",
                    "provider session resolution returned invalid truth",
                    status=503,
                ),
            )
            return None
        return target

    def _handle_provider_controls_snapshot(self, q) -> None:
        raw_session = str(q.get("session_id", [""])[0] or "").strip()
        target = self._provider_control_target(raw_session)
        if target is None:
            return
        try:
            envelope = _provider_control_snapshot_envelope(target)
        except _ProviderControlRouteError as exc:
            _provider_control_send_error(self, exc)
            return
        self._send_json(envelope)

    @staticmethod
    def _provider_control_event_batch(driver, cursor):
        poll = getattr(driver, "poll_events", None)
        if not callable(poll):
            return (), cursor
        try:
            raw = poll(cursor)
        except (TypeError, ValueError):
            if cursor in (None, "", 0):
                raise
            raw = poll(0)
        next_cursor = cursor
        if isinstance(raw, dict):
            events = raw.get("events")
            next_cursor = raw.get("provider_cursor", cursor)
        else:
            events = raw
        if not isinstance(events, (list, tuple)):
            return (), cursor
        return tuple(events[:256]), next_cursor

    @staticmethod
    def _provider_control_public_event(target: dict, event) -> tuple[dict, str] | None:
        if not isinstance(event, dict):
            return None
        if (
            event.get("provider_id") not in {None, target["provider_id"]}
            or event.get("session_id") not in {None, target["session_id"]}
        ):
            return None
        binding_id = event.get("binding_id")
        expected_binding = target["session_truth"].get("binding_id")
        if binding_id not in {None, expected_binding}:
            return None
        provider_cursor = str(
            event.get("provider_cursor")
            or event.get("cursor")
            or ""
        ).strip()
        if not provider_cursor or len(provider_cursor) > 512:
            return None
        try:
            public = _provider_control_public_json(event)
        except _ProviderControlRouteError:
            return None
        if not isinstance(public, dict):
            return None
        return public, provider_cursor

    def _handle_provider_controls_stream(self, q) -> None:
        raw_session = str(q.get("session_id", [""])[0] or "").strip()
        target = self._provider_control_target(raw_session)
        if target is None:
            return
        try:
            initial = _provider_control_snapshot_envelope(target)
        except _ProviderControlRouteError as exc:
            _provider_control_send_error(self, exc)
            return

        self.send_response(200)
        self.send_header("Content-Type", "text/event-stream")
        self.send_header("Cache-Control", "no-store")
        self.send_header("Connection", "keep-alive")
        self.send_header("X-Accel-Buffering", "no")
        self.end_headers()
        self.close_connection = True

        started_at = _time.monotonic()
        last_keepalive = started_at
        last_semantic_hash = initial["content_hash"]
        next_freshness_emission_at = _provider_control_snapshot_renewal_at(initial)
        provider_cursor = initial["status"].get("provider_cursor")
        driver = target["driver"]
        try:
            if not _sse_write_json_event(
                self.wfile,
                "snapshot",
                initial,
                max_bytes=SSE_MAX_EVENT_BYTES,
            ):
                return
            while _time.monotonic() - started_at < PROVIDER_CONTROL_STREAM_SECONDS:
                if not self._stream_authorization_is_current():
                    return
                events, batch_cursor = self._provider_control_event_batch(
                    driver,
                    provider_cursor,
                )
                for event in events:
                    normalized = self._provider_control_public_event(target, event)
                    if normalized is None:
                        continue
                    public_event, event_cursor = normalized
                    provider_cursor = event_cursor
                    payload = {
                        "schema_version": PROVIDER_CONTROL_SCHEMA_VERSION,
                        "session_id": target["session_id"],
                        "provider_id": target["provider_id"],
                        "provider_cursor": event_cursor,
                        "event": public_event,
                    }
                    if not _sse_write_json_event(
                        self.wfile,
                        "provider_event",
                        payload,
                        max_bytes=SSE_MAX_EVENT_BYTES,
                    ):
                        return
                if batch_cursor not in (None, ""):
                    provider_cursor = str(batch_cursor)

                current = _provider_control_snapshot_envelope(target)
                semantic_changed = (
                    current["content_hash"] != last_semantic_hash
                )
                freshness_due = (
                    _time.time() >= next_freshness_emission_at
                )
                if semantic_changed or freshness_due:
                    if not _sse_write_json_event(
                        self.wfile,
                        "snapshot",
                        current,
                        max_bytes=SSE_MAX_EVENT_BYTES,
                    ):
                        return
                    last_semantic_hash = current["content_hash"]
                    next_freshness_emission_at = (
                        _provider_control_snapshot_renewal_at(current)
                    )
                    provider_cursor = current["status"].get(
                        "provider_cursor",
                        provider_cursor,
                    )
                now = _time.monotonic()
                if now - last_keepalive >= PROVIDER_CONTROL_STREAM_KEEPALIVE_SECONDS:
                    self.wfile.write(b": keepalive\n\n")
                    self.wfile.flush()
                    last_keepalive = now
                renewal_delay = max(
                    0.01,
                    next_freshness_emission_at - _time.time(),
                )
                _time.sleep(
                    min(
                        PROVIDER_CONTROL_STREAM_POLL_SECONDS,
                        renewal_delay,
                    )
                )
        except (BrokenPipeError, ConnectionResetError, ClientDisconnected):
            return
        except Exception as exc:
            error = (
                _provider_control_contract_error(exc)
                if isinstance(exc, _ProviderControlContractError)
                else {
                    "code": "provider_stream_unavailable",
                    "message": "provider control stream stopped",
                }
            )
            _sse_write_json_event(
                self.wfile,
                "error",
                {"ok": False, "error": error},
                max_bytes=SSE_MAX_EVENT_BYTES,
            )
        _sse_write_json_event(
            self.wfile,
            "done",
            {"schema_version": PROVIDER_CONTROL_SCHEMA_VERSION},
            max_bytes=SSE_MAX_EVENT_BYTES,
        )

    def _provider_control_definition(self, operation_id: str):
        if _PROVIDER_CONTROL_SERVICE is None:
            raise _ProviderControlRouteError(
                "provider_controls_unavailable",
                "provider operation catalog is unavailable",
                status=503,
            )
        try:
            return _PROVIDER_CONTROL_SERVICE.definition(operation_id)
        except _ProviderControlServiceError as exc:
            raise _ProviderControlRouteError(
                exc.code,
                exc.message,
                status=exc.status,
            ) from exc

    def _provider_control_require_operation_scope(self, definition) -> None:
        if _PROVIDER_CONTROL_SERVICE is None:
            raise _ProviderControlRouteError(
                "provider_controls_unavailable",
                "provider operation catalog is unavailable",
                status=503,
            )
        granted = (
            getattr(getattr(self, "pairling_auth", None), "scopes", ())
            or ()
        )
        try:
            _PROVIDER_CONTROL_SERVICE.require_operation_scope(
                definition,
                granted,
            )
        except _ProviderControlServiceError as exc:
            raise _ProviderControlRouteError(
                exc.code,
                exc.message,
                status=exc.status,
            ) from exc

    @staticmethod
    def _provider_control_normalized_input(definition, request: dict) -> dict:
        if _PROVIDER_CONTROL_SERVICE is None:
            raise _ProviderControlRouteError(
                "provider_controls_unavailable",
                "provider operation catalog is unavailable",
                status=503,
            )
        try:
            return _PROVIDER_CONTROL_SERVICE.normalize_input(
                definition,
                request["input"],
            )
        except _ProviderControlServiceError as exc:
            raise _ProviderControlRouteError(
                exc.code,
                exc.message,
                status=exc.status,
            ) from exc


    @staticmethod
    def _provider_control_preflight(
        target: dict,
        definition,
        request: dict,
        normalized_input: dict,
    ):
        if _PROVIDER_CONTROL_SERVICE is None:
            raise _ProviderControlRouteError(
                "provider_controls_unavailable",
                "provider control contracts are unavailable",
                status=503,
            )
        try:
            prepared = _PROVIDER_CONTROL_SERVICE.preflight(
                target,
                definition,
                request,
                normalized_input,
            )
        except _ProviderControlServiceError as exc:
            raise _ProviderControlRouteError(
                exc.code,
                exc.message,
                status=exc.status,
            ) from exc
        return prepared

    @staticmethod
    def _provider_control_result_fields(
        *,
        target: dict,
        operation_id: str,
        client_action_id: str,
        result_payload: dict,
        ok: bool,
        deduped: bool = False,
    ) -> dict:
        return {
            "ok": bool(ok),
            "schema_version": PROVIDER_CONTROL_SCHEMA_VERSION,
            "session_id": target["session_id"],
            "provider_id": target["provider_id"],
            "operation_id": operation_id,
            "result": _provider_control_public_json(result_payload),
            "receipt": None,
            "confirmation": None,
            "deduped": bool(deduped),
            "client_action_id": client_action_id,
        }

    @staticmethod
    def _provider_control_outcome(status) -> tuple[bool, int, str, str | None]:
        if _PROVIDER_CONTROL_SERVICE is None:
            return False, 503, "indeterminate", "provider_controls_unavailable"
        return _PROVIDER_CONTROL_SERVICE.outcome(status)

    def _provider_control_finalize_error(
        self,
        context: dict | None,
        error: dict,
        *,
        audit_type: str,
    ) -> None:
        if context is None:
            self._send_json(
                {"ok": False, "error": {
                    "code": error["code"],
                    "message": error["message"],
                }},
                status=int(error["status"]),
            )
            return
        running = bool(context.get("running_committed"))
        state = "indeterminate" if running else "rejected"
        error_code = (
            "action_outcome_unknown"
            if running and error["code"] != "provider_operation_rejected"
            else error["code"]
        )
        receipt = _finalize_receipted_mutation(
            context,
            state=state,
            http_status=int(error["status"]),
            backend="provider-control",
            error_code=error_code,
            error_message=error["message"],
            audit_action={
                "type": audit_type,
                "error_code": error_code,
            },
            pty_written=False,
        )
        self._send_json(
            {
                "ok": False,
                "receipt": receipt,
                "error": {
                    "code": error_code,
                    "message": error["message"],
                },
            },
            status=int(error["status"]),
        )

    def _provider_control_recovery(
        self,
        *,
        target: dict,
        operation_id: str,
    ):
        def recover(context: dict):
            if (
                _PROVIDER_CONTROL_SERVICE is None
                or _ProviderOperationCorrelation is None
                or target.get("driver") is None
            ):
                return None
            server_binding = target["driver"].binding
            if (
                context.get("provider_id") != server_binding.provider_id
                or context.get("provider_version") != server_binding.provider_version
                or context.get("provider_channel") != server_binding.provider_channel
                or context.get("operation_id") != operation_id
                or context.get("binding_id") != server_binding.binding_id
                or context.get("capability_generation")
                != target["session_truth"].get("capability_generation")
            ):
                return None
            raw_correlation = context.get("recovery_correlation") or {}
            try:
                correlation = _ProviderOperationCorrelation(
                    provider_operation_id=str(
                        raw_correlation.get("provider_operation_id") or ""
                    ),
                    provider_cursor=raw_correlation.get("provider_cursor"),
                )
                recovery_target = dict(target)
                if operation_id == "session.fork":
                    # ManagedProviderSessionManager owns prepared-fork
                    # reconciliation and must register the child exactly once.
                    recovery_target["manager"] = None
                execution = _PROVIDER_CONTROL_SERVICE.recover(
                    recovery_target,
                    operation_id=operation_id,
                    binding_id=str(context["binding_id"]),
                    capability_generation=int(context["capability_generation"]),
                    client_action_id=str(context["client_action_id"]),
                    correlation=correlation,
                )
            except Exception:
                return None
            if execution is None:
                return None
            ok, http_status, state, error_code = self._provider_control_outcome(
                execution.result.status
            )
            if state == "indeterminate":
                return None
            fields = self._provider_control_result_fields(
                target=target,
                operation_id=operation_id,
                client_action_id=str(context["client_action_id"]),
                result_payload=execution.result_payload,
                ok=ok,
            )
            fields.pop("deduped", None)
            receipt = _make_action_receipt(
                client_action_id=str(context["client_action_id"]),
                state=state,
                deduped=True,
                phases=_receipt_phases(
                    validated=True,
                    applied=state == "applied",
                    pty_written=False,
                ),
                backend="provider-control",
            )
            return _receipt_attach_response(
                receipt,
                http_status=http_status,
                error_code=error_code,
                error_message=(
                    "provider rejected the operation" if error_code else None
                ),
                fields=fields,
            )

        return recover

    def _provider_control_prepare_confirmation_resources(
        self,
        *,
        normalized_input: dict,
        execution_session_id: str | None,
        binding_id: str,
        client_action_id: str,
    ) -> tuple:
        records = normalized_input.get("attachments")
        if not records:
            return ()
        if execution_session_id is None:
            raise _ProviderControlRouteError(
                "attachment_proof_invalid",
                "attachment resource proof could not be validated",
                status=409,
            )
        source_device_id, source_install_id = (
            _provider_control_confirmation_identity(self)
        )
        try:
            return tuple(
                self._pairdrop_store().prepare_attachment_handles(
                    records,
                    session_id=execution_session_id,
                    source_device_id=source_device_id,
                    source_install_id=source_install_id,
                    binding_id=binding_id,
                    client_action_id=client_action_id,
                )
            )
        except Exception as exc:
            error = _provider_control_attachment_error(exc)
            raise _ProviderControlRouteError(
                error["code"],
                error["message"],
                status=error["status"],
            ) from exc


    def _handle_provider_controls_execute(self, q) -> None:
        del q
        try:
            payload = json.loads(self._read_body() or b"{}")
        except (TypeError, ValueError, json.JSONDecodeError):
            self._send_json(
                {"ok": False, "error": {
                    "code": "bad_json",
                    "message": "request body must be one JSON object",
                }},
                status=400,
            )
            return
        required_fields = {
            "session_id",
            "provider_id",
            "binding_id",
            "capability_generation",
            "operation_id",
            "capability_graph_digest",
            "implementation_operation_id",
            "semantic_digest",
            "input",
            "client_action_id",
            "confirmation_challenge",
        }
        if not isinstance(payload, dict) or set(payload) != required_fields:
            self._send_json(
                {"ok": False, "error": {
                    "code": "invalid_request",
                    "message": "provider control request fields are invalid",
                }},
                status=400,
            )
            return
        if (
            not all(
                isinstance(payload.get(key), str) and bool(payload[key].strip())
                for key in (
                    "session_id",
                    "provider_id",
                    "binding_id",
                    "operation_id",
                    "client_action_id",
                    "capability_graph_digest",
                    "implementation_operation_id",
                    "semantic_digest",
                )
            )
            or not isinstance(payload.get("input"), dict)
            or not isinstance(payload.get("capability_generation"), int)
            or isinstance(payload.get("capability_generation"), bool)
            or payload["capability_generation"] <= 0
            or (
                payload.get("confirmation_challenge") is not None
                and (
                    not isinstance(payload["confirmation_challenge"], str)
                    or not payload["confirmation_challenge"]
                )
            )
        ):
            self._send_json(
                {"ok": False, "error": {
                    "code": "invalid_request",
                    "message": "provider control request values are invalid",
                }},
                status=400,
            )
            return
        header_action_id = str(
            self.headers.get("X-Pairling-Action-Id") or ""
        ).strip()
        if (
            not _valid_client_action_id(payload["client_action_id"])
            or payload["client_action_id"] != header_action_id
        ):
            self._send_json(
                {"ok": False, "error": {
                    "code": "action_id_mismatch",
                    "message": (
                        "client_action_id must equal a valid "
                        "X-Pairling-Action-Id"
                    ),
                }},
                status=400,
            )
            return
        try:
            _requested_session, requested_provider, _native_id = (
                _provider_control_exact_session_id(payload["session_id"])
            )
        except _ProviderControlRouteError as exc:
            _provider_control_send_error(self, exc)
            return
        if payload["provider_id"].strip().lower() != requested_provider:
            self._send_json(
                {"ok": False, "error": {
                    "code": "provider_mismatch",
                    "message": (
                        "provider_id does not match the provider-qualified "
                        "session_id"
                    ),
                }},
                status=409,
            )
            return

        try:
            definition = self._provider_control_definition(
                payload["operation_id"]
            )
            self._provider_control_require_operation_scope(definition)
            normalized_input = self._provider_control_normalized_input(
                definition,
                payload,
            )
            source_device_id, profile_install_id = (
                _provider_control_confirmation_identity(self)
            )
        except _ProviderControlRouteError as exc:
            _provider_control_send_error(self, exc)
            return

        confirmation_requirement = str(
            getattr(
                definition.confirmation_requirement,
                "value",
                definition.confirmation_requirement,
            )
        )
        confirmation_artifact = payload["confirmation_challenge"]
        is_mutation = str(
            getattr(definition.risk, "value", definition.risk)
        ) != "read"
        confirmed_mutation = bool(
            is_mutation
            and confirmation_requirement != "none"
            and confirmation_artifact is not None
        )
        receipt_scope = (
            _session_mutation_receipt_scope(self, _requested_session)
            or _requested_session
        )
        receipt_material = {
            "session_id": receipt_scope,
            "provider_id": requested_provider,
            "binding_id": payload["binding_id"],
            "capability_generation": payload["capability_generation"],
            "operation_id": payload["operation_id"],
            "capability_graph_digest": payload["capability_graph_digest"],
            "implementation_operation_id": (
                payload["implementation_operation_id"]
            ),
            "semantic_digest": payload["semantic_digest"],
            "input": normalized_input,
            "client_action_id": payload["client_action_id"],
        }
        if confirmed_mutation:
            stored_receipt, conflict = _receipt_duplicate_response(
                source_device_id,
                receipt_scope,
                payload["client_action_id"],
                _receipt_body_hash(receipt_material),
                action_kind=f"provider_control:{payload['operation_id']}",
                reserve_missing=False,
                defer_running=True,
            )
            if _send_receipted_mutation_duplicate(
                self,
                stored_receipt,
                conflict,
            ):
                return

        target = self._provider_control_target(payload["session_id"])
        if target is None:
            return
        if payload["provider_id"].strip().lower() != target["provider_id"]:
            self._send_json(
                {"ok": False, "error": {
                    "code": "provider_mismatch",
                    "message": "provider_id does not match daemon session truth",
                }},
                status=409,
            )
            return

        receipt_scope = target["session_id"]
        receipt_material = {
            **receipt_material,
            "session_id": receipt_scope,
            "provider_id": target["provider_id"],
        }
        recover_uncertain = self._provider_control_recovery(
            target=target,
            operation_id=payload["operation_id"],
        )
        if confirmed_mutation:
            stored_receipt, conflict = _receipt_duplicate_response(
                source_device_id,
                receipt_scope,
                payload["client_action_id"],
                _receipt_body_hash(receipt_material),
                action_kind=f"provider_control:{payload['operation_id']}",
                recover_uncertain=recover_uncertain,
                reserve_missing=False,
            )
            if _send_receipted_mutation_duplicate(
                self,
                stored_receipt,
                conflict,
            ):
                return

        managed_manager = target.get("manager")
        if (
            payload["operation_id"] == "session.fork"
            and managed_manager is None
        ):
            _provider_control_send_error(
                self,
                _ProviderControlRouteError(
                    "unsupported_lifecycle",
                    "session.fork requires a managed provider session owner",
                    status=409,
                ),
            )
            return

        try:
            prepared = self._provider_control_preflight(
                target,
                definition,
                payload,
                normalized_input,
            )
            normalized_input = prepared.normalized_input
            execution_session_id = prepared.execution_session_id
            input_hash = _provider_control_canonical_input_hash(normalized_input)
        except _ProviderControlRouteError as exc:
            _provider_control_send_error(self, exc)
            return

        prepared_attachments = None
        challenge_binding = {
            "device_id": source_device_id,
            "profile_install_id": profile_install_id,
            "provider_id": target["provider_id"],
            "session_id": target["session_id"],
            "binding_id": payload["binding_id"],
            "capability_generation": payload["capability_generation"],
            "operation_id": payload["operation_id"],
            "capability_graph_digest": payload["capability_graph_digest"],
            "implementation_operation_id": (
                payload["implementation_operation_id"]
            ),
            "semantic_digest": payload["semantic_digest"],
            "input_hash": input_hash,
            "client_action_id": payload["client_action_id"],
        }
        if confirmation_requirement == "none":
            if confirmation_artifact is not None:
                _provider_control_send_error(
                    self,
                    _ProviderControlRouteError(
                        "confirmation_challenge_unexpected",
                        "this provider operation does not accept confirmation",
                        status=400,
                    ),
                )
                return
        elif confirmation_artifact is None:
            try:
                resources = self._provider_control_prepare_confirmation_resources(
                    normalized_input=normalized_input,
                    execution_session_id=execution_session_id,
                    binding_id=payload["binding_id"],
                    client_action_id=payload["client_action_id"],
                )
                action = _provider_control_confirmation_action(
                    target,
                    definition,
                    normalized_input,
                )
                artifact, expires_at = _provider_control_confirmation_issue(
                    challenge_binding,
                    prepared_attachments=resources,
                )
            except _ProviderControlRouteError as exc:
                _provider_control_send_error(self, exc)
                return
            self._send_json(
                {
                    "ok": True,
                    "schema_version": PROVIDER_CONTROL_SCHEMA_VERSION,
                    "session_id": target["session_id"],
                    "provider_id": target["provider_id"],
                    "operation_id": payload["operation_id"],
                    "result": None,
                    "receipt": None,
                    "confirmation": {
                        "artifact": artifact,
                        "expires_at": expires_at,
                        "action": action,
                    },
                    "deduped": False,
                    "client_action_id": payload["client_action_id"],
                },
                status=200,
            )
            return
        else:
            try:
                prepared_attachments = _provider_control_confirmation_consume(
                    confirmation_artifact,
                    challenge_binding,
                )
            except _ProviderControlRouteError as exc:
                _provider_control_send_error(self, exc)
                return

        context = None
        if is_mutation:
            context = _begin_receipted_mutation(
                self,
                receipt_scope=target["session_id"],
                action_kind=f"provider_control:{payload['operation_id']}",
                material=receipt_material,
                action_label="provider control",
                recover_uncertain=recover_uncertain,
            )
            if context is None:
                return
        if _PROVIDER_CONTROL_SERVICE is None:
            self._provider_control_finalize_error(
                context,
                {
                    "code": "provider_controls_unavailable",
                    "message": "provider control contracts are unavailable",
                    "status": 503,
                },
                audit_type="provider_control_reservation_failed",
            )
            return
        try:
            reservation = _PROVIDER_CONTROL_SERVICE.reserve_operation(
                prepared,
                client_action_id=payload["client_action_id"],
            )
        except _ProviderControlServiceError as exc:
            self._provider_control_finalize_error(
                context,
                {
                    "code": exc.code,
                    "message": exc.message,
                    "status": exc.status,
                },
                audit_type="provider_control_reservation_failed",
            )
            return
        operation_correlation = reservation.correlation
        deterministic_operation_id = (
            str(operation_correlation.provider_operation_id)
            if operation_correlation is not None
            else None
        )
        if context is not None and operation_correlation is None:
            self._provider_control_finalize_error(
                context,
                {
                    "code": "provider_operation_correlation_unavailable",
                    "message": (
                        "provider cannot reserve an exact operation identity"
                    ),
                    "status": 503,
                },
                audit_type="provider_control_reservation_failed",
            )
            return

        server_binding = target["driver"].binding
        before_execute = None
        if context is not None:
            before_execute = lambda: _mark_receipted_mutation_running(
                context,
                provider_id=server_binding.provider_id,
                provider_version=server_binding.provider_version,
                provider_channel=server_binding.provider_channel,
                operation_id=payload["operation_id"],
                binding_id=server_binding.binding_id,
                capability_generation=prepared.status["capability_generation"],
                recovery_correlation={
                    "provider_operation_id": deterministic_operation_id,
                    "provider_cursor": operation_correlation.provider_cursor,
                },
            )
        try:
            execution = _PROVIDER_CONTROL_SERVICE.execute(
                prepared,
                reservation,
                confirmation_verified=confirmation_requirement != "none",
                before_execute=before_execute,
                prepared_attachments=prepared_attachments,
                attachment_resolver=(
                    self._pairdrop_store()
                    if prepared_attachments is None
                    else None
                ),
                source_device_id=source_device_id,
                source_install_id=profile_install_id,
            )
            result = execution.result
            result_payload = _provider_control_public_json(
                execution.result_payload
            )
        except _ProviderControlServiceError as exc:
            error = {
                "code": exc.code,
                "message": exc.message,
                "status": exc.status,
            }
            if (
                context is not None
                and context.get("running_committed")
                and exc.code != "provider_operation_rejected"
            ):
                error = {
                    "code": "action_outcome_unknown",
                    "message": "provider execution outcome could not be validated",
                    "status": 409,
                }
            self._provider_control_finalize_error(
                context,
                error,
                audit_type="provider_control_execution_failed",
            )
            return
        except Exception:
            self._provider_control_finalize_error(
                context,
                {
                    "code": "action_outcome_unknown",
                    "message": "provider execution outcome is unknown",
                    "status": 409,
                },
                audit_type="provider_control_execution_failed",
            )
            return

        ok, http_status, state, error_code = self._provider_control_outcome(
            result.status
        )
        fields = self._provider_control_result_fields(
            target=target,
            operation_id=payload["operation_id"],
            client_action_id=payload["client_action_id"],
            result_payload=result_payload,
            ok=ok,
        )
        response = dict(fields)
        if context is not None:
            receipt_fields = dict(fields)
            receipt_fields.pop("deduped", None)
            receipt_fields["provider_operation_id"] = (
                operation_correlation.provider_operation_id
            )
            receipt_fields["provider_cursor"] = (
                operation_correlation.provider_cursor
            )
            receipt = _finalize_receipted_mutation(
                context,
                state=state,
                http_status=http_status,
                backend="provider-control",
                error_code=error_code,
                error_message=(
                    "provider rejected the operation"
                    if error_code == "provider_operation_rejected"
                    else (
                        "provider execution outcome is unknown"
                        if error_code
                        else None
                    )
                ),
                fields=receipt_fields,
                audit_action={
                    "type": "provider_control_completed",
                    "provider_id": target["provider_id"],
                    "operation_id": payload["operation_id"],
                    "result_status": str(
                        getattr(result.status, "value", result.status)
                    ),
                },
                pty_written=False,
            )
            response["receipt"] = receipt
        if error_code:
            response["error"] = {
                "code": error_code,
                "message": (
                    "provider rejected the operation"
                    if error_code == "provider_operation_rejected"
                    else "provider execution outcome is unknown"
                ),
            }
        self._send_json(response, status=http_status)

    # ----- /providers/visibility: the only user choice (SPEC-p1 §2.3) -----
    def _providers_visibility_rows(self) -> tuple[list[dict], list[str]]:
        excluded = sorted(_excluded_provider_ids())
        excluded_set = set(excluded)
        rows: list[dict] = []
        try:
            descriptors = _provider_registry_descriptors() if _provider_registry_descriptors else []
        except Exception:
            descriptors = []
        for descriptor in descriptors:
            rows.append({
                "id": descriptor.provider_id,
                "display_name": descriptor.display_name,
                "adapter_depth": getattr(descriptor, "adapter_depth", "deep"),
                "included": descriptor.provider_id not in excluded_set,
            })
        return rows, excluded

    def _handle_providers_visibility_get(self, q):
        if _provider_visibility_read_excluded is None or _provider_registry_descriptors is None:
            self._send_json({
                "ok": False,
                "error": {
                    "code": "provider_registry_unavailable",
                    "message": "Provider visibility is unavailable",
                },
            }, status=503)
            return
        rows, excluded = self._providers_visibility_rows()
        self._send_json({
            "ok": True,
            "schema_version": 1,
            "excluded": excluded,
            "providers": rows,
        })

    def _handle_providers_visibility_post(self, q, auth_result=None):
        """Toggle one provider's visibility. Writes ONLY Pairling's own
        ~/.pairling/providers.json — never a provider dotdir (Law 3) — and
        emits a PairlingActionReceipt-family record for the mutation."""
        raw = self._read_body() or b"{}"
        mutation = _begin_receipted_mutation(
            self,
            receipt_scope="provider_visibility",
            action_kind="provider_visibility",
            material=raw,
            action_label="provider visibility changes",
        )
        if mutation is None:
            return

        def finish(
            *,
            state: str,
            status: int,
            error_code: str | None = None,
            error_message: str | None = None,
            excluded: list[str] | None = None,
            providers: list[dict] | None = None,
            audit_action: dict | None = None,
        ) -> None:
            fields = {}
            if excluded is not None:
                fields["excluded"] = excluded
            if providers is not None:
                fields["providers"] = providers
            receipt = _finalize_receipted_mutation(
                mutation,
                state=state,
                http_status=status,
                backend="provider_visibility_store",
                error_code=error_code,
                error_message=error_message,
                fields=fields or None,
                audit_action=audit_action,
            )
            body = {"ok": state == "applied", "receipt": receipt, **fields}
            if error_code:
                body["error"] = {
                    "code": error_code,
                    "message": error_message or error_code.replace("_", " "),
                }
            self._send_json(body, status=status)

        if _provider_visibility_set_included is None:
            finish(
                state="failed",
                status=503,
                error_code="provider_registry_unavailable",
                error_message="Provider visibility is unavailable",
            )
            return
        try:
            payload = json.loads(raw)
        except json.JSONDecodeError:
            finish(
                state="rejected",
                status=400,
                error_code="invalid_request",
                error_message="body must be JSON",
            )
            return
        if not isinstance(payload, dict):
            finish(
                state="rejected",
                status=400,
                error_code="invalid_request",
                error_message="body must be a JSON object",
            )
            return
        provider = str(payload.get("provider") or "").strip().lower()
        included = payload.get("included")
        if provider not in _known_agent_provider_ids():
            unknown = _unknown_provider_payload(provider)
            finish(
                state="rejected",
                status=400,
                error_code=str(unknown.get("error", {}).get("code") or "unknown_provider"),
                error_message=str(unknown.get("error", {}).get("message") or "unknown provider"),
            )
            return
        if not isinstance(included, bool):
            finish(
                state="rejected",
                status=400,
                error_code="invalid_request",
                error_message="included must be true or false",
            )
            return
        audit_action = {"type": "provider_visibility", "provider": provider, "included": included}
        try:
            excluded = sorted(_provider_visibility_set_included(provider, included, home=HOME))
        except OSError as exc:
            outcome_unknown = bool(getattr(exc, "outcome_unknown", False))
            finish(
                state="indeterminate" if outcome_unknown else "failed",
                status=500,
                error_code=(
                    "visibility_outcome_unknown"
                    if outcome_unknown
                    else "visibility_write_failed"
                ),
                error_message=str(exc)[:200],
                audit_action={**audit_action, "error": str(exc)[:120]},
            )
            return
        # Visibility shapes the command catalogs; force the streams to
        # re-emit on the next tick (SPEC-p2 §2.4).
        _bump_catalog_epoch()
        rows, _ = self._providers_visibility_rows()
        finish(
            state="applied",
            status=200,
            excluded=excluded,
            providers=rows,
            audit_action=audit_action,
        )

    # ----- /status: hybrid status snapshot (passthrough text + structured fields) -----
    def _handle_status(self, q):
        """One-shot status snapshot for the iPhone status drawer.

        Hybrid shape — both flavors of "what's the session doing right now":
          - `text`: stdout from the user's `statusLine.command` (~/.claude/settings.json
            `statusLine` block). Same payload Claude Code's terminal status
            line shows. iPhone renders verbatim in a monospaced footer.
          - structured fields: branch / dirty_count / effort / context_pct /
            model / cost_usd / session_id. Phone renders these as native
            iOS rows with SF Symbols and is free to localize / format / link.

        Source of truth per field:
          - branch / dirty_count: `git -C <cwd>` (live, no caching)
          - effort / model / tool: the per-uuid turn-state JSON written by
            ~/.claude/hooks/state-track.ts
          - context_pct: derived from /tokens turn total vs 200k context window
          - cost_usd: input/output tokens × published Sonnet/Opus pricing
          - statusLine text: spawned subprocess with the session's stdin JSON

        Best-effort: any field that fails returns `null`. The phone tolerates
        nulls — it just hides those rows.
        """
        session_id = q.get("session", [""])[0]
        provider, native_id = _parse_agent_session_ref(session_id)
        if provider == "codex":
            if not native_id:
                self.send_error(400, "session required")
                return
            native_id = _agent_registry_resolve_native_alias("codex", native_id)
            if not _safe_agent_native_id(native_id):
                self.send_error(400, "bad Codex session id")
                return
            reg = _agent_registry_get("codex", native_id) or {}
            metadata = {}
            try:
                metadata = json.loads(reg.get("metadata_json") or "{}")
                if not isinstance(metadata, dict):
                    metadata = {}
            except Exception:
                metadata = {}
            launch_context = _session_launch_context_from_metadata(metadata)

            transcript_path = _resolve_codex_transcript(native_id)
            meta = _codex_rollout_meta(transcript_path) if transcript_path else None
            last_response_at = (
                _last_meaningful_transcript_turn_at(
                    transcript_path, "codex", native_id
                )
                if transcript_path
                else None
            )
            cwd = (
                reg.get("project")
                or (meta or {}).get("cwd")
                or _codex_project_for_session(native_id)
                or None
            )
            working_on = metadata.get("working_on")
            if not working_on and transcript_path:
                working_on = _codex_first_prompt(transcript_path, native_id, _codex_history_map())

            branch = None
            dirty_count = None
            if cwd and os.path.isdir(cwd):
                try:
                    bp = subprocess.run(
                        ["git", "-C", cwd, "branch", "--show-current"],
                        capture_output=True, text=True, timeout=2,
                    )
                    if bp.returncode == 0:
                        branch = (bp.stdout or "").strip() or None
                    sp = subprocess.run(
                        ["git", "-C", cwd, "status", "--porcelain"],
                        capture_output=True, text=True, timeout=2,
                    )
                    if sp.returncode == 0:
                        dirty_count = sum(1 for ln in sp.stdout.splitlines() if ln.strip())
                except (OSError, subprocess.SubprocessError):
                    pass

            pid = int(reg.get("pid") or 0)
            alive = _process_alive(pid) if pid else False
            model = metadata.get("model") or (meta or {}).get("model")
            effort = metadata.get("effort")
            state = metadata.get("state") or reg.get("state") or ("running" if alive else "idle")
            tool = metadata.get("tool")
            tty = reg.get("terminal_tty") or None
            status_text = "Codex"
            if launch_context and launch_context.get("strategy") == "aperture_cli":
                status_text += " · Aperture CLI"
            if model:
                status_text += f" · {model}"
            if tty:
                status_text += f" · {tty}"

            self._send_json({
                "ok": True,
                "session_id": _qualified_session_id("codex", native_id),
                "provider": "codex",
                "native_id": native_id,
                "claude_uuid": None,
                "cwd": cwd,
                "branch": branch,
                "dirty_count": dirty_count,
                "model": model,
                "effort": effort,
                "tool": tool,
                "state": state,
                "input_tokens": 0,
                "output_tokens": 0,
                "total_tokens": 0,
                "context_window": 200_000,
                "context_pct": 0.0,
                "cost_usd": None,
                "working_on": working_on,
                "last_response_at": last_response_at,
                "text": status_text,
                "text_raw": status_text,
                "permissions_mode": None,
                "stop_reason": None,
                "stop_details": None,
                "system_anomaly": None,
                "launch_context": launch_context,
            })
            return

        session_id = _claude_native_session_id(session_id)
        if not session_id:
            self.send_error(400, "session required")
            return

        # ---- structured fields ------------------------------------------------

        cwd = self._lookup_pg_field(session_id, "project")
        claude_uuid = self._lookup_pg_field(session_id, "claude_uuid")
        working_on = self._lookup_pg_field(session_id, "working_on")
        terminal_tty = self._lookup_terminal_tty(session_id)
        launch_context = _session_launch_context_from_metadata(
            _registry_metadata_from_row(_agent_registry_get_by_tty("claude", terminal_tty))
        )

        branch = None
        dirty_count = None
        if cwd and os.path.isdir(cwd):
            try:
                bp = subprocess.run(
                    ["git", "-C", cwd, "branch", "--show-current"],
                    capture_output=True, text=True, timeout=2,
                )
                if bp.returncode == 0:
                    branch = (bp.stdout or "").strip() or None
                sp = subprocess.run(
                    ["git", "-C", cwd, "status", "--porcelain"],
                    capture_output=True, text=True, timeout=2,
                )
                if sp.returncode == 0:
                    dirty_count = sum(1 for ln in sp.stdout.splitlines() if ln.strip())
            except (OSError, subprocess.SubprocessError):
                pass

        # turn-state JSON (effort, model, tool, state). Hook writes it on
        # every event, so this is fresh within ~1s of the last activity.
        effort = None
        model = None
        tool = None
        state = None
        if claude_uuid:
            ts_path = HOME / ".claude" / "turn-state" / f"{claude_uuid}.json"
            try:
                if ts_path.exists():
                    with open(ts_path, "r") as f:
                        ts = json.load(f)
                    effort = ts.get("effort") or None
                    model = ts.get("model") or None
                    tool = ts.get("tool") or None
                    state = ts.get("state") or None
            except (OSError, ValueError, json.JSONDecodeError):
                pass

        # tokens + context_pct + cost. Walk transcript backwards for current
        # turn only — same accounting as /tokens. Also harvest the model id
        # from the most recent assistant message and any abnormal stop_reason
        # / system-error in the current turn so the phone can surface it.
        in_tokens = 0
        out_tokens = 0
        # stop_reason is "end_turn" / "tool_use" / "max_tokens" / "stop_sequence"
        # / "refusal" / "pause_turn" — first two are normal, rest are anomalies
        # the user wants to see. stop_details is sometimes a dict of additional
        # info (max_tokens detail, etc.). system_anomaly captures type=system|error
        # JSONL lines whose subtype is non-routine ("hook" / "duration" are routine).
        stop_reason: str | None = None
        stop_details: dict | None = None
        system_anomaly: dict | None = None
        path = self._resolve_transcript(session_id)
        last_response_at = (
            _last_meaningful_transcript_turn_at(path, "claude", session_id)
            if path
            else None
        )
        if path and path.exists():
            try:
                lines = _tail_lines(path, max_lines=1000, max_bytes=TRANSCRIPT_STATS_MAX_SCAN_BYTES)
            except OSError:
                lines = []
            for raw in reversed(lines):
                if not raw.strip():
                    continue
                try:
                    obj = json.loads(raw)
                except (ValueError, json.JSONDecodeError):
                    continue
                line_type = obj.get("type")
                msg = obj.get("message") or {}
                role = msg.get("role")
                usage = msg.get("usage") or obj.get("usage") or {}
                # Stop conditions for the current turn — record the latest
                # observed before walking past the user-message turn boundary.
                if stop_reason is None and role == "assistant":
                    sr = msg.get("stop_reason")
                    if isinstance(sr, str) and sr:
                        stop_reason = sr
                    sd = msg.get("stop_details")
                    if isinstance(sd, dict):
                        stop_details = sd
                # System/error events from this turn — skip the routine
                # subtypes Claude Code emits as bookkeeping.
                if system_anomaly is None and line_type in ("system", "error"):
                    subtype = obj.get("subtype")
                    if subtype not in {"stop_hook_summary", "turn_duration"}:
                        system_anomaly = {
                            "type": line_type,
                            "subtype": subtype,
                            # Truncate to keep payload bounded. Phone can fetch
                            # the full transcript via /transcript if needed.
                            "content": (obj.get("content") or obj.get("text") or "")[:600],
                        }
                if model is None and role == "assistant":
                    m = msg.get("model")
                    if isinstance(m, str) and m:
                        model = m
                if role == "user" and line_type == "user":
                    break
                if isinstance(usage, dict):
                    out_tokens += int(usage.get("output_tokens") or 0)
                    in_tokens += int(usage.get("input_tokens") or 0)
        total_tokens = in_tokens + out_tokens
        # Model-aware context window. Opus 4.x ships with 1M-token context,
        # Sonnet / Haiku 4.x stay at 200k.
        context_window = 1_000_000 if (model and "opus" in model.lower()) else 200_000
        context_pct = round((total_tokens / context_window) * 100, 1) if total_tokens else 0.0

        # Rough cost — public per-MTok pricing as of 2026-Q2.
        # Opus 4.x: $15 input / $75 output. Sonnet 4.x: $3 / $15. Haiku 4.x: $1 / $5.
        cost_usd = None
        if model:
            ml = model.lower()
            if "opus" in ml:
                p_in, p_out = 15.0, 75.0
            elif "haiku" in ml:
                p_in, p_out = 1.0, 5.0
            else:  # default: sonnet pricing
                p_in, p_out = 3.0, 15.0
            cost_usd = round(
                (in_tokens / 1_000_000) * p_in + (out_tokens / 1_000_000) * p_out,
                4,
            )

        # ---- statusLine text passthrough -------------------------------------

        status_text_raw = None
        try:
            settings_path = HOME / ".claude" / "settings.json"
            if settings_path.exists():
                with open(settings_path, "r") as f:
                    settings = json.load(f)
                sl = settings.get("statusLine") or {}
                cmd = sl.get("command")
                if cmd:
                    payload = json.dumps({
                        "session_id": session_id,
                        "claude_uuid": claude_uuid,
                        "cwd": cwd,
                        "model": {"id": model, "display_name": model},
                        "transcript_path": str(path) if path else None,
                        "workspace": {"current_dir": cwd},
                    })
                    proc = subprocess.run(
                        ["bash", "-lc", cmd],
                        input=payload, capture_output=True, text=True, timeout=3,
                    )
                    if proc.returncode == 0:
                        status_text_raw = (proc.stdout or "").rstrip("\n") or None
        except (OSError, ValueError, json.JSONDecodeError, subprocess.SubprocessError):
            pass

        # Strip ANSI escapes (CSI / SGR / OSC) so the phone gets a clean text
        # line. The raw string is preserved separately for users who want to
        # re-render the colors themselves.
        ansi_re = re.compile(r'\x1B(?:[@-Z\\-_]|\[[0-?]*[ -/]*[@-~])')
        status_text_clean = ansi_re.sub("", status_text_raw) if status_text_raw else None

        # Permissions / accept-edits / bypass mode is a Claude Code setting
        # the user toggles with shift+tab. The chosen mode is mirrored in
        # ~/.claude/settings.json under `permissions.defaultMode` (one of
        # "default", "acceptEdits", "plan", "bypassPermissions"). Surface
        # it so the phone can render the same banner the terminal shows.
        perm_mode = None
        try:
            settings_path = HOME / ".claude" / "settings.json"
            if settings_path.exists():
                with open(settings_path, "r") as f:
                    settings = json.load(f)
                perm_mode = (settings.get("permissions") or {}).get("defaultMode")
        except (OSError, ValueError, json.JSONDecodeError):
            pass

        body = json.dumps({
            "ok": True,
            "session_id": _qualified_session_id("claude", session_id),
            "provider": "claude",
            "native_id": session_id,
            "claude_uuid": claude_uuid,
            "cwd": cwd,
            "branch": branch,
            "dirty_count": dirty_count,
            "model": model,
            "effort": effort,
            "tool": tool,
            "state": state,
            "input_tokens": in_tokens,
            "output_tokens": out_tokens,
            "total_tokens": total_tokens,
            "context_window": context_window,
            "context_pct": context_pct,
            "cost_usd": cost_usd,
            "working_on": working_on,
            "last_response_at": last_response_at,
            "text": status_text_clean,
            "text_raw": status_text_raw,
            "permissions_mode": perm_mode,
            "stop_reason": stop_reason,
            "stop_details": stop_details,
            "system_anomaly": system_anomaly,
            "launch_context": launch_context,
        }).encode()
        self.send_response(200)
        self.send_header("Content-Type", "application/json")
        self.send_header("Content-Length", str(len(body)))
        self.end_headers()
        self.wfile.write(body)

    # ----- /pickers/*: native iOS provider diagnostics -----
    #
    # Resume and rename use their reviewed session command paths. Permissions,
    # hooks, memory, and MCP are provider-qualified read-only diagnostics.
    # Any supported mutation is advertised and executed through Provider
    # controls instead of writing provider settings or files here.

    def _read_settings_json(self) -> dict:
        """Read ~/.claude/settings.json, returning {} on error or missing.
        Whole-file load — pyright-friendly, all keys preserved."""
        path = HOME / ".claude" / "settings.json"
        try:
            if not path.exists():
                return {}
            with open(path, "r") as f:
                data = json.load(f)
            return data if isinstance(data, dict) else {}
        except (OSError, ValueError, json.JSONDecodeError):
            return {}


    # ----- /pickers/resume: list resumable sessions for a cwd -----
    def _handle_pickers_resume(self, q):
        """List the user's recent Claude Code sessions for a project so the
        phone can render a native picker. Each entry exposes:
          id      — claude_uuid (filename stem)
          mtime   — last-modified epoch seconds
          turns   — JSONL line count (rough)
          preview — first user-message text, truncated to ~120 chars
        Sorted newest-first. Filtered to the requested cwd via the same
        encoded-project-dir scheme Claude Code uses.
        """
        cwd = q.get("cwd", [""])[0]
        provider = q.get("provider", ["claude"])[0].lower()
        if not _valid_provider_filter(provider, allow_all=False):
            _send_unknown_provider(self, provider)
            return
        required_capability = "saved_sessions" if provider == "omp" else "read_transcript"
        if not _provider_supports(provider, required_capability):
            _send_unsupported_provider(self, provider, required_capability)
            return
        if not cwd:
            self.send_error(400, "cwd required")
            return
        if provider == "codex":
            self._handle_codex_pickers_resume(cwd)
            return
        if provider == "omp":
            self._handle_omp_pickers_resume(cwd)
            return
        proj_dir = CLAUDE_PROJECTS_DIR / _encode_project_dir(cwd)
        items: list[dict] = []
        try:
            project_fd = open_directory_fd(proj_dir, root=CLAUDE_PROJECTS_DIR)
        except (OSError, ValueError):
            project_fd = -1
        if project_fd >= 0:
            try:
                for name in os.listdir(project_fd):
                    if not name.endswith(".jsonl"):
                        continue
                    try:
                        file_fd = open_child_regular_file_fd(project_fd, name)
                    except (OSError, ValueError):
                        continue
                    preview = ""
                    turns = 0
                    try:
                        with os.fdopen(file_fd, "rb", closefd=True) as f:
                            file_fd = -1
                            opened = os.fstat(f.fileno())
                            for raw in f:
                                if not raw.strip():
                                    continue
                                turns += 1
                                if not preview:
                                    try:
                                        obj = json.loads(raw)
                                    except (ValueError, json.JSONDecodeError):
                                        continue
                                    if obj.get("type") == "user":
                                        msg = obj.get("message") or {}
                                        content = msg.get("content")
                                        if isinstance(content, str):
                                            preview = content
                                        elif isinstance(content, list):
                                            for blk in content:
                                                if isinstance(blk, dict) and blk.get("type") == "text":
                                                    preview = blk.get("text") or ""
                                                    break
                                        if preview:
                                            preview = preview.replace("\n", " ").strip()[:120]
                    except OSError:
                        continue
                    finally:
                        if file_fd >= 0:
                            os.close(file_fd)
                    items.append({
                        "id": Path(name).stem,
                        "mtime": opened.st_mtime,
                        "turns": turns,
                        "preview": preview,
                        "bytes": opened.st_size,
                    })
            finally:
                os.close(project_fd)
        items.sort(key=lambda x: x["mtime"], reverse=True)
        body = json.dumps({"ok": True, "sessions": items[:80]}).encode()
        self.send_response(200)
        self.send_header("Content-Type", "application/json")
        self.send_header("Content-Length", str(len(body)))
        self.end_headers()
        self.wfile.write(body)

    def _handle_codex_pickers_resume(self, cwd: str):
        items: list[dict] = []
        history = _codex_history_map()
        for path, meta in _codex_selected_rollout_entries():
            if meta.get("cwd") != cwd:
                continue
            sid = meta["id"]
            preview = _codex_first_prompt(path, sid, history) or ""
            turns = 0
            try:
                with _open_session_transcript_file(path) as f:
                    opened = os.fstat(f.fileno())
                    for raw in f:
                        for row in _normalize_codex_line(raw, sid):
                            msg = row.get("message") or {}
                            if msg.get("role") == "user":
                                turns += 1
            except OSError:
                continue
            items.append({
                "id": sid,
                "mtime": opened.st_mtime,
                "turns": turns,
                "preview": preview.replace("\n", " ").strip()[:120],
                "bytes": opened.st_size,
            })
            if len(items) >= 80:
                break
        items.sort(key=lambda x: x["mtime"], reverse=True)
        body = json.dumps({"ok": True, "provider": "codex", "sessions": items[:80]}).encode()
        self.send_response(200)
        self.send_header("Content-Type", "application/json")
        self.send_header("Content-Length", str(len(body)))
        self.end_headers()
        self.wfile.write(body)

    def _handle_omp_pickers_resume(self, cwd: str):
        sessions = (
            _omp_saved_sessions(project=cwd, limit=80)
            if _omp_saved_sessions is not None
            else []
        )
        items: list[dict] = []
        for session in sessions:
            try:
                metadata = Path(session.session_path).stat()
            except OSError:
                continue
            items.append({
                "id": session.session_id,
                "mtime": session.modified_at,
                "turns": 0,
                "preview": (session.title or "OMP session")[:120],
                "bytes": metadata.st_size,
            })
        self._send_json({"ok": True, "provider": "omp", "sessions": items})

    # ----- /pickers/resume/preview: last-N assistant outputs from a session -----
    def _handle_pickers_resume_preview(self, q):
        """Return the last N (default 2) full assistant text outputs from a
        session's JSONL. Walks the file once forward, splits into turns
        bounded by user messages, and returns the assistant text from the
        most recent N completed turns.

        Each preview is the concatenation of every assistant `text` block in
        the turn — that's "the full output". Tool blocks / thinking blocks
        are skipped. Truncated to ~2000 chars per turn so a long-output
        session doesn't ship megabytes over the wire.
        """
        cwd = q.get("cwd", [""])[0]
        provider = q.get("provider", ["claude"])[0].lower()
        session_id = q.get("id", [""])[0]
        try:
            n = int(q.get("n", ["2"])[0])
        except ValueError:
            n = 2
        n = max(1, min(n, 5))
        if not cwd or not session_id:
            self.send_error(400, "cwd and id required")
            return
        if not _valid_provider_filter(provider, allow_all=False):
            _send_unknown_provider(self, provider)
            return
        required_capability = "saved_sessions" if provider == "omp" else "read_transcript"
        if not _provider_supports(provider, required_capability):
            _send_unsupported_provider(self, provider, required_capability)
            return
        if provider == "codex":
            self._handle_codex_pickers_resume_preview(cwd, session_id, n)
            return
        if provider == "omp":
            self._handle_omp_pickers_resume_preview(cwd, session_id, n)
            return
        # session_id arrives as the JSONL filename stem (a UUID); guard
        # against path traversal.
        if "/" in session_id or "\\" in session_id or ".." in session_id:
            self.send_error(400, "invalid id")
            return
        proj_dir = HOME / ".claude" / "projects" / _encode_project_dir(cwd)
        target = proj_dir / f"{session_id}.jsonl"
        try:
            transcript_handle = _session_transcript_handle(target)
        except OSError:
            self.send_error(404, "no such session in this project")
            return

        # Walk: collect text from each assistant message; reset accumulator
        # at every user message so we end up with a list of per-turn outputs.
        turns: list[str] = []
        current: list[str] = []
        try:
            with transcript_handle as f:
                for raw in f:
                    if not raw.strip():
                        continue
                    try:
                        obj = json.loads(raw)
                    except (ValueError, json.JSONDecodeError):
                        continue
                    if obj.get("type") == "user":
                        if current:
                            turns.append("\n\n".join(current))
                            current = []
                        continue
                    if obj.get("type") != "assistant":
                        continue
                    msg = obj.get("message") or {}
                    content = msg.get("content")
                    chunks: list[str] = []
                    if isinstance(content, str):
                        if content.strip():
                            chunks.append(content)
                    elif isinstance(content, list):
                        for blk in content:
                            if not isinstance(blk, dict):
                                continue
                            if blk.get("type") == "text":
                                t = blk.get("text") or ""
                                if t.strip():
                                    chunks.append(t)
                    if chunks:
                        current.append("\n\n".join(chunks))
                if current:
                    turns.append("\n\n".join(current))
        except OSError as e:
            self.send_error(500, f"read failed: {e}")
            return

        last_n = turns[-n:]
        # Per-turn cap so megachat sessions don't ship 5MB of preview
        capped = []
        for t in last_n:
            if len(t) > 2000:
                capped.append(t[:1000] + "\n\n…[truncated]…\n\n" + t[-1000:])
            else:
                capped.append(t)

        body = json.dumps({"ok": True, "turns": capped}).encode()
        self.send_response(200)
        self.send_header("Content-Type", "application/json")
        self.send_header("Content-Length", str(len(body)))
        self.end_headers()
        self.wfile.write(body)

    def _handle_codex_pickers_resume_preview(self, cwd: str, session_id: str, n: int):
        if not _safe_agent_native_id(session_id):
            self.send_error(400, "invalid id")
            return
        path = _resolve_codex_transcript(session_id)
        if not path:
            self.send_error(404, "no such Codex session")
            return
        meta = _codex_rollout_meta(path)
        if meta and meta.get("cwd") != cwd:
            self.send_error(404, "no such Codex session in this project")
            return
        turns: list[str] = []
        current: list[str] = []
        try:
            with _open_session_transcript_file(path) as f:
                for raw in f:
                    if not raw.strip():
                        continue
                    for row in _normalize_codex_line(raw, session_id):
                        msg = row.get("message") or {}
                        role = msg.get("role")
                        if role == "user":
                            if current:
                                turns.append("\n\n".join(current))
                                current = []
                            continue
                        if role != "assistant":
                            continue
                        chunks: list[str] = []
                        for blk in msg.get("content") or []:
                            if isinstance(blk, dict) and blk.get("type") == "text":
                                text = blk.get("text")
                                if isinstance(text, str) and text.strip():
                                    chunks.append(text)
                        if chunks:
                            current.append("\n\n".join(chunks))
                if current:
                    turns.append("\n\n".join(current))
        except OSError as e:
            self.send_error(500, f"read failed: {e}")
            return
        capped: list[str] = []
        for t in turns[-n:]:
            if len(t) > 2000:
                capped.append(t[:1000] + "\n\n...[truncated]...\n\n" + t[-1000:])
            else:
                capped.append(t)
        body = json.dumps({"ok": True, "provider": "codex", "turns": capped}).encode()
        self.send_response(200)
        self.send_header("Content-Type", "application/json")
        self.send_header("Content-Length", str(len(body)))
        self.end_headers()
        self.wfile.write(body)

    def _handle_omp_pickers_resume_preview(self, cwd: str, session_id: str, n: int):
        if not _safe_agent_native_id(session_id):
            self.send_error(400, "invalid id")
            return
        target = next(
            (
                session
                for session in (
                    _omp_saved_sessions(project=cwd, limit=200)
                    if _omp_saved_sessions is not None
                    else []
                )
                if session.session_id == session_id
            ),
            None,
        )
        if target is None:
            self.send_error(404, "no such OMP session in this project")
            return

        descriptor = -1
        turns: list[str] = []
        current: list[str] = []
        try:
            flags = os.O_RDONLY | getattr(os, "O_CLOEXEC", 0) | getattr(os, "O_NOFOLLOW", 0)
            descriptor = os.open(target.session_path, flags)
            metadata = os.fstat(descriptor)
            if not stat.S_ISREG(metadata.st_mode):
                raise OSError("OMP session is not a regular file")
            maximum_bytes = 2 * 1024 * 1024
            maximum_line_bytes = 256 * 1024
            offset = max(0, metadata.st_size - maximum_bytes)
            remaining = metadata.st_size - offset
            os.lseek(descriptor, offset, os.SEEK_SET)
            with os.fdopen(descriptor, "rb", closefd=True) as handle:
                descriptor = -1
                if offset:
                    skipped = handle.readline(min(remaining, maximum_line_bytes) + 1)
                    if len(skipped) > remaining or len(skipped) > maximum_line_bytes:
                        remaining = 0
                    else:
                        remaining -= len(skipped)
                for _line_count in range(10_000):
                    if remaining <= 0:
                        break
                    raw = handle.readline(min(remaining, maximum_line_bytes) + 1)
                    if not raw:
                        break
                    if len(raw) > remaining or len(raw) > maximum_line_bytes:
                        break
                    remaining -= len(raw)
                    if not raw.strip():
                        continue
                    try:
                        event = json.loads(raw)
                    except (ValueError, json.JSONDecodeError):
                        continue
                    if not isinstance(event, dict) or event.get("type") != "message":
                        continue
                    message = event.get("message") or {}
                    if not isinstance(message, dict):
                        continue
                    role = message.get("role")
                    if role == "user":
                        if current:
                            turns.append("\n\n".join(current))
                            current = []
                        continue
                    if role != "assistant":
                        continue
                    content = message.get("content") or []
                    if not isinstance(content, list):
                        continue
                    chunks = [
                        str(block.get("text") or "")
                        for block in content
                        if isinstance(block, dict)
                        and block.get("type") == "text"
                        and str(block.get("text") or "").strip()
                    ]
                    if chunks:
                        current.append("\n\n".join(chunks))
                if current:
                    turns.append("\n\n".join(current))
        except OSError as exc:
            self.send_error(500, f"read failed: {exc}")
            return
        finally:
            if descriptor >= 0:
                os.close(descriptor)

        capped = [
            turn if len(turn) <= 2000 else turn[:1000] + "\n\n…[truncated]…\n\n" + turn[-1000:]
            for turn in turns[-n:]
        ]
        self._send_json({"ok": True, "provider": "omp", "turns": capped})

    def _picker_diagnostics_provider(self, q, diagnostic: str) -> str | None:
        provider = q.get("provider", [""])[0].strip().lower()
        if not provider:
            self._send_json({
                "ok": False,
                "error": {
                    "code": "picker_provider_required",
                    "message": f"{diagnostic} diagnostics require an exact provider.",
                },
            }, status=400)
            return None
        if not _valid_provider_filter(provider, allow_all=False):
            _send_unknown_provider(self, provider)
            return None
        if provider != "claude":
            _send_unsupported_provider(
                self,
                provider,
                f"{diagnostic.lower()}_read",
                status=501,
            )
            return None
        return provider

    # ----- /pickers/permissions: provider-qualified read-only diagnostics -----
    def _handle_pickers_permissions(self, q):
        if (getattr(self, "command", "GET") or "GET").upper() != "GET":
            self.send_error(405, "GET required")
            return
        provider = self._picker_diagnostics_provider(q, "Permissions")
        if provider is None:
            return
        settings = self._read_settings_json()
        permissions = settings.get("permissions") or {}
        self._send_json({
            "ok": True,
            "provider": provider,
            "permissions": {
                "allow": permissions.get("allow") or [],
                "deny": permissions.get("deny") or [],
                "ask": permissions.get("ask") or [],
                "additionalDirectories": permissions.get("additionalDirectories") or [],
                "defaultMode": permissions.get("defaultMode") or "default",
                "effortLevel": settings.get("effortLevel") or "medium",
            },
        })

    # ----- /pickers/hooks: provider-qualified read-only diagnostics -----
    def _handle_pickers_hooks(self, q):
        if (getattr(self, "command", "GET") or "GET").upper() != "GET":
            self.send_error(405, "GET required")
            return
        provider = self._picker_diagnostics_provider(q, "Hooks")
        if provider is None:
            return
        settings = self._read_settings_json()
        self._send_json({
            "ok": True,
            "provider": provider,
            "hooks": settings.get("hooks") or {},
        })

    # ----- /pickers/memory: provider-qualified read-only diagnostics -----
    def _handle_pickers_memory(self, q):
        if (getattr(self, "command", "GET") or "GET").upper() != "GET":
            self.send_error(405, "GET required")
            return
        provider = self._picker_diagnostics_provider(q, "Memory")
        if provider is None:
            return
        cwd = q.get("cwd", [""])[0]
        if not cwd:
            self.send_error(400, "cwd required")
            return
        mem_dir = HOME / ".claude" / "projects" / _encode_project_dir(cwd) / "memory"
        entries: list[dict] = []
        if mem_dir.exists():
            for markdown_path in sorted(mem_dir.glob("*.md")):
                if markdown_path.name == "MEMORY.md":
                    continue
                try:
                    text = markdown_path.read_text(encoding="utf-8")
                except OSError:
                    continue
                frontmatter = _parse_md_frontmatter(text)
                entries.append({
                    "filename": markdown_path.name,
                    "name": frontmatter.get("name") or markdown_path.stem,
                    "description": frontmatter.get("description") or "",
                    "type": frontmatter.get("type") or "project",
                })
        self._send_json({
            "ok": True,
            "provider": provider,
            "entries": entries,
        })

    def _handle_pickers_memory_one(self, q, filename: str):
        if (getattr(self, "command", "GET") or "GET").upper() != "GET":
            self.send_error(405, "GET required")
            return
        provider = self._picker_diagnostics_provider(q, "Memory")
        if provider is None:
            return
        cwd = q.get("cwd", [""])[0]
        if not cwd:
            self.send_error(400, "cwd required")
            return
        if (
            "/" in filename
            or "\\" in filename
            or not filename.endswith(".md")
            or filename == "MEMORY.md"
        ):
            self.send_error(400, "invalid filename")
            return
        mem_dir = HOME / ".claude" / "projects" / _encode_project_dir(cwd) / "memory"
        target = mem_dir / filename
        if not target.exists():
            self.send_error(404, "no such entry")
            return
        try:
            text = target.read_text(encoding="utf-8")
        except OSError as exc:
            self.send_error(500, f"read failed: {exc}")
            return
        frontmatter = _parse_md_frontmatter(text)
        body_text = text
        match = re.match(r"^---\n.*?\n---\n?", text, flags=re.DOTALL)
        if match:
            body_text = text[match.end():]
        self._send_json({
            "ok": True,
            "provider": provider,
            "filename": filename,
            "name": frontmatter.get("name") or target.stem,
            "description": frontmatter.get("description") or "",
            "type": frontmatter.get("type") or "project",
            "content": body_text,
        })

    # ----- /pickers/mcp: provider-qualified, read-only diagnostics -----
    def _handle_pickers_mcp(self, q):
        """Return one provider's MCP diagnostics without exposing mutations."""
        provider = q.get("provider", [""])[0].strip().lower()
        if not provider:
            self._send_json({
                "ok": False,
                "error": {
                    "code": "mcp_provider_required",
                    "message": "MCP diagnostics require an exact provider.",
                },
            }, status=400)
            return
        if not _valid_provider_filter(provider, allow_all=False):
            _send_unknown_provider(self, provider)
            return
        if provider != "claude":
            _send_unsupported_provider(self, provider, "mcp_read", status=501)
            return

        candidates = [
            HOME / ".local" / "bin" / "claude",
            "/usr/local/bin/claude",
            "/opt/homebrew/bin/claude",
        ]
        claude_bin = next((
            str(candidate)
            for candidate in candidates
            if os.path.exists(str(candidate)) and os.access(str(candidate), os.X_OK)
        ), None)
        if claude_bin is None:
            self._send_json({
                "ok": False,
                "error": {
                    "code": "mcp_diagnostics_unavailable",
                    "message": "Claude MCP diagnostics are unavailable because the Claude CLI was not found.",
                    "provider": provider,
                    "reason": "provider_binary_missing",
                },
            }, status=503)
            return

        try:
            proc = subprocess.run(
                [claude_bin, "mcp", "list"],
                capture_output=True,
                text=True,
                timeout=8,
            )
        except subprocess.TimeoutExpired:
            self._send_json({
                "ok": False,
                "error": {
                    "code": "mcp_diagnostics_timeout",
                    "message": "Claude MCP diagnostics did not finish in time.",
                    "provider": provider,
                },
            }, status=504)
            return
        except (OSError, subprocess.SubprocessError) as exc:
            self._send_json({
                "ok": False,
                "error": {
                    "code": "mcp_diagnostics_unavailable",
                    "message": "Claude MCP diagnostics could not be started.",
                    "provider": provider,
                    "reason": type(exc).__name__,
                },
            }, status=503)
            return

        if proc.returncode != 0:
            self._send_json({
                "ok": False,
                "error": {
                    "code": "mcp_diagnostics_failed",
                    "message": f"Claude MCP diagnostics exited with status {proc.returncode}.",
                    "provider": provider,
                    "returncode": proc.returncode,
                },
            }, status=502)
            return

        servers: list[dict] = []
        unparsed_lines = 0
        for raw in proc.stdout.splitlines():
            line = raw.strip()
            if not line or line.startswith("Checking MCP"):
                continue
            if line.startswith(("No MCP servers configured", "No MCP servers found")):
                continue
            try:
                server_text, status_text = line.rsplit(" - ", 1)
                name, target = server_text.rsplit(": ", 1)
            except ValueError:
                unparsed_lines += 1
                continue
            name = name.strip()
            target = target.strip()
            status_text = status_text.strip()
            if not name or not target or not status_text:
                unparsed_lines += 1
                continue
            if "Connected" in status_text or "✓" in status_text:
                status = "connected"
            elif "Connecting" in status_text or "Pending" in status_text:
                status = "connecting"
            elif "Failed" in status_text or "Error" in status_text or "✗" in status_text:
                status = "failed"
            else:
                status = "unknown"
            servers.append({
                "name": name,
                "target": target,
                "status": status,
                "status_text": status_text,
            })

        if unparsed_lines:
            self._send_json({
                "ok": False,
                "error": {
                    "code": "mcp_diagnostics_parse_failed",
                    "message": "Claude MCP diagnostics returned an unsupported output format.",
                    "provider": provider,
                    "unparsed_lines": unparsed_lines,
                },
            }, status=502)
            return
        self._send_json({
            "ok": True,
            "provider": provider,
            "servers": servers,
        })


    # ----- /search: Spotlight-style cross-session text search -----
    def _handle_search(self, q):
        """Walk every Claude and Codex transcript and return the top
        matches for `q`. Substring + token match, scored by:
          - term frequency in the matching turn (×1)
          - recency boost (× decay over 30 days)
          - content-type weight (user prompts ×1.4, code ×1.2, assistant ×1.0)
        Result row: { session_id, project, project_basename, turn_index,
                      timestamp, snippet, kind, score }
        """
        query = (q.get("q", [""])[0] or "").strip()
        if not query:
            self.send_error(400, "q required")
            return
        try:
            limit = max(1, min(100, int(q.get("limit", ["30"])[0])))
        except ValueError:
            limit = 30
        kind_filter = q.get("kind", ["all"])[0]   # all | user | assistant | code
        provider_filter = q.get("provider", ["claude"])[0].lower()
        if not _valid_provider_filter(provider_filter):
            _send_unknown_provider(self, provider_filter)
            return

        # Cheap normalize — case-insensitive whole-substring match. Short
        # tokens get split for token coverage scoring.
        q_lower = query.lower()
        tokens = [t for t in re.split(r"\s+", q_lower) if len(t) >= 2]

        results: list[dict] = []
        def keep_result(row: dict) -> None:
            results.append(row)
            if len(results) > limit * 2:
                results.sort(key=lambda item: item["score"], reverse=True)
                del results[limit:]
        projects_root = HOME / ".claude" / "projects"

        # Newest-first improves locality, but the search remains exhaustive.
        all_jsonl: list[tuple[float, "Path", str]] = []
        if provider_filter in ("all", "claude") and projects_root.exists():
            for project_dir in projects_root.iterdir():
                if not project_dir.is_dir():
                    continue
                if _is_excluded_project_dir_name(project_dir.name):
                    continue
                for jp in project_dir.glob("*.jsonl"):
                    try:
                        st = jp.stat()
                    except OSError:
                        continue
                    all_jsonl.append((st.st_mtime, jp, project_dir.name))
        all_jsonl.sort(reverse=True)

        import time as _time
        now_ts = _time.time()

        for mtime, jp, project_name in all_jsonl:
            try:
                with open(jp, "rb") as f:
                    line_idx = 0
                    for raw in f:
                        line_idx += 1
                        if not raw.strip():
                            continue
                        try:
                            obj = json.loads(raw)
                        except (ValueError, json.JSONDecodeError):
                            continue
                        line_kind = obj.get("type")
                        msg = obj.get("message") or {}
                        # Pull all text content out of this entry — strings or
                        # lists of {text, ...} blocks.
                        chunks: list[str] = []
                        is_code = False
                        content = msg.get("content")
                        if isinstance(content, str):
                            chunks.append(content)
                        elif isinstance(content, list):
                            for blk in content:
                                if not isinstance(blk, dict):
                                    continue
                                btype = blk.get("type")
                                t = blk.get("text") or blk.get("thinking") or ""
                                if btype == "tool_use":
                                    inp = blk.get("input")
                                    if inp is not None:
                                        try:
                                            t = json.dumps(inp)[:1000]
                                        except (TypeError, ValueError):
                                            t = ""
                                    is_code = True
                                elif btype == "tool_result":
                                    c = blk.get("content")
                                    if isinstance(c, str):
                                        t = c
                                    elif isinstance(c, list):
                                        try:
                                            t = "\n".join(
                                                (b.get("text") or "") for b in c
                                                if isinstance(b, dict)
                                            )
                                        except (TypeError, AttributeError):
                                            t = ""
                                    is_code = True
                                if t:
                                    chunks.append(t)
                        body = "\n".join(chunks)
                        if not body:
                            continue
                        body_lower = body.lower()
                        # Substring hit — required.
                        if q_lower not in body_lower:
                            # Token-coverage fallback: still match if all
                            # tokens appear individually.
                            if not tokens or not all(t in body_lower for t in tokens):
                                continue

                        # Apply kind filter
                        if kind_filter != "all":
                            if kind_filter == "user" and line_kind != "user":
                                continue
                            if kind_filter == "assistant" and line_kind != "assistant":
                                continue
                            if kind_filter == "code" and not is_code:
                                continue

                        # Score: substring count + recency decay
                        tf = body_lower.count(q_lower) or sum(body_lower.count(t) for t in tokens)
                        weight = 1.4 if line_kind == "user" else (1.2 if is_code else 1.0)
                        # 30-day half-life; turns within last day get full boost.
                        age_days = max(0.0, (now_ts - mtime) / 86_400.0)
                        recency = 1.0 / (1.0 + age_days / 30.0)
                        score = tf * weight * (0.5 + 0.5 * recency)

                        # Build a snippet around the first match.
                        idx = body_lower.find(q_lower)
                        if idx < 0 and tokens:
                            for t in tokens:
                                idx = body_lower.find(t)
                                if idx >= 0:
                                    break
                        if idx < 0:
                            idx = 0
                        start = max(0, idx - 60)
                        end = min(len(body), idx + len(query) + 80)
                        snippet = body[start:end].replace("\n", " ")
                        if start > 0:
                            snippet = "…" + snippet
                        if end < len(body):
                            snippet = snippet + "…"

                        keep_result({
                            "session_id": _qualified_session_id("claude", jp.stem),
                            "provider": "claude",
                            "native_id": jp.stem,
                            "entry_id": obj.get("uuid"),
                            "project": project_name,
                            "turn_index": line_idx,
                            "timestamp": mtime,
                            "snippet": snippet,
                            "kind": "code" if is_code else (line_kind or "unknown"),
                            "score": round(score, 3),
                        })
            except OSError:
                continue

        if provider_filter in ("all", "codex"):
            for jp in _codex_rollout_paths():
                try:
                    st = jp.stat()
                except OSError:
                    continue
                meta = _codex_rollout_meta(jp)
                if not meta:
                    continue
                native_id = meta["id"]
                project = meta["cwd"]
                try:
                    with open(jp, "rb") as f:
                        line_idx = 0
                        for raw in f:
                            line_idx += 1
                            if not raw.strip():
                                continue
                            for obj in _normalize_codex_line(raw, native_id):
                                line_kind = obj.get("type")
                                msg = obj.get("message") or {}
                                chunks: list[str] = []
                                is_code = False
                                content = msg.get("content")
                                if isinstance(content, str):
                                    chunks.append(content)
                                elif isinstance(content, list):
                                    for blk in content:
                                        if not isinstance(blk, dict):
                                            continue
                                        btype = blk.get("type")
                                        t = blk.get("text") or blk.get("thinking") or ""
                                        if btype == "tool_use":
                                            inp = blk.get("input")
                                            if inp is not None:
                                                try:
                                                    t = json.dumps(inp)[:1000]
                                                except (TypeError, ValueError):
                                                    t = ""
                                            is_code = True
                                        elif btype == "tool_result":
                                            c = blk.get("content")
                                            if isinstance(c, str):
                                                t = c
                                            elif isinstance(c, list):
                                                try:
                                                    t = "\n".join(
                                                        (b.get("text") or "") for b in c
                                                        if isinstance(b, dict)
                                                    )
                                                except (TypeError, AttributeError):
                                                    t = ""
                                            is_code = True
                                        if t:
                                            chunks.append(t)
                                body = "\n".join(chunks)
                                if not body:
                                    continue
                                body_lower = body.lower()
                                if q_lower not in body_lower:
                                    if not tokens or not all(t in body_lower for t in tokens):
                                        continue
                                if kind_filter != "all":
                                    if kind_filter == "user" and line_kind != "user":
                                        continue
                                    if kind_filter == "assistant" and line_kind != "assistant":
                                        continue
                                    if kind_filter == "code" and not is_code:
                                        continue
                                tf = body_lower.count(q_lower) or sum(body_lower.count(t) for t in tokens)
                                weight = 1.4 if line_kind == "user" else (1.2 if is_code else 1.0)
                                age_days = max(0.0, (now_ts - st.st_mtime) / 86_400.0)
                                recency = 1.0 / (1.0 + age_days / 30.0)
                                score = tf * weight * (0.5 + 0.5 * recency)
                                idx = body_lower.find(q_lower)
                                if idx < 0 and tokens:
                                    for t in tokens:
                                        idx = body_lower.find(t)
                                        if idx >= 0:
                                            break
                                if idx < 0:
                                    idx = 0
                                start = max(0, idx - 60)
                                end = min(len(body), idx + len(query) + 80)
                                snippet = body[start:end].replace("\n", " ")
                                if start > 0:
                                    snippet = "…" + snippet
                                if end < len(body):
                                    snippet = snippet + "…"
                                keep_result({
                                    "session_id": _qualified_session_id("codex", native_id),
                                    "provider": "codex",
                                    "native_id": native_id,
                                    "entry_id": obj.get("uuid"),
                                    "project": project,
                                    "turn_index": line_idx,
                                    "timestamp": st.st_mtime,
                                    "snippet": snippet,
                                    "kind": "code" if is_code else (line_kind or "unknown"),
                                    "score": round(score, 3),
                                })
                except OSError:
                    continue

        results.sort(key=lambda r: r["score"], reverse=True)
        self._json_response(200, {
            "ok": True,
            "count": min(len(results), limit),
            "results": results[:limit],
            "exhaustive": True,
        })

    def _json_response(self, code: int, payload: dict) -> None:
        body = json.dumps(payload).encode()
        self.send_response(code)
        self.send_header("Content-Type", "application/json")
        self.send_header("Content-Length", str(len(body)))
        self.end_headers()
        self.wfile.write(body)

    # ----- /sessions/<id>/export: dump a session's JSONL as md / json / html -----
    def _handle_session_export(self, q, session_id: str):
        """Convert the session's JSONL into a portable transcript document.

        Formats:
          md   — opinionated cleanup pipeline (default `clean` verbosity):
                   - strip injected harness blocks (system-reminder, command-*,
                     local-command-*, task-notification)
                   - strip image filesystem paths + persisted-output refs
                   - drop tool_result blocks
                   - condense tool_use to one-liners
                   - merge consecutive same-role turns into one heading
                   - strip standalone "." lines (bracketed-paste flush hack)
          json — passthrough JSONL bytes
          html — TerminalTheme-styled self-contained page (uses md cleanup)

        Verbosity (md/html only):
          prose   — text-only, no tool calls at all
          clean   — text + condensed tool-use one-liners (default)
          full    — current behavior, full tool I/O preserved

        The phone uses iOS share sheet → AirDrop / Mail / Files / iMessage.
        """
        if not session_id or "/" in session_id or "\\" in session_id or ".." in session_id:
            self.send_error(400, "invalid session id")
            return
        fmt = (q.get("format", ["md"])[0] or "md").lower()
        if fmt not in {"md", "json", "html"}:
            self.send_error(400, "unsupported format")
            return
        verbosity = (q.get("verbosity", ["clean"])[0] or "clean").lower()
        if verbosity not in {"prose", "clean", "full"}:
            verbosity = "clean"

        provider, native_id = _parse_agent_session_ref(session_id)
        launch_context = (
            _session_launch_context_for_identity(provider, native_id)
            if fmt != "json"
            else None
        )
        try:
            path = self._resolve_session_transcript_path(
                provider,
                native_id,
                session_id,
            )
        except _UnsupportedTranscriptProviderError as error:
            _send_unsupported_provider(
                self,
                error.provider,
                error.capability,
                status=422,
            )
            return
        if path is None or not path.exists():
            self.send_error(404, "no transcript")
            return

        if provider == "codex":
            try:
                normalized = _normalize_codex_ndjson(path.read_bytes(), native_id)
            except OSError as e:
                self.send_error(500, f"read failed: {e}")
                return
            if fmt == "json":
                data = normalized.encode("utf-8")
                filename = f"codex-{native_id}.jsonl"
                self.send_response(200)
                self.send_header("Content-Type", "application/x-ndjson")
                self.send_header("Content-Disposition", f'attachment; filename="{filename}"')
                self.send_header("Content-Length", str(len(data)))
                self.end_headers()
                self.wfile.write(data)
                return

            sections: list[tuple[str, str]] = []
            first_ts: str | None = None
            last_ts: str | None = None
            for raw in normalized.splitlines():
                try:
                    obj = json.loads(raw)
                except (ValueError, json.JSONDecodeError):
                    continue
                role = obj.get("type")
                if role not in ("user", "assistant"):
                    continue
                ts = obj.get("timestamp")
                if isinstance(ts, str):
                    if first_ts is None:
                        first_ts = ts
                    last_ts = ts
                msg = obj.get("message") or {}
                content = msg.get("content") or []
                parts: list[str] = []
                if isinstance(content, str):
                    cleaned = _clean_transcript_export_text(content)
                    if cleaned:
                        parts.append(cleaned)
                elif isinstance(content, list):
                    for block in content:
                        if not isinstance(block, dict):
                            continue
                        btype = block.get("type")
                        if verbosity == "prose" and btype in ("tool_use", "tool_result"):
                            continue
                        if btype == "text":
                            t = block.get("text")
                            if isinstance(t, str) and t.strip():
                                cleaned = _clean_transcript_export_text(t)
                                if cleaned:
                                    parts.append(cleaned)
                        elif btype == "thinking" and verbosity == "full":
                            t = block.get("thinking") or block.get("text")
                            if isinstance(t, str) and t.strip():
                                cleaned = _clean_transcript_export_text(t)
                                if cleaned:
                                    parts.append(f"[thinking]\n{cleaned}")
                        elif btype == "tool_use":
                            name = block.get("name") or "tool"
                            if verbosity == "full":
                                parts.append(f"[tool use: {name}]\n```json\n{json.dumps(block.get('input') or {}, indent=2, sort_keys=True)}\n```")
                            elif verbosity == "clean":
                                parts.append(f"[tool use: {name}]")
                        elif btype == "tool_result" and verbosity == "full":
                            t = block.get("content")
                            if isinstance(t, str) and t.strip():
                                cleaned = _clean_transcript_export_text(t)
                                if cleaned:
                                    parts.append(f"[tool result]\n```\n{cleaned[:8000]}\n```")
                text = "\n\n".join(p for p in parts if p).strip()
                if text:
                    sections.append((role, text))

            title = f"Codex transcript {native_id}"
            md_lines = [
                "---",
                f"title: {title}",
                f"session_id: codex:{native_id}",
                "provider: codex",
                f"source_file: {path.name}",
            ]
            _append_launch_frontmatter(md_lines, launch_context)
            if first_ts:
                md_lines.append(f"started_at: {first_ts}")
            if last_ts:
                md_lines.append(f"last_event_at: {last_ts}")
            md_lines.extend(["---", ""])
            for role, text in sections:
                heading = "User" if role == "user" else "Assistant"
                md_lines.extend([f"## {heading}", "", text, ""])
            md = "\n".join(md_lines).rstrip() + "\n"
            if fmt == "md":
                data = md.encode("utf-8")
                filename = f"codex-{native_id}.md"
                self.send_response(200)
                self.send_header("Content-Type", "text/markdown; charset=utf-8")
                self.send_header("Content-Disposition", f'attachment; filename="{filename}"')
                self.send_header("Content-Length", str(len(data)))
                self.end_headers()
                self.wfile.write(data)
                return

            body_html = html.escape(md)
            doc = (
                "<!doctype html><meta charset=\"utf-8\">"
                "<style>body{font:14px -apple-system,BlinkMacSystemFont,sans-serif;max-width:880px;margin:32px auto;padding:0 18px;line-height:1.45}"
                "pre{white-space:pre-wrap;background:#f6f6f6;padding:12px;border-radius:8px}"
                "</style>"
                f"<title>{html.escape(title)}</title><pre>{body_html}</pre>"
            )
            data = doc.encode("utf-8")
            filename = f"codex-{native_id}.html"
            self.send_response(200)
            self.send_header("Content-Type", "text/html; charset=utf-8")
            self.send_header("Content-Disposition", f'attachment; filename="{filename}"')
            self.send_header("Content-Length", str(len(data)))
            self.end_headers()
            self.wfile.write(data)
            return

        # JSON: passthrough — fastest path, no transformation.
        if fmt == "json":
            try:
                data = path.read_bytes()
            except OSError as e:
                self.send_error(500, f"read failed: {e}")
                return
            filename = f"{session_id}.jsonl"
            self.send_response(200)
            self.send_header("Content-Type", "application/x-ndjson")
            self.send_header("Content-Disposition", f'attachment; filename="{filename}"')
            self.send_header("Content-Length", str(len(data)))
            self.end_headers()
            self.wfile.write(data)
            return

        def clean_text(text: str) -> str:
            return _clean_transcript_export_text(text)

        # Walk JSONL once. For each turn collect text/tool/image fragments
        # transformed per verbosity. Track session metadata for front matter.
        sections: list[tuple[str, list[str]]] = []
        first_ts: str | None = None
        last_ts: str | None = None
        seen_model: str | None = None
        try:
            with open(path, "rb") as f:
                for raw in f:
                    if not raw.strip():
                        continue
                    try:
                        obj = json.loads(raw)
                    except (ValueError, json.JSONDecodeError):
                        continue
                    line_kind = obj.get("type")
                    ts = obj.get("timestamp")
                    if isinstance(ts, str):
                        if first_ts is None:
                            first_ts = ts
                        last_ts = ts
                    if line_kind not in ("user", "assistant"):
                        continue
                    msg = obj.get("message") or {}
                    if seen_model is None and line_kind == "assistant":
                        m = msg.get("model")
                        if isinstance(m, str) and m:
                            seen_model = m
                    content = msg.get("content")
                    parts: list[str] = []
                    if isinstance(content, str):
                        cleaned = clean_text(content)
                        if cleaned:
                            parts.append(cleaned)
                    elif isinstance(content, list):
                        for blk in content:
                            if not isinstance(blk, dict):
                                continue
                            btype = blk.get("type")
                            if btype == "text":
                                cleaned = clean_text(blk.get("text") or "")
                                if cleaned:
                                    parts.append(cleaned)
                            elif btype == "thinking":
                                if verbosity == "full":
                                    t = (blk.get("thinking") or blk.get("text") or "").strip()
                                    if t:
                                        parts.append(f"_(thinking)_\n\n> {t.replace(chr(10), chr(10) + '> ')}")
                                # prose / clean: drop thinking blocks
                            elif btype == "tool_use":
                                if verbosity == "prose":
                                    continue
                                name = blk.get("name") or "tool"
                                raw_inp = blk.get("input")
                                inp: dict = raw_inp if isinstance(raw_inp, dict) else {}
                                if verbosity == "full":
                                    try:
                                        args = json.dumps(inp, indent=2)[:2000]
                                    except (TypeError, ValueError):
                                        args = "{}"
                                    parts.append(f"**→ {name}**\n\n```json\n{args}\n```")
                                else:
                                    # clean: condense to a one-liner using
                                    # the most informative field available.
                                    desc = (
                                        inp.get("description")
                                        or inp.get("command")
                                        or inp.get("path")
                                        or inp.get("file_path")
                                        or inp.get("query")
                                        or inp.get("pattern")
                                        or ""
                                    )
                                    if isinstance(desc, str):
                                        desc = desc.replace("\n", " ").strip()[:120]
                                    else:
                                        desc = ""
                                    if desc:
                                        parts.append(f"*{name}: {desc}*")
                                    else:
                                        parts.append(f"*{name}*")
                            elif btype == "tool_result":
                                if verbosity == "full":
                                    c = blk.get("content")
                                    txt = ""
                                    if isinstance(c, str):
                                        txt = c
                                    elif isinstance(c, list):
                                        txt = "\n".join(
                                            (b.get("text") or "") for b in c
                                            if isinstance(b, dict)
                                        )
                                    txt = clean_text((txt or "")[:4000])
                                    if txt:
                                        parts.append(f"**← result**\n\n```\n{txt}\n```")
                                # prose / clean: drop tool_results entirely
                            elif btype == "image":
                                parts.append("*(image attached)*")
                    if parts:
                        sections.append((line_kind, parts))
        except OSError as e:
            self.send_error(500, f"read failed: {e}")
            return

        # Merge consecutive same-role turns into one section. This collapses
        # the pattern where Claude emits one assistant entry per text/tool
        # block — much more natural to read as "Claude ran three things,
        # then said this" rather than three separate ### Claude headers.
        merged: list[tuple[str, list[str]]] = []
        for role, parts in sections:
            if merged and merged[-1][0] == role:
                merged[-1][1].extend(parts)
            else:
                merged.append((role, list(parts)))

        if fmt == "md":
            lines: list[str] = []
            # YAML front matter — useful for tools that key on metadata.
            front = ["---", f"session: {session_id}"]
            if first_ts: front.append(f"started: {first_ts}")
            if last_ts:  front.append(f"ended: {last_ts}")
            front.append(f"turns: {len(merged)}")
            if seen_model: front.append(f"model: {seen_model}")
            _append_launch_frontmatter(front, launch_context)
            front.append(f"verbosity: {verbosity}")
            front.append("---")
            front.append("")
            lines.extend(front)
            lines.append(f"# Session {session_id}")
            lines.append("")
            for role, parts in merged:
                heading = "### You" if role == "user" else "### Claude"
                lines.append(heading)
                lines.append("")
                lines.append("\n\n".join(parts))
                lines.append("")
            data = ("\n".join(lines).rstrip() + "\n").encode("utf-8")
            filename = f"{session_id}.md"
            self.send_response(200)
            self.send_header("Content-Type", "text/markdown; charset=utf-8")
            self.send_header("Content-Disposition", f'attachment; filename="{filename}"')
            self.send_header("Content-Length", str(len(data)))
            self.end_headers()
            self.wfile.write(data)
            return

        # html path uses the merged structure too.
        sections = [(role, ["\n\n".join(parts)]) for role, parts in merged]

        # html — self-contained, terminal-styled
        css = """
        body { background:#000; color:#DFDFDF; font-family:Menlo,Monaco,monospace;
               padding:24px; max-width:920px; margin:0 auto; line-height:1.5; }
        h1 { color:#ECECEC; border-bottom:1px solid #1F2933; padding-bottom:8px; }
        h2 { color:#ECECEC; margin-top:32px; font-size:15px; }
        h2.user { color:#66B5EC; }
        h2.assistant { color:#7BCACD; }
        pre { background:#0A0A0A; padding:12px; overflow-x:auto;
              border:1px solid #1F2933; }
        code { color:#66B5EC; }
        blockquote { border-left:2px solid #465C6C; padding-left:12px;
                     color:#6B7680; font-style:italic; }
        strong { color:#ECECEC; }
        """
        def esc(s: str) -> str:
            return (s.replace("&", "&amp;").replace("<", "&lt;").replace(">", "&gt;"))
        body_parts = [f"<h1>Session {esc(session_id)}</h1>"]
        for role, parts_list in sections:
            klass = "user" if role == "user" else "assistant"
            heading_text = "You" if role == "user" else "Claude"
            body_parts.append(f'<h2 class="{klass}">{heading_text}</h2>')
            # parts_list is now a list[str] per turn (post-cleanup). Join
            # them and run the same naive markdown→HTML pass we did before.
            text = esc("\n\n".join(parts_list))
            text = re.sub(
                r"```(\w*)\n(.*?)\n```",
                lambda m: f"<pre><code>{m.group(2)}</code></pre>",
                text, flags=re.DOTALL,
            )
            text = text.replace("\n\n", "</p><p>")
            body_parts.append(f"<p>{text}</p>")
        html_doc = (
            "<!doctype html><html><head><meta charset='utf-8'>"
            f"<title>Session {esc(session_id)}</title>"
            f"<style>{css}</style></head><body>"
            + "\n".join(body_parts)
            + "</body></html>"
        )
        data = html_doc.encode("utf-8")
        filename = f"{session_id}.html"
        self.send_response(200)
        self.send_header("Content-Type", "text/html; charset=utf-8")
        self.send_header("Content-Disposition", f'attachment; filename="{filename}"')
        self.send_header("Content-Length", str(len(data)))
        self.end_headers()
        self.wfile.write(data)

    # ----- /commands-stream: SSE that pushes a fresh catalog snapshot on file change -----
    def _handle_commands_stream(self, q):
        """Subscribes the phone to live updates of the slash-command catalog.

        Polls the 5 source dirs every 5s and computes a stable signature
        (file path + mtime + size). When the signature changes — a command
        file was added, removed, or edited — we rebuild and emit a fresh
        full catalog snapshot. iOS replaces its cached array atomically.

        Why poll instead of fs.watch / FSEvents? Three reasons:
          1. No extra Python deps (watchdog isn't in stdlib).
          2. Plugin install / cd / homebrew updates often touch parent dirs
             without firing precise events; mtime polling catches everything.
          3. 5s cadence + ~5 dirs × ~200 files = ~1000 stat calls every 5s
             on the local fs. Trivial.

        Sends one initial `event: catalog` immediately on connect; then any
        change emits another. 20s keepalive. One-minute connection cap.
        """
        cwd = q.get("cwd", [""])[0].strip()
        provider = q.get("provider", ["claude"])[0].lower()
        if not _valid_provider_filter(provider, allow_all=False):
            _send_unknown_provider(self, provider)
            return

        device_id = str(getattr(self.pairling_auth, "device_id", "") or "")
        lease = _replace_command_stream_lease(device_id) if device_id else threading.Event()
        if device_id:
            self._command_stream_lease = (device_id, lease)

        self.send_response(200)
        self.send_header("Content-Type", "text/event-stream")
        self.send_header("Cache-Control", "no-store")
        self.send_header("Connection", "keep-alive")
        self.send_header("X-Accel-Buffering", "no")
        self.end_headers()

        last_sig = ""
        last_keepalive = _time.time()
        deadline = _time.time() + COMMAND_STREAM_MAX_SECONDS

        def _commands_frame(sig: str) -> bytes:
            items = _build_command_catalog(cwd=cwd, provider=provider)
            annotated, extras = _catalog_payload_extras(provider, items, sig)
            return json.dumps({"count": len(annotated), "items": annotated, **extras}).encode()

        # Initial snapshot.
        try:
            sig = _commands_signature(cwd, provider=provider)
            payload = _commands_frame(sig)
            self.wfile.write(b"event: catalog\ndata: " + payload + b"\n\n")
            self.wfile.flush()
            last_sig = sig
        except (BrokenPipeError, ConnectionResetError):
            return
        except Exception:
            # If the initial scan blows up, send an error frame and bail.
            try:
                self.wfile.write(b"event: error\ndata: {}\n\n")
                self.wfile.flush()
            except Exception:
                pass
            return

        try:
            while _time.time() < deadline:
                if not self._stream_authorization_is_current():
                    return
                if lease.wait(timeout=5):
                    return

                # Re-sign + re-emit only if it changed.
                try:
                    sig = _commands_signature(cwd, provider=provider)
                except Exception:
                    sig = last_sig

                if sig != last_sig:
                    try:
                        payload = _commands_frame(sig)
                        self.wfile.write(b"event: catalog\ndata: " + payload + b"\n\n")
                        self.wfile.flush()
                        last_sig = sig
                    except (BrokenPipeError, ConnectionResetError):
                        return
                    except Exception:
                        pass

                if _time.time() - last_keepalive >= 20:
                    try:
                        self.wfile.write(b"event: keepalive\ndata: {}\n\n")
                        self.wfile.flush()
                    except (BrokenPipeError, ConnectionResetError):
                        return
                    last_keepalive = _time.time()

            try:
                self.wfile.write(b"event: done\ndata: {}\n\n")
                self.wfile.flush()
            except Exception:
                pass
        except (BrokenPipeError, ConnectionResetError):
                return

    # ----- /invocations-stream: SSE full invocation catalog snapshots -----
    def _handle_invocations_stream(self, q):
        cwd = q.get("cwd", [""])[0].strip()
        provider = q.get("provider", ["claude"])[0].lower()
        trigger = q.get("trigger", [""])[0].strip() or None
        if not _valid_provider_filter(provider, allow_all=False):
            _send_unknown_provider(self, provider)
            return
        if trigger is not None and trigger not in {"/", "$"}:
            self.send_error(400, "trigger must be / or $")
            return

        self.send_response(200)
        self.send_header("Content-Type", "text/event-stream")
        self.send_header("Cache-Control", "no-store")
        self.send_header("Connection", "keep-alive")
        self.send_header("X-Accel-Buffering", "no")
        self.end_headers()

        last_sig = ""
        last_keepalive = _time.time()
        deadline = _time.time() + 1800

        def _payload() -> bytes:
            items = _build_invocation_catalog(cwd=cwd, provider=provider, trigger=trigger)
            sig_now = _invocations_signature(cwd=cwd, provider=provider, trigger=trigger)
            annotated, extras = _catalog_payload_extras(provider, items, sig_now)
            return json.dumps({
                "schema_version": _INVOCATION_SCHEMA_VERSION,
                "provider": provider,
                "cwd": cwd,
                "count": len(annotated),
                "items": annotated,
                **extras,
            }).encode()

        try:
            sig = _invocations_signature(cwd=cwd, provider=provider, trigger=trigger)
            self.wfile.write(b"event: catalog\ndata: " + _payload() + b"\n\n")
            self.wfile.flush()
            last_sig = sig
        except (BrokenPipeError, ConnectionResetError):
            return
        except Exception:
            try:
                self.wfile.write(b"event: error\ndata: {}\n\n")
                self.wfile.flush()
            except Exception:
                pass
            return

        try:
            while _time.time() < deadline:
                if not self._stream_authorization_is_current():
                    return
                _time.sleep(5)
                try:
                    sig = _invocations_signature(cwd=cwd, provider=provider, trigger=trigger)
                except Exception:
                    sig = last_sig
                if sig != last_sig:
                    try:
                        self.wfile.write(b"event: catalog\ndata: " + _payload() + b"\n\n")
                        self.wfile.flush()
                        last_sig = sig
                    except (BrokenPipeError, ConnectionResetError):
                        return
                    except Exception:
                        pass
                if _time.time() - last_keepalive >= 20:
                    try:
                        self.wfile.write(b"event: keepalive\ndata: {}\n\n")
                        self.wfile.flush()
                    except (BrokenPipeError, ConnectionResetError):
                        return
                    last_keepalive = _time.time()
            try:
                self.wfile.write(b"event: done\ndata: {}\n\n")
                self.wfile.flush()
            except Exception:
                pass
        except (BrokenPipeError, ConnectionResetError):
            return

    # ----- /compose/recordings/sync: verified PairDrop audio to Mac library -----
    def _compose_recording_store(self):
        if ComposeRecordingStore is None:
            raise RuntimeError("Compose recording store unavailable")
        return ComposeRecordingStore(HOME)

    def _send_compose_recording_error(self, error, *, status: int | None = None):
        code = str(getattr(error, "code", None) or "compose_sync_failed")
        resolved_status = int(status or getattr(error, "status", 400) or 400)
        self._send_json({
            "ok": False,
            "error": {
                "code": code,
                "message": code.replace("_", " "),
            },
        }, status=resolved_status)

    def _handle_compose_recording_sync(self):
        if ComposeRecordingStore is None:
            self._send_json({
                "ok": False,
                "error": {
                    "code": "compose_store_unavailable",
                    "message": "compose store unavailable",
                },
            }, status=503)
            return
        try:
            payload = json.loads(self._read_body() or b"{}")
        except (ValueError, json.JSONDecodeError, UnicodeDecodeError):
            self._send_compose_recording_error(
                ComposeRecordingStoreError("bad_json"), status=400
            )
            return
        if not isinstance(payload, dict):
            self._send_compose_recording_error(
                ComposeRecordingStoreError("bad_json"), status=400
            )
            return
        pairdrop_file_id = payload.get("pairdrop_file_id")
        if not isinstance(pairdrop_file_id, str):
            self._send_compose_recording_error(
                ComposeRecordingStoreError("bad_pairdrop_file_id"), status=400
            )
            return
        try:
            source_device_id, source_install_id = self._pairdrop_source()
            descriptor = self._pairdrop_store().verified_read_descriptor(
                pairdrop_file_id,
                source_device_id=source_device_id,
                source_install_id=source_install_id,
                required_source_route="pairling-connectd",
            )
            receipt = self._compose_recording_store().sync(
                item_id=payload.get("item_id"),
                audio_descriptor=descriptor,
                transcript=payload.get("transcript"),
                synthesis=payload.get("synthesis"),
                prompt=payload.get("prompt"),
                metadata=payload.get("metadata"),
            )
        except PairDropStoreError as error:
            code = str(getattr(error, "code", ""))
            if code in {"not_found", "deleted", "missing_object"}:
                status = 404
            elif code in {
                "byte_size_mismatch",
                "sha256_mismatch",
                "object_escape",
                "missing_sha256",
                "wrong_source",
                "wrong_source_route",
            }:
                status = 409
            else:
                status = 400
            self._send_compose_recording_error(error, status=status)
            return
        except ComposeRecordingStoreError as error:
            self._send_compose_recording_error(error)
            return
        except Exception:
            self._send_compose_recording_error(
                RuntimeError("compose_sync_failed"), status=500
            )
            return
        self._send_json(receipt)

    # ----- /pairdrop/*: private Mac-backed Pairling Connect file vault -----
    def _pairdrop_store(self):
        global _PAIRDROP_STORE_SINGLETON
        if PairDropStore is None:
            raise RuntimeError("PairDrop store unavailable")
        if _PAIRDROP_STORE_SINGLETON is None:
            with _PAIRDROP_STORE_SINGLETON_LOCK:
                if _PAIRDROP_STORE_SINGLETON is None:
                    _PAIRDROP_STORE_SINGLETON = PairDropStore(pairdrop_root())
        return _PAIRDROP_STORE_SINGLETON

    def _pairdrop_source(self) -> tuple[str, str]:
        auth = getattr(self, "pairling_auth", None)
        return (
            str(getattr(auth, "device_id", "") or ""),
            str(getattr(auth, "install_id", "") or ""),
        )

    def _pairdrop_source_route(self) -> str:
        return str(self.headers.get("X-Pairling-Connect-Gateway") or "").strip()

    def _send_pairdrop_error(self, err, *, status: int = 400):
        code = getattr(err, "code", None) or str(err) or "pairdrop_error"
        if code == "transfer_too_large":
            status = 413
        elif code == "insufficient_storage":
            status = 507
        elif code == "free_space_unavailable":
            status = 503
        messages = {
            "transfer_too_large": "PairDrop file exceeds the configured transfer limit",
            "insufficient_storage": "PairDrop does not have enough reserved free space",
            "free_space_unavailable": "PairDrop could not verify free disk space",
        }
        self._send_json({
            "ok": False,
            "error": {
                "code": code,
                "message": messages.get(code, code.replace("_", " ")),
            },
        }, status=status)

    def _route_pairdrop_path(self, path: str, q):
        try:
            if path == "/pairdrop/files":
                if self.command == "GET":
                    self._handle_pairdrop_list(q)
                    return
                if self.command == "POST":
                    self._handle_pairdrop_upload(q)
                    return
                self.send_error(405, "method not allowed")
                return
            if path == "/pairdrop/events":
                if self.command != "GET":
                    self.send_error(405, "GET required")
                    return
                self._handle_pairdrop_events(q)
                return
            content_id = _pairdrop_file_content_id(path)
            if content_id is not None:
                if self.command != "GET":
                    self.send_error(405, "GET required")
                    return
                self._handle_pairdrop_content(content_id)
                return
            if path == "/pairdrop/maintenance/cleanup-partials":
                if self.command != "POST":
                    self.send_error(405, "POST required")
                    return
                self._handle_pairdrop_cleanup(q)
                return
            if path == "/pairdrop/uploads":
                if self.command != "POST":
                    self.send_error(405, "POST required")
                    return
                self._handle_pairdrop_upload_session_create()
                return
            upload_bytes_id = _pairdrop_upload_bytes_id(path)
            if upload_bytes_id is not None:
                if self.command != "PUT":
                    self.send_error(405, "PUT required")
                    return
                self._handle_pairdrop_upload_session_bytes(upload_bytes_id)
                return
            upload_complete_id = _pairdrop_upload_complete_id(path)
            if upload_complete_id is not None:
                if self.command != "POST":
                    self.send_error(405, "POST required")
                    return
                self._handle_pairdrop_upload_session_complete(upload_complete_id)
                return
            upload_id = _pairdrop_upload_id_from_path(path)
            if upload_id is not None:
                if self.command == "GET":
                    self._handle_pairdrop_upload_session_get(upload_id)
                    return
                if self.command == "DELETE":
                    self._handle_pairdrop_upload_session_cancel(upload_id)
                    return
                self.send_error(405, "method not allowed")
                return
            attach_id = _pairdrop_attach_file_id(path)
            if attach_id is not None:
                if self.command != "POST":
                    self.send_error(405, "POST required")
                    return
                self._handle_pairdrop_attach(attach_id, q)
                return
            file_id = _pairdrop_file_id_from_path(path)
            if file_id is not None:
                if self.command == "GET":
                    self._handle_pairdrop_get(file_id, q)
                    return
                if self.command == "DELETE":
                    self._handle_pairdrop_delete(file_id)
                    return
                self.send_error(405, "method not allowed")
                return
            self.send_error(404, "PairDrop route not found")
        except PairDropStoreError as e:
            code = str(getattr(e, "code", "") or "")
            if code in {
                "not_found",
                "deleted",
                "missing_object",
                "upload_not_found",
                "attachment_not_found",
            }:
                status = 404
            elif code.startswith("attachment_") or code in {
                "byte_size_mismatch",
                "sha256_mismatch",
                "object_escape",
            }:
                status = 409
            else:
                status = 400
            self._send_pairdrop_error(e, status=status)
        except OSError as exc:
            if exc.errno in {errno.ENOSPC, getattr(errno, "EDQUOT", -1)}:
                self._send_pairdrop_error(
                    PairDropStoreError("insufficient_storage"),
                    status=507,
                )
                return
            Handler._send_unexpected_pairdrop_error(self, path, exc)
        except sqlite3.OperationalError as exc:
            if "full" in str(exc).lower():
                self._send_pairdrop_error(
                    PairDropStoreError("insufficient_storage"),
                    status=507,
                )
                return
            Handler._send_unexpected_pairdrop_error(self, path, exc)
        except Exception as exc:
            Handler._send_unexpected_pairdrop_error(self, path, exc)

    def _send_unexpected_pairdrop_error(self, path: str, exc: Exception) -> None:
        correlation_id = "pd_err_" + secrets.token_hex(8)
        diagnostic = redact_public_diagnostic({
            "event": "pairdrop.request_failed",
            "correlation_id": correlation_id,
            "route_family": _rate_limit_key_path(path),
            "exception_type": type(exc).__name__,
            "exception_message": str(exc),
            "device_id": str(
                getattr(getattr(self, "pairling_auth", None), "device_id", "")
                or ""
            ),
        })
        print(
            "[pairdrop-error] " + json.dumps(diagnostic, sort_keys=True),
            file=sys.stderr,
            flush=True,
        )
        self._send_json({
            "ok": False,
            "error": {
                "code": "pairdrop_failed",
                "message": "PairDrop could not complete the request",
                "correlation_id": correlation_id,
            },
        }, status=500)

    def _handle_pairdrop_upload(self, q):
        filename = q.get("filename", [""])[0]
        if not filename:
            self._send_json({"ok": False, "error": {"code": "filename_required"}}, status=400)
            return
        body = self._read_body()
        content_type = self.headers.get("Content-Type") or q.get("content_type", ["application/octet-stream"])[0]
        expected_sha256 = q.get("sha256", [""])[0].strip() or None
        session_hint = q.get("session", [""])[0].strip()
        device_id, install_id = self._pairdrop_source()
        item = self._pairdrop_store().upload_bytes(
            filename=filename,
            content_type=content_type,
            data=body,
            source_device_id=device_id,
            source_install_id=install_id,
            session_hint=session_hint,
            expected_sha256=expected_sha256,
        )
        item = self._public_pairdrop_file(item)
        self._send_json({"ok": True, "file": item}, status=201)

    def _read_pairdrop_json_object(self) -> dict:
        body = self._read_body()
        if not body:
            return {}
        try:
            value = json.loads(body.decode("utf-8"))
        except Exception:
            raise PairDropStoreError("bad_json")
        if not isinstance(value, dict):
            raise PairDropStoreError("bad_json")
        return value

    def _public_upload_session(self, session: dict) -> dict:
        return {
            key: session.get(key)
            for key in (
                "upload_id",
                "file_id",
                "display_name",
                "original_name",
                "content_type",
                "total_byte_count",
                "expected_sha256",
                "verified_offset",
                "state",
                "last_error",
                "created_at",
                "updated_at",
                "expires_at",
            )
        }

    def _public_pairdrop_file(self, item: dict) -> dict:
        return {
            key: item.get(key)
            for key in (
                "id",
                "parent_id",
                "kind",
                "display_name",
                "content_type",
                "byte_size",
                "sha256",
                "created_at",
                "updated_at",
                "deleted_at",
                "last_opened_at",
                "tags",
            )
        }

    def _pairdrop_attachment_session(self, raw_session: str) -> str:
        provider, native_id = _parse_agent_session_ref(raw_session)
        if (
            ":" not in raw_session
            or not native_id
            or not _valid_provider_filter(provider, allow_all=False)
            or provider not in _agent_provider_ids()
        ):
            raise PairDropStoreError("bad_attachment_session")
        canonical, registry_row = _session_mutation_receipt_identity(
            self,
            _qualified_session_id(provider, native_id),
        )
        if not canonical or registry_row is None or registry_row.get("closed_at") is not None:
            raise PairDropStoreError("attachment_session_unavailable")
        return canonical

    @staticmethod
    def _public_attachment_handle(attachment: dict) -> dict:
        return {
            "ok": attachment.get("ok") is True,
            "id": attachment.get("id"),
            "handle_id": attachment.get("handle_id"),
            "display_name": attachment.get("display_name"),
            "mime_type": attachment.get("content_type"),
            "size_bytes": attachment.get("byte_size"),
            "sha256": attachment.get("sha256"),
            "expires_at": attachment.get("expires_at"),
            "idempotent": attachment.get("idempotent") is True,
        }

    def _handle_pairdrop_upload_session_create(self):
        payload = self._read_pairdrop_json_object()
        filename_value = payload.get("filename")
        if not isinstance(filename_value, str):
            raise PairDropStoreError("bad_filename")
        filename = filename_value.strip()
        if not filename:
            raise PairDropStoreError("filename_required")
        total = payload.get("total_byte_count", payload.get("byte_size", 0))
        expected_sha256_value = payload.get(
            "sha256",
            payload.get("expected_sha256"),
        )
        if not isinstance(expected_sha256_value, str):
            raise PairDropStoreError("bad_expected_sha256")
        expected_sha256 = expected_sha256_value.strip()
        content_type = payload.get("content_type", "application/octet-stream")
        if not isinstance(content_type, str):
            raise PairDropStoreError("bad_content_type")
        create_idempotency_key = payload.get("create_idempotency_key")
        device_id, install_id = self._pairdrop_source()
        session = self._pairdrop_store().create_upload_session(
            filename=filename,
            content_type=content_type,
            total_byte_count=total,
            expected_sha256=expected_sha256,
            source_device_id=device_id,
            source_install_id=install_id,
            source_route=self._pairdrop_source_route(),
            create_idempotency_key=create_idempotency_key,
        )
        self._send_json({"ok": True, "upload": self._public_upload_session(session)}, status=201)

    def _handle_pairdrop_upload_session_get(self, upload_id: str):
        device_id, install_id = self._pairdrop_source()
        session = self._pairdrop_store().get_upload_session(
            upload_id,
            source_device_id=device_id,
            source_install_id=install_id,
        )
        self._send_json({"ok": True, "upload": self._public_upload_session(session)})

    def _pairdrop_chunk_offset(self, body_len: int) -> tuple[int, int | None]:
        content_range = str(self.headers.get("Content-Range") or "").strip()
        if content_range:
            match = re.fullmatch(r"bytes\s+(\d+)-(\d+)/(\d+|\*)", content_range)
            if not match:
                raise PairDropStoreError("bad_content_range")
            numeric_parts = [match.group(1), match.group(2)]
            if match.group(3) != "*":
                numeric_parts.append(match.group(3))
            if any(len(part) > 20 for part in numeric_parts):
                raise PairDropStoreError("bad_content_range")
            try:
                start = int(match.group(1))
                end = int(match.group(2))
                declared_total = (
                    None if match.group(3) == "*" else int(match.group(3))
                )
            except ValueError as exc:
                raise PairDropStoreError("bad_content_range") from exc
            if end < start or (end - start + 1) != body_len:
                raise PairDropStoreError("content_range_mismatch")
            return start, declared_total
        offset = str(self.headers.get("X-PairDrop-Offset") or "").strip()
        if offset:
            if len(offset) > 20 or not re.fullmatch(r"\d+", offset):
                raise PairDropStoreError("bad_offset")
            try:
                return int(offset), None
            except ValueError as exc:
                raise PairDropStoreError("bad_offset") from exc
        raise PairDropStoreError("offset_required")

    def _handle_pairdrop_upload_session_bytes(self, upload_id: str):
        body = self._read_body()
        chunk_sha256 = str(self.headers.get("X-PairDrop-Chunk-SHA256") or "").strip()
        idempotency_key = str(self.headers.get("Idempotency-Key") or "").strip()
        offset, declared_total = self._pairdrop_chunk_offset(len(body))
        device_id, install_id = self._pairdrop_source()
        session = self._pairdrop_store().write_upload_chunk(
            upload_id,
            offset=offset,
            declared_total_byte_count=declared_total,
            data=body,
            chunk_sha256=chunk_sha256,
            idempotency_key=idempotency_key,
            source_device_id=device_id,
            source_install_id=install_id,
        )
        self._send_json({"ok": True, "upload": self._public_upload_session(session)})

    def _handle_pairdrop_upload_session_complete(self, upload_id: str):
        device_id, install_id = self._pairdrop_source()
        result = self._pairdrop_store().complete_upload_session(
            upload_id,
            source_device_id=device_id,
            source_install_id=install_id,
        )
        file = self._public_pairdrop_file(result["file"])
        self._send_json({"ok": True, "state": result["state"], "upload_id": upload_id, "file": file}, status=201)

    def _handle_pairdrop_upload_session_cancel(self, upload_id: str):
        device_id, install_id = self._pairdrop_source()
        session = self._pairdrop_store().cancel_upload_session(
            upload_id,
            source_device_id=device_id,
            source_install_id=install_id,
        )
        self._send_json({"ok": True, "upload": self._public_upload_session(session)})

    def _handle_pairdrop_list(self, q):
        if q.get("include_deleted", ["false"])[0].lower() == "true":
            raise PairDropStoreError("include_deleted_not_supported")
        raw_limit = q.get("limit", ["100"])[0]
        if not re.fullmatch(r"\d+", raw_limit):
            raise PairDropStoreError("bad_limit")
        cursor = q.get("cursor", [None])[0]
        page = self._pairdrop_store().list_files_page(
            limit=int(raw_limit),
            cursor=cursor,
        )
        files = [self._public_pairdrop_file(item) for item in page["files"]]
        self._send_json({
            "ok": True,
            "schema_version": 2,
            "files": files,
            "page": {
                "limit": page["limit"],
                "has_more": page["has_more"],
                "next_cursor": page["next_cursor"],
            },
        })

    def _handle_pairdrop_get(self, file_id: str, q):
        if q.get("download", ["false"])[0].lower() in {"1", "true", "yes"}:
            self._handle_pairdrop_download(file_id)
            return
        item = self._pairdrop_store().get_file(file_id)
        item = self._public_pairdrop_file(item)
        self._send_json({"ok": True, "file": item})

    def _handle_pairdrop_download(self, file_id: str):
        with self._pairdrop_store().open_download(file_id) as descriptor:
            item = descriptor["item"]
            handle = descriptor["handle"]
            display_name = str(item.get("display_name") or "pairdrop-file")
            content_type = _pairdrop_safe_content_type(
                str(item.get("content_type") or "application/octet-stream")
            )
            byte_size = int(descriptor["stat"].st_size)
            self.send_response(200)
            self.send_header("Content-Type", content_type)
            self.send_header("Content-Length", str(byte_size))
            self.send_header(
                "Content-Disposition",
                _pairdrop_content_disposition(display_name),
            )
            self.send_header("X-PairDrop-File-ID", str(item.get("id") or file_id))
            self.end_headers()
            while True:
                chunk = handle.read(1024 * 256)
                if not chunk:
                    break
                self.wfile.write(chunk)

    def _handle_pairdrop_content(self, file_id: str):
        with self._pairdrop_store().open_download(file_id) as descriptor:
            item = descriptor["item"]
            handle = descriptor["handle"]
            total = int(descriptor["stat"].st_size)
            digest = str(item.get("sha256") or "")
            if not digest:
                raise PairDropStoreError("missing_sha256")

            range_header = str(self.headers.get("Range") or "").strip()
            if_range = str(self.headers.get("If-Range") or "").strip()
            if if_range and if_range != f'"{digest}"':
                range_header = ""

            try:
                start, end, partial = _parse_single_byte_range(range_header, total)
            except PairDropStoreError as exc:
                if exc.code == "range_not_satisfiable":
                    body = (
                        b'{"ok":false,"error":{"code":"range_not_satisfiable",'
                        b'"message":"range not satisfiable"}}'
                    )
                    self.send_response(416)
                    self.send_header("Content-Type", "application/json")
                    self.send_header("Content-Range", f"bytes */{total}")
                    self.send_header("Content-Length", str(len(body)))
                    self.end_headers()
                    self.wfile.write(body)
                    return
                raise

            display_name = str(item.get("display_name") or "pairdrop-file")
            content_type = _pairdrop_safe_content_type(
                str(item.get("content_type") or "application/octet-stream")
            )
            length = end - start + 1
            self.send_response(206 if partial else 200)
            self.send_header("Accept-Ranges", "bytes")
            self.send_header("ETag", f'"{digest}"')
            self.send_header("Content-Type", content_type)
            self.send_header("Content-Length", str(length))
            self.send_header(
                "Content-Disposition",
                _pairdrop_content_disposition(display_name),
            )
            self.send_header("X-PairDrop-File-ID", str(item.get("id") or file_id))
            self.send_header("X-PairDrop-SHA256", digest)
            if partial:
                self.send_header("Content-Range", f"bytes {start}-{end}/{total}")
            self.end_headers()
            handle.seek(start)
            remaining = length
            while remaining > 0:
                chunk = handle.read(min(256 * 1024, remaining))
                if not chunk:
                    break
                self.wfile.write(chunk)
                remaining -= len(chunk)

    def _handle_pairdrop_delete(self, file_id: str):
        self._send_json(self._pairdrop_store().delete_file(file_id))

    def _handle_pairdrop_attach(self, file_id: str, q):
        raw_session = q.get("session", [""])[0].strip()
        session_id = self._pairdrop_attachment_session(raw_session)
        payload = self._read_pairdrop_json_object()
        idempotency_key = str(
            payload.get("client_action_id")
            or self.headers.get("Idempotency-Key")
            or self.headers.get("X-Pairling-Action-Id")
            or ""
        ).strip()
        device_id, install_id = self._pairdrop_source()
        attachment = self._pairdrop_store().create_attachment_handle(
            file_id,
            session_id=session_id,
            source_device_id=device_id,
            source_install_id=install_id,
            idempotency_key=idempotency_key,
        )
        self._send_json(self._public_attachment_handle(attachment))

    def _handle_pairdrop_events(self, q):
        try:
            since = int(q.get("since", ["0"])[0] or "0")
        except ValueError:
            since = 0
        self._send_json({"ok": True, "events": self._pairdrop_store().events_since(since)})

    def _handle_pairdrop_cleanup(self, q):
        try:
            older = int(q.get("older_than_seconds", ["3600"])[0] or "3600")
        except ValueError:
            older = 3600
        self._send_json(self._pairdrop_store().cleanup_partials(older_than_seconds=older))

    # ----- /upload: compatibility upload into PairDrop's opaque capability store -----
    def _handle_upload(self, q):
        filename = q.get("filename", [""])[0].strip()
        if not filename:
            self.send_error(400, "filename required")
            return
        raw_session = q.get("session", [""])[0].strip()
        provider, native_id = _parse_agent_session_ref(raw_session)
        if native_id and not _provider_supports(provider, "upload"):
            _send_unsupported_provider(self, provider, "upload")
            return
        session_id = self._pairdrop_attachment_session(raw_session)
        body = self._read_body()
        if len(body) > MAX_UPLOAD_BODY_BYTES:
            self.send_error(413, "file too large")
            return
        if not body:
            self.send_error(400, "empty body")
            return
        idempotency_key = str(
            self.headers.get("Idempotency-Key")
            or self.headers.get("X-Pairling-Action-Id")
            or ""
        ).strip()
        if not idempotency_key:
            raise PairDropStoreError("bad_attachment_idempotency_key")
        device_id, install_id = self._pairdrop_source()
        store = self._pairdrop_store()
        item = store.upload_bytes(
            filename=filename,
            content_type=(
                self.headers.get("Content-Type")
                or "application/octet-stream"
            ),
            data=body,
            source_device_id=device_id,
            source_install_id=install_id,
            session_hint=session_id,
        )
        attachment = store.create_attachment_handle(
            str(item["id"]),
            session_id=session_id,
            source_device_id=device_id,
            source_install_id=install_id,
            idempotency_key=idempotency_key,
        )
        self._send_json(self._public_attachment_handle(attachment))

    def _lookup_project(self, session_id: str) -> str:
        session_id = _claude_native_session_id(session_id)
        if not session_id:
            return ""
        return str(_claude_sessions_backend().lookup_field(session_id, "project") or "")

    # ----- /turn-state-stream: SSE stream of per-session state transitions -----
    def _handle_turn_state_stream(self, q):
        """Server-Sent Events stream of {state, tool, started_at, effort} for
        one session. State events come from the state-track hook on Mac, which
        writes ~/.claude/turn-state/<claude_uuid>.json on every turn-relevant
        event (UserPromptSubmit / PreToolUse / PostToolUse / Stop).

        We poll the file's mtime at 250ms cadence and emit SSE only when the
        payload changes. 10-minute connection cap (iOS reconnects).

        SSE event types:
          event: state      data: {<full state JSON>}
          event: keepalive  data: {} (every 20s, prevents NAT timeout)
          event: done       data: {} (cap reached or session vanished)
        """
        raw_session = q.get("session", [""])[0]
        provider, session_id = _parse_agent_session_ref(raw_session)
        if not session_id:
            self.send_error(400, "session required")
            return

        if provider in {"codex", "omp"}:
            self._handle_managed_turn_state_stream(provider, session_id)
            return
        session_id = _claude_native_session_id(raw_session)
        if not session_id:
            self.send_error(400, "session required")
            return

        # Race-aware lookup: a freshly-spawned terminal may not have
        # claude_uuid in PG yet (claude bin + session-register hook + asyncpg
        # INSERT pipeline takes ~500ms-2s). LISTEN session_ready instead of
        # immediate 404 — session-register issues NOTIFY session_ready, '<id>'
        # the moment the row hits PG with claude_uuid populated. Falls back
        # to short polling if LISTEN doesn't fire (asyncpg unavailable etc.).
        uuid = self._lookup_claude_uuid(session_id)
        if not uuid:
            uuid = self._wait_for_session_ready(session_id, timeout_s=8.0)
        if not uuid:
            self.send_error(404, "no claude_uuid for session")
            return

        if not re.match(r'^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$', uuid, re.IGNORECASE):
            self.send_error(500, "invalid claude_uuid in PG row")
            return

        state_path = _turn_state_path("claude", uuid)

        self.send_response(200)
        self.send_header("Content-Type", "text/event-stream")
        self.send_header("Cache-Control", "no-store")
        self.send_header("Connection", "keep-alive")
        self.send_header("X-Accel-Buffering", "no")
        self.end_headers()

        last_payload: bytes | None = None
        last_keepalive = _time.time()
        deadline = _time.time() + 600  # 10 min

        def provider_payload(raw: bytes) -> bytes:
            try:
                obj = json.loads(raw.decode("utf-8", errors="replace"))
                if isinstance(obj, dict):
                    obj["session_id"] = _qualified_session_id("claude", session_id)
                    obj["provider"] = "claude"
                    obj["native_id"] = session_id
                    return json.dumps(obj).encode()
            except Exception:
                pass
            return raw

        # Emit initial state immediately if file exists, so the client sees
        # current state without waiting for the next transition.
        try:
            if state_path.is_file():
                payload = provider_payload(state_path.read_bytes())
                self.wfile.write(b"event: state\ndata: " + payload + b"\n\n")
                self.wfile.flush()
                last_payload = payload
        except Exception:
            pass

        turn_wakes = SESSION_EVENT_HUB.subscribe(f"turn:claude:{uuid}") if SESSION_EVENT_HUB is not None else None
        try:
            while _time.time() < deadline:
                if not self._stream_authorization_is_current():
                    return
                if turn_wakes is not None:
                    wake = turn_wakes.get(timeout=1.0)
                    while wake is not None:
                        wake = turn_wakes.get(timeout=0)
                else:
                    _time.sleep(0.25)
                # Re-read file; emit only if content changed.
                try:
                    if state_path.is_file():
                        payload = provider_payload(state_path.read_bytes())
                        if payload and payload != last_payload:
                            self.wfile.write(b"event: state\ndata: " + payload + b"\n\n")
                            self.wfile.flush()
                            last_payload = payload
                except (BrokenPipeError, ConnectionResetError):
                    return
                except Exception:
                    pass

                if _time.time() - last_keepalive >= 20:
                    try:
                        self.wfile.write(b"event: keepalive\ndata: {}\n\n")
                        self.wfile.flush()
                    except (BrokenPipeError, ConnectionResetError):
                        return
                    last_keepalive = _time.time()

            try:
                self.wfile.write(b"event: done\ndata: {}\n\n")
                self.wfile.flush()
            except Exception:
                pass
        except (BrokenPipeError, ConnectionResetError):
            return
        finally:
            if turn_wakes is not None:
                turn_wakes.close()

    def _handle_managed_turn_state_stream(
        self,
        provider: str,
        native_id: str,
    ):
        if provider not in {"codex", "omp"} or not _safe_agent_native_id(native_id):
            self.send_error(400, "bad managed provider session id")
            return
        native_id = _agent_registry_resolve_native_alias(provider, native_id)
        if not _safe_agent_native_id(native_id):
            self.send_error(400, "bad managed provider session id")
            return

        self.send_response(200)
        self.send_header("Content-Type", "text/event-stream")
        self.send_header("Cache-Control", "no-store")
        self.send_header("Connection", "keep-alive")
        self.send_header("X-Accel-Buffering", "no")
        self.end_headers()

        last_payload: bytes | None = None
        last_keepalive = _time.time()
        deadline = _time.time() + 600

        def payload_bytes() -> bytes | None:
            obj = _managed_turn_state_payload(provider, native_id)
            if not obj:
                return None
            return json.dumps(obj, sort_keys=True).encode()

        try:
            initial = payload_bytes()
            if initial:
                self.wfile.write(b"event: state\ndata: " + initial + b"\n\n")
                self.wfile.flush()
                last_payload = initial
        except (BrokenPipeError, ConnectionResetError):
            return
        except Exception:
            pass

        turn_wakes = (
            SESSION_EVENT_HUB.subscribe(f"turn:{provider}:{native_id}")
            if SESSION_EVENT_HUB is not None
            else None
        )
        try:
            while _time.time() < deadline:
                if not self._stream_authorization_is_current():
                    return
                if turn_wakes is not None:
                    wake = turn_wakes.get(timeout=1.0)
                    while wake is not None:
                        wake = turn_wakes.get(timeout=0)
                else:
                    _time.sleep(0.25)
                try:
                    payload = payload_bytes()
                    if payload and payload != last_payload:
                        self.wfile.write(b"event: state\ndata: " + payload + b"\n\n")
                        self.wfile.flush()
                        last_payload = payload
                except (BrokenPipeError, ConnectionResetError):
                    return
                except Exception:
                    pass

                if _time.time() - last_keepalive >= 20:
                    try:
                        self.wfile.write(b"event: keepalive\ndata: {}\n\n")
                        self.wfile.flush()
                    except (BrokenPipeError, ConnectionResetError):
                        return
                    last_keepalive = _time.time()

            try:
                self.wfile.write(b"event: done\ndata: {}\n\n")
                self.wfile.flush()
            except Exception:
                pass
        except (BrokenPipeError, ConnectionResetError):
            return
        finally:
            if turn_wakes is not None:
                turn_wakes.close()

    def _lookup_claude_uuid(self, session_id: str) -> str:
        return _lookup_claude_uuid_for_session(session_id)

    # ----- PG lookup helpers (used by send-text + sigint) -----
    def _wait_for_session_ready(self, session_id: str, timeout_s: float = 8.0) -> str:
        """Block up to timeout_s waiting for the session row to appear in PG
        with a populated claude_uuid. Subscribes to PG channel `session_ready`
        which session-register fires post-INSERT, falling back to short
        polling if asyncpg isn't importable. Returns the claude_uuid string
        on success, "" on timeout / PG unreachable."""
        session_id = _claude_native_session_id(session_id)
        if not session_id:
            return ""
        if _session_backend() == "sqlite":
            return self._wait_for_session_ready_sqlite(session_id, timeout_s)
        try:
            import asyncio
            import asyncpg  # type: ignore
        except Exception:
            # asyncpg missing — fall back to 200ms polling.
            deadline = _time.time() + timeout_s
            while _time.time() < deadline:
                _time.sleep(0.2)
                u = self._lookup_claude_uuid(session_id)
                if u:
                    return u
            return ""

        pg_url = (
            os.environ.get("CONTINUOUS_CLAUDE_DB_URL")
            or os.environ.get("DATABASE_URL")
        )
        if not pg_url:
            # Item-8 postgres hardening (2026-05-06): TCP auth on
            # localhost:5432 is scram-sha-256 with per-role secret files;
            # claude:claude_dev no longer authenticates. cc_app is the
            # designated application role.
            try:
                with open(
                    os.path.expanduser(
                        "~/.claude/secrets/postgres-cc_app-password"
                    ),
                    "r",
                    encoding="utf-8",
                ) as fh:
                    _cc_app_pw = fh.read().strip()
            except OSError:
                _cc_app_pw = ""
            if _cc_app_pw:
                from urllib.parse import quote as _pg_quote

                pg_url = (
                    "postgresql://cc_app:"
                    + _pg_quote(_cc_app_pw, safe="")
                    + "@localhost:5432/continuous_claude"
                )
            else:
                pg_url = "postgresql://claude:claude_dev@localhost:5432/continuous_claude"

        async def _wait() -> str:
            conn = await asyncpg.connect(pg_url)
            try:
                # Re-check after the connection is up: the row may have
                # arrived between the caller's first lookup and our LISTEN.
                row = await conn.fetchrow(
                    "SELECT claude_uuid FROM sessions WHERE id = $1", session_id
                )
                if row and row["claude_uuid"]:
                    return row["claude_uuid"]

                evt = asyncio.Event()
                hit = {"uuid": ""}

                def _cb(_c, _pid, _channel, payload):
                    if payload == session_id:
                        evt.set()

                await conn.add_listener("session_ready", _cb)
                try:
                    await asyncio.wait_for(evt.wait(), timeout=timeout_s)
                except asyncio.TimeoutError:
                    pass

                row = await conn.fetchrow(
                    "SELECT claude_uuid FROM sessions WHERE id = $1", session_id
                )
                if row and row["claude_uuid"]:
                    hit["uuid"] = row["claude_uuid"]
                return hit["uuid"]
            finally:
                try:
                    await conn.close()
                except Exception:
                    pass

        try:
            return asyncio.run(_wait())
        except Exception:
            return ""

    def _wait_for_session_ready_sqlite(self, session_id: str, timeout_s: float) -> str:
        """In-process replacement for the asyncpg LISTEN path: the internal
        register endpoint sets a threading.Event keyed by session id; we wake
        on it, with 200ms registry polling as the safety net (covers register
        landing between our registry check and the event subscription)."""
        evt = _session_ready_event(session_id)
        try:
            deadline = _time.time() + max(0.1, float(timeout_s))
            while True:
                row = _agent_registry_get("claude", session_id)
                if row and row.get("claude_uuid"):
                    return str(row["claude_uuid"])
                remaining = deadline - _time.time()
                if remaining <= 0:
                    return ""
                if evt.wait(timeout=min(0.2, remaining)):
                    evt.clear()
        finally:
            _discard_session_ready_event(session_id)

    def _lookup_session_age_seconds(self, session_id: str):
        """Returns seconds since the session row was inserted, or None if the
        row is missing / backend is unreachable. Used by /send-text to gate
        very-fresh terminals before bracketed-paste markers are honored."""
        session_id = _claude_native_session_id(session_id)
        if not session_id:
            return None
        canonical_id = _agent_registry_resolve_native_alias("claude", session_id)
        registry_row = _agent_registry_get("claude", canonical_id)
        if registry_row and registry_row.get("started_at"):
            return max(0.0, _time.time() - float(registry_row["started_at"]))
        return _claude_sessions_backend().session_age_seconds(canonical_id)

    def _lookup_terminal_tty(self, session_id: str) -> str:
        session_id = _claude_native_session_id(session_id)
        if not session_id:
            return ""
        canonical_id = _agent_registry_resolve_native_alias("claude", session_id)
        registry_row = _agent_registry_get("claude", canonical_id)
        registry_tty = str((registry_row or {}).get("terminal_tty") or "")
        return registry_tty or _claude_sessions_backend().terminal_tty(canonical_id)

    def _lookup_claude_pid(self, session_id: str) -> int:
        session_id = _claude_native_session_id(session_id)
        if not session_id:
            return 0
        canonical_id = _agent_registry_resolve_native_alias("claude", session_id)
        registry_row = _agent_registry_get("claude", canonical_id)
        registry_pid = int((registry_row or {}).get("pid") or 0)
        return registry_pid or _claude_sessions_backend().claude_pid(canonical_id)

    # ----- /llm-route-stream: SSE streaming variant -----
    def _handle_llm_route_stream(self, q):
        """Same input as /llm-route but streams output via Server-Sent Events.
        SSE frames:
          event: chunk     data: <text fragment>
          event: done      data: {}
          event: error     data: {"message": "..."}
        """
        model = q.get("model", ["sonnet"])[0]
        if model not in ("sonnet", "haiku", "opus"):
            self.send_error(400, "model must be sonnet|haiku|opus")
            return

        try:
            payload = json.loads(self._read_body() or b"{}")
        except json.JSONDecodeError:
            self.send_error(400, "body must be JSON")
            return

        prompt = (payload.get("prompt") or "").strip()
        system = (payload.get("system") or "").strip()
        max_chars = int(payload.get("max_chars") or 8000)
        if not prompt:
            self.send_error(400, "prompt required")
            return
        if len(prompt) > max_chars:
            prompt = prompt[:max_chars]

        if run_remote_llm is None:
            self.send_error(503, "remote LLM route helper unavailable")
            return
        try:
            content = run_remote_llm(
                model=model,
                prompt=prompt,
                system=system,
                timeout_seconds=120,
            )
        except Exception as exc:
            status = int(getattr(exc, "status", 502) or 502)
            message = str(getattr(exc, "message", str(exc)) or str(exc))
            self.send_error(status, message)
            return

        # SSE response headers
        self.send_response(200)
        self.send_header("Content-Type", "text/event-stream")
        self.send_header("Cache-Control", "no-store")
        self.send_header("X-Accel-Buffering", "no")
        self.end_headers()

        def write_sse(event: str, data: str):
            try:
                self.wfile.write(f"event: {event}\n".encode())
                # SSE multi-line data: each line prefixed with "data: "
                for line in data.split("\n"):
                    self.wfile.write(f"data: {line}\n".encode())
                self.wfile.write(b"\n")
                self.wfile.flush()
            except (BrokenPipeError, ConnectionResetError):
                # Client disconnected; bail out
                raise

        try:
            proc = subprocess.Popen(
                cmd,
                stdin=subprocess.PIPE,
                stdout=subprocess.PIPE,
                stderr=subprocess.PIPE,
                text=True,
                bufsize=1,
                cwd="/tmp",
                env=_provider_child_environment(),
            )
            # Send the prompt
            assert proc.stdin is not None and proc.stdout is not None and proc.stderr is not None
            proc.stdin.write(prompt)
            proc.stdin.close()

            while True:
                chunk = proc.stdout.read(64)  # small chunks for responsiveness
                if not chunk:
                    break
                try:
                    write_sse("chunk", chunk)
                except (BrokenPipeError, ConnectionResetError):
                    proc.terminate()
                    return

            proc.wait(timeout=120)
            if proc.returncode == 0:
                write_sse("done", json.dumps({"model": model}))
            else:
                err = (proc.stderr.read() or "").strip()[:300]
                write_sse("error", json.dumps({"message": err or "claude exited non-zero"}))
        except subprocess.TimeoutExpired:
            if proc is not None:
                try:
                    proc.kill()
                except Exception:
                    pass
            try:
                write_sse("error", json.dumps({"message": "claude timeout"}))
            except Exception:
                pass
        except Exception as e:
            try:
                write_sse("error", json.dumps({"message": f"{type(e).__name__}: {e}"}))
            except Exception:
                pass

    # ----- /corpus: deterministic Claude + Codex transcript inventory -----
    def _handle_corpus(self, q):
        try:
            since = float(q.get("since", ["0"])[0])
        except ValueError:
            self.send_error(400, "since must be unix timestamp")
            return
        try:
            limit = int(q.get("limit", ["500"])[0])
        except ValueError:
            self.send_error(400, "limit must be int")
            return
        limit = max(1, min(limit, 2000))

        after_mtime_raw = q.get("after_mtime", [None])[0]
        after_session_id = q.get("after_session_id", [None])[0]
        if (after_mtime_raw is None) != (after_session_id is None):
            self.send_error(400, "after_mtime and after_session_id must be supplied together")
            return
        after_key = None
        if after_mtime_raw is not None:
            try:
                after_key = (float(after_mtime_raw), str(after_session_id))
            except ValueError:
                self.send_error(400, "after_mtime must be unix timestamp")
                return

        projects_root = HOME / ".claude" / "projects"
        items = []
        if projects_root.is_dir():
            for project_dir in projects_root.iterdir():
                if not project_dir.is_dir():
                    continue
                if _is_excluded_project_dir_name(project_dir.name):
                    continue
                for p in project_dir.glob("*.jsonl"):
                    try:
                        st = p.stat()
                    except OSError:
                        continue
                    if st.st_mtime >= since:
                        items.append({
                            "session_id": p.stem,
                            "provider": "claude",
                            "project_dir": project_dir.name,
                            "size": st.st_size,
                            "mtime": st.st_mtime,
                        })

        for p, meta in _codex_selected_rollout_entries():
            native_id = str((meta or {}).get("id") or "")
            if not native_id:
                continue
            try:
                st = p.stat()
            except OSError:
                continue
            if st.st_mtime >= since:
                items.append({
                    "session_id": _qualified_session_id("codex", native_id),
                    "provider": "codex",
                    "project_dir": str((meta or {}).get("cwd") or ""),
                    "size": st.st_size,
                    "mtime": st.st_mtime,
                })

        items.sort(key=lambda x: (x["mtime"], x["session_id"]))
        if after_key is not None:
            items = [item for item in items if (item["mtime"], item["session_id"]) > after_key]
        page = items[:limit]
        has_more = len(items) > len(page)
        next_cursor = None
        if has_more and page:
            next_cursor = {
                "mtime": page[-1]["mtime"],
                "session_id": page[-1]["session_id"],
            }
        body = json.dumps({
            "count": len(page),
            "items": page,
            "has_more": has_more,
            "next_cursor": next_cursor,
        }).encode()

        self.send_response(200)
        self.send_header("Content-Type", "application/json")
        self.send_header("Content-Length", str(len(body)))
        self.end_headers()
        self.wfile.write(body)

    # ----- helpers -----
    def _send_text(self, code, body: bytes):
        try:
            self.send_response(code)
            self.send_header("Content-Type", "text/plain")
            self.send_header("Content-Length", str(len(body)))
            self.end_headers()
            self.wfile.write(body)
        except (BrokenPipeError, ConnectionResetError) as exc:
            raise ClientDisconnected() from exc

    def log_message(self, format, *args):
        sys.stderr.write(f"[{self.log_date_time_string()}] {format % args}\n")


class _PairlingThreadingHTTPServer(ThreadingHTTPServer):
    daemon_threads = True
    request_queue_size = max(16, RUNTIME_MAX_ACTIVE_CONNECTIONS)

    def service_actions(self):
        super().service_actions()
        try:
            with _FIRST_PROMPT_DELIVERY_LOCK:
                _ensure_first_prompt_delivery_receipt_retry_worker_locked()
        except Exception:  # noqa: BLE001 - queued truth survives for the next tick
            # The enqueue or worker exit path already logged the start failure.
            # Do not let a temporary thread-start failure stop serve_forever.
            return

    def process_request(self, request, client_address):
        if not _CONNECTION_ADMISSION_SEMAPHORE.acquire(blocking=False):
            body = b'{"ok":false,"error":{"code":"connection_capacity_exceeded","message":"Pairling runtime is busy; retry shortly"},"retry_after":1}\n'
            try:
                request.sendall(
                    b"HTTP/1.1 503 Service Unavailable\r\n"
                    b"Content-Type: application/json\r\n"
                    b"Retry-After: 1\r\n"
                    b"Connection: close\r\n"
                    + f"Content-Length: {len(body)}\r\n\r\n".encode("ascii")
                    + body
                )
            except OSError:
                pass
            finally:
                self.shutdown_request(request)
            return
        try:
            super().process_request(request, client_address)
        except Exception:
            _CONNECTION_ADMISSION_SEMAPHORE.release()
            raise

    def process_request_thread(self, request, client_address):
        try:
            super().process_request_thread(request, client_address)
        finally:
            try:
                _CONNECTION_ADMISSION_SEMAPHORE.release()
            except ValueError:
                pass

    def handle_error(self, request, client_address):
        exc_type, exc, _ = sys.exc_info()
        if isinstance(exc, (BrokenPipeError, ConnectionResetError)) or exc_type in {BrokenPipeError, ConnectionResetError}:
            return
        super().handle_error(request, client_address)

def _peer_uid_for_socket(connection: socket.socket) -> int | None:
    try:
        if sys.platform == "darwin":
            uid = ctypes.c_uint()
            gid = ctypes.c_uint()
            getpeereid = ctypes.CDLL(None, use_errno=True).getpeereid
            getpeereid.argtypes = [
                ctypes.c_int,
                ctypes.POINTER(ctypes.c_uint),
                ctypes.POINTER(ctypes.c_uint),
            ]
            getpeereid.restype = ctypes.c_int
            if getpeereid(connection.fileno(), ctypes.byref(uid), ctypes.byref(gid)) != 0:
                return None
            return int(uid.value)
        if hasattr(socket, "SO_PEERCRED"):
            raw = connection.getsockopt(
                socket.SOL_SOCKET,
                socket.SO_PEERCRED,
                struct.calcsize("3i"),
            )
            _pid, uid, _gid = struct.unpack("3i", raw)
            return int(uid)
    except (AttributeError, OSError, ValueError, ctypes.ArgumentError, struct.error):
        return None
    return None


def _prepare_local_control_socket_path(path: Path) -> None:
    if not path.is_absolute():
        raise OSError(errno.EINVAL, "local control socket path must be absolute", str(path))
    parent = path.parent
    parent.mkdir(parents=True, exist_ok=True, mode=0o700)
    parent_stat = parent.lstat()
    if not stat.S_ISDIR(parent_stat.st_mode) or stat.S_ISLNK(parent_stat.st_mode):
        raise OSError(errno.ENOTDIR, "local control socket parent must be a directory", str(parent))
    if int(parent_stat.st_uid) != os.getuid():
        raise PermissionError(errno.EACCES, "local control socket parent must be owned by this uid", str(parent))
    os.chmod(parent, 0o700)

    try:
        existing = path.lstat()
    except FileNotFoundError:
        return
    if not stat.S_ISSOCK(existing.st_mode):
        raise OSError(errno.EEXIST, "refusing to replace a non-socket local control path", str(path))
    if int(existing.st_uid) != os.getuid():
        raise PermissionError(errno.EACCES, "refusing to replace a socket owned by another uid", str(path))

    probe = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
    probe.settimeout(0.2)
    try:
        probe.connect(str(path))
    except OSError as exc:
        if exc.errno not in {errno.ECONNREFUSED, errno.ENOENT}:
            raise
    else:
        raise OSError(errno.EADDRINUSE, "local control socket is already active", str(path))
    finally:
        probe.close()
    try:
        path.unlink()
    except FileNotFoundError:
        pass


class _PairlingLocalControlHTTPServer(_PairlingThreadingHTTPServer):
    address_family = socket.AF_UNIX
    pairling_local_control = True

    def __init__(self, socket_path: str | os.PathLike[str], handler_class):
        self.control_socket_path = Path(socket_path).expanduser()
        self._control_socket_identity: tuple[int, int] | None = None
        _prepare_local_control_socket_path(self.control_socket_path)
        super().__init__(
            str(self.control_socket_path),
            handler_class,
            bind_and_activate=False,
        )
        try:
            self.server_bind()
            bound = self.control_socket_path.lstat()
            if not stat.S_ISSOCK(bound.st_mode) or int(bound.st_uid) != os.getuid():
                raise PermissionError(
                    errno.EACCES,
                    "local control socket ownership could not be established",
                    str(self.control_socket_path),
                )
            self._control_socket_identity = (int(bound.st_dev), int(bound.st_ino))
            os.chmod(self.control_socket_path, 0o600)
            secured = self.control_socket_path.lstat()
            if (
                not stat.S_ISSOCK(secured.st_mode)
                or int(secured.st_uid) != os.getuid()
                or (int(secured.st_dev), int(secured.st_ino)) != self._control_socket_identity
                or stat.S_IMODE(secured.st_mode) != 0o600
            ):
                raise PermissionError(
                    errno.EACCES,
                    "local control socket permissions could not be established",
                    str(self.control_socket_path),
                )
            self.server_activate()
        except Exception:
            super().server_close()
            self._unlink_owned_control_socket()
            raise

    def server_bind(self):
        socketserver.TCPServer.server_bind(self)
        self.server_name = "localhost"
        self.server_port = 0

    def verify_request(self, request, client_address):
        return _peer_uid_for_socket(request) == os.getuid()

    def _unlink_owned_control_socket(self) -> None:
        identity = self._control_socket_identity
        if identity is None:
            return
        try:
            current = self.control_socket_path.lstat()
        except FileNotFoundError:
            self._control_socket_identity = None
            return
        if (
            stat.S_ISSOCK(current.st_mode)
            and int(current.st_uid) == os.getuid()
            and (int(current.st_dev), int(current.st_ino)) == identity
        ):
            try:
                self.control_socket_path.unlink()
            except FileNotFoundError:
                pass
        self._control_socket_identity = None

    def server_close(self):
        try:
            super().server_close()
        finally:
            self._unlink_owned_control_socket()


def _maybe_backfill_claude_registry_from_pg() -> None:
    """One-time best-effort import of live PG session rows into the SQLite
    registry on the first sqlite-mode boot. Docker may be down — that is
    fine; live sessions re-register on their next hook fire. Never raises."""
    if _session_backend() != "sqlite":
        return
    if os.environ.get("PAIRLING_SKIP_PG_BACKFILL") == "1":
        return  # test harnesses / fresh installs skip the docker probe entirely
    try:
        if any(row.get("claude_uuid") for row in _agent_registry_live("claude")):
            return  # registry already has live claude rows — nothing to do
        sql = (
            "SELECT id, project, COALESCE(working_on, ''), "
            "COALESCE(claude_uuid, ''), COALESCE(terminal_tty, ''), "
            "COALESCE(claude_pid, 0), "
            "EXTRACT(EPOCH FROM started_at)::bigint, "
            "EXTRACT(EPOCH FROM last_heartbeat)::bigint "
            "FROM sessions "
            "WHERE closed_at IS NULL "
            "AND last_heartbeat > NOW() - INTERVAL '7 days' "
            "ORDER BY last_heartbeat DESC LIMIT 200;"
        )
        proc = subprocess.run(
            ["docker", "exec", "continuous-claude-postgres",
             "psql", "-U", "claude", "-d", "continuous_claude",
             "-A", "-F", "\t", "-t", "-c", sql],
            capture_output=True, text=True, timeout=10,
        )
        if proc.returncode != 0:
            return
        imported = 0
        for line in (proc.stdout or "").strip().split("\n"):
            if not line.strip():
                continue
            parts = line.split("\t")
            if len(parts) < 8 or not _safe_session_id(parts[0]):
                continue
            ok = _agent_registry_upsert(
                "claude",
                parts[0],
                parts[1],
                pid=int(parts[5]) if parts[5].isdigit() else 0,
                terminal_tty=parts[4],
                claude_uuid=parts[3],
                working_on=parts[2],
            )
            if ok:
                # Preserve the PG timeline instead of stamping "now": started_at
                # must survive for the bracketed-paste freshness guard, and a
                # fresh last_heartbeat would resurrect stale sessions as live.
                started_at = float(parts[6]) if parts[6].lstrip("-").isdigit() else 0
                heartbeat = float(parts[7]) if parts[7].lstrip("-").isdigit() else 0
                if started_at and heartbeat:
                    with _agent_registry_conn() as conn:
                        conn.execute(
                            "UPDATE agent_sessions SET started_at = ?, last_heartbeat = ? "
                            "WHERE provider = 'claude' AND native_id = ?",
                            (started_at, heartbeat, parts[0]),
                        )
                imported += 1
        if imported:
            print(
                f"[registry-backfill] imported {imported} live claude session rows from PG",
                file=sys.stderr, flush=True,
            )
    except Exception as exc:
        print(f"[registry-backfill] skipped: {type(exc).__name__}", file=sys.stderr, flush=True)


def _reconcile_broker_sessions_on_boot() -> None:
    _recover_orphaned_approval_decisions_on_startup()
    if PTY_BROKER is None:
        return
    survivors: dict[str, dict] = {}
    deadline = _time.time() + 10
    last_error = ""
    while _time.time() < deadline:
        try:
            survivors = {
                str(item.get("session_id") or ""): item
                for item in PTY_BROKER.list_sessions()
                if isinstance(item, dict) and item.get("session_id")
            }
            break
        except Exception as exc:
            last_error = f"{type(exc).__name__}: {str(exc)[:120]}"
            _time.sleep(0.25)
    if last_error and not survivors:
        print(f"[broker-reconcile] deferred: {last_error}", file=sys.stderr, flush=True)
        return

    for provider in ("claude", "codex"):
        for row in _agent_registry_live(provider):
            metadata = _registry_metadata_from_row(row)
            broker_id = str(metadata.get("broker_id") or "").strip()
            native_id = str(row.get("native_id") or "").strip()
            if not broker_id or not native_id:
                continue
            desc = survivors.get(broker_id)
            if desc is None:
                _agent_registry_mark_closed(provider, native_id)
                continue
            _agent_registry_update_control(
                provider,
                native_id,
                pid=_broker_pid(desc),
                terminal_tty=_broker_slave_tty(desc),
                state="running",
                reopen=True,
            )

    for approval in _pending_approvals_open():
        broker_id = str(approval.get("broker_id") or "").strip()
        request_nonce = str(approval.get("request_nonce") or "").strip()
        provider = str(approval.get("provider") or "").strip() or "claude"
        native_id = str(approval.get("native_id") or "").strip()
        if not native_id:
            _native, _broker, _tty = _approval_resolve_session(provider, str(approval.get("session_id") or ""))
            native_id = _native
        if broker_id and broker_id in survivors:
            if native_id:
                _write_agent_turn_state(
                    provider,
                    native_id,
                    "attention",
                    tool=str(approval.get("command_preview") or approval.get("tool_name") or "")[:80],
                    event="broker_reconcile",
                    request_nonce=request_nonce,
                    mac_install_id=getattr(PAIRING_STORE, "install_id", "") if PAIRING_STORE else "",
                )
            continue
        if request_nonce:
            _pending_approval_resolve_terminal(request_nonce, "session_gone")


if __name__ == "__main__":
    host = _bind_host()
    BOUND_HOST = host
    os.environ["PAIRLING_BOUND_HOST"] = host
    _maybe_backfill_claude_registry_from_pg()
    _reconcile_broker_sessions_on_boot()
    _start_ptybroker_handover_reconciler()
    _recover_pending_first_prompt_deliveries()
    FD_WATCHDOG = _start_fd_watchdog()
    if PUSH_DISPATCHER is not None and DEVICE_REGISTRY is not None:
        try:
            _gc = PUSH_DISPATCHER.gc_revoked(revoked_device_ids=DEVICE_REGISTRY.revoked_device_ids())
            if _gc.get("dropped"):
                print(f"[push-device-gc] dropped {len(_gc['dropped'])} revoked device registrations", file=sys.stderr, flush=True)
        except Exception as exc:
            print(f"[push-device-gc] sweep failed: {type(exc).__name__}: {str(exc)[:120]}", file=sys.stderr, flush=True)
    PUSH_DELIVERY_RETRY_WORKER = _start_push_delivery_retry_worker()
    LIVE_ACTIVITY_PUBLISHER = _start_live_activity_publisher()
    FLEET_ACTIVITY_PUBLISHER = _start_fleet_activity_publisher()
    STANDARD_TURN_PUSH_PUBLISHER = _start_standard_turn_push_publisher()
    MAC_HEALTH_PUSH_PUBLISHER = _start_mac_health_push_publisher()
    SENTINEL_PUSH_PUBLISHER = _start_sentinel_push_publisher()
    _start_codex_approval_scanner()
    _start_keep_awake()
    server = _PairlingThreadingHTTPServer((host, PORT), Handler)
    server.daemon_threads = True
    _sessions_provider_inventory_bundle(
        set(_visible_agent_provider_ids())
        & _session_membership_provider_ids()
    )
    try:
        control_server = _PairlingLocalControlHTTPServer(CONTROL_SOCKET_PATH, Handler)
    except Exception:
        server.server_close()
        raise
    control_thread = threading.Thread(
        target=control_server.serve_forever,
        name="pairling-local-control",
        daemon=True,
    )
    try:
        control_thread.start()
    except Exception:
        server.server_close()
        control_server.server_close()
        raise
    try:
        # Name the inputs that produced this bind. On 2026-07-08 a daemon boot
        # served 0.0.0.0 while the plist said loopback and nothing on disk could
        # say why; a non-loopback bind is a security posture change, so the boot
        # line must carry its own provenance.
        _bind_mode_env = os.environ.get("PAIRLING_BIND_MODE") or "<unset>"
        _webhook_host_env = "set" if os.environ.get("PAIRLING_WEBHOOK_HOST") else "unset"
        print(
            f"pairlingd listening on {host}:{PORT} and unix:{CONTROL_SOCKET_PATH} "
            f"(bind_mode={_bind_mode_env}, webhook_host={_webhook_host_env}, ppid={os.getppid()})",
            file=sys.stderr,
            flush=True,
        )
        server.serve_forever()
    except KeyboardInterrupt:
        pass
    finally:
        server.server_close()
        control_server.shutdown()
        control_server.server_close()
        control_thread.join(timeout=5)
