g1t/apps/web/app/lib/catch-up.test.ts

68 lines2,633 bytesCodeBlame

Pick any line to see why it is the way it is: the commit, the pull request and issue it came from, and what the agent was thinking.

Catching up with main takes seconds when the two sides touched different files1import assert from "node:assert/strict";
2import { test } from "node:test";
3
4import type { AgentRun } from "@g1t/contracts";
5
6import { CATCH_UP_TIMEOUT_MS, catchUpPhase, catchUpRun, catchUpTitle, catchUpWhy } from "./catch-up.ts";
7
8const START = Date.parse("2026-10-05T12:00:00Z");
9
10function run(kind: AgentRun["kind"], status: AgentRun["status"], createdAt: string): AgentRun {
11 return {
12 id: `run-${kind}-${createdAt}`,
13 repo: { namespace: "acme", name: "app" },
14 number: 7,
15 title: null,
16 kind,
g1t is one name: its agent's work, commits and comments show as @g1t, and nobody can claim g1t or g1t-agent17 agent: "g1t",
Catching up with main takes seconds when the two sides touched different files18 model: null,
19 status,
20 step: null,
21 steps: [],
22 stepCount: 0,
23 startedBy: "octo",
24 error: null,
25 costUsd: null,
26 turns: null,
27 createdAt,
28 startedAt: null,
29 finishedAt: null,
30 updatedAt: createdAt,
31 };
32}
33
34test("the update run for a request is the newest one since it was made", () => {
35 const runs = [
36 run("update", "failed", "2026-10-05T11:00:00Z"),
37 run("review", "running", "2026-10-05T12:00:05Z"),
38 run("update", "running", "2026-10-05T12:00:03Z"),
39 ];
40 assert.equal(catchUpRun(runs, START)?.createdAt, "2026-10-05T12:00:03Z");
41 assert.equal(catchUpRun(runs.slice(0, 2), START), null);
42});
43
44test("it is done as soon as the pull request is no longer behind", () => {
45 assert.equal(catchUpPhase({ behind: false, run: null, startedAt: START, now: START + 1000 }), "done");
46 const failed = run("update", "failed", "2026-10-05T12:00:03Z");
47 assert.equal(catchUpPhase({ behind: false, run: failed, startedAt: START, now: START }), "done");
48});
49
50test("a run that ended while still behind failed", () => {
51 for (const status of ["failed", "stopped"] as const) {
52 const ended = run("update", status, "2026-10-05T12:00:03Z");
53 assert.equal(catchUpPhase({ behind: true, run: ended, startedAt: START, now: START + 60_000 }), "failed");
54 }
55});
56
57test("it never waits forever", () => {
58 const going = run("update", "running", "2026-10-05T12:00:03Z");
59 assert.equal(catchUpPhase({ behind: true, run: going, startedAt: START, now: START + 60_000 }), "working");
60 assert.equal(catchUpPhase({ behind: true, run: null, startedAt: START, now: START + CATCH_UP_TIMEOUT_MS + 1 }), "timed_out");
61});
62
63test("the box says who is doing what", () => {
g1t is one name: its agent's work, commits and comments show as @g1t, and nobody can claim g1t or g1t-agent64 assert.equal(catchUpTitle("conflicting", "main"), "g1t is resolving conflicts with main");
65 assert.equal(catchUpTitle("overlap", "main"), "g1t is merging main into this pull request");
Catching up with main takes seconds when the two sides touched different files66 assert.match(catchUpWhy({ reason: "overlap", paths: ["a.rs"] }, "main"), /both changed one file/);
67 assert.match(catchUpWhy({ reason: "conflicting", paths: ["a.rs", "b.rs"] }, "main"), /conflicts in 2 files/);
68});