Skip to content

Where people and agents ship software together. The open-source git platform for the whole job: issues, agents, checks and deploys to the edge.

432 linesCodeBlameRaw
1import assert from "node:assert/strict";
2import { test } from "node:test";
3
4import type { SignalAuthor, SignalPull, SignalWeek, Usage, WorkspaceSignals } from "@g1t/contracts";
5
6import {
7 type SignalContext,
8 type WeekTotals,
9 agentStep,
10 blockedSignal,
11 dayList,
12 emptySignals,
13 findings,
14 mergeSignals,
15 newGround,
16 newHabits,
17 namesWords,
18 pulse,
19 quarterSpend,
20 quarterStart,
21 quietHeadline,
22 reviewSignal,
23 reworkSignal,
24 rhythm,
25 shippedSignal,
26 short,
27 signalsRange,
28 silos,
29 spendFlow,
30 spendSignal,
31 spoken,
32 spreadSignal,
33 spreading,
34 stalledSignal,
35 weekStarts,
36 weekTotals,
37 weeklySpend,
38} from "./signals.ts";
39
40const NOW = Date.parse("2026-10-18T15:00:00Z");
41const DAY = 86_400_000;
42const repos = { r1: { namespace: "acme", name: "web" }, r2: { namespace: "acme", name: "tax" } };
43
44function week(start: string, fields: Partial<WeekTotals> = {}): WeekTotals {
45 return { start, merged: 0, agentMerged: 0, agentReworked: 0, agentDrafted: 0, agentDraftSeconds: 0, reviewed: 0, reviewSeconds: 0, stalled: 0, ...fields };
46}
47
48function usage(fields: Partial<Usage> = {}): Usage {
49 return {
50 since: "",
51 spentMicros: 0,
52 costMicros: 0,
53 providerMicros: 0,
54 usedMicros: 0,
55 free: false,
56 runs: 0,
57 byDay: [],
58 byTask: [],
59 byRepo: [],
60 byPull: [],
61 byModel: [],
62 addedMicros: 0,
63 ...fields,
64 };
65}
66
67function ctx(fields: Partial<SignalContext> = {}): SignalContext {
68 return { slug: "acme", now: NOW, repos, signals: emptySignals(), weeks: [], quarterUsage: null, quarter: "2026-10-01", ...fields };
69}
70
71function pull(fields: Partial<SignalPull>): SignalPull {
72 return {
73 repoId: "r1",
74 number: 1,
75 title: "A change",
76 status: "merged",
77 agent: false,
78 ownerId: "u1",
79 ownerName: "ana",
80 createdAt: "2026-10-05T00:00:00Z",
81 mergedAt: "2026-10-06T00:00:00Z",
82 item: null,
83 milestone: null,
84 ...fields,
85 };
86}
87
88function author(fields: Partial<SignalAuthor>): SignalAuthor {
89 return {
90 repoId: "r1",
91 ownerId: "u1",
92 ownerName: "ana",
93 firstMergedAt: "2026-01-01T00:00:00Z",
94 lastMergedAt: "2026-10-10T00:00:00Z",
95 merged: 10,
96 recent: 10,
97 ...fields,
98 };
99}
100
101test("weeks of seven days end with the last day, and the quarter starts on its first month", () => {
102 assert.deepEqual(weekStarts("2026-10-18", 3), ["2026-09-28", "2026-10-05", "2026-10-12"]);
103 assert.deepEqual(dayList("2026-10-18", 3), ["2026-10-16", "2026-10-17", "2026-10-18"]);
104 assert.equal(quarterStart("2026-10-18"), "2026-10-01");
105 assert.equal(quarterStart("2026-03-31"), "2026-01-01");
106 assert.equal(quarterStart("2026-08-02"), "2026-07-01");
107 // The reach covers a milestone's build even early in a quarter.
108 assert.equal(signalsRange(NOW).since, "2026-06-20");
109});
110
111test("batches add up per repository, and quiet weeks stay in the line", () => {
112 const rows: SignalWeek[] = [
113 { repoId: "r1", ...week("2026-10-12", { merged: 2, agentMerged: 1 }) },
114 { repoId: "r2", ...week("2026-10-12", { merged: 3, agentMerged: 3, stalled: 1 }) },
115 { repoId: "r9", ...week("2026-01-01", { merged: 9 }) },
116 ];
117 const totals = weekTotals(rows, ["2026-10-05", "2026-10-12"]);
118 assert.deepEqual(
119 totals.map((w) => [w.start, w.merged, w.agentMerged, w.stalled]),
120 [
121 ["2026-10-05", 0, 0, 0],
122 ["2026-10-12", 5, 4, 1],
123 ],
124 );
125 assert.equal(weekTotals(rows, ["2026-10-12"], new Set(["r1"]))[0]!.merged, 2);
126 const a: WorkspaceSignals = {
127 ...emptySignals(),
128 items: [{ number: 4, title: "Old", state: "open", milestone: null }],
129 waiting: [{ repoId: "r1", number: 2, title: "b", createdAt: "2026-10-02", agent: false, draftSeconds: null, item: null, blocks: [] }],
130 };
131 const b: WorkspaceSignals = {
132 ...emptySignals(),
133 items: [{ number: 4, title: "Old", state: "open", milestone: null }],
134 waiting: [{ repoId: "r2", number: 1, title: "a", createdAt: "2026-10-01", agent: false, draftSeconds: null, item: null, blocks: [] }],
135 };
136 const merged = mergeSignals([a, b]);
137 assert.equal(merged.items.length, 1, "an item named by two batches is one item");
138 assert.deepEqual(
139 merged.waiting.map((w) => w.number),
140 [1, 2],
141 "the oldest waits first across batches",
142 );
143});
144
145test("usage by day falls into its week", () => {
146 const spend = weeklySpend(
147 usage({
148 byDay: [
149 { key: "2026-10-12/review", micros: 5, runs: 1 },
150 { key: "2026-10-18/run", micros: 7, runs: 1 },
151 { key: "2026-10-11/run", micros: 3, runs: 1 },
152 ],
153 }),
154 ["2026-10-05", "2026-10-12"],
155 );
156 assert.deepEqual(spend, [3, 12]);
157 assert.equal(weeklySpend(null, ["2026-10-12"]), null, "usage that did not answer is not zero");
158});
159
160test("the pulse says each figure against last week, and whether that is good news", () => {
161 const weeks = [
162 week("2026-10-05", { merged: 60, agentMerged: 52, agentReworked: 11, stalled: 16 }),
163 week("2026-10-12", { merged: 70, agentMerged: 61, agentReworked: 11, stalled: 23 }),
164 ];
165 const tiles = pulse({ slug: "acme", weeks, spend: [52 * 72_000_000, 61 * 86_000_000] });
166 const by = Object.fromEntries(tiles.map((tile) => [tile.key, tile]));
167 assert.equal(by.merges!.value, "61");
168 assert.deepEqual(by.merges!.delta, { text: "+9", tone: "good" });
169 assert.equal(by.spend!.value, "$86");
170 assert.deepEqual(by.spend!.delta, { text: "+$14", tone: "bad" }, "spend going up is not good news");
171 assert.deepEqual(by.stalled!.delta, { text: "+7", tone: "bad" });
172 assert.equal(by.rework!.value, "18%");
173 assert.equal(by.rework!.delta!.text, "−3.1 pts");
174 assert.equal(by.rework!.delta!.tone, "good");
175 const unknown = pulse({ slug: "acme", weeks, spend: null });
176 assert.equal(unknown.find((tile) => tile.key === "spend")!.value, "—", "no usage, no figure");
177 assert.equal(unknown.find((tile) => tile.key === "spend")!.delta, null);
178});
179
180test("the change holding up the most work items leads, with what it holds up", () => {
181 const signals = {
182 ...emptySignals(),
183 waiting: [
184 { repoId: "r1", number: 7, title: "Small", createdAt: "2026-10-10T00:00:00Z", agent: true, draftSeconds: 600, item: 3, blocks: [4] },
185 {
186 repoId: "r2",
187 number: 4821,
188 title: "Nexus threshold configuration",
189 createdAt: "2026-10-16T15:00:00Z",
190 agent: true,
191 draftSeconds: 600,
192 item: 5,
193 blocks: [8, 9, 10],
194 },
195 { repoId: "gone", number: 1, title: "Unreadable", createdAt: "2026-10-01T00:00:00Z", agent: false, draftSeconds: null, item: 1, blocks: [2, 3, 4, 5] },
196 ],
197 };
198 const signal = blockedSignal(ctx({ signals }))!;
199 assert.equal(signal.headline, "Three work items are waiting on one unreviewed change.");
200 assert.deepEqual(signal.facts, ["tax#4821 Nexus threshold configuration", "open 2 days", "holds up #8, #9, #10"]);
201 assert.equal(signal.link!.to, "/acme/tax/pull/4821");
202 assert.equal(blockedSignal(ctx()), null);
203});
204
205test("a quick draft waiting long for review is said with both times; a slowdown alone is said against the weeks before", () => {
206 const weeks = [
207 week("2026-09-28", { reviewed: 4, reviewSeconds: 4 * 0.8 * 86400 }),
208 week("2026-10-05", { reviewed: 4, reviewSeconds: 4 * 1.2 * 86400 }),
209 week("2026-10-12", { reviewed: 10, reviewSeconds: 10 * 2.1 * 86400, agentDrafted: 5, agentDraftSeconds: 5 * 48 * 60 }),
210 ];
211 const gap = reviewSignal(ctx({ weeks }))!;
212 assert.equal(gap.headline, "Changes an agent drafts in under an hour are waiting 2.1 days for first review.");
213 assert.deepEqual(gap.facts, ["48m to draft", "2.1d to first review", "this week"]);
214 assert.equal(gap.trend!.range, "19h → 2.1d over 3 weeks");
215 const slower = reviewSignal(ctx({ weeks: weeks.map((w, i) => (i === 2 ? { ...w, agentDrafted: 0, agentDraftSeconds: 0 } : w)) }))!;
216 assert.match(slower.headline, /^First reviews are taking 2\.1 days, up from a day in the weeks before\.$/);
217 assert.equal(reviewSignal(ctx({ weeks: [week("2026-10-12")] })), null, "no reviews, nothing to say");
218});
219
220test("spend that concentrates in one milestone is a finding; spread-out spend is not", () => {
221 const signals = {
222 ...emptySignals(),
223 milestones: [{ number: 1, title: "the Checkout replatform", state: "open", dueOn: null, createdAt: "2026-08-01T00:00:00Z", closedAt: null }],
224 items: [{ number: 5, title: "Tax cutover", state: "open", milestone: 1 }],
225 pulls: [pull({ number: 1, item: 5, milestone: 1 }), pull({ number: 2 }), pull({ repoId: "r2", number: 3 })],
226 };
227 const quarterUsage = usage({
228 byPull: [
229 { key: "acme/web#1", micros: 28_300_000_000, runs: 1 },
230 { key: "acme/web#2", micros: 14_000_000_000, runs: 1 },
231 { key: "acme/tax#3", micros: 10_100_000_000, runs: 1 },
232 ],
233 });
234 const signal = spendSignal(ctx({ signals, quarterUsage }))!;
235 assert.equal(signal.headline, "More than half of this quarter's agent spend is going into the Checkout replatform.");
236 assert.deepEqual(signal.facts, ["$28.3K of $52.4K", "quarter to date"]);
237 const even = usage({ byPull: quarterUsage.byPull.map((slice) => ({ ...slice, micros: 1_000_000 })) });
238 assert.equal(spendSignal(ctx({ signals, quarterUsage: even })), null);
239 assert.equal(spendSignal(ctx({ signals, quarterUsage: null })), null);
240});
241
242test("a milestone closed this week says when against its due date, and what it took", () => {
243 const closedAt = "2026-10-13T18:00:00Z";
244 const signals = {
245 ...emptySignals(),
246 milestones: [{ number: 2, title: "Single sign-on", state: "closed", dueOn: "2026-11-03", createdAt: "2026-07-28T00:00:00Z", closedAt }],
247 pulls: [
248 pull({ milestone: 2, number: 1 }),
249 pull({ milestone: 2, number: 2, repoId: "r2" }),
250 pull({ milestone: 2, number: 3, status: "closed", mergedAt: null }),
251 ],
252 };
253 const signal = shippedSignal(ctx({ signals }))!;
254 assert.equal(signal.headline, "Single sign-on shipped on Tuesday, three weeks ahead of schedule.");
255 assert.deepEqual(signal.facts, ["11 weeks in build", "2 changes", "2 projects"]);
256 const old = { ...signals, milestones: [{ ...signals.milestones[0]!, closedAt: "2026-09-01T00:00:00Z" }] };
257 assert.equal(shippedSignal(ctx({ signals: old })), null, "only the last week's");
258});
259
260test("stalled changes and rework are findings only when they moved", () => {
261 assert.equal(
262 stalledSignal(ctx({ weeks: [week("a", { stalled: 16 }), week("b", { stalled: 23 })] }))!.headline,
263 "23 open changes have gone three days with nothing happening, 7 more than last week.",
264 );
265 assert.equal(stalledSignal(ctx({ weeks: [week("a", { stalled: 16 }), week("b", { stalled: 17 })] })), null);
266 const steady = [1, 2, 3, 4].map((i) => week(`w${i}`, { agentMerged: 10, agentReworked: 1 }));
267 assert.match(
268 reworkSignal(ctx({ weeks: [...steady, week("now", { agentMerged: 10, agentReworked: 4 })] }))!.headline,
269 /^People asked for changes on 40% .* up from 10%\.$/,
270 );
271 assert.equal(reworkSignal(ctx({ weeks: [...steady, week("now", { agentMerged: 10, agentReworked: 1 })] })), null);
272});
273
274test("who works where: new ground, one person carrying a project, and a first agent merge", () => {
275 const recent = new Date(NOW - 3 * DAY).toISOString();
276 const authors = [
277 author({ ownerId: "u1", ownerName: "ana", repoId: "r1", recent: 9, merged: 40 }),
278 author({ ownerId: "u2", ownerName: "bo", repoId: "r1", firstMergedAt: recent, recent: 1, merged: 1 }),
279 author({ ownerId: "u2", ownerName: "bo", repoId: "r2", firstMergedAt: "2026-02-01T00:00:00Z", merged: 12, recent: 2 }),
280 ];
281 assert.deepEqual(
282 newGround(authors, NOW).map((row) => [row.name, row.repoId, row.elsewhere]),
283 [["bo", "r1", 12]],
284 );
285 const [silo] = silos(authors, NOW);
286 assert.equal(silo!.name, "ana");
287 assert.equal(silo!.share, 0.9);
288 assert.deepEqual(silo!.joining, [{ ownerId: "u2", name: "bo" }]);
289 const pulls = [1, 2, 3].map((n) => pull({ number: n, mergedAt: `2026-09-0${n}T00:00:00Z` }));
290 const habits = newHabits([...pulls, pull({ number: 9, agent: true, mergedAt: recent })], NOW);
291 assert.deepEqual(
292 habits.map((row) => [row.name, row.byHand]),
293 [["ana", 3]],
294 );
295 const signal = findings(ctx({ signals: { ...emptySignals(), authors } })).find((s) => s.key === "ground")!;
296 assert.equal(signal.headline, "bo is starting to work in web, which ana has carried almost alone.");
297});
298
299test("findings come highest first, and a quiet week still says something", () => {
300 const signals = {
301 ...emptySignals(),
302 waiting: [{ repoId: "r1", number: 2, title: "Fix", createdAt: "2026-10-16T00:00:00Z", agent: false, draftSeconds: null, item: 1, blocks: [3, 4] }],
303 };
304 const found = findings(ctx({ signals, weeks: [week("a", { stalled: 1 }), week("b", { stalled: 10 })] }));
305 assert.deepEqual(
306 found.map((s) => s.key),
307 ["blocked", "stalled"],
308 );
309 assert.equal(quietHeadline(week("x")), "A quiet week: nothing has merged yet, and nothing is stuck.");
310 assert.equal(
311 quietHeadline(week("x", { merged: 4, agentMerged: 2 })),
312 "Four changes merged this week, 50% of them an agent's, and nothing needs a closer look.",
313 );
314});
315
316test("waits are said in words and in a few characters", () => {
317 assert.equal(spoken(48 * 60), "48 minutes");
318 assert.equal(spoken(5 * 3600), "5 hours");
319 assert.equal(spoken(2.1 * 86400), "2.1 days");
320 assert.equal(short(48 * 60), "48m");
321 assert.equal(short(5.5 * 3600), "5.5h");
322 assert.equal(short(null), "—");
323});
324
325test("the spend flow threads each pull request through its milestone, work item and project", () => {
326 const signals = {
327 ...emptySignals(),
328 milestones: [{ number: 1, title: "Checkout replatform", state: "open", dueOn: null, createdAt: "2026-08-01T00:00:00Z", closedAt: null }],
329 items: [{ number: 5, title: "Tax service cutover", state: "open", milestone: 1 }],
330 pulls: [
331 pull({ number: 1, item: 5, milestone: 1, agent: true, createdAt: "2026-10-02T00:00:00Z" }),
332 pull({ number: 2, item: 5, milestone: 1, repoId: "r2", createdAt: "2026-10-03T00:00:00Z" }),
333 pull({ number: 3, createdAt: "2026-10-04T00:00:00Z" }),
334 pull({ number: 4, createdAt: "2026-05-01T00:00:00Z", mergedAt: "2026-05-02T00:00:00Z" }),
335 ],
336 };
337 const flow = spendFlow({
338 slug: "acme",
339 repos,
340 signals,
341 quarter: "2026-10-01",
342 quarterUsage: usage({ byPull: [{ key: "acme/web#1", micros: 900, runs: 1 }] }),
343 });
344 assert.deepEqual(
345 flow.map((node) => [node.label, node.pulls, node.agent, node.micros]),
346 [
347 ["Checkout replatform", 2, 1, 900],
348 ["No milestone", 1, 0, 0],
349 ],
350 "last quarter's work is left out; the costliest comes first",
351 );
352 const item = flow[0]!.children[0]!;
353 assert.equal(item.label, "Tax service cutover");
354 assert.deepEqual(
355 item.children.map((set) => [set.label, set.list!.map((p) => p.number)]),
356 [
357 ["web", [1]],
358 ["tax", [2]],
359 ],
360 );
361 assert.equal(agentStep(0.71), 3);
362 assert.equal(agentStep(0.1), 0);
363});
364
365test("the rhythm adds each group's days and leaves out groups with nothing", () => {
366 const days = [
367 { repoId: "r1", day: "2026-10-17", opened: 2, merged: 1, agentMerged: 1, reworked: 0, reviews: 3, sessions: 4 },
368 { repoId: "r2", day: "2026-10-18", opened: 1, merged: 0, agentMerged: 0, reworked: 1, reviews: 0, sessions: 0 },
369 ];
370 const rows = rhythm(
371 days,
372 ["2026-10-17", "2026-10-18"],
373 [
374 { key: "pay", label: "Payments", note: "3 people", to: "/t/pay", repoIds: ["r1", "r2"] },
375 { key: "idle", label: "Idle", note: "", to: "/t/idle", repoIds: ["r9"] },
376 ],
377 );
378 assert.equal(rows.length, 1);
379 assert.deepEqual(
380 rows[0]!.days.map((day) => [day.opened, day.reviews, day.sessions, day.reworked]),
381 [
382 [2, 3, 4, 0],
383 [1, 0, 0, 1],
384 ],
385 );
386});
387
388test("quarter spend adds each pull request's share of its sessions to g1t's usage", () => {
389 const signals = {
390 ...emptySignals(),
391 pulls: [
392 pull({ number: 1, sessionCostUsd: 2.5 }),
393 pull({ number: 2, sessionCostUsd: 1, createdAt: "2026-05-01T00:00:00Z", mergedAt: "2026-05-02T00:00:00Z" }),
394 ],
395 };
396 const quarterUsage = usage({
397 byPull: [
398 { key: "acme/web#1", micros: 1_000_000, runs: 1 },
399 { key: "acme/other#9", micros: 500_000, runs: 1 },
400 ],
401 });
402 const spend = quarterSpend({ repos, signals, quarterUsage, quarter: "2026-10-01" })!;
403 assert.equal(spend.byPull.get("acme/web#1"), 3_500_000);
404 assert.equal(spend.byPull.get("acme/web#2"), undefined, "last quarter's sessions are left out");
405 assert.equal(spend.total, 4_000_000, "usage on pull requests not listed still counts in the total");
406 assert.equal(spend.sessions, 2_500_000);
407 assert.equal(quarterSpend({ repos, signals, quarterUsage: null, quarter: "2026-10-01" }), null);
408});
409
410test("a harness catching on: two or more people started this month, two weeks or more after the first", () => {
411 const at = (days: number) => new Date(NOW - days * DAY).toISOString();
412 const harnesses = [
413 { repoId: "r1", ownerId: "u1", ownerName: "ana", harness: "codex", firstAt: at(60), sessions: 30 },
414 { repoId: "r2", ownerId: "u1", ownerName: "ana", harness: "codex", firstAt: at(20), sessions: 3 },
415 { repoId: "r1", ownerId: "u2", ownerName: "bo", harness: "codex", firstAt: at(10), sessions: 4 },
416 { repoId: "r2", ownerId: "u3", ownerName: "cy", harness: "codex", firstAt: at(3), sessions: 2 },
417 { repoId: "r1", ownerId: "u2", ownerName: "bo", harness: "cursor", firstAt: at(5), sessions: 1 },
418 ];
419 const [spread] = spreading(harnesses, NOW);
420 assert.equal(spread!.harness, "codex");
421 assert.equal(spread!.first.name, "ana", "a person's first session anywhere counts");
422 assert.deepEqual(
423 spread!.recent.map((p) => p.name),
424 ["bo", "cy"],
425 );
426 assert.equal(spreading(harnesses, NOW, { only: new Set(["r1"]) }).length, 0, "within one project only bo is new");
427 assert.equal(
428 spreadSignal(ctx({ signals: { ...emptySignals(), harnesses } }))!.headline,
429 "Codex is catching on: bo and cy started using it this month, after ana.",
430 );
431 assert.equal(namesWords(["a", "b", "c", "d"]), "a, b and 2 others");
432});