pr Split Prompt Anchor Stability
# Prompt/Input Anchor Stability Audit
**Date:** 2026-03-16
**Task:** T000 — Architecture audit of `sendToHandle()` PTY anchor pipeline
**Error:** `"failed to send prompt to Claude: unable to locate stable prompt/input anchors before submit"`
## Executive Summary
The reported error occurs in the **PTY-based Claude interaction pipeline** (`pr_split_10b_pipeline_send.js`), NOT in the BubbleTea TUI overlay system. The error is triggered when `osm pr-split` sends a prompt to a Claude Code PTY session and the terminal screenshot does not stabilize within the configured timeout window.
**Key finding:** The original task description conflates two architecturally separate systems — BubbleZone (TUI mouse tracking) and the PTY anchor pipeline (terminal screenshot analysis). This audit corrects that confusion and provides a focused analysis of the actual error path.
---
## Architecture: Two Separate Systems
| System | Purpose | Location | Error Source? |
|--------|---------|----------|:---:|
| **BubbleTea TUI Overlay** | User types message → keyboard-driven submit | `pr_split_15b_tui_chrome.js:502` (defined), `pr_split_16f_tui_model.js:711` (used) | ❌ |
| **PTY Anchor Pipeline** | Automated prompt delivery to Claude Code PTY | `pr_split_10b_pipeline_send.js` | ✅ |
The BubbleTea overlay (`viewClaudeConvoOverlay`) contains **zero `zone.mark()` calls** and has no Submit button — `Enter` is handled directly via `updateClaudeConvo`. The overlay dimensions are recomputed on every view call via `Math.min((s.width || 80) - 4, 76)` and centered with `lipgloss.place()`. This system is architecturally sound and not implicated in the error.
---
## Root Cause Investigation
### Root Cause 1: Screenshot Reliability
**Function:** `captureScreenshot()` (line 148)
| Condition | Behavior | Risk |
|-----------|----------|------|
| `tuiMux` undefined | Returns `null` → `observed: false` | Graceful — pipeline enters unobserved mode |
| `tuiMux.screenshot()` returns null | Returns `''` (empty string) | Safe — anchor detection finds nothing, waits |
| `tuiMux.screenshot()` throws | Returns `null` → unobserved mode | Graceful |
| `tuiMux.screenshot()` returns stale content | Anchor positions jitter | **Root cause contributor** — stale screenshots cause stableKey mismatch |
**Verdict:** Screenshot reliability is adequate. The `null` fallback to unobserved mode is the correct design.
### Root Cause 2: Anchor Detection Accuracy
**Functions:** `findPromptMarker()` (line 204), `getTextTailAnchor()` (line 161), `captureInputAnchors()` (line 222)
The anchor detection correctly handles:
- Multiple prompt marker candidates: takes the **last** `❯`/`>` on screen
- First-run setup blocker: `detectPromptBlocker()` catches "choose the text style" screen
- Proximity requirement: input and prompt must be within ±2 lines of each other
- `[Pasted text...]` indicator as fallback when text tail isn't visible
**Identified gap:** `isPromptMarkerLine()` (line 186) checks for `❯` and `>` as first non-whitespace character but excludes numbered setup entries (`/^\d+\./`). This correctly avoids `❯ 1. Dark mode` but may false-positive on user content starting with `>` (e.g., a markdown blockquote in conversation history).
**Verdict:** Detection accuracy is good. The `>` false-positive risk is mitigated by the proximity requirement (input anchor must be within ±2 lines of prompt).
### Root Cause 3: Stability Timeout Calibration
**Function:** `waitForStableInputAnchors()` (line 329)
Default configuration:
- **Timeout:** 1500ms (`SEND_PRE_SUBMIT_STABLE_TIMEOUT_MS`)
- **Poll interval:** 50ms (`SEND_PRE_SUBMIT_STABLE_POLL_MS`)
- **Stable samples:** 3 (`SEND_PRE_SUBMIT_STABLE_SAMPLES`)
This means: up to 30 polls, requiring 3 consecutive identical `stableKey` readings where both anchors are present and co-located.
**Analysis:** For a 10KB classification prompt at 512-byte chunks with 2ms delays:
- Paste time: ~40 chunks × 2ms = ~80ms
- Terminal reflow time: varies by terminal emulator, typically 10-200ms
- Total expected stabilization: 80-280ms
- Available budget: 1500ms (5-18× headroom)
The timeout is **adequate for typical prompts**. For very large prompts (>50KB) or sluggish PTY connections, the timeout may be insufficient. The graceful fallback at line 365 (accept last state if anchors are valid but not stable) provides additional resilience.
**Verdict:** Timeout calibration is reasonable. Consider increasing to 3000ms for robustness, or making the timeout proportional to text length.
### Root Cause 4: Paste-Reflow Jitter
**Mechanism:** Text is pasted in 512-byte chunks with 2ms inter-chunk delays (line 499-515 of `sendToHandle`). After the last chunk, the pipeline calls `waitForStableInputAnchors()`.
**Jitter sources:**
1. Terminal emulator reflow rendering after paste completes
2. Claude Code's own UI re-rendering (syntax highlighting, line wrapping)
3. `tuiMux.screenshot()` capturing mid-render state
**The specific failure mode:** After all text chunks are written to the PTY, the terminal is still reflowing. Each `captureScreenshot()` returns a slightly different layout. The `stableKey` (combination of `promptBottom|inputBottom`) changes between polls. If 3 consecutive identical readings never occur within 1500ms, the error fires.
**Mitigation already present:** A `SEND_TEXT_NEWLINE_DELAY_MS` (10ms) delay is inserted before the newline to give the terminal time to settle. Additionally, the graceful fallback (line 365) accepts the last state if anchors are co-located.
**Verdict:** This is the most likely failure trigger. The 10ms pre-newline delay may be insufficient for complex terminal layouts.
---
## Error Path Tracewhen to use it
Community prompt sourced from the open-source GitHub repo joeycumines/one-shot-man (GPL-3.0). A "pr Split Prompt Anchor Stability" style prompt — adapt the placeholders and specifics to your task. Imported as-is and not independently retested here, so check the output before relying on it.
tags
productivitycommunitydeveloper
source
joeycumines/one-shot-man · GPL-3.0
more in Productivity
Productivity✓ tested
Summarize a doc into decisions & actions
chief of staff who extracts what to DO, not just what was said
Productivity✓ tested
Draft a reply to a hard email
calm, direct communicator who de-escalates without caving
Productivity✓ tested
Turn a brain-dump into a weekly plan
planning coach who protects your focus, not just your calendar