Skip to content

propose_code_change: take the diff from the swarm's worktree capture, refuse incomplete runs - #5308

Merged
Evanfeenstra merged 2 commits into
masterfrom
propose-code-change-worktree-diff
Sep 15, 2026
Merged

Evanfeenstra merged 2 commits into
masterfrom
propose-code-change-worktree-diff

Conversation

@Evanfeenstra

@Evanfeenstra Evanfeenstra commented Sep 15, 2026 •

Copy link
Copy Markdown
Contributor

Problem

propose_code_change preview runs were coming back with the model's narration as the answer and no diff, while the edit had actually landed in the swarm's worktree. Root cause and swarm-side fix are in stakwork/stakgraph#1692: a gateway tool-version rewrite made the AI SDK's tool loop exit silently on the edit step, and the swarm reported success.

The swarm now reads the diff from the ephemeral worktree itself and reports it on the terminal result as preview, the counterpart of pr on create_pr runs, with the same shape: { ok: true, diff, filesChanged } or { ok: false, failure, error }. It also sets incomplete: { reason } when the run never reached a proper termination. This PR consumes both.

Changes (src/lib/ai/codeChangeTools.ts)

  • Prefer preview.diff over anything in the model's text. It is ground truth and includes new files; the model's pasted diff was a transcription, and git diff HEAD would have left new files out of it.
  • Refuse incomplete runs with a clear message. The text is narration and the worktree may hold a half-applied change, so no proposal card.
  • Believe a failed preview (no_changes, change_too_large, secrets_detected, otherwise generic) over a diff the model pasted.
  • Keep the regex-on-text fallback for swarms that predate the capture, and make the prompt ask for git add -A && git diff --cached so that path includes new files too.
  • Surface the swarm's error text on failure instead of "timed out or returned an error".

Testing

  • codeChangeTools.test.ts: 15 passed (7 new cases: worktree diff preferred, text fallback, incomplete refused, no_changes believed over pasted diff, secrets mapping, error passthrough, prompt stages before diffing)
  • eslint and prettier --check clean on touched files

Notes

  • Backward compatible: an older swarm returns none of the new fields and the tool behaves as before, minus the staging fix in the prompt.
  • Deploy order between this and the stakgraph PR does not matter.

… refuse incomplete runs

Preview runs were coming back with narration instead of a diff while the
edit had landed in the swarm's worktree (stakwork/stakgraph#1692 has the
root cause: a gateway tool-version rewrite made the AI SDK's tool loop
exit silently, and the swarm reported success). The swarm now reads the
diff from the ephemeral worktree itself and returns it as `diff`, with
`diff_error` when it looked and found a reason there is none, and
`incomplete` when the run never reached a proper termination.

- Prefer the swarm's `diff` over anything in the model's text. It is
  ground truth and includes new files; the model's pasted diff was a
  transcription that `git diff HEAD` would have left new files out of.
- Refuse `incomplete` runs outright: the text is narration and the
  worktree may hold a half-applied change, so no proposal card.
- Believe `diff_error` (no_changes, change_too_large, secrets_detected)
  over a diff the model pasted, with a specific message for each.
- Keep the regex-on-text extraction as the fallback for swarms that
  predate the capture, and make that fallback stage first
  (`git add -A && git diff --cached`) so it too includes new files.
- Surface the swarm's error text when the run fails instead of a generic
  "timed out or returned an error".

Tests cover each source and refusal, the error passthrough, and the
prompt change. Backward compatible with older swarms.
The swarm reports the ephemeral worktree diff as one `preview` field with
the create_pr result's ok / failure / error shape, instead of three
top-level fields.
@Evanfeenstra
Evanfeenstra merged commit 4c67d86 into master Sep 15, 2026
8 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant