home/productivity/pr-split-prompt-anchor-stability

pr Split Prompt Anchor Stability

GPTClaudeDeepSeek··692 copies·updated 2026-07-14
pr-split-prompt-anchor-stability.prompt
# 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 Trace

when 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