fix: merge_agent_work blocks until complete instead of requiring polling

The mergemaster agent was burning all 30 turns polling get_merge_status
every 2 seconds while the merge pipeline takes ~2 minutes. It would
exhaust turns, exit, restart, and repeat — never seeing the result.

merge_agent_work now blocks with a 10-second internal poll loop and
returns the final result directly. The agent calls it once and gets
the answer. No more polling turns wasted.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
dave
2026-04-11 17:43:50 +00:00
parent 599fbdc71d
commit d06241c20c
9 changed files with 242 additions and 159 deletions
@@ -139,15 +139,27 @@ impl AgentPool {
);
let empty_diff_reason = "Feature branch has no code changes — the coder agent \
did not produce any commits.";
// Write merge_failure and blocked to content store + CRDT.
let contents = crate::db::read_content(story_id)
.unwrap_or_else(|| "---\nname: unknown\n---\n".to_string());
let updated = crate::io::story_metadata::write_merge_failure_in_content(
&contents,
empty_diff_reason,
);
let blocked = crate::io::story_metadata::write_blocked_in_content(&updated);
crate::db::write_item_with_content(story_id, stage_dir, &blocked);
// Write merge_failure and blocked to content store.
if let Some(contents) = crate::db::read_content(story_id) {
let updated = crate::io::story_metadata::write_merge_failure_in_content(
&contents,
empty_diff_reason,
);
let blocked = crate::io::story_metadata::write_blocked_in_content(&updated);
crate::db::write_content(story_id, &blocked);
crate::db::write_item_with_content(story_id, stage_dir, &blocked);
} else {
// Fallback: filesystem.
let story_path = project_root
.join(".huskies/work")
.join(stage_dir)
.join(format!("{story_id}.md"));
let _ = crate::io::story_metadata::write_merge_failure(
&story_path,
empty_diff_reason,
);
let _ = crate::io::story_metadata::write_blocked(&story_path);
}
let _ = self.watcher_tx.send(crate::io::watcher::WatcherEvent::StoryBlocked {
story_id: story_id.to_string(),
reason: empty_diff_reason.to_string(),