Fork Horse repository, listed by its owner. Publisher snapshot.

packages/forkhorse-dashboard/test/race-fixtures.ts

Snapshot at 34e3175

Containing directory

8,863 bytes · typescriptView raw
1import type { Race, RaceEntrant, StateResponse } from "../src/contracts.ts";
2import { fixtureReceipt, fixtureState, HEAD } from "./fixtures.ts";
3
4export const raceScenarios = [
5  "race-open",
6  "race-finished",
7  "race-photo",
8  "race-photo-unattempted",
9  "race-empty",
10  "race-loading",
11  "race-error",
12  "race-unknown",
13  "race-standard",
14  "race-advisory",
15  "race-reused-forks",
16  "race-timed-out",
17  "race-couldnt-run",
18  "race-two-digit",
19];
20const at = (seconds: number) =>
21  new Date(Date.parse("2026-10-13T14:02:00Z") + seconds * 1000).toISOString();
22const entrant = (
23  agent: string,
24  claimed: number,
25): RaceEntrant & {
26  closedBy: null | "release" | "owner" | "race-finished";
27  usage: { reported: null; metered: null };
28  budget: "unchecked";
29} => ({
30  agent,
31  repoName: `race--${agent}-1`,
32  claimedAt: at(claimed),
33  firstPushAt: null,
34  reviewRequestedAt: null,
35  receiptPassedAt: null,
36  approvedAt: null,
37  promotedAt: null,
38  place: null,
39  closedAt: null,
40  closedBy: null,
41  promoteRejected: null,
42  usage: { reported: null, metered: null },
43  budget: "unchecked",
44});
45// The contract test checks these slices against core's public declarations without
46// pulling the Worker environment into the browser package's compiler.
47export type RaceFixture = Omit<StateResponse, "races"> & {
48  agents: { name: string; createdAt: string | null }[];
49  races: (Race &
50    Required<Pick<Race, "finishedAt" | "winner" | "ledgerEntryId" | "places">> & {
51      tokenBudget: null;
52      judge: null;
53      verdict: null;
54      entrants: ReturnType<typeof entrant>[];
55    })[];
56  reviews: (StateResponse["reviews"][number] & {
57    receipt: NonNullable<StateResponse["reviews"][number]["receipt"]>;
58    returned: null;
59  })[];
60};
61/** Fixed offline FH-052/053 snapshots. Never implies an enrolled/live race. */
62export function raceFixtureState(scenario = "race-open"): RaceFixture {
63  const state: RaceFixture = {
64    ...fixtureState("quiet"),
65    agents: [],
66    races: [],
67    ledger: [],
68    reviews: [],
69  };
70  state.project.id = scenario;
71  state.project.repoName = "race-fixture";
72  state.project.settings = { requireReceipt: scenario !== "race-advisory" };
73  // Response order deliberately differs from stable identity and lane order.
74  state.agents = [
75    { name: "cedar", createdAt: "2026-10-13T14:00:00Z" },
76    { name: "amber", createdAt: null },
77    { name: "birch", createdAt: null },
78  ];
79  if (scenario === "race-two-digit") {
80    // Nine earlier enrollments exercise identities 10, 11 and 12, not race places.
81    state.agents.unshift(...Array.from({ length: 9 }, (_, index) => ({
82      name: `agent-${String(index + 1).padStart(2, "0")}`, createdAt: null,
83    })));
84  }
85  state.packets = [
86    {
87      id: "race-01",
88      title: "Add retries to the webhook client",
89      goal: "Retry transient webhook errors.",
90      paths: ["src/webhooks/**"],
91      acceptance: ["Retries stay bounded"],
92      mode: scenario === "race-standard" ? "standard" : "race",
93    },
94  ];
95  const birch = entrant("birch", 0),
96    cedar = entrant("cedar", 10),
97    amber = entrant("amber", 60);
98  Object.assign(birch, {
99    firstPushAt: at(240),
100    reviewRequestedAt: at(360),
101    receiptPassedAt: at(540),
102  });
103  Object.assign(cedar, {
104    firstPushAt: at(180),
105    reviewRequestedAt: at(300),
106    receiptPassedAt: at(480),
107    approvedAt: at(600),
108  });
109  const finished = ["race-finished", "race-photo", "race-photo-unattempted", "race-reused-forks", "race-timed-out", "race-couldnt-run", "race-two-digit"].includes(scenario);
110  const race: RaceFixture["races"][number] = {
111    packet: "race-01",
112    tokenBudget: null,
113    judge: null,
114    verdict: null,
115    status: finished ? ("finished" as const) : ("open" as const),
116    finishedAt: finished ? at(720) : null,
117    winner: finished ? "cedar" : null,
118    ledgerEntryId: finished ? "ledger-race-1" : null,
119    places: finished
120      ? [
121          { agent: "cedar", place: 1 },
122          { agent: "birch", place: 2 },
123          { agent: "amber", place: 3 },
124        ]
125      : [],
126    entrants: [amber, cedar, birch],
127  };
128  if (finished) {
129    Object.assign(cedar, {
130      promotedAt: at(720),
131      place: 1,
132      closedAt: at(720),
133      closedBy: "race-finished",
134    });
135    Object.assign(birch, {
136      approvedAt: scenario.startsWith("race-photo") ? at(660) : null,
137      place: 2,
138      closedAt: at(720),
139      closedBy: "race-finished",
140    });
141    Object.assign(amber, {
142      firstPushAt: at(420),
143      reviewRequestedAt: at(540),
144      place: 3,
145      closedAt: at(720),
146      closedBy: "race-finished",
147    });
148    if (scenario === "race-photo")
149      birch.promoteRejected = {
150        at: "2026-10-13T14:14:00.400Z",
151        expected: HEAD,
152        found: "c".repeat(40),
153      };
154    state.ledger = [
155      {
156        id: "ledger-race-1",
157        review: "race-review-cedar",
158        repoName: cedar.repoName,
159        ref: "refs/heads/main",
160        before: HEAD,
161        after: "c".repeat(40),
162        receiptDigest: "d".repeat(64),
163        recordedAt: at(720),
164        race: race.packet,
165      },
166    ];
167  }
168  if (scenario === "race-reused-forks") {
169    race.entrants = [cedar, birch];
170    race.places = race.places.filter((entry) => entry.agent !== "amber");
171  }
172  if (scenario === "race-advisory") cedar.receiptPassedAt = null;
173  if (scenario === "race-empty") race.entrants = [];
174  state.races = scenario === "race-standard" || scenario === "race-unknown" ? [] : [race];
175  state.forks = [birch, cedar, amber].map((entry, index) => ({
176    agent: entry.agent,
177    repoName: entry.repoName,
178    head: ["b", "c", "e"][index].repeat(40),
179    remote: `https://git.idiot.tax/${entry.repoName}`,
180    createdAt: entry.claimedAt,
181  }));
182  state.claims = race.entrants
183    .filter((entry) => !entry.closedAt)
184    .map((entry) => ({
185      packet: race.packet,
186      agent: entry.agent,
187      repoName: entry.repoName,
188      paths: state.packets[0].paths,
189      createdAt: entry.claimedAt,
190    }));
191  state.reviews = race.entrants
192    .filter((entry) => entry.reviewRequestedAt)
193    .map((entry) => {
194      const fork = state.forks.find((candidate) => candidate.repoName === entry.repoName)!;
195      const receipt = fixtureReceipt(
196        entry.agent === "amber" || (scenario === "race-advisory" && entry.agent === "cedar")
197          ? "failed"
198          : "passed",
199      );
200      if (entry.agent === "amber" && (scenario === "race-timed-out" || scenario === "race-couldnt-run"))
201        receipt.status = scenario === "race-timed-out" ? "timed-out" : "infrastructure-error";
202      receipt.startedAt = entry.reviewRequestedAt!;
203      receipt.finishedAt = entry.receiptPassedAt ?? at(600);
204      receipt.durationMs = Date.parse(receipt.finishedAt) - Date.parse(receipt.startedAt);
205      receipt.checks = [
206        {
207          name: "brand",
208          tier: "quick",
209          runtime: "dynamic-worker",
210          outcome: receipt.status,
211          durationMs: 13000,
212        },
213      ];
214      return {
215        id: `race-review-${entry.agent}`,
216        packet: race.packet,
217        repoName: entry.repoName,
218        agent: entry.agent,
219        sha: fork.head,
220        base: HEAD,
221        receiptDigest: receipt.digest,
222        receipt,
223        approval: entry.approvedAt ? { sha: fork.head, receiptDigest: receipt.digest } : null,
224        stale: finished && !entry.promotedAt,
225        promoted: !!entry.promotedAt,
226        returned: null,
227        createdAt: entry.reviewRequestedAt!,
228      };
229    });
230  state.activity = race.entrants
231    .filter((entry) => entry.firstPushAt)
232    .map((entry, index) => ({
233      sequence: index + 1,
234      namespace: "fixture",
235      repoName: entry.repoName,
236      agent: entry.agent,
237      ref: "refs/heads/main",
238      before: HEAD,
239      after: state.forks.find((fork) => fork.repoName === entry.repoName)!.head,
240      changedPaths: ["src/webhooks/client.ts"],
241      eventTimestamp: entry.firstPushAt!,
242      recordedAt: entry.firstPushAt!,
243    }));
244  // A canonical event at the first claim establishes loaded history coverage.
245  state.activity.unshift({
246    sequence: 0, namespace: "fixture", repoName: state.project.repoName, agent: null,
247    ref: "refs/heads/main", before: "f".repeat(40), after: HEAD, changedPaths: [],
248    eventTimestamp: at(0), recordedAt: at(0),
249  });
250  if (scenario === "race-reused-forks") {
251    const history = [birch, cedar].flatMap((entry, forkIndex) =>
252      Array.from({ length: forkIndex === 0 ? 19 : 2 }, (_, index) => ({
253        ...state.activity.find((event) => event.repoName === entry.repoName)!,
254        recordedAt: at(-60 * (index + 1)),
255        eventTimestamp: at(-60 * (index + 1)),
256      })),
257    );
258    state.activity = [...history, ...state.activity]
259      .toSorted((a, b) => Date.parse(a.recordedAt) - Date.parse(b.recordedAt))
260      .map((event, index) => ({ ...event, sequence: index + 1 }));
261  }
262  return state;
263}
264