Skip to content
428 linesCodeBlameRaw

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.

Mission control shows where you are needed and what agents landed without you; git answers in about 200ms1import assert from "node:assert/strict";
2import { test } from "node:test";
3
4import {
5 type Merged,
Merge branch 'main' into actions-toolkit-oidc-artifacts6 placePushes,
Merge branch 'worktree-agent-ab9543c492a7ed481' into spend-guardrails7 historyCovers,
Mission control shows where you are needed and what agents landed without you; git answers in about 200ms8 change,
Fast pages, required checks on the branch, self-hosted runners, honest incidents9 checksFact,
Thirteen MCP tools and classic token scopes; agents rate their confidence and can be put on an issue in one step10 confidenceAsk,
11 confidenceLine,
Mission control shows where you are needed and what agents landed without you; git answers in about 200ms12 dayKey,
13 isTestFile,
14 landedByAgents,
15 landedToday,
16 parseSort,
17 parseTab,
18 pullFacts,
19 reachesBack,
20 reasonFor,
21 signedPercent,
22 sortRows,
23 stallReason,
24 summaryLine,
Merge leftovers: plan activity filtered in the query, pushes counted by account, ghost during the deletion window, profile time zones (identity 0039)25 pushedByPerson,
Mission control counts people's direct pushes to the default branch26 pushedCommits,
Mission control shows where you are needed and what agents landed without you; git answers in about 200ms27 waitingRows,
28 weekOf,
29 whyFor,
Thirteen MCP tools and classic token scopes; agents rate their confidence and can be put on an issue in one step30 withConfidence,
Mission control shows where you are needed and what agents landed without you; git answers in about 200ms31} from "./mission-control.ts";
32
33const HOUR = 3_600_000;
34const DAY = 24 * HOUR;
35// Monday 2026-10-05, 18:00 UTC.
36const NOW = Date.parse("2026-10-05T18:00:00Z");
37const repo = { namespace: "acme", name: "web" };
38
39test("each kind of need gets its reason chip", () => {
40 assert.equal(reasonFor({ kind: "deploy", detail: "" }), "blocking");
41 assert.equal(reasonFor({ kind: "limit", detail: "" }), "blocking");
42 assert.equal(reasonFor({ kind: "review", detail: "" }), "asked_for_you");
43 assert.equal(reasonFor({ kind: "invitation", detail: "" }), "asked_for_you");
44 assert.equal(reasonFor({ kind: "ready", detail: "" }), "ready_to_merge");
45 assert.equal(reasonFor({ kind: "checks", detail: "" }), "checks_failing");
46 assert.equal(reasonFor({ kind: "stuck", detail: "" }), "stalled");
47});
48
49test("a stopped pull request's reason comes from the sentence g1t stopped with", () => {
Fast pages, required checks on the branch, self-hosted runners, honest incidents50 assert.equal(stallReason("The required check CI still fails after the agent revised 3 times."), "checks_failing");
51 assert.equal(stallReason("The required checks CI and Lint still fail after the agent revised twice."), "checks_failing");
Mission control shows where you are needed and what agents landed without you; git answers in about 200ms52 assert.equal(stallReason("CI / push still fails after the agent revised 2 times."), "checks_failing");
Fast pages, required checks on the branch, self-hosted runners, honest incidents53 assert.equal(stallReason("It failed in the merge queue after the agent revised twice."), "checks_failing");
54 assert.equal(stallReason("Its checks could not be run."), "checks_failing");
Mission control shows where you are needed and what agents landed without you; git answers in about 200ms55 assert.equal(
56 stallReason("g1t stopped the agent's implement run when it reached its cost cap. Raise the cap under Settings, Guardrails."),
57 "outside_guardrails",
58 );
59 assert.equal(stallReason("g1t stopped the agent's review run when it reached its time cap."), "outside_guardrails");
60 assert.equal(stallReason("g1t could not merge this: the branch moved"), "blocking");
61 assert.equal(stallReason("Needs 1 approving review from someone with write access."), "needs_review");
62 assert.equal(stallReason("The review still asks for changes after the agent revised 3 times."), "needs_review");
63 assert.equal(stallReason("alex asked for changes, and the agent has already revised 3 times."), "needs_review");
64 assert.equal(stallReason("syntaqx stopped the agent's implement run."), "stalled");
65 assert.equal(stallReason("g1t could not start the next step: no slot"), "stalled");
66});
67
68test("why a need needs a person is said for every reason", () => {
69 for (const kind of ["deploy", "limit", "invitation", "review", "stuck", "checks", "ready", "conflict"] as const) {
70 const need = { kind, detail: "" };
71 assert.ok(whyFor(reasonFor(need), need).length > 20, kind);
72 }
73 const stalled = { kind: "stalled" as const, detail: "It reached its cost cap." };
74 assert.match(whyFor(reasonFor(stalled), stalled), /Guardrails/);
75});
76
77test("what the agent knows lists only what is known", () => {
78 const facts = pullFacts({
79 checkStatus: "failed",
80 files: [
81 { path: "src/retry.ts", additions: 40, deletions: 2 },
82 { path: "src/retry.test.ts", additions: 60, deletions: 0 },
83 ],
84 lifecycle: { revisions: 2 },
85 runs: [
86 { kind: "implement", costUsd: 0.5 },
87 { kind: "revise", costUsd: 0.25 },
88 { kind: "checks", costUsd: null },
89 ],
90 });
91 const by = Object.fromEntries(facts.map((f) => [f.label, f]));
Fast pages, required checks on the branch, self-hosted runners, honest incidents92 assert.equal(by["Required checks"].value, "Failed in the merge queue");
93 assert.equal(by["Required checks"].tone, "bad");
Mission control shows where you are needed and what agents landed without you; git answers in about 200ms94 assert.equal(by["Files changed"].value, "2");
95 assert.equal(by.Lines.value, "+100 −2");
96 assert.equal(by.Tests.value, "1 file");
97 assert.equal(by["Sent back"].value, "2 times");
98 assert.equal(by["Agent runs"].value, "2 · $0.75");
99
100 const bare = pullFacts({ checkStatus: null, files: [] });
Fast pages, required checks on the branch, self-hosted runners, honest incidents101 assert.deepEqual(bare, [{ label: "Required checks", value: "Not known yet", tone: null }]);
102});
103
104test("the required checks are read from where the agent's pull request stands", () => {
105 const at = (stage: Parameters<typeof checksFact>[1] extends infer L ? NonNullable<L>["stage"] : never, detail: string) =>
106 checksFact(null, { stage, detail });
107 assert.deepEqual(at("checking", "Waiting for CI / pull_request to finish."), { label: "Required checks", value: "Running", tone: null });
108 assert.equal(at("checking", "Waiting for the required check Deploy to report on its latest commit.").value, "Not reported yet");
109 assert.equal(at("revising", "CI / pull_request failed. The agent is being sent back to fix it.").value, "Failing");
110 assert.equal(at("needs_you", "The required check CI still fails after the agent revised twice.").value, "Failing");
111 // Past the checks: a review, an approval or a person's decision holds it, not them.
112 assert.equal(at("revising", "The review asked for changes. The agent is being sent back to make them.").value, "Passing");
113 assert.equal(at("needs_you", "This repository requires 1 approving review before a pull request merges; this one has 0.").value, "Passing");
114 assert.equal(at("ready", "Everything this repository asks for is met. Ready to merge.").tone, "good");
g1t is one name: its agent's work, commits and comments show as @g1t, and nobody can claim g1t or g1t-agent115 assert.equal(at("working", "g1t is making the change.").value, "Not run yet");
Fast pages, required checks on the branch, self-hosted runners, honest incidents116 assert.equal(checksFact("failed", { stage: "revising", detail: "It failed in the merge queue." }).value, "Failed in the merge queue");
Mission control shows where you are needed and what agents landed without you; git answers in about 200ms117});
118
Thirteen MCP tools and classic token scopes; agents rate their confidence and can be put on an issue in one step119test("a change held for low confidence is its own reason, ahead of what it would read as", () => {
120 const held =
121 "The agent's confidence in this change is low (checks failing, tests not added). This repository asks a person before merging it: approve it to let it land, or ask for changes.";
122 // Its reasons name checks and approval, but it is held for its confidence.
123 assert.equal(stallReason(held), "low_confidence");
124 assert.equal(reasonFor({ kind: "stalled", detail: held }), "low_confidence");
125
126 const low = { level: "low" as const, reasons: ["tests not added", "3 revisions"], uncertainAbout: ["the retry limit"] };
127 assert.equal(withConfidence("ready_to_merge", low), "low_confidence");
128 assert.equal(withConfidence("needs_review", low), "low_confidence");
129 // A failure that needs someone anyway keeps its own chip.
130 assert.equal(withConfidence("checks_failing", low), "checks_failing");
131 assert.equal(withConfidence("ready_to_merge", { level: "medium" }), "ready_to_merge");
132 assert.equal(withConfidence("ready_to_merge", null), "ready_to_merge");
133
134 assert.equal(confidenceLine(low), "Low — tests not added, 3 revisions");
135 assert.equal(confidenceLine({ level: "high", reasons: [] }), "High");
136 assert.match(confidenceAsk(low), /not sure of the change: tests not added, 3 revisions\. Approve it/);
137
138 const why = whyFor("low_confidence", { kind: "stalled", detail: held }, low);
139 assert.match(why, /from tests not added, 3 revisions\./);
140 assert.match(why, /unsure about the retry limit/);
141 assert.match(why, /nothing merges it until you approve it/);
142 // Ready, not held: it says to look before merging.
143 assert.match(whyFor("low_confidence", { kind: "ready", detail: "" }, low), /Look at it before you merge it/);
144});
145
146test("what the agent knows gains its confidence, across the row", () => {
147 const facts = pullFacts({
148 checkStatus: "passed",
149 files: [{ path: "src/retry.ts", additions: 40, deletions: 2 }],
150 lifecycle: { revisions: 3 },
151 confidence: { level: "low", reasons: ["tests not added", "3 revisions"] },
152 });
153 const fact = facts.find((f) => f.label === "Confidence");
154 assert.deepEqual(fact, { label: "Confidence", value: "Low — tests not added, 3 revisions", tone: "bad", wide: true });
155 assert.equal(facts.at(-1)?.label, "Confidence");
156});
157
Mission control shows where you are needed and what agents landed without you; git answers in about 200ms158test("test files are recognised by the names test runners use", () => {
159 assert.ok(isTestFile("src/a.test.ts"));
160 assert.ok(isTestFile("src/__tests__/a.ts"));
161 assert.ok(isTestFile("tests/api.rs"));
162 assert.ok(isTestFile("pkg/store_test.go"));
163 assert.ok(!isTestFile("src/testing-utils.ts"));
164 assert.ok(!isTestFile("src/contest.ts"));
A file named test.js or spec.rb counts as a test: confidence no longer says tests not added when they were165 assert.ok(isTestFile("test.js"));
166 assert.ok(isTestFile("lib/spec.rb"));
Mission control shows where you are needed and what agents landed without you; git answers in about 200ms167});
168
Mission control counts people's own changes as theirs; a shorter sidebar with setup under Settings, and a 56px top bar169const merged = (daysAgo: number, mergedBy: string | null, number = 1, authoredByAgent = true): Merged => ({
Mission control shows where you are needed and what agents landed without you; git answers in about 200ms170 repo,
171 number,
172 title: `Change ${number}`,
g1t is one name: its agent's work, commits and comments show as @g1t, and nobody can claim g1t or g1t-agent173 agent: "g1t",
Mission control counts people's own changes as theirs; a shorter sidebar with setup under Settings, and a 56px top bar174 authoredByAgent,
Mission control shows where you are needed and what agents landed without you; git answers in about 200ms175 mergedBy,
176 mergedAt: new Date(NOW - daysAgo * DAY).toISOString(),
177 files: [],
178});
179
Merge leftovers: plan activity filtered in the query, pushes counted by account, ghost during the deletion window, profile time zones (identity 0039)180test("a push to the default branch counts a person's own commits, not merges or g1t's", () => {
181 const c = (hash: string, email: string, parents = 1) => ({ hash, author: { name: "g1t", email }, parents: Array(parents).fill("p") });
182 // Every commit is named "g1t": the name decides nothing, the address does.
183 const history = [c("e", "chase@example.com"), c("d", "agent@g1t.sh"), c("m", "chase@example.com", 2), c("b", "chase@example.com"), c("a", "chase@example.com")];
184 const byG1t = (commit: { author: { email: string } }) => commit.author.email === "agent@g1t.sh";
185 assert.deepEqual(pushedCommits(history, "a", byG1t).map((x) => x.hash), ["e", "b"]);
Mission control counts people's direct pushes to the default branch186 // Where it pointed before was not read: everything read counts.
Merge leftovers: plan activity filtered in the query, pushes counted by account, ghost during the deletion window, profile time zones (identity 0039)187 assert.deepEqual(pushedCommits(history, "zz", byG1t).map((x) => x.hash), ["e", "b", "a"]);
188});
189
190test("who pushed is the account that signed in, not the name on the commits", () => {
191 assert.ok(pushedByPerson({ actor: "usr_chase", data: {} }));
192 assert.ok(pushedByPerson({ actor: null, data: {} }));
193 assert.ok(!pushedByPerson({ actor: "usr_g1t_agent", data: {} }));
194 assert.ok(!pushedByPerson({ actor: "g1t_policy", data: {} }));
195 // A workflow job's own token is not a person either.
196 assert.ok(!pushedByPerson({ actor: "usr_chase", data: { causedByJob: "run_1" } }));
197
198 const c = (hash: string, name: string) => ({ hash, parents: ["p"], author: { name, email: `${hash}@example.com` } });
199 // A person whose git name is "g1t" pushed m1; g1t pushed w1 under a person's name.
200 const history = [c("w1", "Chase Pierce"), c("m1", "g1t"), c("old", "Chase Pierce")];
201 const pushes = [
202 { time: "2026-10-07T12:00:00Z", actor: "usr_g1t_agent", data: { after: "w1", before: "m1" } },
203 { time: "2026-10-05T12:00:00Z", actor: "usr_chase", data: { after: "m1", before: "old" } },
204 ];
205 assert.deepEqual(placePushes(history, pushes), [{ hash: "m1", at: "2026-10-05T12:00:00Z" }]);
Mission control counts people's direct pushes to the default branch206});
207
Merge branch 'worktree-agent-ab9543c492a7ed481' into spend-guardrails208test("a short read of the branch is enough when it reaches the oldest push", () => {
209 const h = (...hashes: string[]) => hashes.map((hash) => ({ hash }));
210 const pushes = [
211 { time: "2026-10-07T12:00:00Z", data: { after: "c1", before: "c2" } },
212 { time: "2026-10-05T12:00:00Z", data: { after: "c2", before: "c3" } },
213 ];
214 // Holds the oldest push's before.
215 assert.ok(historyCovers(h("c1", "c2", "c3"), pushes, 3));
216 // Full, and the oldest push reaches past it: read further.
217 assert.ok(!historyCovers(h("c1", "c2", "x"), pushes, 3));
218 // Shorter than asked: the whole branch.
219 assert.ok(historyCovers(h("c1", "c2"), pushes, 3));
220 // The oldest push made the branch: only the whole branch will do.
221 assert.ok(!historyCovers(h("c1", "c2", "c3"), [{ time: "", data: { after: "c1" } }], 3));
222});
223
Mission control shows where you are needed and what agents landed without you; git answers in about 200ms224test("a change landed without a person when g1t merged it", () => {
225 assert.ok(landedByAgents({ mergedBy: "g1t" }));
g1t is one name: its agent's work, commits and comments show as @g1t, and nobody can claim g1t or g1t-agent226 assert.ok(landedByAgents({ mergedBy: "g1t" }));
Mission control shows where you are needed and what agents landed without you; git answers in about 200ms227 assert.ok(landedByAgents({ mergedBy: null }));
228 assert.ok(!landedByAgents({ mergedBy: "syntaqx" }));
229});
230
Mission control counts people's own changes as theirs; a shorter sidebar with setup under Settings, and a 56px top bar231test("the week is seven days, each split by who did the work, with the week before", () => {
Mission control shows where you are needed and what agents landed without you; git answers in about 200ms232 const week = weekOf(
Mission control counts people's own changes as theirs; a shorter sidebar with setup under Settings, and a 56px top bar233 [
234 merged(0, "g1t"),
235 merged(0, "syntaqx"),
236 // A person's own change, merged by them and auto-merged by g1t: both theirs.
237 merged(0, "syntaqx", 2, false),
238 merged(1, "g1t", 3, false),
239 merged(1, "g1t"),
240 merged(6, "g1t"),
241 merged(8, "g1t"),
242 merged(10, "alex"),
243 merged(20, "g1t"),
244 ],
Mission control shows where you are needed and what agents landed without you; git answers in about 200ms245 NOW,
246 "UTC",
247 );
248 assert.equal(week.days.length, 7);
249 assert.equal(week.days[6].key, "2026-10-05");
250 assert.equal(week.days[6].label, "Mon");
251 assert.deepEqual(
Mission control counts people's own changes as theirs; a shorter sidebar with setup under Settings, and a 56px top bar252 week.days.map((d) => [d.agents, d.assisted, d.people]),
253 [[1, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [1, 0, 1], [1, 1, 1]],
Mission control shows where you are needed and what agents landed without you; git answers in about 200ms254 );
Mission control counts people's own changes as theirs; a shorter sidebar with setup under Settings, and a 56px top bar255 assert.equal(week.total, 6);
Mission control shows where you are needed and what agents landed without you; git answers in about 200ms256 assert.equal(week.byAgents, 3);
Mission control counts people's own changes as theirs; a shorter sidebar with setup under Settings, and a 56px top bar257 assert.equal(week.agentChanges, 4);
258 assert.equal(week.people, 2);
Mission control shows where you are needed and what agents landed without you; git answers in about 200ms259 assert.equal(week.previous, 2);
260 // Not knowing the week before is not the same as nothing in it.
261 assert.equal(weekOf([merged(0, "g1t")], NOW, "UTC", false).previous, null);
262});
263
264test("days follow the viewer's time zone", () => {
265 // 02:00 UTC on the 5th is still the 4th in Los Angeles.
266 const late = Date.parse("2026-10-05T02:00:00Z");
267 assert.equal(dayKey(late, "America/Los_Angeles"), "2026-10-04");
268 assert.equal(dayKey(late, "UTC"), "2026-10-05");
269 assert.equal(dayKey(late, "Not/AZone"), "2026-10-05");
Mission control counts people's own changes as theirs; a shorter sidebar with setup under Settings, and a 56px top bar270 const week = weekOf([{ mergedAt: new Date(late).toISOString(), mergedBy: "g1t", authoredByAgent: true }], NOW, "America/Los_Angeles");
Mission control shows where you are needed and what agents landed without you; git answers in about 200ms271 assert.equal(week.days.find((d) => d.key === "2026-10-04")?.agents, 1);
272});
273
274test("the change from last week, and how it reads", () => {
275 assert.equal(change(12, 10), 0.2);
276 assert.equal(change(5, 0), null);
277 assert.equal(change(5, null), null);
278 assert.equal(signedPercent(0.2), "+20%");
279 assert.equal(signedPercent(-0.054), "−5%");
280 assert.equal(signedPercent(0.001), "0%");
281});
282
283test("a repository's merged list reaches back when it is not full or its oldest is old enough", () => {
284 const since = NOW - 14 * DAY;
285 const at = (days: number) => ({ mergedAt: new Date(NOW - days * DAY).toISOString(), updatedAt: new Date(NOW).toISOString() });
286 assert.ok(reachesBack([at(1), at(2)], since, 100));
287 assert.ok(reachesBack([at(1), at(20)], since, 2));
288 assert.ok(!reachesBack([at(1), at(3)], since, 2));
289});
290
291test("landed today is the viewer's calendar day, newest first", () => {
292 const rows = landedToday([merged(0.1, "g1t", 3), merged(0.5, "syntaqx", 4), merged(1, "g1t", 2)], NOW, "UTC");
293 assert.deepEqual(
294 rows.map((r) => [r.ref, r.byAgents]),
295 [
296 ["#3", true],
297 ["#4", false],
298 ],
299 );
300 assert.equal(rows[1].by?.name, "syntaqx");
301});
302
303test("waiting on agents holds each pull request once, running ones first, and nothing that needs you", () => {
304 const pull = (number: number, minutesAgo: number) => ({
305 number,
306 title: `Pull ${number}`,
g1t is one name: its agent's work, commits and comments show as @g1t, and nobody can claim g1t or g1t-agent307 agent: "g1t",
Mission control shows where you are needed and what agents landed without you; git answers in about 200ms308 updatedAt: new Date(NOW - minutesAgo * 60_000).toISOString(),
309 checkStatus: null,
310 files: [],
311 });
312 const rows = waitingRows({
313 active: [
Fast pages, required checks on the branch, self-hosted runners, honest incidents314 { pull: pull(1, 30), lifecycle: { stage: "checking", detail: "Waiting for CI / pull_request to finish.", revisions: 0 }, repo },
Mission control shows where you are needed and what agents landed without you; git answers in about 200ms315 { pull: pull(2, 5), lifecycle: { stage: "needs_you", detail: "Stopped.", revisions: 0 }, repo },
316 { pull: pull(3, 50), lifecycle: { stage: "queued", detail: "In the merge queue.", revisions: 0 }, repo },
317 { pull: pull(9, 1), lifecycle: { stage: "reviewing", detail: "Reviewing.", revisions: 0 }, repo },
318 ],
319 live: [
320 {
321 id: "r1",
322 repo,
323 number: 3,
324 title: "Pull 3",
325 kind: "update",
g1t is one name: its agent's work, commits and comments show as @g1t, and nobody can claim g1t or g1t-agent326 agent: "g1t",
Mission control shows where you are needed and what agents landed without you; git answers in about 200ms327 step: "Merging main in",
328 costUsd: 0.1,
329 startedAt: new Date(NOW - 60_000).toISOString(),
330 createdAt: new Date(NOW - 60_000).toISOString(),
331 updatedAt: new Date(NOW - 10_000).toISOString(),
332 },
333 {
334 id: "r2",
335 repo,
336 number: null,
337 title: null,
338 kind: "plan",
g1t is one name: its agent's work, commits and comments show as @g1t, and nobody can claim g1t or g1t-agent339 agent: "g1t",
Mission control shows where you are needed and what agents landed without you; git answers in about 200ms340 step: null,
341 costUsd: null,
342 startedAt: null,
343 createdAt: new Date(NOW - 120_000).toISOString(),
344 updatedAt: new Date(NOW - 120_000).toISOString(),
345 },
346 ],
347 drafts: [
348 { ...pull(1, 30), repo },
349 { ...pull(4, 20), repo },
350 { ...pull(5, 20), agent: "syntaqx", repo },
351 ],
352 needKeys: new Set(["acme/web#9"]),
353 });
354 assert.deepEqual(
355 rows.map((r) => [r.ref, r.chip, r.live]),
356 [
357 ["#3", "In queue", true],
358 [null, "Planning", true],
359 ["#4", "Working", false],
360 ["#1", "Checking", false],
361 ],
362 );
363 assert.equal(rows[0].detail, "Merging main in");
364 assert.equal(rows[0].run, "/acme/web/agents/runs/r1");
365 assert.equal(rows[1].title, "Planning in web");
366});
367
368test("tabs and sorting come from the address", () => {
369 assert.equal(parseTab("waiting"), "waiting");
370 assert.equal(parseTab("nope"), null);
371 assert.equal(parseSort("newest"), "newest");
372 assert.equal(parseSort(null), "impact");
373 const rows = [{ at: 1 }, { at: 3 }, { at: 2 }];
374 assert.deepEqual(sortRows(rows, "impact"), rows);
375 assert.deepEqual(
376 sortRows(rows, "newest").map((r) => r.at),
377 [3, 2, 1],
378 );
379});
380
381test("the summary says the week honestly", () => {
Mission control counts people's own changes as theirs; a shorter sidebar with setup under Settings, and a 56px top bar382 const none = { total: 0, byAgents: 0, agentChanges: 0, people: 0, live: 0, needs: 0 };
383 assert.equal(
384 summaryLine({ ...none, total: 47, byAgents: 39, agentChanges: 47 }),
385 "Agents landed 39 of their 47 changes this week without you.",
386 );
387 assert.equal(
388 summaryLine({ ...none, total: 3, byAgents: 3, agentChanges: 3 }),
389 "Agents landed all 3 changes of theirs this week without you.",
390 );
391 assert.equal(
392 summaryLine({ ...none, total: 2, agentChanges: 2 }),
393 "Agents made 2 changes this week, each merged by a person.",
394 );
395 // People's own work is counted as theirs, never as agents' that needed help.
396 assert.equal(
397 summaryLine({ ...none, total: 7, byAgents: 4, agentChanges: 5, people: 2 }),
398 "Agents landed 4 of their 5 changes this week without you, and people landed 2 changes of their own.",
399 );
400 assert.equal(summaryLine({ ...none, total: 3, people: 3 }), "People landed 3 changes this week; none were agents'.");
401 assert.equal(summaryLine({ ...none, live: 1 }), "1 agent is at work. Nothing has landed this week yet.");
402 assert.match(summaryLine(none), /Assign an issue/);
Mission control shows where you are needed and what agents landed without you; git answers in about 200ms403});
Usage, Billing settings and prepaid AI credit; fixes from the UX audit404
405test("a job waiting for a self-hosted runner says so, not that an agent went quiet", () => {
406 const runner = { kind: "runner" as const, detail: "No runner with labels self-hosted, docker is online." };
407 assert.equal(reasonFor(runner), "stalled");
408 const why = whyFor(reasonFor(runner), runner);
409 assert.match(why, /self-hosted runner/);
410 assert.doesNotMatch(why, /agent/);
411});
Merge branch 'main' into actions-toolkit-oidc-artifacts412
413test("each push to the default branch places the commits it brought, at its time, from one read of the history", () => {
Merge leftovers: plan activity filtered in the query, pushes counted by account, ghost during the deletion window, profile time zones (identity 0039)414 const c = (hash: string, parents = ["p"], email = "chase@example.com") => ({ hash, parents, author: { name: "Chase Pierce", email } });
Merge branch 'main' into actions-toolkit-oidc-artifacts415 // Newest first: a Wednesday push of two, a Monday push of one, a merge, and g1t's own commit.
Merge leftovers: plan activity filtered in the query, pushes counted by account, ghost during the deletion window, profile time zones (identity 0039)416 const history = [c("w2"), c("w1"), c("m1"), c("merge", ["a", "b"]), c("bot", ["p"], "g1t@users.noreply.g1t.sh"), c("old")];
Merge branch 'main' into actions-toolkit-oidc-artifacts417 const pushes = [
Merge leftovers: plan activity filtered in the query, pushes counted by account, ghost during the deletion window, profile time zones (identity 0039)418 { time: "2026-10-07T12:00:00Z", actor: "usr_chase", data: { after: "w2", before: "m1" } },
419 { time: "2026-10-05T12:00:00Z", actor: "usr_chase", data: { after: "m1", before: "old" } },
420 { time: "2026-10-01T12:00:00Z", actor: "usr_chase", data: { after: "gone", before: "older" } },
Merge branch 'main' into actions-toolkit-oidc-artifacts421 ];
Merge leftovers: plan activity filtered in the query, pushes counted by account, ghost during the deletion window, profile time zones (identity 0039)422 const byG1t = (commit: { author: { email: string } }) => commit.author.email.endsWith("@users.noreply.g1t.sh");
423 assert.deepEqual(placePushes(history, pushes, byG1t), [
Merge branch 'main' into actions-toolkit-oidc-artifacts424 { hash: "m1", at: "2026-10-05T12:00:00Z" },
425 { hash: "w2", at: "2026-10-07T12:00:00Z" },
426 { hash: "w1", at: "2026-10-07T12:00:00Z" },
427 ]);
428});

This file's history is long; its oldest lines are credited to the oldest commit read.