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 products | 1 | import assert from "node:assert/strict"; |
| 2 | import { test } from "node:test"; | |
| 3 | ||
| 4 | import { | |
| 5 | type Merged, | |
| Merge branch 'main' into actions-toolkit-oidc-artifacts | 6 | placePushes, |
| Merge branch 'worktree-agent-ab9543c492a7ed481' into spend-guardrails | 7 | historyCovers, |
| The plan says what g1t is for without measuring it against other products | 8 | 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 products | 14 | 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 products | 23 | pushedCommits, |
| 24 | weekOf, | |
| 25 | whyFor, | |
| 26 | } from "./mission-control.ts"; | |
| 27 | ||
| 28 | const HOUR = 3_600_000; | |
| 29 | const DAY = 24 * HOUR; | |
| 30 | // Monday 2026-10-05, 18:00 UTC. | |
| 31 | const NOW = Date.parse("2026-10-05T18:00:00Z"); | |
| 32 | const repo = { namespace: "acme", name: "web" }; | |
| 33 | ||
| 34 | test("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 products | 40 | }); |
| 41 | ||
| 42 | test("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 products | 46 | } |
| 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. | 49 | test("what is known lists only what is known", () => { |
| The plan says what g1t is for without measuring it against other products | 50 | 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. | 68 | test("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 products | 72 | }); |
| 73 | ||
| 74 | test("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 were | 81 | assert.ok(isTestFile("test.js")); |
| 82 | assert.ok(isTestFile("lib/spec.rb")); | |
| The plan says what g1t is for without measuring it against other products | 83 | }); |
| 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. | 85 | const merged = (daysAgo: number, mergedBy: string | null, number = 1): Merged => ({ |
| The plan says what g1t is for without measuring it against other products | 86 | 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) | 94 | test("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 products | 100 | // 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 | ||
| 104 | test("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 products | 120 | }); |
| 121 | ||
| Merge branch 'worktree-agent-ab9543c492a7ed481' into spend-guardrails | 122 | test("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. | 138 | test("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 | ||
| 155 | test("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 products | 159 | }); |
| 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. | 161 | test("the week is seven days of landed changes, with the week before", () => { |
| The plan says what g1t is for without measuring it against other products | 162 | 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 products | 164 | 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 products | 173 | ); |
| 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 | ||
| 180 | test("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 products | 188 | }); |
| 189 | ||
| 190 | test("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 | ||
| 199 | test("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 | ||
| 207 | test("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 products | 211 | [ |
| 212 | ["#3", true], | |
| 213 | ["#4", false], | |
| 214 | ], | |
| 215 | ); | |
| 216 | assert.equal(rows[1].by?.name, "syntaqx"); | |
| 217 | }); | |
| 218 | ||
| 219 | test("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 products | 222 | 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. | 233 | test("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 products | 238 | }); |
| Usage, Billing settings and prepaid AI credit; fixes from the UX audit | 239 | |
| 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. | 240 | test("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 audit | 242 | 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-artifacts | 244 | }); |
This file's history is long; its oldest lines are credited to the oldest commit read.