# Prompt-Lock & Input Delivery Failure — Code-Level Analysis Report - **Reviewer**: Reviewer Cline (`canary-projects-multi-agent-mux-reviewer-cline`, role: reviewer) - **Date**: 2026-07-11 - **Brief**: `.mam/reports/brief-prompt-lock-fix.md` - **Scope**: Code-level analysis of the "prompt typing lock / input delivery failure" in the TMUX-based multi-agent environment; concrete prevention helper + migration plan. --- ## 1. The Problem (recap) When the orchestrator issues commands via `tmux send-keys` to a target agent TUI: 1. Text gets printed inside the prompt input box but is **never submitted** (Enter ignored) or the cursor freezes. 2. Root causes: blessed UI renderer thread bottleneck during heavy output; dialog popups (Approve/Reject permission prompts) stealing input focus; OAuth/list-selection dialog blocks intercepting keystrokes. The core failure mode is: **`send-keys` delivers keystrokes to whatever currently has focus.** If a permission dialog, an OAuth browser-prompt, or a list-selection popup is open, the keystrokes go to the dialog (or are swallowed), not the main input box — so the prompt text appears but Enter does nothing, or the cursor appears frozen. --- ## 2. Exact Code Locations — Every `send-keys` / Input-Delivery Site I grepped the entire `.agents/` tree. There are **6 input-delivery sites**; only 2 use a helper, the rest are raw `tmux send-keys`. ### Site A — `lib.sh:1086-1100` (`inject_instructions`) — HELPER, central ```bash inject_instructions() { local sess="$1" instructions="$2" job_id="${3:-onboard}" local local_tmux="tmux" if [ -n "${TMUX_SERVER_NAME:-}" ] && [ "$TMUX_SERVER_NAME" != "default" ]; then local_tmux="tmux -L $TMUX_SERVER_NAME" fi $local_tmux set-buffer -b "job_buf_$job_id" "$instructions" $local_tmux paste-buffer -b "job_buf_$job_id" -t "$sess" sleep 0.5 $local_tmux send-keys -t "$sess" C-m # ← Enter, no focus guard $local_tmux delete-buffer -b "job_buf_$job_id" } ``` **Vulnerability**: No focus recovery. If a permission/dialog popup is open when `C-m` fires, Enter goes to the dialog. The fixed `sleep 0.5` is too short under heavy renderer load (the brief's "renderer thread bottleneck"). No delivery verification. ### Site B — `multi-agent-mux-delegate-job:364-369` — DUPLICATE of Site A, raw ```bash $_tmux set-buffer -b "job_buf_$job_id" "$instructions" $_tmux paste-buffer -b "job_buf_$job_id" -t "$sess" sleep 0.5 $_tmux send-keys -t "$sess" C-m $_tmux delete-buffer -b "job_buf_$job_id" ``` **Vulnerability**: Identical logic to Site A, copy-pasted (violates lib.sh's "single source of truth" mandate, lib.sh header §4.1). Same no-focus-guard + too-short-sleep defects. This is the delegate-job path — the *primary* way the orchestrator hands work to agents, so it's the highest-traffic vulnerable site. ### Site C — `resume/SKILL.md:150-156` — RAW, dialog auto-handle (MOST VULNERABLE) ```bash # auto-handle trust / bypass dialogs sleep 5 tmux send-keys -t "$SESSION_NAME" Enter 2>/dev/null || true sleep 3 tmux send-keys -t "$SESSION_NAME" Down 2>/dev/null || true sleep 0.3 tmux send-keys -t "$SESSION_NAME" Enter 2>/dev/null || true ``` **Vulnerability**: This is the *exact* lock symptom from the brief. It fires blind `Enter`/`Down`/`Enter` on fixed sleeps to auto-dismiss a trust dialog. Problems: (a) no check that a dialog actually exists — if the TUI rendered late and focus is still the main input, these keystrokes type garbage into the prompt; (b) if a *different* dialog (OAuth, list-select) appeared instead of the expected trust prompt, `Down`+`Enter` selects the wrong option; (c) `2>/dev/null || true` swallows all errors silently — the operator never learns delivery failed; (d) no `wait_for_tui_ready` gate before sending. ### Site D — `stop_session.sh:192` (`graceful_stop`) — RAW ```bash tmux send-keys -t "$SESSION_NAME" "$exitkey" Enter 2>/dev/null || true ``` **Vulnerability**: Sends `/exit` + Enter without focus recovery. If a permission dialog is open, `/exit` is typed into the dialog (harmless there) but Enter may dismiss the dialog with an unintended choice, and the agent never receives the exit command. The graceful chain *does* have a proper fallback (kill-session → SIGTERM → SIGKILL with `has-session` checks, lines 194-205), so this site is low-severity — but it still benefits from focus recovery. ### Site E — `create/SKILL.md:215` — RAW, probe (documentation example) ```bash tmux send-keys -t "$SESSION_NAME" "" Enter ``` **Vulnerability**: This is in a verification snippet (sends empty + Enter). Low impact — it's an optional manual probe, not an automated path. But it sets a bad example for users. ### Site F — `create_session.sh:384` — USES HELPER (Site A) ```bash inject_instructions "$SESSION_NAME" "$instructions" "$DELEGATE_JOB_ID" ``` **Status**: This is the correct pattern — it routes through `inject_instructions`. It's only as safe as Site A. Also note: `create_session.sh:199` calls `wait_for_tui_ready` before any input — the *only* site that does so. ### Existing mitigation already present (good, underused) `lib.sh:1040-1084` defines `wait_for_tui_ready ` — a gated capture-pane loop (15×1s) that grep-checks the pane content for each agent's TUI banner before returning. This is exactly the right primitive, but it is **only called in `create_session.sh:199`**. Resume, stop, and delegate-job never gate on TUI readiness.