Skip to content

feat: Reliable slash-command initial prompt delivery #358

Description

@parsakhaz

type: feature-ticket
id: slash-command-submission
status: ready
zone: 2
pr:
github: #358

Feature: Reliable slash-command initial prompt delivery

Intent

Initial prompt handling has two ways to fail a slash command, and both fail silently:

  1. Composer path: in a four-pane dogfood run (issue feat: add event-driven RunPane orchestration and reliable agent startup #353), /do TM-x was staged
    but never executed on 3 of 4 panes — the autocomplete menu consumed the bare \r
    the raw delivery path emits. Each pane was rescued manually with
    panels submit-composer --strategy auto --yes.
  2. Argument path (discovered during capture): Codex creates always deliver the
    initial input as a CLI argument, and PTY probes prove argument delivery bypasses
    Codex's TUI command layer — codex "/status" goes to the model as literal text.
    Yet submitCreateInitialInput reports verifiedSubmitted: true unconditionally
    for Codex argument delivery (main/src/ipc/runpane.ts:690) — a false success: the
    skill/command never expands, the model improvises on the literal text.

Delivery must be chosen per agent × prompt shape, and "verified" must mean verified.
Staged is not submitted; delivered-as-text is not executed-as-command.

Peeled from #353 during capture of epic #356. Epic phase 4 (verified startup) prefers
this landed first. Probe evidence: refs/submission-probe-evidence.md.

Desired end state

  • /do TM-x, ordinary prose, a multiline pasted prompt, or an unknown slash command
    supplied as initial input reliably executes on both agents — or returns a
    structured, actionable failure at creation time. Never silently staged text, never
    a false verifiedSubmitted.
  • If a composer submit is swallowed by autocomplete, RunPane retries through the
    semantic strategy — only on positive evidence, never duplicating the command.

Key architecture directions

  • D1 — Delivery mode is chosen per agent × prompt shape (probe-validated matrix):
    fresh Claude creates default to argument delivery (claude --session-id <id> "<prompt>" — verified to execute slash commands, eliminating the composer failure
    class); Codex non-slash input keeps today's argument delivery; Codex
    slash-command input and any composer-bound case (resumed Claude sessions, agents
    without argument support) route through the semantic submit-composer path — never
    a bare-\r assumption · rejected: composer-verify-retry as the universal fix
    (argument mode is strictly more reliable where it works); argument mode as the
    universal fix (bypasses Codex's TUI command layer, and resumed Claude sessions drop
    the prompt argument today).
  • D2verifiedSubmitted is earned, never assumed: the unconditional
    verifiedSubmitted: true for Codex argument delivery is replaced by
    shape-aware reporting (argument delivery of a slash command on Codex is a routing
    decision per D1, not a verified success). Composer-path success requires the
    composer cleared AND activity/command execution begun.
  • D3 — Retry is evidence-gated: re-submit only when the staged text is provably
    still present in the composer readback (the dogfood failure signature). Composer
    cleared without activity → structured submission_unverified blocker with attempt
    count and nextCommand — never a blind retry, never a hang, never a false success.
    Delayed verification therefore cannot produce a duplicate submission.
  • D4 — Preserve the exact command text and arguments; never select or rewrite an
    autocomplete candidate.
  • D5 — Additive and parity-kept: existing commands/JSON untouched, npm CLI /
    daemon schema / generated contracts / Python wrapper updated together, stdout stays
    machine-clean. (Matches epic feat: Event-driven RunPane orchestration #356 D7.)

Proposed approach

  • The --wait-ready create path is already semantic (write +
    submitComposerForPanel(panel, 'auto'), main/src/ipc/runpane.ts:717-719) and
    suppresses the raw path via initialInputSentAt (runpane.ts:631-644); the raw
    bare-\r path (main/src/services/terminalPanelManager.ts:379) serves
    no-wait-ready creates, GUI-created sessions, and resumed Claude sessions.
  • Claude argument delivery already exists (terminalPanelManager.ts:253-268) —
    fresh Claude creates need initialInputMode: 'argument' set the way
    runpane.ts:640 does for Codex, plus slash-shape detection for the Codex branch.
  • Fix the false success at runpane.ts:690-701; reuse the submit-composer
    contract (shared/types/runpaneOrchestration.ts:389) and its verification
    heuristic (runpane.ts:1128) for the composer-bound cases, adding the
    evidence-gated retry (D3).
  • Regression fixtures: prose, multiline, known slash (/do TM-x), unknown slash —
    per agent where the matrix differs (main/src/ipc/runpane.test.ts pattern);
    contract/parity via scripts/test-runpane-contract.js.

Verification criteria

  • AC1 — WHEN a fresh Claude pane is created with a slash-command initial input,
    the spawned command line shall carry the prompt as a quoted argument
    (--session-id <id> "<prompt>") and the create result shall not report composer
    delivery.
  • AC2 — WHEN a Codex pane is created with a slash-command initial input, delivery
    shall route through the semantic composer path and the create result's
    verifiedSubmitted shall be true only after verification — never the current
    unconditional true.
  • AC3 — WHEN a composer submit is swallowed (staged text still present in the
    composer readback), the system shall re-submit via the semantic strategy and report
    verifiedSubmitted: true with the command executed exactly once.
  • AC4 — IF the composer is cleared but verification has not completed, THEN the
    system shall not re-submit (no duplicate execution under delayed verification).
  • AC5 — IF submission cannot be verified within the bounded retry budget, THEN
    the response shall be ok: false with prompt.staged: true,
    verifiedSubmitted: false, an attempt count, blocker.kind: "submission_unverified", and a nextCommand — within bounded time.
  • AC6 — WHEN ordinary prose or a multiline pasted prompt is supplied on either
    agent, submission shall complete with verifiedSubmitted: true (no regression
    from the routing change).
  • AC7 — WHEN an unknown slash command is supplied, the exact text shall be
    preserved (no autocomplete candidate selected or rewritten) and the outcome shall
    be verified submission or the AC5 blocker.
Criterion Method Command / flow
AC1, AC2 automated command-construction + delivery-routing tests (pattern: main/src/ipc/runpane.test.ts) [ ]
AC3, AC4 automated composer fixtures: staged-text-present vs composer-cleared-verification-lagging [ ]
AC5 automated verification forced to fail; assert payload + bounded duration [ ]
AC6, AC7 automated prose / multiline / unknown-slash fixtures per agent [ ]
all automated scripts/test-runpane-contract.js npm/Python parity run [ ]

Out of scope

Justification

  • Composer-verify-retry as the universal fix — rejected by probe: argument delivery
    executes Claude slash commands directly (claude 2.1.217, Status panel rendered, no
    model roundtrip), so fresh Claude creates default to argument mode and the composer
    failure class is eliminated where possible.
  • Argument mode as the universal fix — rejected by probe: codex "/status" bypasses
    the TUI command layer (codex-cli 0.144.4, conversational reply), and resumed Claude
    sessions drop the prompt argument today (terminalPanelManager.ts:266-268); those
    cases stay composer-bound with semantic submit.
  • "The initial-input path emits a raw Enter" — corrected during the gate: wait-ready
    is already semantic (runpane.ts:717-719); the true gap is threefold, including a
    newly discovered unconditional verifiedSubmitted: true for Codex argument
    delivery (runpane.ts:690) that this ticket now fixes.
  • Duplicate-free retry — safe because retry is evidence-gated on staged text still
    visible in the composer readback; absence of verification alone never triggers a
    re-submit.

Open questions

  • [NEEDS CLARIFICATION] Whether claude --resume <id> "<prompt>" accepts a prompt
    argument (the code drops it today, terminalPanelManager.ts:266-268) — check at
    plan time; if yes, resumed Claude sessions can ride the argument path too.

References (in refs/)

  • refs/discussion.md — decision log from the 2026-07-21 discussion.
  • refs/submission-probe-evidence.md — PTY probes proving argument-mode slash
    execution on Claude and bypass on Codex; code trace of the three delivery paths and
    the verifiedSubmitted: true false-success bug.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions