Files
fusion/.changeset/fix-post-session-branch-attribution-audit.md
gsxdsm 5848606a9a feat(engine): post-session branch attribution audit
Contamination on fusion/<id> branches (FN-5233 was the recent example:
two untrailered feat(FN-5353): commits sitting on fusion/fn-5233) used
to be invisible until merge time, days after it happened. The executor
already runs assertCleanBranchAtBase at worktree acquisition and reclaim
— the gap was the active session window itself.

Add reportBranchAttribution(repoDir, branch, baseSha, taskId) which
walks base..branch and bins every commit into ownTrailed (healthy),
ownUntrailed (subject tag but commit-msg hook didn't fire), foreign
(different FN-id), or unattributed (no subject pattern, no trailer —
typically a hand-merge or plumbing commit). Wire it into the executor
right after captureModifiedFiles in the post-session path: when any
anomaly bucket is non-empty, emit a structured branch:attribution-
anomaly audit event and a task log entry. The audit itself is wrapped
in a try/catch so a probe failure never destabilizes a completing
session. New branch:attribution-anomaly and branch:auto-reattach-
authoritative GitMutationType variants accept the structured metadata
(the latter for the handoff re-attach added earlier this session).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-21 19:20:33 -07:00

1.5 KiB

@runfusion/fusion
@runfusion/fusion
patch

Engine reliability: post-session branch-attribution audit catches contamination within minutes instead of days.

  • The executor already checks branch contamination at acquisition time (assertCleanBranchAtBase) and at reclaim time. The gap was the active session window itself: commits added to fusion/<id> between acquisition and merge handoff went undetected until merge-time refusal, which is how FN-5233 ended up with two untrailered feat(FN-5353): commits sitting on fusion/fn-5233.
  • New reportBranchAttribution(repoDir, branch, baseSha, taskId) walks base..branch and classifies every commit into four buckets: ownTrailed (subject tag + Fusion-Task-Id trailer — healthy), ownUntrailed (subject tag but missing trailer — signals the commit-msg hook didn't fire), foreign (different FN-id via subject or trailer — contamination), and unattributed (neither — typically a hand-merge or plumbing commit).
  • Wired into the executor's post-session path (right after captureModifiedFiles): if any anomaly bucket is non-empty, the executor logs a structured branch:attribution-anomaly audit event and a task log entry. Failures in the audit itself are caught and warn-only — the audit must never destabilize a completing session. New branch:attribution-anomaly and branch:auto-reattach-authoritative git-mutation types accept the structured metadata.
  • Five new vitest cases cover the four anomaly buckets and the empty-range no-op.