Skip to content

fix(claude): keep a numbered list above a question from hiding its card - #170

Open
Luke-Norland wants to merge 1 commit into
devswha:mainfrom
Luke-Norland:fix/claude-question-numbered-list
Open

Luke-Norland wants to merge 1 commit into
devswha:mainfrom
Luke-Norland:fix/claude-question-numbered-list

Conversation

@Luke-Norland

@Luke-Norland Luke-Norland commented Oct 6, 2026 •

Copy link
Copy Markdown

Bug

parseClaudeQuestion in tmux-interactive-prompt.service.ts scans up to 64 lines above the Enter to select · ↑/↓ to navigate · Esc to cancel hint with parseNumberedRows, and sequentialRows then requires every numbered row it found to run 1..N.

When the assistant's reply just above the question ends in a numbered list, the list's items fall inside that window and are read as rows too: 37., 38., 39., 40. ahead of the question's real 1.–4.. The sequence check fails, the parser returns null, and the chat gets no card for a short question that fits the screen. The user has to answer in the terminal.

The hardest case is a list numbered 1.–3. directly above the question frame, whose numbers do start at 1.

Reproduce

  1. Run Claude Code (checked on 2.1.291) in a tall tmux pane, e.g. 78x73.
  2. Ask it to write a plain numbered list of 40 short lines, then use AskUserQuestion once with a short single-select question (three options).
  3. Call POST /api/providers/sessions/external/interactive for the pane.

On main the response is {"prompt":null} while the question is on screen. This happens on both Claude renderers (default and fullscreen).

Fix

The card now takes only the current run of rows: the contiguous run that ends at the last row above the hint (Chat about this) and counts back down to 1.. Numbered lines above that 1. are ignored (currentClaudeRun). The question text is read as before, and the answer path is unchanged.

Transcript-ask path

parseClaudeAskSelectionScreen in tmux-ask-selection.service.ts also scans 64 lines above the hint, but it is not affected. It slides a window over the numbered rows that must number 1..N, match the transcript's own labels in order, and end in Type something. and Chat about this, with the question text visible above it. A list above the frame cannot complete such a window, so the real rows are still found. Even a 1.–3. list that repeats the option labels fails the numbering at the frame's own 1.. No code change there; a test pins it.

Tests

New server/modules/providers/tests/claude-question-numbered-list.test.ts, with fixtures captured from a real Claude Code TUI in a 78x73 pane (scratch paths replaced with neutral ones of the same length):

  • s1 (fullscreen), s2, list40 (default): a 40-item list above the question. The card returns the real question and options, through getTmuxInteractivePrompt on the -S -80 capture and on the visible screen alone.
  • list3: a 40-item list in scrollback and a 3-item list numbered 1.–3. directly above the frame.
  • Synthetic: a 1.–3. list repeating the option labels directly above the frame, with and without the divider.
  • Control: the same question with no list above parses as before.
  • Transcript asks: each of the screens above maps the option and direct-input selections to the real rows.
main this branch
claude-question-numbered-list.test.ts 2 pass, 5 fail (card is null) 7 pass
tmux-interactive-prompt.service.test.ts 14 pass 14 pass
tmux-ask-selection.service.test.ts 11 pass 11 pass

The two tests that pass on main are the no-list control and the transcript-ask test, which pin behaviour that should not change. Restoring the unbounded scan turns the five list tests red. Restricting the transcript parser to the first rows in its window turns the transcript-ask test red.

npm run typecheck and eslint on the touched files are clean.

End to end

Real Claude Code 2.1.291 in a private tmux server, 78x73, and a dev server from this branch. The assistant wrote a 40-item numbered list of tmux tips, then asked "Which fruit for the picnic?" (Apple, Banana, Cherry). The card was read and answered through POST /api/providers/sessions/external/interactive and /respond. Each run used a fresh conversation in a fresh pane.

