fix(swarm): recognize unit-specific completion tools as implicit complete
Detected via supervisory check 2026-05-17: SF stuck in degenerate reassess-
roadmap loop on M010/S03 (5 iterations in 8min, all returning
outcome=continue). Root cause: synthesized-checkpoint in runUnitViaSwarm
only treats the generic `checkpoint` tool as a completion signal — but
units routinely complete via their unit-specific tool (reassess_roadmap
with verdict=roadmap-confirmed, validate_milestone, complete_milestone,
complete_slice, save_summary). The LLM correctly emitted the unit's
specific completion tool + assistant text "<turn_status>complete</turn_status>",
but workerSignaledOutcome stayed null → synthesized checkpoint fell back
to continue → solver re-iterated.
Fix: recognize UNIT_COMPLETION_TOOLS = {reassess_roadmap,
validate_milestone, complete_milestone, complete_slice, save_summary}
as implicit "complete" signals. The check fires when those tools are
called and an earlier explicit checkpoint hasn't already said
"complete" or "blocked".
This resolves sf-mp94lth4-ew26om and should prevent future
degenerate-iteration loops on reassess-roadmap and milestone completion
units. 13/13 existing M010 tests still pass.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
460db52504
commit
0c0608fa50
1 changed files with 26 additions and 0 deletions
|
|
@ -562,6 +562,32 @@ async function runUnitViaSwarm(ctx, _pi, s, unitType, unitId, prompt, options) {
|
|||
input: toolCall.arguments ?? {},
|
||||
});
|
||||
|
||||
// #sf-mp94lth4-ew26om: Recognize unit-specific completion tools as
|
||||
// implicit "complete" signals. Workers often call the unit's specific
|
||||
// completion tool (reassess_roadmap with verdict, validate_milestone,
|
||||
// complete_milestone, complete_slice, save_summary) and skip the
|
||||
// generic checkpoint tool. Without this, the synthesized checkpoint
|
||||
// falls back to outcome=continue and the solver iterates indefinitely
|
||||
// despite the worker having genuinely finished (witnessed on
|
||||
// reassess-roadmap M010/S03 — 5 iterations in 8min, all confirming
|
||||
// completion in their text but never calling `checkpoint`).
|
||||
const UNIT_COMPLETION_TOOLS = new Set([
|
||||
"reassess_roadmap",
|
||||
"validate_milestone",
|
||||
"complete_milestone",
|
||||
"complete_slice",
|
||||
"save_summary",
|
||||
]);
|
||||
if (
|
||||
UNIT_COMPLETION_TOOLS.has(toolCall.name) &&
|
||||
workerSignaledOutcome !== "complete" &&
|
||||
workerSignaledOutcome !== "blocked"
|
||||
) {
|
||||
// Mark as complete unless an earlier explicit checkpoint already
|
||||
// said otherwise (don't override blocked / explicit progress).
|
||||
workerSignaledOutcome = "complete";
|
||||
}
|
||||
|
||||
// Detect the canonical completion-signal tool: "checkpoint".
|
||||
// This is the same tool inspected by the legacy runUnit path's solver pass
|
||||
// (phases-unit.js line ~989: activeToolsAllowlist: ["checkpoint"]).
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue