import { assertDetail } from "./review.tsx";
import { useEffect, useState, type ReactNode } from "react";
import type { Brand, ProjectState, Race, ReviewDetail } from "./contracts.ts";
import { entrantChecks, raceEntrants, raceStart, raceSplit } from "./race-model.ts";
import { oldestLoadedActivity, packetPushes, timestamp } from "./fork-graph-model.ts";
import { BudgetUsage } from "./usage.tsx";
import { totalTokens } from "./usage.ts";
import { agentIdentities, Saddlecloth, type AgentIdentity } from "./lane.tsx";
const elapsed = (start: number | undefined, end?: string | null) => {
const at = Date.parse(end ?? "");
return start !== undefined && Number.isFinite(start) && Number.isFinite(at) && at >= start
? at - start
: undefined;
};
const best = (values: (number | undefined)[], index: number) =>
values.length > 1 &&
values.every((value) => value !== undefined) &&
new Set(values).size > 1 &&
values[index] === Math.min(...(values as number[]));
function CompareCell({ agent, identity, children }: { agent: string; identity?: AgentIdentity; children: ReactNode }) {
return
{agent}
{children}
| ;
}
/** Facts below the accepted FH-055 track, using its claim order and recorded race clock. */
export function RaceCompare({
race: rawRace,
state,
brand,
getReview,
advice,
}: {
race: Race;
state: ProjectState;
brand: Brand;
advice?: ReactNode;
getReview?: (id: string) => Promise;
}) {
const race = { ...rawRace, entrants: raceEntrants(rawRace) };
const reviews = race.entrants.map((entrant) =>
state.reviews
.filter(
(r) =>
r.packet === race.packet && r.repoName === entrant.repoName && r.agent === entrant.agent,
)
.toSorted((a, b) => (b.requestedAt ?? "").localeCompare(a.requestedAt ?? ""))
.at(0),
);
const keys = JSON.stringify(reviews.map((r) => (r ? [r.id, r.sha] : null)));
const [details, setDetails] = useState>({});
useEffect(() => {
let active = true;
setDetails({});
if (getReview)
void Promise.allSettled(
reviews
.filter((r) => !!r)
.map(async (review) => {
const detail = await getReview(review.id);
assertDetail(detail, review.id);
if (
active &&
detail.review.id === review.id &&
detail.review.sha === review.sha &&
Number.isSafeInteger(detail.changes.fileCount)
)
setDetails((loaded) => ({ ...loaded, [review.id]: detail }));
}),
);
return () => {
active = false;
};
// Exact review identities trigger reads; host action objects need not be stable.
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [keys, getReview]);
const start = raceStart(race);
const activity = state.recentActivity ?? [];
const oldestLoaded = oldestLoadedActivity(activity);
const pushesAvailable = oldestLoaded !== Infinity && race.entrants.every((entrant) => {
const claimed = timestamp(entrant.claimedAt);
return claimed !== undefined && oldestLoaded <= claimed;
});
const now = Date.now();
const approved = race.entrants.map((e) => elapsed(start, e.approvedAt));
const promoted = race.entrants.map((e) => elapsed(start, e.promotedAt));
const changes = reviews.map((r) => (r ? details[r.id]?.changes.fileCount : undefined));
const tokenValues = (source: "reported" | "metered") =>
race.entrants.map((e) => (e.usage?.[source] ? totalTokens(e.usage[source]!) : undefined));
const tokens = (index: number, compare = true) => {
const e = race.entrants[index];
return (
<>
{compare &&
(["reported", "metered"] as const).map(
(source) =>
best(tokenValues(source), index) && (
fewest ({source})
),
)}
>
);
};
const identities = agentIdentities(state.agents);
return (
Compare
{advice}
Times since the first entrant claimed. Files come from the latest review detail.
{pushesAvailable && " Push counts cover each entrant's race interval in loaded activity."}
| Fact |
{race.entrants.map((e) => (
{e.agent}
|
))}
{(
[
["Time to Approved", approved, "approvedAt"],
["Time to Promoted", promoted, "promotedAt"],
] as const
).map(([label, values, key]) => (
| {label} |
{values.map((_value, i) => (
{raceSplit(race.entrants[i][key], start) || "Not yet"}
{best([...values], i) && fastest}
))}
))}
| Checks passed |
{race.entrants.map((e) => (
{entrantChecks(state, race, e)}
))}
| Files changed |
{changes.map((value, i) => (
{value ?? (reviews[i] ? "Unavailable" : "No review yet")}
{best(changes, i) && fewest}
))}
{pushesAvailable &&
| Recorded pushes |
{race.entrants.map((e) => (
{packetPushes(
activity, e.repoName, state.project.defaultBranch,
timestamp(e.claimedAt) ?? Infinity,
timestamp(e.closedAt) ?? timestamp(race.finishedAt) ?? now,
).length}
))}
}
| Tokens |
{race.entrants.map((e, i) => (
{tokens(i)}
))}
);
}