From 4179b98e16b532203d7711f9dd6cde21318ddfc7 Mon Sep 17 00:00:00 2001 From: Paul Itoi <814886+pitoi@users.noreply.github.com> Date: Mon, 31 Aug 2026 03:59:32 +0000 Subject: [PATCH] [Jamie] Stop Consolidated Report runs from appearing in the Legal Benchmarks Runs tab (complete fix) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Problem The Legal Benchmarks "Runs" tab for a task shows `LEGAL_BENCHMARK_CONSOLIDATED` runs (cross-run Consolidated Report comparisons, a separate Stakwork workflow/ID) mixed in with the task's actual `LEGAL_BENCHMARK_RUNNER` runs (workflow 57179). ## Root cause `src/hooks/useLegalBenchmarkRunList.ts` tags fetched Consolidated Report rows with the same `"recursion"` `runType` used for genuine eval/recursion rows. A code comment claims this tag keeps them "invisible" in the Runs tab table, but `src/components/legal/BenchmarkRunsHistory.tsx`'s `secondaryRows` filter is a deny-list (`runType !== "manual"`) that does not actually exclude `"recursion"`-tagged rows — so Consolidated rows render there. ## Fix (single, complete change — supersedes two abandoned prior attempts, PR #5204 and #5206, which split this across mismatched branches) 1. `src/hooks/useLegalBenchmarkRunList.ts`: add a new `"consolidated"` value to the `BenchmarkRunType` union; tag `rawConsolidatedRows` with `"consolidated"` instead of `"recursion"` when merging. Keep fetching/merging them (still needed for the Recursion tab's Pusher-driven live status after a page refresh). 2. `src/components/legal/RecursionBox.tsx`: update `existingConsolidated`'s filter to match the new `runType === "consolidated"` tag (instead of `"recursion"`), so the Recursion tab's own in-flight-consolidated-run lookup keeps working correctly with the renamed tag. 3. `src/components/legal/BenchmarkRunsHistory.tsx`: change `secondaryRows`'s filter from a deny-list (`runType !== "manual"`) to an explicit allow-list (`runType === "recursion"`), so only genuine eval/recursion rows land in the table; the new `"consolidated"` tag is excluded by construction. 4. `src/__tests__/unit/components/RecursionBox.test.tsx`: update the `makeConsolidatedRow` test fixture's `runType` field from `"recursion"` to `"consolidated"` to match the renamed tag, so the existing "detects a PENDING in-flight consolidated run via the allRuns prop" test continues to pass against the new logic. ## Scope Client-side/UI + test-fixture only — no API route, Prisma schema, or dispatch/webhook changes. All four edits land together in this one PR/branch, avoiding the split-branch mismatch that broke the two earlier attempts. --- .../unit/components/RecursionBox.test.tsx | 2 +- src/components/legal/BenchmarkRunsHistory.tsx | 7 +++- src/components/legal/RecursionBox.tsx | 2 +- src/hooks/useLegalBenchmarkRunList.ts | 33 ++++++++++++------- 4 files changed, 29 insertions(+), 15 deletions(-) diff --git a/src/__tests__/unit/components/RecursionBox.test.tsx b/src/__tests__/unit/components/RecursionBox.test.tsx index f02d4f8aec..e8c884e15f 100644 --- a/src/__tests__/unit/components/RecursionBox.test.tsx +++ b/src/__tests__/unit/components/RecursionBox.test.tsx @@ -971,7 +971,7 @@ describe("RecursionCard — allRuns prop (consolidated-run detection)", () => { return { id: overrides.id ?? "con-run-1", workspaceId: "ws-1", - runType: "recursion" as const, + runType: "consolidated" as const, pipeline: "LEGAL_BENCHMARK_CONSOLIDATED" as import("@prisma/client").StakworkRunType, status: overrides.status ?? "PENDING" as import("@prisma/client").WorkflowStatus, projectId: null, diff --git a/src/components/legal/BenchmarkRunsHistory.tsx b/src/components/legal/BenchmarkRunsHistory.tsx index b254c6ef3d..60e35d0b11 100644 --- a/src/components/legal/BenchmarkRunsHistory.tsx +++ b/src/components/legal/BenchmarkRunsHistory.tsx @@ -309,11 +309,16 @@ export function BenchmarkRunsHistory({ // Cron-pipeline rows shown alongside (or instead of) the manual window when // the type filter asks for them. Operational only — no scores, no windowing. + // Explicit allow-list (rather than `!== "manual"`) so only eval/recursion- + // pipeline rows are eligible here: manual rows go through their own path + // above, and "consolidated" rows are deliberately excluded — they flow + // through the merged `runs` list solely for the Recursion tab's Pusher + // tracking and must never render as their own row in this table. const secondaryRows = useMemo( () => runs.filter( (r) => - r.runType !== "manual" && + r.runType === "recursion" && (!selectedTask || r.taskSlug === selectedTask.slug), ), [runs, selectedTask], diff --git a/src/components/legal/RecursionBox.tsx b/src/components/legal/RecursionBox.tsx index 04d92fdf90..888b5e58f1 100644 --- a/src/components/legal/RecursionBox.tsx +++ b/src/components/legal/RecursionBox.tsx @@ -399,7 +399,7 @@ function RecursionCard({ entry, refetch, allRuns }: RecursionCardProps) { .filter( (r) => r.taskSlug === entry.id && - r.runType === "recursion" && + r.runType === "consolidated" && (r.status === WorkflowStatus.PENDING || r.status === WorkflowStatus.IN_PROGRESS) && !r.hasReport, diff --git a/src/hooks/useLegalBenchmarkRunList.ts b/src/hooks/useLegalBenchmarkRunList.ts index 5cbee35a0d..93b941afe7 100644 --- a/src/hooks/useLegalBenchmarkRunList.ts +++ b/src/hooks/useLegalBenchmarkRunList.ts @@ -8,16 +8,23 @@ import { getWorkspaceChannelName, PUSHER_EVENTS } from "@/lib/pusher"; /** * Display name per StakworkRun pipeline: - * - "manual" — LEGAL_BENCHMARK_RUNNER: a human clicked Run; scored - * - "recursion" — the automated loop, covering BOTH cron pipelines: - * LEGAL_BENCHMARK_EVAL (failure analysis; writes cause - * annotations onto the source run) and - * LEGAL_BENCHMARK_RECURSION (the fix-proposal step). - * Analysis is an internal stage of the loop, not a category - * an operator distinguishes — neither pipeline ever scores; - * re-scored attempts land graph-side (Recursion tab). + * - "manual" — LEGAL_BENCHMARK_RUNNER: a human clicked Run; scored + * - "recursion" — the automated loop, covering BOTH cron pipelines: + * LEGAL_BENCHMARK_EVAL (failure analysis; writes cause + * annotations onto the source run) and + * LEGAL_BENCHMARK_RECURSION (the fix-proposal step). + * Analysis is an internal stage of the loop, not a category + * an operator distinguishes — neither pipeline ever scores; + * re-scored attempts land graph-side (Recursion tab). + * - "consolidated" — LEGAL_BENCHMARK_CONSOLIDATED: cross-run "Consolidated + * Report" comparisons. Tagged distinctly from "recursion" + * so BenchmarkRunsHistory's allow-list filter excludes + * these rows from the Runs tab table, while they remain + * in the merged `runs` list so the Recursion tab's Pusher + * subscription/RecursionCard can still find and track + * in-flight / completed consolidated report generation. */ -export type BenchmarkRunType = "manual" | "recursion"; +export type BenchmarkRunType = "manual" | "recursion" | "consolidated"; export interface BenchmarkRunListRow { id: string; @@ -227,9 +234,11 @@ export function useLegalBenchmarkRunList( // CONSOLIDATED rows are merged so Pusher updates for them flow through // the existing channel subscription without new polling logic, enabling // RecursionCard to surface in-flight / completed consolidated report - // status after a page refresh. They are not surfaced in the Runs tab - // table — the runType tag keeps them invisible there. - ...rawConsolidatedRows.map((r) => mapSecondary(r, "recursion")), + // status after a page refresh. Tagged "consolidated" (distinct from + // "recursion") so BenchmarkRunsHistory's allow-list filter excludes + // them from the Runs tab table — they stay invisible there while + // remaining discoverable in the merged `runs` list for the Recursion tab. + ...rawConsolidatedRows.map((r) => mapSecondary(r, "consolidated")), ].sort((a, b) => new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime()); runsRef.current = merged;