fix(FN-4526): finalize stale merge stats repairs and changeset

Fusion-Task-Id: FN-4526
Fusion-Task-Lineage: 38dc93d6-3e56-4e22-aaaa-d09b2eed43e5
This commit is contained in:
Fusion
2026-05-14 14:36:56 -07:00
committed by gsxdsm
parent 015085a541
commit 74f46f0f76
3 changed files with 42 additions and 8 deletions

View File

@@ -110,7 +110,7 @@ describeIfGit("SelfHealingManager recoverDoneTaskMergeMetadata stale stats", ()
it("does not rewrite when stats are already correct", async () => {
const { repo, sha } = setupRepo();
const expected = parseShortstat(git(repo, `git show --shortstat --format= ${sha}`));
const task = makeTask("FN-4526-OK", repo, sha, expected);
const task = makeTask("FN-4526-STATS", repo, sha, expected);
const tasks = new Map([[task.id, task]]);
const store = createStore(tasks);
const manager = new SelfHealingManager(store, { rootDir: repo, getExecutingTaskIds: () => new Set() });
@@ -119,4 +119,22 @@ describeIfGit("SelfHealingManager recoverDoneTaskMergeMetadata stale stats", ()
expect((store.updateTask as any).mock.calls).toHaveLength(0);
});
it("repairs stale stats in unconfirmed branch when SHA matches landed commit", async () => {
const { repo, sha } = setupRepo();
const expected = parseShortstat(git(repo, `git show --shortstat --format= ${sha}`));
const task = makeTask("FN-4526-STATS", repo, sha, { filesChanged: 777, insertions: 888, deletions: 999, mergeConfirmed: false });
const tasks = new Map([[task.id, task]]);
const store = createStore(tasks);
const manager = new SelfHealingManager(store, { rootDir: repo, getExecutingTaskIds: () => new Set() });
await manager.recoverDoneTaskMergeMetadata();
const repaired = tasks.get(task.id)!;
expect(repaired.mergeDetails?.commitSha).toBe(sha);
expect(repaired.mergeDetails?.filesChanged).toBe(expected.filesChanged);
expect(repaired.mergeDetails?.insertions).toBe(expected.insertions);
expect(repaired.mergeDetails?.deletions).toBe(expected.deletions);
expect(repaired.mergeDetails?.mergeConfirmed).toBe(true);
});
});

View File

@@ -2550,7 +2550,12 @@ export class SelfHealingManager {
cwd: this.options.rootDir,
maxBuffer: 1024 * 1024,
});
return parseShortstat(stats.stdout);
const parsed = parseShortstat(stats.stdout);
return {
filesChanged: parsed.filesChanged ?? 0,
insertions: parsed.insertions ?? 0,
deletions: parsed.deletions ?? 0,
};
} catch {
return null;
}
@@ -2630,15 +2635,21 @@ export class SelfHealingManager {
continue;
}
const landedStats = {
filesChanged: landed.filesChanged ?? 0,
insertions: landed.insertions ?? 0,
deletions: landed.deletions ?? 0,
};
const needsRepair =
task.mergeDetails?.commitSha !== landed.sha ||
task.mergeDetails?.filesChanged === undefined ||
task.mergeDetails?.insertions === undefined ||
task.mergeDetails?.deletions === undefined || (
task.mergeDetails?.commitSha === landed.sha && (
task.mergeDetails?.filesChanged !== landed.filesChanged ||
task.mergeDetails?.insertions !== landed.insertions ||
task.mergeDetails?.deletions !== landed.deletions
task.mergeDetails?.filesChanged !== landedStats.filesChanged ||
task.mergeDetails?.insertions !== landedStats.insertions ||
task.mergeDetails?.deletions !== landedStats.deletions
)
);
@@ -2648,9 +2659,9 @@ export class SelfHealingManager {
mergeDetails: {
...task.mergeDetails,
commitSha: landed.sha,
filesChanged: landed.filesChanged,
insertions: landed.insertions,
deletions: landed.deletions,
filesChanged: landedStats.filesChanged,
insertions: landedStats.insertions,
deletions: landedStats.deletions,
mergeCommitMessage: landed.subject,
mergedAt: task.mergeDetails?.mergedAt ?? new Date().toISOString(),
mergeConfirmed: true,