fix(FN-5633): guarantee the squash subject starts with the task id

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>
This commit is contained in:
gsxdsm
2026-05-28 20:18:41 -07:00
parent c1d558c765
commit 7f536eb619
2 changed files with 40 additions and 15 deletions

View File

@@ -148,9 +148,12 @@ describe("runAiMerge", () => {
expect(mainAfter).not.toBe(mainBefore);
// The squash landed the feature file.
expect(existsSync(join(dir, "feature.txt"))).toBe(true);
// The landed commit carries the board-association trailer even though the
// (mock) merge agent committed without it — ensureTaskTrailersOnHead adds it.
expect(git(dir, "log -1 --pretty=%B main")).toContain("Fusion-Task-Id: FN-1");
// The landed commit carries the board-association trailer AND its subject
// starts with the task id, even though the (mock) merge agent committed
// "squash: feature" without either — ensureCommitTaskMetadata adds both.
const landedMsg = git(dir, "log -1 --pretty=%B main");
expect(landedMsg).toContain("Fusion-Task-Id: FN-1");
expect(git(dir, "log -1 --pretty=%s main")).toMatch(/^FN-1: /);
// Task moved to done + event emitted.
expect(store.moveTask).toHaveBeenCalledWith("FN-1", "done");
expect(emitted.some((e) => e.event === "task:merged")).toBe(true);