Problem
The issue builder (builder-N in --role issue mode) exits as soon as it sees no open issues and agents appear idle. But "idle" just means between milestones — the milestone reviewer and validator are still draining their queues. They continue filing bugs and findings after the issue builder has already written its done sentinel and exited. Nobody is left to fix those issues.
In the Stretto test run (20260226-143251), 13 issues were filed after the issue builder shut down, including a build-breaking bug (merge conflict markers committed) and several real findings.
Root cause
Circular dependency in shutdown signals:
- Non-builder agents (reviewer, milestone reviewer, tester, validator) wait for all
builder-*.done files before draining and exiting
- The issue builder writes
builder-N.done before non-builder agents are finished
- Non-builder agents file issues during their drain phase that nobody picks up
Proposed fix: Split the "done" signal
-
Non-builder agents ignore the issue builder's sentinel. Change the drain trigger so reviewers, milestone reviewer, tester, and validator only wait for milestone builder sentinels (builder-1.done through builder-{N-1}.done), not the issue builder's. This unblocks their drain without the issue builder having to exit first.
-
Non-builder agents write their own done sentinels. After draining, each writes logs/{agent}.done (e.g. validator.done, milestone-reviewer.done, tester.done, reviewer-N.done).
-
Issue builder waits for non-builder done sentinels. Instead of using log-staleness as a proxy for "agents finished," the issue builder explicitly waits for validator.done, milestone-reviewer.done, tester.done, and all reviewer-N.done files. It keeps polling for and fixing open issues while waiting.
-
Issue builder does a final sweep. Once all non-builder sentinels exist and no open bugs/findings remain, the issue builder writes builder-N.done and exits last.
-
Orchestrator waits for all done files. is_builder_done() continues to wait for all builder-*.done files as today — no change needed there.
Shutdown sequence after fix
Milestone builders finish → write builder-{1..M-1}.done
↓
Non-builder agents see milestone builders done → drain remaining milestones → file last issues → write {agent}.done
↓
Issue builder sees non-builder done files + no open issues → final sweep → write builder-N.done
↓
Orchestrator sees all builder-*.done → exit
Files likely affected
src/agentic_dev/sentinel.py — is_builder_done() needs a variant that excludes the issue builder; new is_agent_done() / write_agent_done() helpers
src/agentic_dev/builder.py — issue builder shutdown loop: wait for non-builder sentinels instead of log-staleness
src/agentic_dev/watcher.py — reviewer drain trigger: only check milestone builder sentinels
src/agentic_dev/milestone_reviewer.py — same drain trigger change; write done sentinel after drain
src/agentic_dev/tester.py — same
src/agentic_dev/validator.py — same
src/agentic_dev/orchestrator.py — clear non-builder sentinels at startup alongside builder sentinels
Problem
The issue builder (builder-N in
--role issuemode) exits as soon as it sees no open issues and agents appear idle. But "idle" just means between milestones — the milestone reviewer and validator are still draining their queues. They continue filing bugs and findings after the issue builder has already written its done sentinel and exited. Nobody is left to fix those issues.In the Stretto test run (20260226-143251), 13 issues were filed after the issue builder shut down, including a build-breaking bug (merge conflict markers committed) and several real findings.
Root cause
Circular dependency in shutdown signals:
builder-*.donefiles before draining and exitingbuilder-N.donebefore non-builder agents are finishedProposed fix: Split the "done" signal
Non-builder agents ignore the issue builder's sentinel. Change the drain trigger so reviewers, milestone reviewer, tester, and validator only wait for milestone builder sentinels (
builder-1.donethroughbuilder-{N-1}.done), not the issue builder's. This unblocks their drain without the issue builder having to exit first.Non-builder agents write their own done sentinels. After draining, each writes
logs/{agent}.done(e.g.validator.done,milestone-reviewer.done,tester.done,reviewer-N.done).Issue builder waits for non-builder done sentinels. Instead of using log-staleness as a proxy for "agents finished," the issue builder explicitly waits for
validator.done,milestone-reviewer.done,tester.done, and allreviewer-N.donefiles. It keeps polling for and fixing open issues while waiting.Issue builder does a final sweep. Once all non-builder sentinels exist and no open bugs/findings remain, the issue builder writes
builder-N.doneand exits last.Orchestrator waits for all done files.
is_builder_done()continues to wait for allbuilder-*.donefiles as today — no change needed there.Shutdown sequence after fix
Files likely affected
src/agentic_dev/sentinel.py—is_builder_done()needs a variant that excludes the issue builder; newis_agent_done()/write_agent_done()helperssrc/agentic_dev/builder.py— issue builder shutdown loop: wait for non-builder sentinels instead of log-stalenesssrc/agentic_dev/watcher.py— reviewer drain trigger: only check milestone builder sentinelssrc/agentic_dev/milestone_reviewer.py— same drain trigger change; write done sentinel after drainsrc/agentic_dev/tester.py— samesrc/agentic_dev/validator.py— samesrc/agentic_dev/orchestrator.py— clear non-builder sentinels at startup alongside builder sentinels