fix(dashboard): remove Lineage commit associations from Task Changes UI

The lineage commit associations panel surfaced low-value provenance
metadata. Remove the UI section, its dead state/fetch wiring in
TaskChangesTab, the orphaned .task-lineage-* CSS, and the obsolete
tests. The fetchTaskCommitAssociations API helper is retained.
This commit is contained in:
gsxdsm
2026-06-02 07:40:37 -07:00
parent be95b3f2c3
commit 7c7fb065dc
4 changed files with 0 additions and 202 deletions

View File

@@ -35,103 +35,3 @@
box-shadow: none;
}
.task-lineage-associations {
display: flex;
flex-direction: column;
gap: var(--space-sm);
margin-bottom: var(--space-md);
padding: var(--space-sm);
border: 1px solid var(--border);
border-radius: var(--radius-md);
background: var(--surface);
}
.task-lineage-associations-header {
display: flex;
align-items: center;
justify-content: space-between;
gap: var(--space-sm);
}
.task-lineage-associations-header h4 {
display: inline-flex;
align-items: center;
gap: var(--space-xs);
margin: 0;
}
.task-lineage-id,
.task-lineage-sha {
font-family: var(--font-mono);
font-size: 0.75rem;
}
.task-lineage-associations-empty {
margin: 0;
color: var(--text-muted);
}
.task-lineage-associations-list {
display: flex;
flex-direction: column;
gap: var(--space-xs);
}
.task-lineage-association {
display: flex;
flex-direction: column;
gap: var(--space-xs);
padding: var(--space-sm);
border-radius: var(--radius-sm);
border: 1px solid var(--border);
background: var(--card);
}
.task-lineage-association--legacy,
.task-lineage-association--ambiguous {
opacity: 0.78;
}
.task-lineage-association-main {
display: flex;
align-items: center;
gap: var(--space-sm);
}
.task-lineage-subject {
min-width: 0;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.task-lineage-association-meta {
display: flex;
flex-wrap: wrap;
gap: var(--space-sm);
color: var(--text-muted);
font-size: 0.75rem;
}
.task-lineage-note {
margin: 0;
color: var(--text-dim);
font-size: 0.75rem;
}
@media (max-width: 768px) {
.task-lineage-associations-header {
flex-direction: column;
align-items: flex-start;
}
.task-lineage-association-main {
flex-wrap: wrap;
}
.task-lineage-subject {
white-space: normal;
overflow: visible;
text-overflow: clip;
}
}

View File

@@ -4,9 +4,7 @@ import type { MergeDetails, Column } from "@fusion/core";
import { getErrorMessage } from "@fusion/core";
import {
fetchTaskDiff,
fetchTaskCommitAssociations,
type TaskDiff,
type TaskCommitAssociationRow,
} from "../api";
import { highlightDiff } from "../utils/highlightDiff";
import { ChangesDiffModal } from "./ChangesDiffModal";
@@ -129,8 +127,6 @@ export function TaskChangesTab({ taskId, worktree, projectId, column, mergeDetai
const [stats, setStats] = useState<{ filesChanged: number; additions: number; deletions: number }>({ filesChanged: 0, additions: 0, deletions: 0 });
const [loading, setLoading] = useState(true);
const [error, setError] = useState<string | null>(null);
const [commitAssociations, setCommitAssociations] = useState<TaskCommitAssociationRow[]>([]);
const [lineageId, setLineageId] = useState<string | null>(null);
const [expandedFiles, setExpandedFiles] = useState<Set<string>>(new Set());
const [currentFileIndex, setCurrentFileIndex] = useState<number | null>(null);
const [wordWrap, setWordWrap] = useState(true);
@@ -150,9 +146,6 @@ export function TaskChangesTab({ taskId, worktree, projectId, column, mergeDetai
try {
setLoading(true);
setError(null);
const associationsData = await fetchTaskCommitAssociations(taskId, projectId);
setLineageId(associationsData.lineageId);
setCommitAssociations(associationsData.associations);
if (!canLoad) {
setFiles([]);
@@ -261,47 +254,6 @@ export function TaskChangesTab({ taskId, worktree, projectId, column, mergeDetai
}
const renderCommitAssociations = () => (
<section className="task-lineage-associations" aria-label="Task commit associations">
<div className="task-lineage-associations-header">
<h4>
<GitCommit size={16} />
Lineage commit associations
</h4>
{lineageId && (
<code className="task-lineage-id">{lineageId}</code>
)}
</div>
{commitAssociations.length === 0 ? (
<p className="task-lineage-associations-empty">No associated commits recorded yet.</p>
) : (
<div className="task-lineage-associations-list">
{commitAssociations.map((association) => {
const matchedLabel = association.matchedBy.replace(/-/g, " ");
return (
<article
key={`${association.commitSha}-${association.matchedBy}`}
className={`task-lineage-association task-lineage-association--${association.confidence}`}
>
<div className="task-lineage-association-main">
<code className="task-lineage-sha">{association.commitSha.slice(0, 7)}</code>
<span className="task-lineage-subject">{association.commitSubject}</span>
</div>
<div className="task-lineage-association-meta">
<span>{new Date(association.authoredAt).toLocaleString()}</span>
<span>Confidence: {association.confidence}</span>
<span>Match: {matchedLabel}</span>
<span>Task snapshot: {association.taskIdSnapshot}</span>
</div>
{association.note && <p className="task-lineage-note">{association.note}</p>}
</article>
);
})}
</div>
)}
</section>
);
if (files.length === 0) {
if (isDone && !isDoneWithCommit) {
const doneFallbackFiles = mergeDetails?.landedFiles && mergeDetails.landedFiles.length > 0
@@ -337,7 +289,6 @@ export function TaskChangesTab({ taskId, worktree, projectId, column, mergeDetai
return (
<div className="detail-section task-changes-tab">
{renderCommitAssociations()}
<div className="task-changes-state task-changes-state--empty">
<FileCode size={24} />
<p>No files modified.</p>
@@ -353,7 +304,6 @@ export function TaskChangesTab({ taskId, worktree, projectId, column, mergeDetai
return (
<div className="detail-section task-changes-tab">
{renderCommitAssociations()}
{/* Commit metadata for done tasks */}
{isDone && mergeDetails && (
<div className="commit-diff-meta">

View File

@@ -6,7 +6,6 @@ import { TaskChangesTab } from "../TaskChangesTab";
const useTaskDiffStatsMock = vi.fn();
const fetchTaskDiffMock = vi.fn();
const fetchTaskCommitAssociationsMock = vi.fn();
vi.mock("../../hooks/useTaskDiffStats", async (importOriginal) => {
const actual = await importOriginal<typeof import("../../hooks/useTaskDiffStats")>();
@@ -21,7 +20,6 @@ vi.mock("../../api", async (importOriginal) => {
return {
...actual,
fetchTaskDiff: (...args: unknown[]) => fetchTaskDiffMock(...args),
fetchTaskCommitAssociations: (...args: unknown[]) => fetchTaskCommitAssociationsMock(...args),
};
});
@@ -83,8 +81,6 @@ describe("TaskCard/TaskChangesTab files-changed parity", () => {
beforeEach(() => {
useTaskDiffStatsMock.mockReset();
fetchTaskDiffMock.mockReset();
fetchTaskCommitAssociationsMock.mockReset();
fetchTaskCommitAssociationsMock.mockResolvedValue({ taskId: "FN-4521", lineageId: null, associations: [] });
});
it.each([

View File

@@ -5,11 +5,9 @@ import { TaskChangesTab } from "../TaskChangesTab";
import type { MergeDetails, Column } from "@fusion/core";
const mockFetchTaskDiff = vi.fn();
const mockFetchTaskCommitAssociations = vi.fn();
vi.mock("../../api", () => ({
fetchTaskDiff: (...args: any[]) => mockFetchTaskDiff(...args),
fetchTaskCommitAssociations: (...args: any[]) => mockFetchTaskCommitAssociations(...args),
}));
vi.mock("lucide-react", () => ({
@@ -51,52 +49,6 @@ const MERGE_DETAILS: MergeDetails = {
beforeEach(() => {
mockFetchTaskDiff.mockReset();
mockFetchTaskCommitAssociations.mockReset();
mockFetchTaskCommitAssociations.mockResolvedValue({
taskId: "FN-001",
lineageId: "lineage-1",
associations: [],
});
});
describe("TaskChangesTab — commit associations", () => {
it("renders empty-state copy when no commit associations exist", async () => {
mockFetchTaskDiff.mockResolvedValue({ files: [], stats: { filesChanged: 0, additions: 0, deletions: 0 } });
render(<TaskChangesTab taskId="FN-001" worktree="/path/to/worktree" column="in-progress" />);
await waitFor(() => {
expect(screen.getByText("No associated commits recorded yet.")).toBeTruthy();
});
});
it("renders populated commit association rows with confidence metadata", async () => {
mockFetchTaskDiff.mockResolvedValue({ files: [], stats: { filesChanged: 0, additions: 0, deletions: 0 } });
mockFetchTaskCommitAssociations.mockResolvedValue({
taskId: "FN-001",
lineageId: "lineage-1",
associations: [
{
commitSha: "abc1234567",
commitSubject: "feat: lineage",
authoredAt: "2026-05-11T00:00:00.000Z",
matchedBy: "manual-reconciliation",
confidence: "ambiguous",
taskIdSnapshot: "FN-3953",
note: "legacy mismatch",
},
],
});
const { container } = render(<TaskChangesTab taskId="FN-001" worktree="/path/to/worktree" column="in-progress" />);
await waitFor(() => {
expect(screen.getByText("feat: lineage")).toBeTruthy();
});
expect(screen.getByText("Confidence: ambiguous")).toBeTruthy();
expect(screen.getByText("Match: manual reconciliation")).toBeTruthy();
expect(container.querySelector(".task-lineage-association--ambiguous")).toBeTruthy();
});
});
describe("TaskChangesTab — worktree-backed (non-done tasks)", () => {