feat(FN-5103): surface landed-files attribution flags in task changes UI

Fusion-Task-Id: FN-5103
Fusion-Task-Lineage: e4e4d9ba-4884-4feb-b18b-a30e799c3fb1
This commit is contained in:
Fusion (runfusion.ai)
2026-05-19 00:06:30 -07:00
committed by gsxdsm
parent 0abb1fad2c
commit 71928aeda3
2 changed files with 30 additions and 0 deletions

View File

@@ -372,6 +372,12 @@ export function TaskChangesTab({ taskId, worktree, projectId, column, mergeDetai
Merged {new Date(mergeDetails.mergedAt).toLocaleString()}
</div>
)}
{mergeDetails.noOpVerifiedShortCircuit && (
<div className="text-muted">Verified short-circuit work was already on main (rebase walked foreign commits).</div>
)}
{mergeDetails.landedFilesCaptureFallback === "attribution-failed" && (
<div className="text-muted">Landed-files set may include foreign commits (attribution unavailable).</div>
)}
</div>
)}

View File

@@ -316,6 +316,30 @@ describe("TaskChangesTab — commit-backed (done tasks)", () => {
expect(screen.getByText(/Merged .+/)).toBeTruthy();
});
it("renders attribution notes for short-circuit and fallback merge details", async () => {
mockFetchTaskDiff.mockResolvedValue(DONE_TASK_DIFF);
render(
<TaskChangesTab
taskId="FN-001"
worktree={undefined}
column="done"
mergeDetails={{
...MERGE_DETAILS,
noOpVerifiedShortCircuit: true,
landedFilesCaptureFallback: "attribution-failed",
}}
/>,
);
await waitFor(() => {
expect(screen.getByText("Verified short-circuit — work was already on main (rebase walked foreign commits)."))
.toBeTruthy();
});
expect(screen.getByText("Landed-files set may include foreign commits (attribution unavailable)."))
.toBeTruthy();
});
it("uses mergeDetails stats for summary", async () => {
mockFetchTaskDiff.mockResolvedValue(DONE_TASK_DIFF);