Skip to content
407 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.

Security matches the workspace's other pages and leaves out deleted repositories; every section has a name in the trail1/**
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.2 * The shaping behind Code's Overview: why each thing needs the viewer,
3 * what is known about it, the tabs, the week of landed changes, and the
4 * one sentence under the title. Pure, so it is tested on its own; it
Security matches the workspace's other pages and leaves out deleted repositories; every section has a name in the trail5 * imports only types.
6 */
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.7import type { CheckStatus, ChangedFile, RepoPath } from "@g1t/contracts";
Security matches the workspace's other pages and leaves out deleted repositories; every section has a name in the trail8
9import type { Need } from "./mission";
10
11const DAY = 24 * 60 * 60 * 1000;
12
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/** Accounts that are g1t's own machinery: `isAgent` in ./mission, kept here so this module imports only types. Older rows still name them. */
Security matches the workspace's other pages and leaves out deleted repositories; every section has a name in the trail14export function isAgent(name: string | null | undefined): boolean {
15 return name === "g1t" || (name ?? "").endsWith("-agent");
16}
17
18// --- Reasons ----------------------------------------------------------------
19
20/** Why something is waiting on a person, as the chip beside it says. */
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.21export type Reason = "blocking" | "invited" | "needs_review" | "checks_failing" | "stalled";
Security matches the workspace's other pages and leaves out deleted repositories; every section has a name in the trail22
23export const REASON_LABEL: Record<Reason, string> = {
24 blocking: "Blocking",
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.25 invited: "Invitation",
26 needs_review: "Review requested",
Security matches the workspace's other pages and leaves out deleted repositories; every section has a name in the trail27 checks_failing: "Checks failing",
28 stalled: "Stalled",
29};
30
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.31/** The reason a need is shown, from its kind. */
32export function reasonFor(need: Pick<Need, "kind">): Reason {
Security matches the workspace's other pages and leaves out deleted repositories; every section has a name in the trail33 switch (need.kind) {
34 case "deploy":
35 case "conflict":
36 return "blocking";
37 case "invitation":
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.38 return "invited";
Security matches the workspace's other pages and leaves out deleted repositories; every section has a name in the trail39 case "review":
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.40 case "ready":
41 return "needs_review";
Security matches the workspace's other pages and leaves out deleted repositories; every section has a name in the trail42 case "checks":
43 return "checks_failing";
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.44 case "stalled":
Security matches the workspace's other pages and leaves out deleted repositories; every section has a name in the trail45 case "stuck":
Usage, Billing settings and prepaid AI credit; fixes from the UX audit46 case "runner":
Security matches the workspace's other pages and leaves out deleted repositories; every section has a name in the trail47 return "stalled";
48 }
49}
50
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.51/** Why only a person can move it: the callout beside what is known. */
52export function whyFor(reason: Reason, need: Pick<Need, "kind">): string {
Security matches the workspace's other pages and leaves out deleted repositories; every section has a name in the trail53 if (need.kind === "deploy")
54 return "Production still serves the build before this one. Every push to the default branch builds again, so this fails until what broke is fixed.";
55 if (need.kind === "invitation") return "An invitation is to you. No one else can accept it.";
56 if (need.kind === "review") return "You were asked to review it by name, so it waits for your verdict.";
Usage, Billing settings and prepaid AI credit; fixes from the UX audit57 if (need.kind === "runner")
58 return "The job runs only on a self-hosted runner with those labels, and none is connected. It starts as soon as one is; nothing else picks it up.";
Security matches the workspace's other pages and leaves out deleted repositories; every section has a name in the trail59 switch (reason) {
60 case "blocking":
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.61 return "Nothing moves until someone decides how it lands, or whether it should.";
Security matches the workspace's other pages and leaves out deleted repositories; every section has a name in the trail62 case "checks_failing":
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.63 return "It was taken out of the merge queue because its checks failed with what was ahead of it. Push a fix, then merge it again.";
Security matches the workspace's other pages and leaves out deleted repositories; every section has a name in the trail64 case "needs_review":
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.65 return "It waits for a verdict before it can land.";
66 case "invited":
67 return "It is addressed to you.";
Security matches the workspace's other pages and leaves out deleted repositories; every section has a name in the trail68 case "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.69 return "It has stopped moving and needs a look.";
Security matches the workspace's other pages and leaves out deleted repositories; every section has a name in the trail70 }
71}
72
73/** Reasons where nothing moves until a person acts on it. */
74export const BLOCKING: ReadonlySet<Reason> = new Set<Reason>(["blocking"]);
75
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.76// --- What is known ----------------------------------------------------------
Security matches the workspace's other pages and leaves out deleted repositories; every section has a name in the trail77
78export type FactTone = "good" | "warn" | "bad" | null;
79/** One thing known; a `wide` one takes the whole row and wraps. */
80export type Fact = { label: string; value: string; tone: FactTone; wide?: boolean };
81
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.82/** How the checks the default branch requires stand on a pull request, from what a list knows without opening it. */
83export function checksFact(checkStatus: CheckStatus | null): Fact {
Security matches the workspace's other pages and leaves out deleted repositories; every section has a name in the trail84 const fact = (value: string, tone: FactTone): Fact => ({ label: "Required checks", value, tone });
85 if (checkStatus === "failed") return fact("Failed in the merge queue", "bad");
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.86 if (checkStatus === "passed") return fact("Passing", "good");
87 if (checkStatus === "queued" || checkStatus === "running") return fact("Running", null);
Security matches the workspace's other pages and leaves out deleted repositories; every section has a name in the trail88 return fact("Not known yet", null);
89}
90
91/** Test files, by the names test runners look for. */
92export function isTestFile(path: string): boolean {
A file named test.js or spec.rb counts as a test: confidence no longer says tests not added when they were93 return (
94 /(^|\/)(__tests__|tests?|spec)\//i.test(path) ||
95 /[._-](test|spec)\.[a-z0-9]+$/i.test(path) ||
96 /_test\.(go|rs|py)$/i.test(path) ||
97 // A file named for what it is: test.js, tests.py, spec.rb.
98 /(^|\/)(tests?|specs?)\.[a-z0-9]+$/i.test(path)
99 );
Security matches the workspace's other pages and leaves out deleted repositories; every section has a name in the trail100}
101
102const plural = (n: number, one: string, many = `${one}s`) => `${n.toLocaleString("en-US")} ${n === 1 ? one : many}`;
103
104/**
105 * What is known about a pull request without opening it: its checks, how
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.106 * much it changes and the tests it touches. Only what is known is listed.
Security matches the workspace's other pages and leaves out deleted repositories; every section has a name in the trail107 */
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.108export function pullFacts(input: { checkStatus: CheckStatus | null; files: ChangedFile[] }): Fact[] {
109 const facts: Fact[] = [checksFact(input.checkStatus)];
Security matches the workspace's other pages and leaves out deleted repositories; every section has a name in the trail110 if (input.files.length > 0) {
111 const added = input.files.reduce((sum, f) => sum + f.additions, 0);
112 const removed = input.files.reduce((sum, f) => sum + f.deletions, 0);
113 facts.push({ label: "Files changed", value: input.files.length.toLocaleString("en-US"), tone: null });
114 facts.push({ label: "Lines", value: `+${added.toLocaleString("en-US")} −${removed.toLocaleString("en-US")}`, tone: null });
115 const tests = input.files.filter((f) => isTestFile(f.path)).length;
116 facts.push({ label: "Tests", value: tests > 0 ? plural(tests, "file") : "None touched", tone: tests > 0 ? "good" : "warn" });
117 }
118 return facts;
119}
120
121// --- Rows -------------------------------------------------------------------
122
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.123/** Someone on a row: a person, or g1t itself on older rows. */
Security matches the workspace's other pages and leaves out deleted repositories; every section has a name in the trail124export type Who = { name: string; agent: boolean };
125
126export const who = (name: string | null | undefined): Who | null => (name ? { name, agent: isAgent(name) } : null);
127
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.128/** A form on the page that acts without leaving it. */
Security matches the workspace's other pages and leaves out deleted repositories; every section has a name in the trail129export type QuickAction = { label: string; to: string; fields: Record<string, string>; done: string };
130
131/** One thing that needs the viewer, with what is known about it. */
132export type NeedRow = {
133 key: string;
134 reason: Reason;
135 repo: RepoPath | null;
136 /** "#41", when it is an issue or pull request. */
137 ref: string | null;
138 title: string;
139 /** The ask, in one sentence. */
140 ask: string;
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.141 /** Who is waiting: the author, or the person who asked. */
Security matches the workspace's other pages and leaves out deleted repositories; every section has a name in the trail142 by: Who | null;
143 at: number;
144 to: string;
145 open: string;
146 facts: Fact[];
147 why: string;
148 quick: QuickAction | null;
149 /** Somewhere else to act, when that is the next step. */
150 link: { label: string; to: string } | null;
151};
152
153const pathKey = (repo: RepoPath, number: number | null) => `${repo.namespace}/${repo.name}#${number ?? "-"}`.toLowerCase();
154
155// --- Landed -----------------------------------------------------------------
156
Mission control counts people's direct pushes to the default branch157/**
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.158 * The accounts g1t itself acts as on the event log: the account older rows
159 * name, and the policy that merges and pushes for it. An event's `actor`
160 * is an account id, so this is what tells g1t apart, whatever name a
161 * commit carries.
Merge leftovers: plan activity filtered in the query, pushes counted by account, ghost during the deletion window, profile time zones (identity 0039)162 */
163export const G1T_ACCOUNT_IDS: ReadonlySet<string> = new Set(["usr_g1t_agent", "g1t_policy"]);
164
165/** A `git.push` from the log, as far as placing its commits needs it. */
166export type PushRecord = {
167 time: string;
168 /** The account that pushed; null when the log does not say. */
169 actor?: string | null;
170 data: { after: string; before?: string; causedByJob?: string };
171};
172
173/**
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.174 * Whether a person pushed: not g1t itself (by the account that signed in
175 * to push), and not a workflow job's own token.
Mission control counts people's direct pushes to the default branch176 */
Merge leftovers: plan activity filtered in the query, pushes counted by account, ghost during the deletion window, profile time zones (identity 0039)177export function pushedByPerson(push: Pick<PushRecord, "actor" | "data">): boolean {
178 if (push.data.causedByJob) return false;
179 return !(push.actor && G1T_ACCOUNT_IDS.has(push.actor));
180}
181
182/**
183 * The commits a person's push to the default branch brought, from the
184 * history at its `after` (newest first) back to its `before`: their own,
185 * not merges (a pull request landing) and not g1t's (`byG1t`: a commit
186 * g1t wrote, told by its author address, which a person may fast-forward
187 * onto the branch). A push whose `before` is not in what was read gives
188 * what was read. Who pushed is the caller's to decide (`pushedByPerson`);
189 * a commit's author name says nothing about it.
190 */
191export function pushedCommits<C extends { hash: string; parents: string[] }>(
Mission control counts people's direct pushes to the default branch192 history: C[],
193 before: string | undefined,
Merge leftovers: plan activity filtered in the query, pushes counted by account, ghost during the deletion window, profile time zones (identity 0039)194 byG1t: (commit: C) => boolean = () => false,
Mission control counts people's direct pushes to the default branch195): C[] {
196 const end = before ? history.findIndex((commit) => commit.hash === before) : -1;
197 const brought = end === -1 ? history : history.slice(0, end);
Merge leftovers: plan activity filtered in the query, pushes counted by account, ghost during the deletion window, profile time zones (identity 0039)198 return brought.filter((commit) => commit.parents.length <= 1 && !byG1t(commit));
Mission control counts people's direct pushes to the default branch199}
200
Merge branch 'main' into actions-toolkit-oidc-artifacts201/**
Merge leftovers: plan activity filtered in the query, pushes counted by account, ghost during the deletion window, profile time zones (identity 0039)202 * Each commit of `history` (newest first) a person's push in `pushes`
203 * (newest first) brought, at that push's time. A commit pushed twice
204 * (after a force push, say) counts once, at its first landing; a push
205 * whose `after` is no longer in the history (rewritten) brings nothing,
206 * and g1t's own pushes bring nothing here: pull requests count those.
Merge branch 'main' into actions-toolkit-oidc-artifacts207 */
Merge leftovers: plan activity filtered in the query, pushes counted by account, ghost during the deletion window, profile time zones (identity 0039)208export function placePushes<C extends { hash: string; parents: string[] }>(
Merge branch 'main' into actions-toolkit-oidc-artifacts209 history: C[],
Merge leftovers: plan activity filtered in the query, pushes counted by account, ghost during the deletion window, profile time zones (identity 0039)210 pushes: PushRecord[],
211 byG1t: (commit: C) => boolean = () => false,
Merge branch 'main' into actions-toolkit-oidc-artifacts212): { hash: string; at: string }[] {
213 const index = new Map(history.map((commit, i) => [commit.hash, i]));
Merge leftovers: plan activity filtered in the query, pushes counted by account, ghost during the deletion window, profile time zones (identity 0039)214 // Each commit's first landing: the time, or null when g1t landed it.
215 const seen = new Map<string, string | null>();
Merge branch 'main' into actions-toolkit-oidc-artifacts216 for (const push of [...pushes].reverse()) {
217 const start = index.get(push.data.after);
218 if (start === undefined) continue;
219 const end = push.data.before ? index.get(push.data.before) : undefined;
Merge leftovers: plan activity filtered in the query, pushes counted by account, ghost during the deletion window, profile time zones (identity 0039)220 const range = history.slice(start, end ?? history.length);
221 const at = pushedByPerson(push) ? push.time : null;
222 for (const commit of pushedCommits(range, undefined, byG1t)) {
223 if (!seen.has(commit.hash)) seen.set(commit.hash, at);
Merge branch 'main' into actions-toolkit-oidc-artifacts224 }
225 }
Merge leftovers: plan activity filtered in the query, pushes counted by account, ghost during the deletion window, profile time zones (identity 0039)226 return [...seen].flatMap(([hash, at]) => (at ? [{ hash, at }] : []));
Merge branch 'main' into actions-toolkit-oidc-artifacts227}
228
Merge branch 'worktree-agent-ab9543c492a7ed481' into spend-guardrails229/**
230 * Whether a read of the default branch reaches back far enough to place
231 * every push, newest first: it holds the oldest push's `before`, or it is
232 * the whole branch. A shorter read than `asked` is the whole branch.
233 */
234export function historyCovers(history: { hash: string }[], pushes: PushRecord[], asked: number): boolean {
235 if (history.length < asked) return true;
236 const oldest = pushes.at(-1)?.data.before;
237 return oldest != null && history.some((commit) => commit.hash === oldest);
238}
239
Merge leftovers: plan activity filtered in the query, pushes counted by account, ghost during the deletion window, profile time zones (identity 0039)240/** A merged pull request, as the week counts it. */
Security matches the workspace's other pages and leaves out deleted repositories; every section has a name in the trail241export type Merged = {
242 repo: RepoPath;
243 number: number;
244 title: string;
245 mergedBy: string | null;
246 mergedAt: string;
247 files: ChangedFile[];
248};
249
250/**
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.251 * Whether a change landed without anyone pressing merge: g1t merged it, by
252 * auto-merge or from the merge queue.
Security matches the workspace's other pages and leaves out deleted repositories; every section has a name in the trail253 */
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.254export function mergedAutomatically(change: Pick<Merged, "mergedBy">): boolean {
Security matches the workspace's other pages and leaves out deleted repositories; every section has a name in the trail255 return change.mergedBy == null || isAgent(change.mergedBy);
256}
257
258/** A day's date in a time zone, as `YYYY-MM-DD`; UTC when the zone is unknown. */
259export function dayKey(at: number, timeZone: string | null): string {
260 try {
261 return new Intl.DateTimeFormat("en-CA", { year: "numeric", month: "2-digit", day: "2-digit", timeZone: timeZone || "UTC" }).format(at);
262 } catch {
263 return new Date(at).toISOString().slice(0, 10);
264 }
265}
266
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.267/** One day's landed changes. */
268export type WeekDay = { key: string; label: string; count: number };
Security matches the workspace's other pages and leaves out deleted repositories; every section has a name in the trail269
270export type Week = {
271 days: WeekDay[];
272 /** Changes landed in the last seven days. */
273 total: number;
274 /** The seven days before, or null when the lists read do not reach back that far. */
275 previous: number | null;
276};
277
278/**
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.279 * The last seven days in the viewer's zone, oldest first, each with how
280 * many changes landed, and the week before as one number. `complete` says
281 * whether what was read reaches back two weeks; when it does not, the week
282 * before is not guessed.
Security matches the workspace's other pages and leaves out deleted repositories; every section has a name in the trail283 */
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.284export function weekOf(changes: Pick<Merged, "mergedAt">[], now: number, timeZone: string | null, complete = true): Week {
Security matches the workspace's other pages and leaves out deleted repositories; every section has a name in the trail285 const days: WeekDay[] = [];
286 const index = new Map<string, number>();
287 for (let back = 6; back >= 0; back -= 1) {
288 const at = now - back * DAY;
289 const key = dayKey(at, timeZone);
290 if (index.has(key)) continue;
291 index.set(key, days.length);
292 let label: string;
293 try {
294 label = new Intl.DateTimeFormat("en-US", { weekday: "short", timeZone: timeZone || "UTC" }).format(at);
295 } catch {
296 label = new Intl.DateTimeFormat("en-US", { weekday: "short", timeZone: "UTC" }).format(at);
297 }
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.298 days.push({ key, label, count: 0 });
Security matches the workspace's other pages and leaves out deleted repositories; every section has a name in the trail299 }
300 const oldest = days[0]?.key ?? "";
301 const twoWeeks = dayKey(now - 13 * DAY, timeZone);
302 let previous = 0;
303 for (const change of changes) {
304 const at = Date.parse(change.mergedAt);
305 if (!Number.isFinite(at) || at > now) continue;
306 const key = dayKey(at, timeZone);
307 const slot = index.get(key);
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.308 if (slot != null) days[slot].count += 1;
309 else if (key < oldest && key >= twoWeeks) previous += 1;
Security matches the workspace's other pages and leaves out deleted repositories; every section has a name in the trail310 }
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.311 return { days, total: days.reduce((sum, day) => sum + day.count, 0), previous: complete ? previous : null };
Security matches the workspace's other pages and leaves out deleted repositories; every section has a name in the trail312}
313
314/** The change from one number to another, as a share; null from nothing. */
315export function change(current: number, previous: number | null): number | null {
316 if (previous == null || previous === 0) return null;
317 return (current - previous) / previous;
318}
319
320/** "+18%", "−5%", "0%". */
321export function signedPercent(share: number): string {
322 const n = Math.round(share * 100);
323 return n > 0 ? `+${n}%` : n < 0 ? `−${Math.abs(n)}%` : "0%";
324}
325
326/**
327 * Whether the merged pull requests read for one repository reach back to
328 * `since`: the list is not full, or its oldest goes back that far.
329 */
330export function reachesBack(list: { mergedAt: string | null; updatedAt: string }[], since: number, page: number): boolean {
331 if (list.length < page) return true;
332 const oldest = Math.min(...list.map((pull) => Date.parse(pull.mergedAt ?? pull.updatedAt)).filter(Number.isFinite));
333 return oldest <= since;
334}
335
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.336/** One change that landed, as the Landed tab lists it. */
Security matches the workspace's other pages and leaves out deleted repositories; every section has a name in the trail337export type LandedRow = {
338 key: string;
339 repo: RepoPath;
340 ref: string;
341 title: string;
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.342 /** Who merged it; g1t for a change that merged automatically. */
Security matches the workspace's other pages and leaves out deleted repositories; every section has a name in the trail343 by: Who | null;
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.344 automatic: boolean;
Security matches the workspace's other pages and leaves out deleted repositories; every section has a name in the trail345 at: number;
346 to: string;
347 facts: Fact[];
348};
349
350/** What landed on the viewer's calendar day, newest first. */
351export function landedToday(changes: Merged[], now: number, timeZone: string | null): LandedRow[] {
352 const today = dayKey(now, timeZone);
353 return changes
354 .filter((change) => dayKey(Date.parse(change.mergedAt), timeZone) === today)
355 .sort((a, b) => Date.parse(b.mergedAt) - Date.parse(a.mergedAt))
356 .map((change) => ({
357 key: pathKey(change.repo, change.number),
358 repo: change.repo,
359 ref: `#${change.number}`,
360 title: change.title,
361 by: who(change.mergedBy ?? "g1t"),
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.362 automatic: mergedAutomatically(change),
Security matches the workspace's other pages and leaves out deleted repositories; every section has a name in the trail363 at: Date.parse(change.mergedAt),
364 to: `/${change.repo.namespace}/${change.repo.name}/pull/${change.number}`,
365 facts: pullFacts({ checkStatus: "passed", files: change.files }).filter((fact) => fact.label !== "Required checks"),
366 }));
367}
368
369// --- Tabs and sorting -------------------------------------------------------
370
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.371export type Tab = "needs" | "landed";
Security matches the workspace's other pages and leaves out deleted repositories; every section has a name in the trail372export type Sort = "impact" | "newest";
373
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.374export const TABS: Tab[] = ["needs", "landed"];
Security matches the workspace's other pages and leaves out deleted repositories; every section has a name in the trail375
376export function parseTab(value: string | null): Tab | null {
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.377 return value === "needs" || value === "landed" ? value : null;
Security matches the workspace's other pages and leaves out deleted repositories; every section has a name in the trail378}
379
380export function parseSort(value: string | null): Sort {
381 return value === "newest" ? "newest" : "impact";
382}
383
384/** Rows in the order chosen: as ranked (most urgent first), or newest first. */
385export function sortRows<T extends { at: number }>(rows: T[], sort: Sort): T[] {
386 return sort === "newest" ? [...rows].sort((a, b) => b.at - a.at) : rows;
387}
388
389// --- The summary ------------------------------------------------------------
390
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.391/** The sentence under the title: the week, in one line. */
392export function summaryLine(input: { total: number; needs: number }): string {
393 const { total, needs } = input;
394 if (total > 0) return `${plural(total, "change")} landed in the last 7 days.`;
Security matches the workspace's other pages and leaves out deleted repositories; every section has a name in the trail395 if (needs > 0) return "Nothing has landed this week. What is waiting on you is below.";
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.396 return "Nothing has landed this week yet.";
Security matches the workspace's other pages and leaves out deleted repositories; every section has a name in the trail397}
398
399/** "Monday, Oct 5", in the viewer's zone. */
400export function dateLine(now: number, timeZone: string | null): string {
401 const options: Intl.DateTimeFormatOptions = { weekday: "long", month: "short", day: "numeric" };
402 try {
403 return new Intl.DateTimeFormat("en-US", { ...options, timeZone: timeZone || "UTC" }).format(now);
404 } catch {
405 return new Intl.DateTimeFormat("en-US", { ...options, timeZone: "UTC" }).format(now);
406 }
407}

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