specs/025-resume-selected-executable/spec.md

Specification: Resume Retains Selected Executable Path

Feature Branch: t3/resume-selected-executable
Created: 2026-10-08
Status: Implemented Input: When an agent session is launched with an explicit path-qualified binary (such as /opt/tools/codex), subsequent resume commands generated by session reporters and executed by pane.resume must retain the selected executable path rather than falling back to bare binary lookup in $PATH.

Problem

When a terminal pane is spawned with an explicit path-qualified executable (e.g. /opt/.../codex), the agent is detected by its executable basename. However, when session identity is reported via report-session or hook-event, the writers fetch the adapter's official resume argv via adapter.resume_capability(&session_id). Built-in adapters emit bare command names (e.g. ["codex", "resume", "<session_id>"]).

Consequently:

  1. pane.agent.resume_argv stores a bare command ("codex"), losing the path qualifier from the original launch.
  2. When the user or automation calls pane.resume, h_pane_resume spawns this bare argv. If /opt/.../codex is not on $PATH, or if an incompatible binary exists earlier on $PATH, pane.resume either fails to spawn or invokes the wrong binary.
  3. Furthermore, Codex local runtime probe (supports_no_daemon) in signaltty-server::codex runs --no-daemon --version against argv[0]. If argv[0] is bare "codex", probing fails or probes the wrong binary, disabling per-pane local runtime isolation.

Requirements

Functional Requirements

  • FR-001 (Executable Retention): When a pane's original launch argv[0] is absolute (including relative launch paths anchored at spawn) and its filename/basename matches the bare official resume command (resume_argv[0]), the resume command's argv[0] must be replaced with the original path-qualified argv[0].

  • FR-002 (Preserve Adapter Arguments): The remaining arguments from the adapter's official resume command (e.g. ["resume", "<session_id>"] or ["--resume", "<session_id>"]) must be retained intact. Original launch options, model names, profile arguments, or suffix flags must NOT be copied into the resume argv.

  • FR-003 (Preserve Configuration Environment): The pane's retained agent.config_env (e.g. CODEX_HOME, CLAUDE_CONFIG_DIR) must continue to be passed to the resumed process unchanged.

  • FR-004 (Preserve Promoted Shells): If a pane was started with a shell (e.g. /bin/bash or /usr/bin/zsh) and later promoted to an agent kind, the original basename ("bash") does not match the bare official command ("codex"). In this case, the helper must NOT replace the command; bare "codex" is preserved.

  • FR-005 (Preserve Differing Basename Wrappers): If a pane was launched via a wrapper executable whose basename differs from the official agent command (e.g. /usr/local/bin/codex-wrapper), the helper must NOT replace the command; bare "codex" is preserved.

  • FR-006 (Preserve Explicit Manifest Templates): If an agent manifest specifies an explicit path-qualified resume template (e.g. resume = ["/custom/bin/codex", "resume", "{session_id}"]), the helper must NOT override this explicit official path, even if its basename matches the launch binary.

  • FR-007 (Dual Application Seams): The resolution helper must be applied:

    1. At both session identity writers: h_hook_event and h_pane_report_session.
    2. At resume execution: h_pane_resume, dynamically repairing existing panes or persisted snapshots that contain bare resume commands.
  • FR-008 (No Schema Changes): The IPC schema, parameter types, and wire models remain unchanged.

  • FR-009 (Stable Relative Launch): Anchor path-qualified relative executables to the initial spawn or split directory before process launch and store that absolute path in existing pane argv. Live cwd refresh must not redirect resume.

  • FR-010 (Legacy Relative Compatibility): A restored relative original launch path must not replace a bare adapter resume command, because the initial launch directory is not reliably persisted.

Matrix and Edge Cases

  1. Built-in Adapters Matrix:
    • codex -> official bare command "codex"
    • claude -> official bare command "claude"
    • opencode -> official bare command "opencode"
    • cursor -> official bare command "cursor-agent"
    • pi -> official bare command "pi"
  2. Path Qualification:
    • Absolute paths (e.g. /opt/agents/codex) are retained.
    • New relative paths containing / are anchored to the launch directory before spawn/split and retained as absolute paths. Legacy relative snapshot paths keep the adapter command.
    • Bare commands (no /, e.g. codex) remain bare.
  3. Empty or Degenerate Inputs:
    • Empty original_argv or empty original_argv[0] leaves resume argv unchanged.
    • Empty resume_argv returns an empty vector without panic.

Success Criteria

  • SC-001: Pure unit tests in signaltty-agent verify the matrix of all 5 built-in adapters, relative paths, empty inputs, bare commands, promoted shells, explicit manifest paths, wrapper differences, and suffix flags.
  • SC-002: Real IPC regression sibling test report_session_builds_resume_retains_selected_executable_without_manifest launches an absolute Codex fixture without any manifest resume template, reports session, calls pane.resume, and verifies both fixture-resume:<id> and fixture-local-runtime.
  • SC-003: Hook-event writer and stale snapshot repair tests verify dynamic resolution at both entry points.
  • SC-004: Zero new clippy warnings and formatting clean.