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.

g1t.sh
244 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.

The plan says what g1t is for without measuring it against other products1import 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,
The plan says what g1t is for without measuring it against other products8 change,
9 checksFact,
10 dayKey,
11 isTestFile,
12 landedToday,
The site no longer has g1t's own agents. g1t is where the coding agents you already use do their work, so the Agents mode is gone from the rail, with every page under /<workspace>/-/agents: personas, faces, skills, abilities, routines, computers, sessions and agent spend. Customize (skills, connectors, plugins, marketplaces), the context hub, model providers, the AI Gateway page, the Spend page and pill, Ask g1t, and the repository's Agents, Plans and agent settings pages go too, and their addresses now answer 404.13 mergedAutomatically,
The plan says what g1t is for without measuring it against other products14 parseSort,
15 parseTab,
16 pullFacts,
17 reachesBack,
18 reasonFor,
19 signedPercent,
20 sortRows,
21 summaryLine,
Merge leftovers: plan activity filtered in the query, pushes counted by account, ghost during the deletion window, profile time zones (identity 0039)22 pushedByPerson,
The plan says what g1t is for without measuring it against other products23 pushedCommits,
24 weekOf,
25 whyFor,
26} from "./mission-control.ts";
27
28const HOUR = 3_600_000;
29const DAY = 24 * HOUR;
30// Monday 2026-10-05, 18:00 UTC.
31const NOW = Date.parse("2026-10-05T18:00:00Z");
32const repo = { namespace: "acme", name: "web" };
33
34test("each kind of need gets its reason chip", () => {
The site no longer has g1t's own agents. g1t is where the coding agents you already use do their work, so the Agents mode is gone from the rail, with every page under /<workspace>/-/agents: personas, faces, skills, abilities, routines, computers, sessions and agent spend. Customize (skills, connectors, plugins, marketplaces), the context hub, model providers, the AI Gateway page, the Spend page and pill, Ask g1t, and the repository's Agents, Plans and agent settings pages go too, and their addresses now answer 404.35 assert.equal(reasonFor({ kind: "deploy" }), "blocking");
36 assert.equal(reasonFor({ kind: "review" }), "needs_review");
37 assert.equal(reasonFor({ kind: "invitation" }), "invited");
38 assert.equal(reasonFor({ kind: "checks" }), "checks_failing");
39 assert.equal(reasonFor({ kind: "runner" }), "stalled");
The plan says what g1t is for without measuring it against other products40});
41
42test("why a need needs a person is said for every reason", () => {
The site no longer has g1t's own agents. g1t is where the coding agents you already use do their work, so the Agents mode is gone from the rail, with every page under /<workspace>/-/agents: personas, faces, skills, abilities, routines, computers, sessions and agent spend. Customize (skills, connectors, plugins, marketplaces), the context hub, model providers, the AI Gateway page, the Spend page and pill, Ask g1t, and the repository's Agents, Plans and agent settings pages go too, and their addresses now answer 404.43 for (const kind of ["deploy", "invitation", "review", "stuck", "checks", "ready", "conflict", "stalled", "runner"] as const) {
44 const need = { kind };
45 assert.ok(whyFor(reasonFor(need), need).length > 15, kind);
The plan says what g1t is for without measuring it against other products46 }
47});
48
The site no longer has g1t's own agents. g1t is where the coding agents you already use do their work, so the Agents mode is gone from the rail, with every page under /<workspace>/-/agents: personas, faces, skills, abilities, routines, computers, sessions and agent spend. Customize (skills, connectors, plugins, marketplaces), the context hub, model providers, the AI Gateway page, the Spend page and pill, Ask g1t, and the repository's Agents, Plans and agent settings pages go too, and their addresses now answer 404.49test("what is known lists only what is known", () => {
The plan says what g1t is for without measuring it against other products50 const facts = pullFacts({
51 checkStatus: "failed",
52 files: [
53 { path: "src/retry.ts", additions: 40, deletions: 2 },
54 { path: "src/retry.test.ts", additions: 60, deletions: 0 },
55 ],
56 });
57 const by = Object.fromEntries(facts.map((f) => [f.label, f]));
58 assert.equal(by["Required checks"].value, "Failed in the merge queue");
59 assert.equal(by["Required checks"].tone, "bad");
60 assert.equal(by["Files changed"].value, "2");
61 assert.equal(by.Lines.value, "+100 −2");
62 assert.equal(by.Tests.value, "1 file");
63
64 const bare = pullFacts({ checkStatus: null, files: [] });
65 assert.deepEqual(bare, [{ label: "Required checks", value: "Not known yet", tone: null }]);
66});
67
The site no longer has g1t's own agents. g1t is where the coding agents you already use do their work, so the Agents mode is gone from the rail, with every page under /<workspace>/-/agents: personas, faces, skills, abilities, routines, computers, sessions and agent spend. Customize (skills, connectors, plugins, marketplaces), the context hub, model providers, the AI Gateway page, the Spend page and pill, Ask g1t, and the repository's Agents, Plans and agent settings pages go too, and their addresses now answer 404.68test("the required checks are read from the pull request's check status", () => {
69 assert.deepEqual(checksFact("running"), { label: "Required checks", value: "Running", tone: null });
70 assert.equal(checksFact("passed").tone, "good");
71 assert.equal(checksFact("failed").value, "Failed in the merge queue");
The plan says what g1t is for without measuring it against other products72});
73
74test("test files are recognised by the names test runners use", () => {
75 assert.ok(isTestFile("src/a.test.ts"));
76 assert.ok(isTestFile("src/__tests__/a.ts"));
77 assert.ok(isTestFile("tests/api.rs"));
78 assert.ok(isTestFile("pkg/store_test.go"));
79 assert.ok(!isTestFile("src/testing-utils.ts"));
80 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 were81 assert.ok(isTestFile("test.js"));
82 assert.ok(isTestFile("lib/spec.rb"));
The plan says what g1t is for without measuring it against other products83});
84
The site no longer has g1t's own agents. g1t is where the coding agents you already use do their work, so the Agents mode is gone from the rail, with every page under /<workspace>/-/agents: personas, faces, skills, abilities, routines, computers, sessions and agent spend. Customize (skills, connectors, plugins, marketplaces), the context hub, model providers, the AI Gateway page, the Spend page and pill, Ask g1t, and the repository's Agents, Plans and agent settings pages go too, and their addresses now answer 404.85const merged = (daysAgo: number, mergedBy: string | null, number = 1): Merged => ({
The plan says what g1t is for without measuring it against other products86 repo,
87 number,
88 title: `Change ${number}`,
89 mergedBy,
90 mergedAt: new Date(NOW - daysAgo * DAY).toISOString(),
91 files: [],
92});
93
Merge leftovers: plan activity filtered in the query, pushes counted by account, ghost during the deletion window, profile time zones (identity 0039)94test("a push to the default branch counts a person's own commits, not merges or g1t's", () => {
95 const c = (hash: string, email: string, parents = 1) => ({ hash, author: { name: "g1t", email }, parents: Array(parents).fill("p") });
96 // Every commit is named "g1t": the name decides nothing, the address does.
97 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")];
98 const byG1t = (commit: { author: { email: string } }) => commit.author.email === "agent@g1t.sh";
99 assert.deepEqual(pushedCommits(history, "a", byG1t).map((x) => x.hash), ["e", "b"]);
The plan says what g1t is for without measuring it against other products100 // 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)101 assert.deepEqual(pushedCommits(history, "zz", byG1t).map((x) => x.hash), ["e", "b", "a"]);
102});
103
104test("who pushed is the account that signed in, not the name on the commits", () => {
105 assert.ok(pushedByPerson({ actor: "usr_chase", data: {} }));
106 assert.ok(pushedByPerson({ actor: null, data: {} }));
107 assert.ok(!pushedByPerson({ actor: "usr_g1t_agent", data: {} }));
108 assert.ok(!pushedByPerson({ actor: "g1t_policy", data: {} }));
109 // A workflow job's own token is not a person either.
110 assert.ok(!pushedByPerson({ actor: "usr_chase", data: { causedByJob: "run_1" } }));
111
112 const c = (hash: string, name: string) => ({ hash, parents: ["p"], author: { name, email: `${hash}@example.com` } });
113 // A person whose git name is "g1t" pushed m1; g1t pushed w1 under a person's name.
114 const history = [c("w1", "Chase Pierce"), c("m1", "g1t"), c("old", "Chase Pierce")];
115 const pushes = [
116 { time: "2026-10-07T12:00:00Z", actor: "usr_g1t_agent", data: { after: "w1", before: "m1" } },
117 { time: "2026-10-05T12:00:00Z", actor: "usr_chase", data: { after: "m1", before: "old" } },
118 ];
119 assert.deepEqual(placePushes(history, pushes), [{ hash: "m1", at: "2026-10-05T12:00:00Z" }]);
The plan says what g1t is for without measuring it against other products120});
121
Merge branch 'worktree-agent-ab9543c492a7ed481' into spend-guardrails122test("a short read of the branch is enough when it reaches the oldest push", () => {
123 const h = (...hashes: string[]) => hashes.map((hash) => ({ hash }));
124 const pushes = [
125 { time: "2026-10-07T12:00:00Z", data: { after: "c1", before: "c2" } },
126 { time: "2026-10-05T12:00:00Z", data: { after: "c2", before: "c3" } },
127 ];
128 // Holds the oldest push's before.
129 assert.ok(historyCovers(h("c1", "c2", "c3"), pushes, 3));
130 // Full, and the oldest push reaches past it: read further.
131 assert.ok(!historyCovers(h("c1", "c2", "x"), pushes, 3));
132 // Shorter than asked: the whole branch.
133 assert.ok(historyCovers(h("c1", "c2"), pushes, 3));
134 // The oldest push made the branch: only the whole branch will do.
135 assert.ok(!historyCovers(h("c1", "c2", "c3"), [{ time: "", data: { after: "c1" } }], 3));
136});
137
The site no longer has g1t's own agents. g1t is where the coding agents you already use do their work, so the Agents mode is gone from the rail, with every page under /<workspace>/-/agents: personas, faces, skills, abilities, routines, computers, sessions and agent spend. Customize (skills, connectors, plugins, marketplaces), the context hub, model providers, the AI Gateway page, the Spend page and pill, Ask g1t, and the repository's Agents, Plans and agent settings pages go too, and their addresses now answer 404.138test("each push to the default branch places the commits it brought, at its time, from one read of the history", () => {
139 const c = (hash: string, parents = ["p"], email = "chase@example.com") => ({ hash, parents, author: { name: "Chase Pierce", email } });
140 // Newest first: a Wednesday push of two, a Monday push of one, a merge, and g1t's own commit.
141 const history = [c("w2"), c("w1"), c("m1"), c("merge", ["a", "b"]), c("bot", ["p"], "g1t@users.noreply.g1t.sh"), c("old")];
142 const pushes = [
143 { time: "2026-10-07T12:00:00Z", actor: "usr_chase", data: { after: "w2", before: "m1" } },
144 { time: "2026-10-05T12:00:00Z", actor: "usr_chase", data: { after: "m1", before: "old" } },
145 { time: "2026-10-01T12:00:00Z", actor: "usr_chase", data: { after: "gone", before: "older" } },
146 ];
147 const byG1t = (commit: { author: { email: string } }) => commit.author.email.endsWith("@users.noreply.g1t.sh");
148 assert.deepEqual(placePushes(history, pushes, byG1t), [
149 { hash: "m1", at: "2026-10-05T12:00:00Z" },
150 { hash: "w2", at: "2026-10-07T12:00:00Z" },
151 { hash: "w1", at: "2026-10-07T12:00:00Z" },
152 ]);
153});
154
155test("a change merged automatically when g1t merged it", () => {
156 assert.ok(mergedAutomatically({ mergedBy: "g1t" }));
157 assert.ok(mergedAutomatically({ mergedBy: null }));
158 assert.ok(!mergedAutomatically({ mergedBy: "syntaqx" }));
The plan says what g1t is for without measuring it against other products159});
160
The site no longer has g1t's own agents. g1t is where the coding agents you already use do their work, so the Agents mode is gone from the rail, with every page under /<workspace>/-/agents: personas, faces, skills, abilities, routines, computers, sessions and agent spend. Customize (skills, connectors, plugins, marketplaces), the context hub, model providers, the AI Gateway page, the Spend page and pill, Ask g1t, and the repository's Agents, Plans and agent settings pages go too, and their addresses now answer 404.161test("the week is seven days of landed changes, with the week before", () => {
The plan says what g1t is for without measuring it against other products162 const week = weekOf(
The site no longer has g1t's own agents. g1t is where the coding agents you already use do their work, so the Agents mode is gone from the rail, with every page under /<workspace>/-/agents: personas, faces, skills, abilities, routines, computers, sessions and agent spend. Customize (skills, connectors, plugins, marketplaces), the context hub, model providers, the AI Gateway page, the Spend page and pill, Ask g1t, and the repository's Agents, Plans and agent settings pages go too, and their addresses now answer 404.163 [merged(0, "g1t"), merged(0, "syntaqx"), merged(0, "syntaqx", 2), merged(1, "g1t", 3), merged(1, "g1t"), merged(6, "g1t"), merged(8, "g1t"), merged(10, "alex"), merged(20, "g1t")],
The plan says what g1t is for without measuring it against other products164 NOW,
165 "UTC",
166 );
167 assert.equal(week.days.length, 7);
168 assert.equal(week.days[6].key, "2026-10-05");
169 assert.equal(week.days[6].label, "Mon");
170 assert.deepEqual(
The site no longer has g1t's own agents. g1t is where the coding agents you already use do their work, so the Agents mode is gone from the rail, with every page under /<workspace>/-/agents: personas, faces, skills, abilities, routines, computers, sessions and agent spend. Customize (skills, connectors, plugins, marketplaces), the context hub, model providers, the AI Gateway page, the Spend page and pill, Ask g1t, and the repository's Agents, Plans and agent settings pages go too, and their addresses now answer 404.171 week.days.map((d) => d.count),
172 [1, 0, 0, 0, 0, 2, 3],
The plan says what g1t is for without measuring it against other products173 );
174 assert.equal(week.total, 6);
175 assert.equal(week.previous, 2);
176 // Not knowing the week before is not the same as nothing in it.
177 assert.equal(weekOf([merged(0, "g1t")], NOW, "UTC", false).previous, null);
178});
179
180test("days follow the viewer's time zone", () => {
181 // 02:00 UTC on the 5th is still the 4th in Los Angeles.
182 const late = Date.parse("2026-10-05T02:00:00Z");
183 assert.equal(dayKey(late, "America/Los_Angeles"), "2026-10-04");
184 assert.equal(dayKey(late, "UTC"), "2026-10-05");
185 assert.equal(dayKey(late, "Not/AZone"), "2026-10-05");
The site no longer has g1t's own agents. g1t is where the coding agents you already use do their work, so the Agents mode is gone from the rail, with every page under /<workspace>/-/agents: personas, faces, skills, abilities, routines, computers, sessions and agent spend. Customize (skills, connectors, plugins, marketplaces), the context hub, model providers, the AI Gateway page, the Spend page and pill, Ask g1t, and the repository's Agents, Plans and agent settings pages go too, and their addresses now answer 404.186 const week = weekOf([{ mergedAt: new Date(late).toISOString() }], NOW, "America/Los_Angeles");
187 assert.equal(week.days.find((d) => d.key === "2026-10-04")?.count, 1);
The plan says what g1t is for without measuring it against other products188});
189
190test("the change from last week, and how it reads", () => {
191 assert.equal(change(12, 10), 0.2);
192 assert.equal(change(5, 0), null);
193 assert.equal(change(5, null), null);
194 assert.equal(signedPercent(0.2), "+20%");
195 assert.equal(signedPercent(-0.054), "−5%");
196 assert.equal(signedPercent(0.001), "0%");
197});
198
199test("a repository's merged list reaches back when it is not full or its oldest is old enough", () => {
200 const since = NOW - 14 * DAY;
201 const at = (days: number) => ({ mergedAt: new Date(NOW - days * DAY).toISOString(), updatedAt: new Date(NOW).toISOString() });
202 assert.ok(reachesBack([at(1), at(2)], since, 100));
203 assert.ok(reachesBack([at(1), at(20)], since, 2));
204 assert.ok(!reachesBack([at(1), at(3)], since, 2));
205});
206
207test("landed today is the viewer's calendar day, newest first", () => {
208 const rows = landedToday([merged(0.1, "g1t", 3), merged(0.5, "syntaqx", 4), merged(1, "g1t", 2)], NOW, "UTC");
209 assert.deepEqual(
The site no longer has g1t's own agents. g1t is where the coding agents you already use do their work, so the Agents mode is gone from the rail, with every page under /<workspace>/-/agents: personas, faces, skills, abilities, routines, computers, sessions and agent spend. Customize (skills, connectors, plugins, marketplaces), the context hub, model providers, the AI Gateway page, the Spend page and pill, Ask g1t, and the repository's Agents, Plans and agent settings pages go too, and their addresses now answer 404.210 rows.map((r) => [r.ref, r.automatic]),
The plan says what g1t is for without measuring it against other products211 [
212 ["#3", true],
213 ["#4", false],
214 ],
215 );
216 assert.equal(rows[1].by?.name, "syntaqx");
217});
218
219test("tabs and sorting come from the address", () => {
The site no longer has g1t's own agents. g1t is where the coding agents you already use do their work, so the Agents mode is gone from the rail, with every page under /<workspace>/-/agents: personas, faces, skills, abilities, routines, computers, sessions and agent spend. Customize (skills, connectors, plugins, marketplaces), the context hub, model providers, the AI Gateway page, the Spend page and pill, Ask g1t, and the repository's Agents, Plans and agent settings pages go too, and their addresses now answer 404.220 assert.equal(parseTab("landed"), "landed");
221 assert.equal(parseTab("waiting"), null);
The plan says what g1t is for without measuring it against other products222 assert.equal(parseTab("nope"), null);
223 assert.equal(parseSort("newest"), "newest");
224 assert.equal(parseSort(null), "impact");
225 const rows = [{ at: 1 }, { at: 3 }, { at: 2 }];
226 assert.deepEqual(sortRows(rows, "impact"), rows);
227 assert.deepEqual(
228 sortRows(rows, "newest").map((r) => r.at),
229 [3, 2, 1],
230 );
231});
232
The site no longer has g1t's own agents. g1t is where the coding agents you already use do their work, so the Agents mode is gone from the rail, with every page under /<workspace>/-/agents: personas, faces, skills, abilities, routines, computers, sessions and agent spend. Customize (skills, connectors, plugins, marketplaces), the context hub, model providers, the AI Gateway page, the Spend page and pill, Ask g1t, and the repository's Agents, Plans and agent settings pages go too, and their addresses now answer 404.233test("the summary says the week plainly", () => {
234 assert.equal(summaryLine({ total: 47, needs: 0 }), "47 changes landed in the last 7 days.");
235 assert.equal(summaryLine({ total: 1, needs: 2 }), "1 change landed in the last 7 days.");
236 assert.equal(summaryLine({ total: 0, needs: 2 }), "Nothing has landed this week. What is waiting on you is below.");
237 assert.equal(summaryLine({ total: 0, needs: 0 }), "Nothing has landed this week yet.");
The plan says what g1t is for without measuring it against other products238});
Usage, Billing settings and prepaid AI credit; fixes from the UX audit239
The site no longer has g1t's own agents. g1t is where the coding agents you already use do their work, so the Agents mode is gone from the rail, with every page under /<workspace>/-/agents: personas, faces, skills, abilities, routines, computers, sessions and agent spend. Customize (skills, connectors, plugins, marketplaces), the context hub, model providers, the AI Gateway page, the Spend page and pill, Ask g1t, and the repository's Agents, Plans and agent settings pages go too, and their addresses now answer 404.240test("a job waiting for a self-hosted runner says so", () => {
241 const runner = { kind: "runner" as const };
Usage, Billing settings and prepaid AI credit; fixes from the UX audit242 assert.equal(reasonFor(runner), "stalled");
The site no longer has g1t's own agents. g1t is where the coding agents you already use do their work, so the Agents mode is gone from the rail, with every page under /<workspace>/-/agents: personas, faces, skills, abilities, routines, computers, sessions and agent spend. Customize (skills, connectors, plugins, marketplaces), the context hub, model providers, the AI Gateway page, the Spend page and pill, Ask g1t, and the repository's Agents, Plans and agent settings pages go too, and their addresses now answer 404.243 assert.match(whyFor(reasonFor(runner), runner), /self-hosted runner/);
Merge branch 'main' into actions-toolkit-oidc-artifacts244});

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