Skip to content

Model-list guard: a hint split inside a word or over more than six lines is missed, and a quoted hint holds pending delivery #542

Closed

Description

@devswha

Found by Codex adversarial delta passes during the review of #520 (bridge-owned pending messages), on head d76fb24. Reported here so it is not lost. It does not block #520.

Background

Enter on Claude Code's /model list saves the row under the cursor as the default for new sessions. claudeModelListWaits() in server/prompt.ts recognises that list by its hint (Enter to set as default · s to use this session only · Esc to cancel) even when the reader cannot read the rows. Until #520 it only withheld the fallback card. #520 also uses it, through modelListWaits(), to refuse pending delivery (pendingContext() in server/index.ts), because a pending message ends in Enter.

The guard joins up to six trailing lines with a space, requires the match to run into the line it ends at, and removes Claude's own footer (the session's rule, the task list) from under the hint first.

Gaps

1. A hint split inside a word is not recognised

  Enter to set as default · s to use this ses
  sion only · Esc to cancel

Joined with a space this reads ses sion and CLAUDE_MODEL_HINT_RE fails. The footer under it is then not removed either, since the same reading decides that. With the pane idle or working, pending delivery goes ahead; with the pane blocked, the fallback card with Enter can be offered. The card reader (parseClaudeModel, promptTailIsActive) has the same limit with a smaller window, so this part predates #520.

2. A hint over more than six lines is not recognised

Same result, for a pane narrow enough to need seven lines.

3. A quoted hint can hold pending delivery

⏺ Example: Enter to set as default · s to use this session only · Esc to
  cancel
──────────── Summary ─

No list is open, but the hint's text ends the screen once the labeled rule under it is taken for Claude's footer, so pending sends and Send now are refused until the screen changes. 264d803 brought this back while fixing the wrapped hint over a real session rule; the guard before a3d875a matched this screen too.

4. A line under the hint that is not Claude's footer

Since a3d875a a list whose hint is followed by anything but the session's rule and the task list reads as answered. The screens captured from Claude Code 2.1.289 draw the effort line above the hint, so no real layout is known to do this; it is listed because the guard before a3d875a matched such a screen within six lines.

Possible fix

  • Capture the list as Claude Code draws it in narrow panes first (a phone-width pane, with a named session and with a task list), and fix the fixtures to those.
  • Compare the hint with whitespace removed, as codexModelListWaits() does, and read the whole hint block instead of six lines, keeping the "runs into its last line" rule.
  • Do not take a hint for a panel's when it sits in a line of agent output (a ⏺ or ● bullet before it).
  • Apply the same reading in parseClaudeModel and promptTailIsActive, so the card and the guard agree.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions