fix(issue-30): review ad3d8206 - a prompt glyph inside a draft is draft text; the R4 regression test tells the defect apart

- input_region: in the prompt-line shape the input box starts only at a
  column-0 prompt (codex indents a draft's continuation lines), and the
  prompt and the (whole-line) placeholder are stripped from the box's first
  non-blank line only, so `› Explain this terminal prompt:\n  ›` is not empty.
- test_r4 runs with S=40 again: the defective code nudged ~30 s after a
  missed transition, which S=10 could not tell from the fixed ~10 s.

Both new checks fail against the defective versions (stall_watch.py at
47e4274 -> 30.24 s < 40; input_region.py at bf0f5c1 -> nudge sent) and pass
now, each with its passing twin.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
GodopuandClaude Opus 5.5 committed 2026-09-25 16:02:39 +00:00
1 parent bf0f5c1014
commit 9ec0569401
2 files changed
+62 -12

No files matched your search

+18 -10
View File
@@ -11,12 +11,13 @@ def extract_input_region(pane_text: str, agent_name: str) -> str:
1. an `input_block_prefix` -> the last contiguous block of lines starting
with it, prefix removed, cut at the first `input_stop_pattern` line;
2. two or more `input_rule_pattern` rules -> the lines between the last two;
3. an `input_prompt` -> from the last line starting with the prompt to
3. an `input_prompt` -> from the last line starting (column 0) with the prompt to
the end of the pane, minus a last non-blank line matching
`input_stop_pattern` (the status footer). Every other line below the
prompt line is input: a multi-line draft is never cut to its first line.
Then `input_frame_chars`, the prompt and the placeholder are stripped. There
Then `input_frame_chars` are stripped, and the prompt and the placeholder
(whole-line) are stripped from the box's first non-blank line only. There
is no whole-pane fallback: a pane with none of these shapes has no input
region and yields a non-empty "unknown" result rather than a guess.
Raises ValueError for agents without input area facts (like hermes' peers).
@@ -52,7 +53,10 @@ def extract_input_region(pane_text: str, agent_name: str) -> str:
region_lines = lines[rule_indices[-2] + 1:rule_indices[-1]]
if region_lines is None:
starts = [i for i, line in enumerate(lines) if line.lstrip().startswith(prompt)]
# The composer's prompt sits at column 0; a draft's continuation lines
# are indented, so an indented prompt character is draft text (review
# ad3d8206), never the start of the input box.
starts = [i for i, line in enumerate(lines) if line.startswith(prompt)]
if starts:
region_lines = [line for line in lines[starts[-1]:]]
while region_lines and not region_lines[-1].strip():
@@ -68,11 +72,15 @@ def extract_input_region(pane_text: str, agent_name: str) -> str:
if frame:
region_lines = [line.strip().strip(frame) for line in region_lines]
region_text = "\n".join(region_lines)
region_text = re.sub(r'^\s*' + re.escape(prompt) + r'\s*', '', region_text, flags=re.MULTILINE)
# The prompt and the placeholder belong to the box's first line only: the
# same characters further down are what the user typed.
region_lines = list(region_lines)
first = next((i for i, line in enumerate(region_lines) if line.strip()), None)
if first is not None:
head = re.sub(r'^\s*' + re.escape(prompt) + r'\s*', '', region_lines[first], count=1)
placeholder = adapter.input_placeholder
if placeholder and head.strip() == placeholder:
head = ''
region_lines[first] = head
placeholder = adapter.input_placeholder
if placeholder:
region_text = region_text.replace(placeholder, '')
return region_text.strip()
return "\n".join(region_lines).strip()