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

+44 -2
View File
@@ -676,7 +676,7 @@ def test_r4_a_missed_transition_restarts_the_idle_window(mam_sandbox, mock_herdr
wait mock. process-info retains its measured nested result shape.
"""
reg = mam_sandbox / ".mam" / "jobs"
env = _env(mam_sandbox, MAM_STALL_IDLE_S=10)
env = _env(mam_sandbox, MAM_STALL_IDLE_S=40)
jid = _job(env, reg)
agent = _proc("exec sleep 300")
observed = mam_sandbox / "observed.json"
@@ -729,7 +729,10 @@ def test_r4_a_missed_transition_restarts_the_idle_window(mam_sandbox, mock_herdr
w.terminate()
w.communicate(timeout=10)
idle_time = times['prompted'] - times.get('changed', times['started'])
assert idle_time >= 10, {'continuous_idle_seconds': idle_time, 'threshold': 10}
# S must exceed the 30 s re-judgement interval: with the old code the nudge came
# ~30 s after the missed transition, which only fails the assertion when S > 30
# (review ad3d8206; S=10 passed on the defective code too).
assert idle_time >= 40, {'continuous_idle_seconds': idle_time, 'threshold': 40}
finally:
if w is not None and w.poll() is None:
w.terminate()
@@ -745,3 +748,42 @@ def test_r1_the_codex_extractor_keeps_every_line_under_the_prompt():
assert extract_input_region(draft, "codex") == "draft on the second input line"
no_footer = "\n".join(idle.splitlines()[:-1]).replace("› Ask Codex to do anything", "›\n a · b · c")
assert extract_input_region(no_footer, "codex") != "", "only the last line may be the footer"
# Review ad3d8206 (planner-reviewer-codex-01): a prompt glyph inside the draft
# is draft text, not the start of the input box (the reviewer's reproduction).
@pytest.mark.parametrize("draft", [False, True])
def test_r1b_a_draft_containing_the_prompt_glyph_is_not_empty(mam_sandbox, mock_herdr, draft):
reg = mam_sandbox / ".mam" / "jobs"
env = _env(mam_sandbox, MAM_STALL_IDLE_S=1)
jid = _job(env, reg)
agent = _proc("exec sleep 300")
w = None
try:
pane = _pane("codex")
if draft:
pane = pane.replace("› Ask Codex to do anything", "› Explain this terminal prompt:\n ›")
_agent(mock_herdr, "reviewer-codex-t", "codex", agent.pid, "idle", pane)
w = _watch(env, reg, jid, "reviewer-codex-t", "codex")
if draft:
time.sleep(5)
else:
assert _until(lambda: _prompts(mock_herdr))
prompts = _prompts(mock_herdr)
_finish(env, reg, jid, w)
assert len(prompts) == (0 if draft else 1), prompts
finally:
if w is not None and w.poll() is None:
w.terminate()
w.communicate(timeout=10)
_kill(agent)
def test_r1b_the_extractor_strips_the_prompt_from_the_first_line_only():
from lib_py.agents.input_region import extract_input_region
idle = _pane("codex")
for draft in ("› Explain this terminal prompt:\n ›", "›\n ›", "› Ask Codex to do anything\n more"):
assert extract_input_region(idle.replace("› Ask Codex to do anything", draft), "codex") != "", draft
typed = re.sub(r"^❯\s*$", "❯ x\n ❯", _pane("claude"), count=1, flags=re.M)
assert typed != _pane("claude") and extract_input_region(typed, "claude") != ""