fix(merger): restrict staging to allowlist and harden git invocations

Replaces blanket `git add -A` in `commitOrAmendMergeWithFixes` with an
explicit allowlist of (squash-staged ∪ fix-agent-modified) paths, so
unrelated dirty files in the project root no longer get swept into a
task's squash commit. The in-merge fix agent now snapshots the working
tree before/after its session to capture exactly which files it touched.

Hardens the git invocations the allowlist relies on:
- All `git add` and `git checkout --ours/--theirs` calls switched from
  shell-interpolated `execAsync` to `execFile` array form, eliminating
  path-injection surface and batching per-file spawns into one call.
- `snapshotDirtyFiles` adopts `git -z` NUL-delimited parsing so paths
  with embedded spaces or specials are handled correctly.
- Long allowlist debug logs are truncated to 20 entries with an overflow
  marker.

Refused-to-stage paths emit a warn naming each file so the user can
audit what was filtered.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
gsxdsm
2026-05-04 13:17:29 -07:00
parent 0536df748b
commit 54f2832691
5 changed files with 837 additions and 20 deletions

View File

@@ -0,0 +1,9 @@
---
"@fusion/engine": patch
---
Restrict merger staging to squash + fix-agent files; refuse to commit unrelated working-tree changes
Replaces the blanket `git add -A` in `commitOrAmendMergeWithFixes` with an explicit allowlist: only files that were squash-staged or explicitly modified by the in-merge verification fix agent are staged. Any other dirty files in the working tree are left untouched and a warning is logged naming each excluded path. Fixes a production bug where ~13 unrelated user-edited files were bundled into a task's squash commit.
Hardened by code review: replaced all shell-interpolated `git add` calls in `commitOrAmendMergeWithFixes` and the conflict-resolution helpers (`resolveWithOurs`, `resolveWithTheirs`, `resolveTrivialWhitespace`) with `execFile` array form to eliminate path-injection surface; adopted `git -z` NUL-delimited output for all dirty-file path queries in both `snapshotDirtyFiles` and `commitOrAmendMergeWithFixes` so paths with embedded spaces round-trip correctly; truncated long allowlist debug log lines to at most 20 entries.