From 00bdf44735c363c4d24615883211a8e23cfde2eb Mon Sep 17 00:00:00 2001 From: Fabro Date: Mon, 18 May 2026 21:48:11 +0000 Subject: [PATCH] fabro(01KRYF0MS6Q5MRHW06WYNR0HKE): simplify_gpt (succeeded) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fabro-Run: 01KRYF0MS6Q5MRHW06WYNR0HKE Fabro-Completed: 7 Fabro-Checkpoint: a33a821f8e7d5b9851c5f02291aa91b149879342 ⚒️ Generated with [Fabro](https://fabro.sh) --- apps/fabro-web/app/data/runs.ts | 9 +- apps/fabro-web/app/lib/board-events.test.tsx | 4 +- apps/fabro-web/app/lib/board-events.ts | 2 +- apps/fabro-web/app/lib/mutations.ts | 1 - apps/fabro-web/app/lib/queries.ts | 6 +- apps/fabro-web/app/lib/query-keys.ts | 2 +- apps/fabro-web/app/routes/run-detail.tsx | 1 - apps/fabro-web/app/routes/runs.test.tsx | 93 +++++++++---------- apps/fabro-web/app/routes/runs.tsx | 29 ++---- docs/public/api-reference/fabro-api.yaml | 5 +- lib/crates/fabro-server/src/demo/mod.rs | 4 - .../fabro-server/src/server/handler/runs.rs | 38 +++----- lib/crates/fabro-server/src/server/tests.rs | 19 ++-- .../fabro-api-client/src/api/runs-api.ts | 30 +++--- .../src/models/board-column.ts | 4 +- 15 files changed, 92 insertions(+), 155 deletions(-) diff --git a/apps/fabro-web/app/data/runs.ts b/apps/fabro-web/app/data/runs.ts index 36b7c2f3c..b24abc825 100644 --- a/apps/fabro-web/app/data/runs.ts +++ b/apps/fabro-web/app/data/runs.ts @@ -41,23 +41,19 @@ export interface RunItem { } export const columnStatuses = [ - BoardColumn.QUEUED, BoardColumn.INITIALIZING, BoardColumn.RUNNING, BoardColumn.BLOCKED, BoardColumn.SUCCEEDED, BoardColumn.FAILED, - BoardColumn.ARCHIVED, ] as const satisfies readonly BoardColumn[]; export const columnStatusDisplay: Record = { - queued: { label: "Queued", dot: "bg-fg-muted", text: "text-fg-muted" }, initializing: { label: "Initializing", dot: "bg-amber", text: "text-amber" }, running: { label: "Running", dot: "bg-teal-500", text: "text-teal-500" }, blocked: { label: "Blocked", dot: "bg-amber", text: "text-amber" }, succeeded: { label: "Succeeded", dot: "bg-teal-300", text: "text-teal-300" }, failed: { label: "Failed", dot: "bg-coral", text: "text-coral" }, - archived: { label: "Archived", dot: "bg-fg-muted", text: "text-fg-muted" }, }; export interface RunWithStatus extends RunItem { @@ -112,7 +108,6 @@ export function columnForStatus(status: ApiRunStatus | null | undefined): BoardC switch (status?.kind) { case "submitted": case "queued": - return "queued"; case "starting": return "initializing"; case "running": @@ -132,13 +127,13 @@ export function columnForStatus(status: ApiRunStatus | null | undefined): BoardC } export function columnForRun(run: Run): BoardColumn | null { - if (run.lifecycle.archived) return "archived"; + if (run.lifecycle.archived) return null; return columnForStatus(run.lifecycle.status); } export function toRunWithStatus(run: Run): RunWithStatus { const item = mapRunListItem(run); - const column = columnForRun(run) ?? "queued"; + const column = columnForRun(run) ?? "initializing"; return { ...item, status: column, diff --git a/apps/fabro-web/app/lib/board-events.test.tsx b/apps/fabro-web/app/lib/board-events.test.tsx index a032d0a12..46b3ac4ab 100644 --- a/apps/fabro-web/app/lib/board-events.test.tsx +++ b/apps/fabro-web/app/lib/board-events.test.tsx @@ -71,7 +71,7 @@ describe("subscribeToBoardEvents", () => { source.emit({ event: "run.running" }); expect(created).toEqual(["/api/v1/attach"]); - expect(keys).toEqual([queryKeys.boards.runs(false), queryKeys.boards.runs(true)]); + expect(keys).toEqual([queryKeys.boards.runs()]); firstCleanup(); expect(source.closed).toBe(false); @@ -101,7 +101,7 @@ describe("subscribeToBoardEvents", () => { source.emit({ event: "run.running" }); expect(created).toEqual(["/api/v1/attach"]); - expect(keys).toEqual([queryKeys.boards.runs(false), queryKeys.boards.runs(true)]); + expect(keys).toEqual([queryKeys.boards.runs()]); firstCleanup(); expect(source.closed).toBe(false); diff --git a/apps/fabro-web/app/lib/board-events.ts b/apps/fabro-web/app/lib/board-events.ts index 77e44f520..ece047540 100644 --- a/apps/fabro-web/app/lib/board-events.ts +++ b/apps/fabro-web/app/lib/board-events.ts @@ -85,7 +85,7 @@ function boardInvalidation(payload: EventPayload) { } function boardRunKeys() { - return [queryKeys.boards.runs(false), queryKeys.boards.runs(true)]; + return [queryKeys.boards.runs()]; } export function useBoardEvents() { diff --git a/apps/fabro-web/app/lib/mutations.ts b/apps/fabro-web/app/lib/mutations.ts index 5852a7544..30f0aec36 100644 --- a/apps/fabro-web/app/lib/mutations.ts +++ b/apps/fabro-web/app/lib/mutations.ts @@ -117,7 +117,6 @@ export function useUpdateRunTitle(id: string | undefined) { if (!id) return; void mutate(queryKeys.runs.detail(id), run, { revalidate: false }); void mutate(queryKeys.boards.runs()); - void mutate(queryKeys.boards.runs(true)); }, }, ); diff --git a/apps/fabro-web/app/lib/queries.ts b/apps/fabro-web/app/lib/queries.ts index 8f7bce147..998631592 100644 --- a/apps/fabro-web/app/lib/queries.ts +++ b/apps/fabro-web/app/lib/queries.ts @@ -91,12 +91,12 @@ export function useSystemInfo() { ); } -export function useBoardsRuns(includeArchived: boolean = false) { +export function useBoardsRuns() { return useSWR( - queryKeys.boards.runs(includeArchived), + queryKeys.boards.runs(), () => fetchAllPages("board runs", (limit, offset) => - apiData(() => runsApi.listBoardRuns(limit, offset, includeArchived)), + apiData(() => runsApi.listBoardRuns(limit, offset)), ), ); } diff --git a/apps/fabro-web/app/lib/query-keys.ts b/apps/fabro-web/app/lib/query-keys.ts index eaf2b952c..23c7ce008 100644 --- a/apps/fabro-web/app/lib/query-keys.ts +++ b/apps/fabro-web/app/lib/query-keys.ts @@ -38,7 +38,7 @@ export const queryKeys = { attachUrl: () => "/api/v1/attach", }, boards: { - runs: (includeArchived = false) => ["boards", "runs", includeArchived] as const, + runs: () => ["boards", "runs"] as const, }, runs: { detail: (id: string) => ["runs", "detail", id] as const, diff --git a/apps/fabro-web/app/routes/run-detail.tsx b/apps/fabro-web/app/routes/run-detail.tsx index ba02cf0ea..581fe9f68 100644 --- a/apps/fabro-web/app/routes/run-detail.tsx +++ b/apps/fabro-web/app/routes/run-detail.tsx @@ -267,7 +267,6 @@ export default function RunDetail({ params }: { params: { id: string } }) { try { await deleteRun(params.id); void mutate(queryKeys.boards.runs()); - void mutate(queryKeys.boards.runs(true)); push({ message: "Run deleted." }); navigate("/runs"); } catch (error) { diff --git a/apps/fabro-web/app/routes/runs.test.tsx b/apps/fabro-web/app/routes/runs.test.tsx index 54722ae0d..fb1f1fc33 100644 --- a/apps/fabro-web/app/routes/runs.test.tsx +++ b/apps/fabro-web/app/routes/runs.test.tsx @@ -10,16 +10,14 @@ import { function boardRun(id: string, column: BoardColumn, questionText?: string): Run { const status = column === "blocked" - ? { kind: "blocked" as const, reason: "interview", pending_question_id: null } + ? { kind: "blocked" as const, blocked_reason: "human_input_required" } : column === "succeeded" ? { kind: "succeeded" as const, reason: "completed" } : column === "failed" - ? { kind: "failed" as const, reason: "error" } - : column === "queued" - ? { kind: "queued" as const } - : column === "initializing" - ? { kind: "starting" as const } - : { kind: "running" as const }; + ? { kind: "failed" as const, reason: "workflow_error" } + : column === "initializing" + ? { kind: "starting" as const } + : { kind: "running" as const }; return { id, goal: `Run ${id}`, @@ -35,8 +33,8 @@ function boardRun(id: string, column: BoardColumn, questionText?: string): Run { pending_control: null, queue_position: null, error: null, - archived: column === "archived", - archived_at: column === "archived" ? "2026-04-19T12:05:00Z" : null, + archived: false, + archived_at: null, }, sandbox: null, models: [], @@ -60,7 +58,6 @@ describe("runs route board mapping", () => { test("keeps blocked runs in the blocked lane and preserves question text", () => { const columns = buildBoardColumns({ columns: [ - { id: "queued", name: "Queued" }, { id: "initializing", name: "Initializing" }, { id: "running", name: "Running" }, { id: "blocked", name: "Blocked" }, @@ -79,45 +76,9 @@ describe("runs route board mapping", () => { expect(columns.find((column) => column.id === "blocked")?.items[0]?.question).toBe("Older unresolved question?"); }); - test("renders an archived column when the response includes one", () => { + test("renders the five board columns returned by the API", () => { const columns = buildBoardColumns({ columns: [ - { id: "queued", name: "Queued" }, - { id: "initializing", name: "Initializing" }, - { id: "running", name: "Running" }, - { id: "blocked", name: "Blocked" }, - { id: "succeeded", name: "Succeeded" }, - { id: "failed", name: "Failed" }, - { id: "archived", name: "Archived" }, - ], - data: [ - boardRun("succeeded-run", "succeeded"), - boardRun("archived-run", "archived"), - ], - meta: { has_more: false }, - }); - - expect(columns.map((column) => column.id)).toEqual([ - "queued", - "initializing", - "running", - "blocked", - "succeeded", - "failed", - "archived", - ]); - expect( - columns.find((column) => column.id === "archived")?.items.map((item) => item.id), - ).toEqual(["archived-run"]); - expect( - columns.find((column) => column.id === "succeeded")?.items.map((item) => item.id), - ).toEqual(["succeeded-run"]); - }); - - test("omits the archived column when the response does not include it", () => { - const columns = buildBoardColumns({ - columns: [ - { id: "queued", name: "Queued" }, { id: "initializing", name: "Initializing" }, { id: "running", name: "Running" }, { id: "blocked", name: "Blocked" }, @@ -128,7 +89,43 @@ describe("runs route board mapping", () => { meta: { has_more: false }, }); - expect(columns.some((column) => column.id === "archived")).toBe(false); + expect(columns.map((column) => column.id)).toEqual([ + "initializing", + "running", + "blocked", + "succeeded", + "failed", + ]); + expect( + columns.find((column) => column.id === "succeeded")?.items.map((item) => item.id), + ).toEqual(["succeeded-run"]); + }); + + test("omits archived runs because archived is not a board column", () => { + const archivedRun = boardRun("archived-run", "succeeded"); + archivedRun.lifecycle.archived = true; + archivedRun.lifecycle.archived_at = "2026-04-19T12:05:00Z"; + + const columns = buildBoardColumns({ + columns: [ + { id: "initializing", name: "Initializing" }, + { id: "running", name: "Running" }, + { id: "blocked", name: "Blocked" }, + { id: "succeeded", name: "Succeeded" }, + { id: "failed", name: "Failed" }, + ], + data: [boardRun("succeeded-run", "succeeded"), archivedRun], + meta: { has_more: false }, + }); + + expect(columns.map((column) => column.id)).toEqual([ + "initializing", + "running", + "blocked", + "succeeded", + "failed", + ]); + expect(columns.flatMap((column) => column.items).map((item) => item.id)).toEqual(["succeeded-run"]); }); test("refreshes for blocked status and interview events", () => { diff --git a/apps/fabro-web/app/routes/runs.tsx b/apps/fabro-web/app/routes/runs.tsx index 6eb1652cd..a16026723 100644 --- a/apps/fabro-web/app/routes/runs.tsx +++ b/apps/fabro-web/app/routes/runs.tsx @@ -1,6 +1,6 @@ import { useState, useCallback, useEffect, useMemo, useRef } from "react"; import { Link, useSearchParams } from "react-router"; -import { ArchiveBoxIcon, ChevronDownIcon, CommandLineIcon, MagnifyingGlassIcon } from "@heroicons/react/24/outline"; +import { ChevronDownIcon, CommandLineIcon, MagnifyingGlassIcon } from "@heroicons/react/24/outline"; import { EllipsisVerticalIcon } from "@heroicons/react/20/solid"; import { Menu, MenuButton, MenuItem, MenuItems } from "@headlessui/react"; import { useSWRConfig } from "swr"; @@ -45,13 +45,11 @@ interface ColumnStyle { } const columnStyles: Record = { - queued: { actions: [] }, initializing: { actions: [] }, running: { actions: [] }, blocked: { actions: ["Answer Question"] }, succeeded: { actions: [] }, failed: { actions: [] }, - archived: { actions: [] }, }; const defaultColumnStyle: ColumnStyle = { actions: [] }; @@ -72,9 +70,8 @@ type Column = { items: RunItem[]; }; -function buildSkeletonColumns(includeArchived: boolean): Column[] { +function buildSkeletonColumns(): Column[] { return columnStatuses - .filter((id) => includeArchived || id !== "archived") .map((id) => { const colors = columnStatusDisplay[id]; return { @@ -768,7 +765,6 @@ export default function Runs() { const repoFilter = searchParams.get("repo") ?? "all"; const workflowFilter = searchParams.get("workflow") ?? "all"; const createdFilter = parseCreatedFilter(searchParams.get("created")); - const includeArchived = searchParams.get("archived") === "1"; const view = parseView(searchParams.get("view")); const updateParam = useCallback( @@ -793,10 +789,9 @@ export default function Runs() { const setRepoFilter = (value: string) => updateParam("repo", value === "all" ? null : value); const setWorkflowFilter = (value: string) => updateParam("workflow", value === "all" ? null : value); const setCreatedFilter = (value: CreatedFilter) => updateParam("created", value === "all" ? null : value); - const setIncludeArchived = (value: boolean) => updateParam("archived", value ? "1" : null); const setView = (value: ViewMode) => updateParam("view", value === "columns" ? null : value); - const boardRuns = useBoardsRuns(includeArchived); + const boardRuns = useBoardsRuns(); const authConfig = useAuthConfig(); const systemInfo = useSystemInfo(); const isLandingReady = @@ -807,8 +802,8 @@ export default function Runs() { () => boardRuns.data ? buildBoardColumns(boardRuns.data) - : buildSkeletonColumns(includeArchived), - [boardRuns.data, includeArchived], + : buildSkeletonColumns(), + [boardRuns.data], ); const hasGitHubAuth = authConfig.data?.methods.includes("github") === true; const serverUrl = systemInfo.data?.server_url; @@ -871,9 +866,7 @@ export default function Runs() { (sum, col) => sum + col.items.length, 0, ); - const visibleColumns = filteredColumns.filter( - (col) => col.id !== "queued" || col.items.length > 0, - ); + const visibleColumns = filteredColumns; return ( @@ -935,16 +928,6 @@ export default function Runs() { -