Fork Horse repository, listed by its owner. Publisher snapshot.
packages/forkhorse-dashboard/test/races-fixtures.ts
Snapshot at 34e3175
1import type { Race, StateResponse } from "../src/contracts.ts";
2import { raceFixtureState } from "./race-fixtures.ts";
3
4export const racesScenarios = ["races-list", "races-empty"];
5
6/** Synthetic FH-081 read snapshots, including every requested list/capture state. */
7export function racesFixtureState(scenario = "races-list"): StateResponse {
8 const state: StateResponse = raceFixtureState("race-open");
9 state.project.id = scenario;
10 state.races = [];
11 state.packets = [];
12 state.claims = [];
13 state.reviews = [];
14 state.forks = [];
15 state.activity = [];
16 state.ledger = [];
17 if (scenario === "races-empty") return state;
18 const add = (id: string, title: string, source = "race-open", offset = 0) => {
19 const fixture = raceFixtureState(source);
20 const race: Race = structuredClone(fixture.races[0]);
21 race.packet = id;
22 const shift = (at: string | null | undefined) => at
23 ? new Date(Date.parse(at) + offset * 60_000).toISOString() : null;
24 race.finishedAt = shift(race.finishedAt);
25 for (const entrant of race.entrants) {
26 entrant.repoName = `${id}--${entrant.agent}`;
27 for (const key of ["claimedAt", "firstPushAt", "reviewRequestedAt", "receiptPassedAt", "approvedAt", "promotedAt", "closedAt"] as const) {
28 // The original claimedAt is always present in these fixed fixtures.
29 const at = shift(entrant[key]);
30 if (key === "claimedAt") entrant.claimedAt = at!;
31 else entrant[key] = at;
32 }
33 }
34 state.races!.push(race);
35 state.packets.push({ ...fixture.packets[0], id, title });
36 state.forks.push(...fixture.forks.map((fork) => ({ ...fork, repoName: `${id}--${fork.agent}` })));
37 state.claims.push(...race.entrants.filter((entrant) => !entrant.closedAt).map((entrant) => ({
38 packet: id, agent: entrant.agent, repoName: entrant.repoName,
39 paths: fixture.packets[0].paths, createdAt: entrant.claimedAt,
40 })));
41 return race;
42 };
43 add("race-three", "Bound retries for transient webhook failures", "race-open", 30);
44 const one = add("race-one", "Make delivery failures readable", "race-open", 40);
45 one.entrants = one.entrants.filter((entrant) => entrant.agent === "cedar");
46 state.claims = state.claims.filter((claim) => claim.packet !== one.packet || claim.agent === "cedar");
47 add("race-zero", "Prepare the next race", "race-empty");
48 add("race-winner", "Record delivery outcomes", "race-finished", 10);
49 const photo = add("race-photo", "Handle simultaneous approved changes", "race-photo", 20);
50 state.packets.find((packet) => packet.id === photo.packet)!.archived = {
51 at: "2026-10-13T15:00:00Z", by: "owner",
52 };
53 const judged = add("race-judged", "Compare bounded retry strategies", "race-open", 50);
54 judged.judge = "fixture-judge";
55 judged.verdict = { ranking: ["birch", "cedar", "amber"], rationale: "Fixture advice only.", at: "2026-10-13T15:10:00Z" };
56 const waiting = add("race-advice", "Review timeout handling", "race-open", 60);
57 waiting.judge = "fixture-judge";
58 waiting.verdict = null;
59 // Reverse response order to exercise the recorded-time sort rather than API order.
60 state.races.reverse();
61 return state;
62}
63