From 43b246e17b31df997312bb27f1264736ab359a0b Mon Sep 17 00:00:00 2001
From: Cursor Agent
Date: Sun, 16 Aug 2026 15:34:47 +0000
Subject: [PATCH] fix(ui): show analysis-run digest prefixes on detail
The #89 review asked for 12-character code and config prefixes so an
operator can match the approved revision. Full digests stay on the API
only. Do not merge until this review item is checked.
Co-authored-by: Seongho Bae
---
frontend/src/App.test.tsx | 10 ++++++++++
frontend/src/App.tsx | 13 +++++++++++++
frontend/src/api.ts | 2 ++
3 files changed, 25 insertions(+)
diff --git a/frontend/src/App.test.tsx b/frontend/src/App.test.tsx
index a3da5de6b..570d9a684 100644
--- a/frontend/src/App.test.tsx
+++ b/frontend/src/App.test.tsx
@@ -190,6 +190,9 @@ describe("App, authenticated", () => {
},
],
visible_posts: [{ post_id: "post-1", post_title: "Public post" }],
+ code_revision_sha: "abcdef0123456789deadbeefcafebabe",
+ configuration_sha256:
+ "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef",
status_history: [
{
status_ordinal: 1,
@@ -1386,6 +1389,13 @@ describe("App, authenticated", () => {
expect(await screen.findByRole("heading", { name: "Lineage reconstruction · Succeeded · Demo Corp" })).toBeInTheDocument();
expect(screen.getByText(/Cutoff 2026-01-12/)).toBeInTheDocument();
expect(screen.getByText(/Requested 2026-01-12/)).toBeInTheDocument();
+ const digests = screen.getByLabelText("Analysis run reproducibility digests");
+ expect(digests).toHaveTextContent("Code abcdef012345");
+ expect(digests).toHaveTextContent("Config 0123456789ab");
+ expect(digests).not.toHaveTextContent("abcdef0123456789deadbeefcafebabe");
+ expect(digests).not.toHaveTextContent(
+ "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef",
+ );
const history = screen.getByRole("list", { name: "Analysis run status history" });
expect(history).toHaveTextContent("Pending 2026-01-12 12:31");
expect(history).toHaveTextContent("Running 2026-01-12 12:32");
diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx
index f866bb302..3952de96c 100644
--- a/frontend/src/App.tsx
+++ b/frontend/src/App.tsx
@@ -1431,6 +1431,19 @@ function AnalysisRunsPanel({
{" · "}
Requested {selected.requested_at.slice(0, 10)}
+ {(selected.code_revision_sha || selected.configuration_sha256) && (
+
+ {selected.code_revision_sha
+ ? `Code ${selected.code_revision_sha.slice(0, 12)}`
+ : ""}
+ {selected.code_revision_sha && selected.configuration_sha256
+ ? " · "
+ : ""}
+ {selected.configuration_sha256
+ ? `Config ${selected.configuration_sha256.slice(0, 12)}`
+ : ""}
+
+ )}
{selected.source_counts.map((count) => (
-
diff --git a/frontend/src/api.ts b/frontend/src/api.ts
index 3dacb054c..740529cba 100644
--- a/frontend/src/api.ts
+++ b/frontend/src/api.ts
@@ -521,6 +521,8 @@ export interface AnalysisRun {
source_counts: AnalysisRunCount[];
status_history?: AnalysisRunStatusEvent[];
visible_posts?: { post_id: string; post_title: string }[];
+ code_revision_sha?: string;
+ configuration_sha256?: string;
}
export function fetchAnalysisRuns(accessToken: string): Promise<{ analysis_runs: AnalysisRun[] }> {