Refuse AI merge landing on a checked-out dirty integration worktree by default. This prevents Fusion from stashing/restoring unrelated project-root edits into main and then marking tasks done against contaminated state.
Fusion-Task-Id: FN-5780
ensureCommitTaskMetadata (was ensureTaskTrailersOnHead) now also prefixes the
commit subject with `<taskId>: ` when includeTaskIdInCommit is on, in addition
to ensuring the Fusion-Task-Id / lineage trailers — so the landed commit both
starts with the task id and carries the board-association trailers even if the
AI agent omits them. Single idempotent amend.
Test: asserts the landed subject matches /^FN-1: / when the agent committed
without a prefix.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- Commit message: the merge agent writes a concise change-summary subject (not
just the task title), and every landed squash carries board-association
trailers — `Fusion-Task-Id: <taskId>` plus the canonical lineage trailer when
the task has a lineageId — guaranteed via an idempotent amend
(ensureTaskTrailersOnHead) even if the agent omits them.
- Verify-and-fix: the merge prompt instructs the agent to run the project's
tests / type-check / lint after resolving the merge and fix any NEW failure
the merge introduced (not pre-existing breakage) before committing.
- Editable prompt: the AI merge agent's base persona is the editable "merger"
role prompt (Settings -> Prompts); the clean-room / verification / trailer
rules are always appended so a custom prompt can't drop them.
- Reviewer model: reviewer uses the project reviewer/validator model lane
(resolveValidatorSettingsModel); the bespoke merger.reviewerModel setting is
removed.
Changeset updated to cover all AI merger changes.
Tests: trailer present on landed commit (+ lineage when set), editable-prompt
incorporation, new-breakage verification wording.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The AI merge path treated a missing task branch as a benign no-op. That's
correct when the task was never executed or already merged (branch cleaned up
on a re-process), but if the task WAS executed (a baseCommitSha was recorded)
and has no recorded merge, the branch should still exist — its work appears
lost. Now that case throws instead of silently marking the task done; the
benign cases still finalize as a no-op (reason "already-merged" / "no-branch").
Tests: executed+never-merged → throws; already-merged → no-op done;
never-executed → no-op done.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
New default merge path (merger.mode="ai"), self-contained in merger-ai.ts and
dispatched from ProjectEngine.onMerge instead of the legacy aiMergeTask pipeline
(kept for merger.mode="deterministic").
Flow: clean-room detached worktree at the target branch tip → AI agent merges
the task branch + squashes (resolving conflicts) → fresh read-only AI reviewer
audits with corrective retries (blocking vs advisory; advisory lands, unfixable
correctness hard-fails via AiMergeBlockedError; fail-safe verdict parsing) →
land via `git merge --ff-only` when the checkout is on the target (else
update-ref CAS) → sync the local checkout (stash → ff → restore; AI reconciles
a conflicting restore and keeps the original edits in a backup stash;
un-stashable dirt advances the ref + warns) → finalize (delete task branch —
never the integration branch — task→done, remove temp worktree).
- Per-task target branch honored (falls back to the default integration
branch); local checkout synced only when on that target.
- Structurally immune to the dirty-clobber and stale-base/non-FF bug classes of
the legacy path (clean room + FF-by-construction).
- Progress surfaced on the task status pill + task log stream.
- Clear error when the target branch has no local ref.
Settings: merger.mode / merger.reviewerModel / merger.maxReviewPasses, surfaced
in Settings → Merge; legacy merge-mechanics settings hidden when AI mode is on.
Tests: merger-ai.test.ts (verdict parser, clean merge, blocking hard-fail,
advisory land, empty no-op, target-branch isolation, missing-target error,
landSquash clean/other-branch/dirty-restore/AI-resolved). Legacy
merge-orchestration tests pinned to deterministic mode.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>