FN-5839: prevent stale integration-advance sync prompts

Treat rewritten integration-branch advances as handled when the working tree is already aligned.

- Add a new `superseded` resolution for unreachable advance SHAs that remain after history rewrites while HEAD matches the local integration tip.
- Update Git status collection logic and route/API status typings to propagate the new resolution state.
- Update Git Manager modal messaging and dismiss behavior so handled `superseded` entries do not show a sync CTA.
- Extend dashboard route and modal tests, and refresh dashboard guide docs for the new classification behavior.

Files changed:
 docs/dashboard-guide.md                            |  5 +--
 packages/dashboard/app/api/legacy.ts               |  2 +-
 .../dashboard/app/components/GitManagerModal.tsx   |  6 ++--
 .../components/__tests__/GitManagerModal.test.tsx  |  5 ++-
 .../dashboard/src/__tests__/routes-git.test.ts     | 36 ++++++++++++++++++++--
 .../dashboard/src/routes/register-git-github.ts    | 13 ++++++--
 6 files changed, 55 insertions(+), 12 deletions(-)

Fusion-Task-Id: FN-5839

Fusion-Task-Lineage: 6b4afb73-587d-4319-8ad8-f1d5d54bc7bf
This commit is contained in:
gsxdsm
2026-06-01 11:52:02 -07:00
parent 4a20aa140e
commit 3602fb9a23
6 changed files with 55 additions and 12 deletions

View File

@@ -443,7 +443,7 @@ export interface ExtendedGitStatus {
advancedAt: string;
autoSyncOutcome?: string;
needsAction: boolean;
resolution: "reachable" | "orphaned" | "subsumed" | "pending";
resolution: "reachable" | "orphaned" | "subsumed" | "superseded" | "pending";
}>;
}
@@ -604,6 +604,7 @@ export async function collectRecentMergeAdvances(
},
worktreePath: string,
headSha: string | undefined,
localIntegrationTipSha: string | undefined,
): Promise<ExtendedGitStatus["recentMergeAdvances"]> {
if (typeof scopedStore.getRunAuditEvents !== "function") return [];
const advances = scopedStore.getRunAuditEvents({
@@ -648,7 +649,7 @@ export async function collectRecentMergeAdvances(
if (!tid) continue;
const autoSyncOutcome = autoSyncByAdvance.get(pairKey(tid, md.toSha)) ?? autoSyncByTaskFallback.get(tid);
let resolution: "reachable" | "orphaned" | "subsumed" | "pending" = "pending";
let resolution: "reachable" | "orphaned" | "subsumed" | "superseded" | "pending" = "pending";
let toShaExists = true;
if (headSha && headSha === md.toSha) {
resolution = "reachable";
@@ -690,6 +691,13 @@ export async function collectRecentMergeAdvances(
}
}
}
// When HEAD is already aligned with the local integration tip, resetting
// to that tip cannot make an unreachable advance SHA become reachable.
// Treat this as handled (superseded by rewrite), not actionable pending.
if (toShaExists && resolution === "pending" && localIntegrationTipSha && headSha === localIntegrationTipSha) {
resolution = "superseded";
}
}
const needsAction = resolution === "pending"
@@ -786,6 +794,7 @@ export async function computeExtendedGitStatus(rootDir: string, scopedStore: Tas
},
rootDir,
headSha,
localIntegrationTip ?? undefined,
),
]);