refactor(lens): remove dead live helpers and use generated in-flight types

This commit is contained in:
Ishaan Jaff 2026-10-04 18:10:57 -07:00
parent d58c7a2187
commit e50f53965d
No known key found for this signature in database
5 changed files with 24 additions and 148 deletions

View file

@ -5,9 +5,9 @@ import { useState, type ReactNode } from "react";
import { StatusBadge, type StatusTone } from "@/components/shared/table_cells";
import { Sheet, SheetContent, SheetDescription, SheetHeader, SheetTitle } from "@/components/ui/sheet";
import { conclusions, type InFlight } from "../../model/live";
import { conclusions } from "../../model/live";
import { releasedReviews } from "../../model/stage";
import type { Job, Review, Settings } from "../../model/types";
import type { InFlight, Job, Review, Settings } from "../../model/types";
import { ConclusionsPanel } from "./ConclusionsPanel";
import { ModelName } from "./LiveStrip";
import { NowReading } from "./NowReading";

View file

@ -25,7 +25,6 @@ export function LiveRun({
name: string;
queue?: QueueContext;
}) {
const live = job.status === "queued" || job.status === "running";
const reason = useQueueReason(job, queue);
const [stripOpen, setStripOpen] = useStripOpen();
const [drawerOpen, setDrawerOpen] = useState(false);

View file

@ -9,7 +9,6 @@ import {
newestFirst,
nowLine,
inFlight,
liveRows,
grownGroups,
inGroup,
share,
@ -19,12 +18,10 @@ import {
shortVerdict,
stripState,
liveJob,
liveStats,
outcome,
providerOf,
rateLabel,
secondsToFinishReading,
tokenLabel,
polling,
} from "./live";
import type { Job, Review } from "./types";
@ -273,6 +270,13 @@ describe("incremental reviews", () => {
expect(feed.reviews[0].execution_id).toBe("r50");
expect(feed.cursor).toBe(250);
});
it("keeps polling a finished run until every review it reported has arrived", () => {
const fetched = { reviews: [], cursor: 28 };
expect(polling({ status: "running", reviewed: 28 }, fetched)).toBe(true);
expect(polling({ status: "completed", reviewed: 30 }, fetched)).toBe(true);
expect(polling({ status: "completed", reviewed: 30 }, { ...fetched, cursor: 30 })).toBe(false);
});
});
describe("time left reading", () => {
@ -301,73 +305,6 @@ describe("short verdict", () => {
});
});
describe("live stats", () => {
const job = {
reviewed: 30,
cost: 0.042,
created_at: "2026-10-03T16:00:00Z",
finished_at: null,
steps: [
{
at: "2026-10-03T16:00:05Z",
kind: "stage",
label: "Reading executions",
model: "",
purpose: "",
cost: 0,
prompt_tokens: 0,
completion_tokens: 0,
},
{
at: "2026-10-03T16:00:06Z",
kind: "model",
label: "extract",
model: "m",
purpose: "extract",
cost: 0.01,
prompt_tokens: 1200,
completion_tokens: 300,
},
{
at: "2026-10-03T16:00:07Z",
kind: "model",
label: "extract",
model: "m",
purpose: "extract",
cost: 0.01,
prompt_tokens: 800,
completion_tokens: 200,
},
],
} as unknown as Job;
it("measures rate from when reading started and sums model tokens", () => {
const stats = liveStats(job, Date.parse("2026-10-03T16:00:15Z"));
expect(stats.elapsedSeconds).toBe(10);
expect(stats.perSecond).toBe(3);
expect(stats.tokens).toBe(2500);
expect(stats.cost).toBe(0.042);
});
it("stops the clock when the job finishes", () => {
const finished = { ...job, finished_at: "2026-10-03T16:00:25Z" };
expect(liveStats(finished, Date.parse("2026-10-03T18:00:00Z")).elapsedSeconds).toBe(20);
});
it("has no rate before anything is reviewed", () => {
expect(liveStats({ ...job, reviewed: 0 }, Date.parse("2026-10-03T16:00:15Z")).perSecond).toBeNull();
});
it("formats rate and tokens for the footer", () => {
expect(rateLabel(null)).toBe("–");
expect(rateLabel(2.25)).toBe("2.3 traces/s");
expect(rateLabel(0.5)).toBe("30.0 traces/min");
expect(tokenLabel(950)).toBe("950 tok");
expect(tokenLabel(2500)).toBe("2.5k tok");
expect(tokenLabel(3_400_000)).toBe("3.4M tok");
});
});
describe("honest live list", () => {
it("lists completed reviews newest first in the order they finished, never re-sorted by time", () => {
const reviews = [
@ -387,33 +324,11 @@ describe("honest live list", () => {
expect(nowLine(job(3, 0), 1)).toBe("3 done · 1 in flight");
});
it("keeps a trace as the same row from in flight to finished", () => {
const reading = (id: string) => ({
execution_id: id,
trace_id: `t-${id}`,
agent: "bot",
started_at: "2026-10-03T16:00:00Z",
});
const before = liveRows([reading("x"), reading("y")], [review("a")], 10);
expect(before.map((row) => [row.kind, row.key])).toEqual([
["reading", "x"],
["reading", "y"],
["done", "a"],
]);
const after = liveRows([reading("x"), reading("y")], [review("a"), review("y")], 10);
expect(after.map((row) => [row.kind, row.key])).toEqual([
["reading", "x"],
["done", "y"],
["done", "a"],
]);
});
it("only shows in-flight traces while the job runs", () => {
const item = { execution_id: "x", trace_id: "t", agent: "bot", started_at: "2026-10-03T16:00:00Z" };
const job = (status: Job["status"]) => ({ status, reading: [item] }) as unknown as Job;
expect(inFlight(job("running"))).toEqual([item]);
expect(inFlight(job("completed"))).toEqual([]);
expect(inFlight({ status: "running" } as Job)).toEqual([]);
});
it("sums up a finished run from when reading started", () => {

View file

@ -1,5 +1,5 @@
import { durationText } from "./format";
import type { Job, Review, ReviewVerdict, Settings } from "./types";
import type { InFlight, Job, Review, ReviewVerdict, Settings } from "./types";
export type Outcome = "issue" | "clear" | "unknown";
@ -13,15 +13,8 @@ export interface Conclusion {
issue: boolean;
}
export interface LiveStats {
perSecond: number | null;
tokens: number;
cost: number;
elapsedSeconds: number;
}
export function liveJob(jobs: readonly Job[]): Job | undefined {
const active = jobs.find((job) => job.status === "queued" || job.status === "running");
const active = jobs.find(isActive);
if (active) return active;
const latest = jobs[0];
return latest && latest.reviewed > 0 ? latest : undefined;
@ -104,6 +97,14 @@ export function appendPage(feed: ReviewFeed, page: { reviews: readonly Review[];
return { reviews: [...feed.reviews, ...added].slice(-KEPT_REVIEWS), cursor: page.reviewed };
}
export function polling(job: Pick<Job, "status" | "reviewed">, feed: ReviewFeed): boolean {
return isActive(job) || feed.cursor < job.reviewed;
}
export function isActive(job: Pick<Job, "status">): boolean {
return job.status === "queued" || job.status === "running";
}
export function unseen(reviews: readonly Review[], seen: ReadonlySet<string>): Review[] {
return reviews.filter((review) => !seen.has(reviewKey(review)));
}
@ -185,53 +186,12 @@ export function secondsToFinishReading(
return Math.ceil(remaining / (job.reviewed / elapsed));
}
export function liveStats(job: Job, now: number): LiveStats {
const models = job.steps.filter((step) => step.kind === "model");
const end = job.finished_at ? Date.parse(job.finished_at) : now;
const elapsedSeconds = Math.max(0, Math.floor((end - Date.parse(readingStart(job))) / 1000));
return {
perSecond: elapsedSeconds > 0 && job.reviewed > 0 ? job.reviewed / elapsedSeconds : null,
tokens: models.reduce((sum, step) => sum + step.prompt_tokens + step.completion_tokens, 0),
cost: job.cost,
elapsedSeconds,
};
}
export function rateLabel(perSecond: number | null): string {
if (perSecond === null) return "–";
return perSecond >= 1 ? `${perSecond.toFixed(1)} traces/s` : `${(perSecond * 60).toFixed(1)} traces/min`;
}
export function tokenLabel(tokens: number): string {
if (tokens >= 1_000_000) return `${(tokens / 1_000_000).toFixed(1)}M tok`;
return tokens >= 1000 ? `${(tokens / 1000).toFixed(1)}k tok` : `${tokens} tok`;
}
export function newestFirst(reviews: readonly Review[], limit: number): Review[] {
return [...reviews].reverse().slice(0, limit);
}
export interface InFlight {
execution_id: string;
trace_id: string;
agent: string;
started_at: string;
}
export function inFlight(job: Job): readonly InFlight[] {
const reading = (job as Job & { reading?: readonly InFlight[] }).reading;
return job.status === "running" ? reading ?? [] : [];
}
export type LiveRow = { kind: "reading"; key: string; item: InFlight } | { kind: "done"; key: string; review: Review };
export function liveRows(reading: readonly InFlight[], reviews: readonly Review[], limit: number): LiveRow[] {
const finished = new Set(reviews.map((review) => review.execution_id));
const open = reading.filter((item) => !finished.has(item.execution_id));
return [
...open.map((item) => ({ kind: "reading" as const, key: item.execution_id, item })),
...newestFirst(reviews, limit).map((review) => ({ kind: "done" as const, key: review.execution_id, review })),
];
export function inFlight(job: Pick<Job, "status" | "reading">): readonly InFlight[] {
return job.status === "running" ? job.reading : [];
}
export function nowLine(job: Pick<Job, "coverage" | "reviewed">, reading: number): string {

View file

@ -35,4 +35,6 @@ export type Worker = LensList["workers"][number];
export type Review = components["schemas"]["Review"];
export type InFlight = components["schemas"]["InFlight"];
export type ReviewVerdict = components["schemas"]["ReviewVerdict"];