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>
1.5 KiB
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 tofusion/<id>between acquisition and merge handoff went undetected until merge-time refusal, which is how FN-5233 ended up with two untraileredfeat(FN-5353):commits sitting onfusion/fn-5233. - New
reportBranchAttribution(repoDir, branch, baseSha, taskId)walksbase..branchand classifies every commit into four buckets:ownTrailed(subject tag +Fusion-Task-Idtrailer — healthy),ownUntrailed(subject tag but missing trailer — signals the commit-msg hook didn't fire),foreign(different FN-id via subject or trailer — contamination), andunattributed(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 structuredbranch:attribution-anomalyaudit event and a task log entry. Failures in the audit itself are caught and warn-only — the audit must never destabilize a completing session. Newbranch:attribution-anomalyandbranch:auto-reattach-authoritativegit-mutation types accept the structured metadata. - Five new vitest cases cover the four anomaly buckets and the empty-range no-op.