fix(work): bump sandcastle maxIterations so agents finish + commit

Sandcastle's default maxIterations: 1 cut every agent off after its
first response, so files written inside the sandbox never made it
into a captured commit. The decomposer wrote 9 epic + story files,
hit the limit, and sandcastle returned 0 commits — the host saw
nothing.

decompose.mjs: maxIterations 10 (small authoring task — read
context, write files, commit). Override via env
SANDCASTLE_DECOMPOSE_ITERATIONS.

dispatch.mjs:
- Implementer: maxIterations 30 (full TDD slice — read context,
  red test, green impl, run all five gates, commit). Override via
  SANDCASTLE_IMPLEMENTER_ITERATIONS.
- Reviewer: maxIterations 10 (read diff + task spec, decide).
  Override via SANDCASTLE_REVIEWER_ITERATIONS.

Each call site documents WHY the value was picked + names the env
override inline so tuning is discoverable from the code.
This commit is contained in:
2026-05-13 18:56:59 +02:00
parent 71c04f521a
commit 26aa97f0ef
2 changed files with 16 additions and 0 deletions

View File

@@ -160,6 +160,12 @@ export async function executeDecompose(prdId, prdPath, prdText) {
promptFile: decomposerPrompt,
promptArgs: { PRD_FILE_CONTENT: prdText },
cwd: REPO_ROOT,
// Sandcastle's default maxIterations: 1 cut the agent off after its
// first response — files were written inside the sandbox but never
// captured as commits. Decompose is a small authoring task (read
// context, write epic + stories, commit); 10 iterations is enough
// room. Tune via env SANDCASTLE_DECOMPOSE_ITERATIONS.
maxIterations: Number(process.env.SANDCASTLE_DECOMPOSE_ITERATIONS ?? 10),
});
} catch (e) {
console.error("✗ Decomposer dispatch failed:", e.message);

View File

@@ -231,6 +231,12 @@ async function executeDispatch() {
promptFile: implementerPrompt,
promptArgs: { TASK_FILE_CONTENT: taskSpec },
cwd: REPO_ROOT,
// Implementer runs a full TDD slice (read context, red test, green
// impl, run all five gates, commit). 30 iterations matches typical
// slice shape. Tune via env SANDCASTLE_IMPLEMENTER_ITERATIONS.
maxIterations: Number(
process.env.SANDCASTLE_IMPLEMENTER_ITERATIONS ?? 30,
),
});
} catch (e) {
console.error("✗ Implementer dispatch failed:", e.message);
@@ -280,6 +286,10 @@ async function executeDispatch() {
promptFile: reviewerPrompt,
promptArgs: { TASK_FILE_CONTENT: taskSpec, DIFF: diff },
cwd: REPO_ROOT,
// Reviewer reads the diff + task spec and decides (approve/reject).
// Smaller surface than the implementer; 10 iterations is plenty.
// Tune via env SANDCASTLE_REVIEWER_ITERATIONS.
maxIterations: Number(process.env.SANDCASTLE_REVIEWER_ITERATIONS ?? 10),
});
console.log(`Reviewer returned. stdout follows:\n${reviewResult.stdout}`);