Skip to content

graph: stop the fix loop early when impl writes nothing - #156

Merged
alpibrupa merged 1 commit into
mainfrom
fix/fixloop-noop-impl-guard
Sep 9, 2026
Merged

graph: stop the fix loop early when impl writes nothing#156
alpibrupa merged 1 commit into
mainfrom
fix/fixloop-noop-impl-guard

Conversation

@alpibrupa

Copy link
Copy Markdown
Contributor

Summary

  • FixLoopDef.setup (SequenceNode([impl, test])) ran unconditionally — test always ran after impl, even when impl never called write or edit at all.
  • Reproduced live this session: glm-5.3-flash spent its entire step budget deliberating in plain assistant text (second-guessing Lex syntax, drafting code in prose) without ever writing the target file, and the pipeline still ran test (120 steps) and verify (84 steps) against a file that was never created — 298 steps burned before the final lex check criterion in task_spec.lex caught it, the only thing that ever did.
  • wrote_or_edited(events) scans a turn's trail for a cap.completed event naming the write or edit tool — same shape as verify_found_failure's existing FAIL-substring scan, reading what the dispatcher recorded rather than trusting the model's own closing text.
  • run_setup runs setup's first stage with event tracking when the shape allows it (an AgentNode alone, or the head of a SequenceNode — the exact shape every current FixLoopDef.setup uses) and stops immediately, before test or the mechanical verify_program ever run, if nothing was written. Any other setup shape falls back to the previous unconditional run_node, so this only ever adds coverage, never narrows it.

Test plan

  • lex check (full sweep), lex fmt --check, lex doc-sync --check, lex test (unit suite) all pass
  • wrote_or_edited's own examples {} block covers write/edit/read/invoked-not-completed
  • Live integration test in a throwaway worktree: a real task answerable by reading alone ("how many functions does this file define") correctly stopped after impl done — 16 steps with no test/verify stage following, versus the unguarded behavior that would have run both anyway

🤖 Generated with Claude Code

FixLoopDef.setup ran unconditionally: SequenceNode([impl, test])
always ran test after impl, even when impl never called write or edit
at all. Reproduced live: glm-5.3-flash spent its entire step budget
deliberating in plain assistant text (second-guessing Lex syntax,
drafting code in prose) without ever writing the target file, and the
pipeline still ran test (120 steps) and verify (84 steps) against a
file that was never created -- 298 steps burned before the final
`lex check` criterion in task_spec.lex caught it, the only thing that
ever did.

wrote_or_edited(events) scans a turn's trail for a cap.completed event
naming the write or edit tool -- same shape as verify_found_failure's
existing FAIL-substring scan, reading what the dispatcher recorded
rather than trusting the model's own closing text. run_setup runs
setup's first stage with event tracking when the shape allows it (an
AgentNode alone, or the head of a SequenceNode -- the exact shape
every current FixLoopDef.setup uses) and stops immediately, before
test or the mechanical verify_program ever run, if nothing was
written. Any other setup shape (ParallelNode, FixLoopNode, empty
SequenceNode) falls back to the previous unconditional run_node, so
this only ever adds coverage, never narrows it.

Verified two ways: wrote_or_edited's own examples{} block (lex check),
and a live integration test in a throwaway worktree -- a real task
answerable by reading alone ("how many functions does this file
define") correctly stopped after "impl done -- 16 steps" with no test
or verify stage following, versus the unguarded behavior that would
have run both anyway.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@alpibrupa
alpibrupa merged commit 82e0ea0 into main Sep 9, 2026
1 check passed
@alpibrupa
alpibrupa deleted the fix/fixloop-noop-impl-guard branch September 9, 2026 02:32
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