Renderer main this branch Answer tool_result
default prompt: null card with the 3 options, custom option 4 2 "Which fruit for the picnic?"="Banana"
fullscreen prompt: null card with the 3 options, custom option 4 3 "Which fruit for the picnic?"="Cherry"

Both answers returned 200 {"action":"selected"}.

🤖 Generated with Claude Code

Summary by CodeRabbit

  • Bug Fixes
    • Claude questions now correctly recognize their numbered options when other numbered lists appear earlier in the conversation.
    • Improved option detection across terminal and transcript views, including prompts with repeated option text or custom choices.

The Claude question parser scanned up to 64 lines above the "Enter to
select" hint and required every numbered row in that window to run 1..N.
When the assistant's reply above the question ended in a numbered list,
those items were read as rows too (37., 38., ... ahead of the real 1.),
the check failed, and a short question that fits the screen got no card.

Take only the current run of rows: the contiguous run that ends at the
last row above the hint and counts back down to 1. Numbered lines above
that 1. are ignored. The question text and the answer path are unchanged.

The transcript-ask parser already finds the real rows: it slides a window
that must number 1..N, match the transcript's labels in order and end in
"Type something." and "Chat about this", so a list above the frame cannot
complete a match. A test pins that.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Oct 6, 2026 •

Copy link
Copy Markdown

Review in Change Stack →

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration
  • Configuration used: defaults
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: 90199956-cec8-485a-8d9a-7cd52bd28c95
📥 Commits

Reviewing files that changed from the base of the PR and between b258b57 and 1ab2831.

📒 Files selected for processing (10)
  • server/modules/providers/services/tmux-interactive-prompt.service.ts
  • server/modules/providers/tests/claude-question-numbered-list.test.ts
  • server/modules/providers/tests/fixtures/claude-question-numbered-list/list3-78x73.joined.ansi
  • server/modules/providers/tests/fixtures/claude-question-numbered-list/list3-78x73.screen.ansi
  • server/modules/providers/tests/fixtures/claude-question-numbered-list/list40-78x73.joined.ansi
  • server/modules/providers/tests/fixtures/claude-question-numbered-list/list40-78x73.screen.ansi
  • server/modules/providers/tests/fixtures/claude-question-numbered-list/s1-78x73.joined.txt
  • server/modules/providers/tests/fixtures/claude-question-numbered-list/s1-78x73.screen.txt
  • server/modules/providers/tests/fixtures/claude-question-numbered-list/s2-78x73.joined.txt
  • server/modules/providers/tests/fixtures/claude-question-numbered-list/s2-78x73.screen.txt

Included review availability: This review used your included allowance. Your plan provides up to 10 included reviews per hour; 7 remain after this review.


📝 Walkthrough

Walkthrough

Claude question parsing now isolates the final consecutive numbered option run. Regression tests use captured prompts with numbered lists above question cards.

Changes

Claude question parsing

Layer / File(s) Summary
Select the current numbered run
server/modules/providers/services/tmux-interactive-prompt.service.ts
The parser now uses the trailing consecutive numbered run only when it begins at 1.
Test captured prompts
server/modules/providers/tests/claude-question-numbered-list.test.ts, server/modules/providers/tests/fixtures/claude-question-numbered-list/*
Regression tests and captured terminal fixtures cover prompts with earlier numbered lists, including question-card parsing and transcript-ask selection. A control test covers parsing without a preceding list.

Priority: ➖ Normal

Estimated code review effort: 2 (Simple) | ~15 minutes

Change: Bug fix

Merge Risk: ⚪ Minimal · up to 1ab28

The change has no identified issue that needs resolution before merge; complete normal checks.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 66.67% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 6 functions across 2 files. (8 skipped: 8… Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly describes the main change: preventing a numbered list above a Claude question from hiding its question card.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Full details: Docstring Coverage

Explanation

Docstring coverage is 66.67% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 6 functions across 2 files. (8 skipped: 8 unsupported.)

  • Fix all pre-merge checks with AI
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create a new PR
  • Autopilot · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Comment @coderabbitai help to get the list of available commands.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant