fix(work): emit completion signal to stop sandcastle agent loops

Sandcastle re-invokes agents up to maxIterations even when the work is
already done — the decomposer was looping 4x re-writing the same epic
on every dispatch. Two halves to the fix:

- Pass completionSignal: "<promise>COMPLETE</promise>" explicitly on
  all three run() calls (decompose, implementer, reviewer). Makes the
  contract visible alongside maxIterations instead of relying on
  sandcastle's default.
- Append a "Signal completion (required)" section to each prompt
  telling the agent to emit the literal marker as its final line when
  the work is genuinely done, plus a "do NOT emit if..." list to
  discourage premature signaling.
This commit is contained in:
2026-05-13 19:11:44 +02:00
parent d6bf2f638f
commit eadbb7ebd9
5 changed files with 47 additions and 0 deletions

View File

@@ -98,3 +98,15 @@ When done, return structured JSON:
```
Do NOT modify the task markdown or `_state.json` yourself — the orchestrator handles state writes.
## Signal completion (required)
After you have committed the slice (or returned a terminal `blocked` / `needs-clarification` status), emit the literal string `<promise>COMPLETE</promise>` as the final line of your response.
Sandcastle uses this marker to stop the iteration loop. Without it, the orchestrator will re-invoke you up to `maxIterations` times even when the work is already done — every redundant iteration costs subscription quota and time.
Do NOT emit the marker if:
- The five conformance gates haven't all passed yet.
- You still have files to write, fixes to apply, or commits to make.
- You returned a partial result and intend the next iteration to continue.