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

Fixes from the page sweep1/**
2 * Every state change in g1t is published as an event. Services react to
3 * each other through events rather than direct calls, and the same stream
4 * feeds timelines, webhooks and workflows.
5 *
6 * The envelope follows CloudEvents: `type` says what happened, `subject`
7 * says to what, `data` is the type-specific payload.
8 */
9
Merge Actions: cross-repo workflows and actions, release and deployment triggers, step timeouts10import type { Release } from "./about";
Fixes from the page sweep11import type { RepoRole } from "./access";
Merge checks: statuses and check runs on every commit12import type { CheckRunEventData, CheckSuiteEventData, StatusEventData } from "./checks";
Merge branch 'main' into worktree-agent-a69aeabc4b0deeb9713import type { DeploymentStatus, RepoDeployment } from "./deployments";
Teams and CODEOWNERS, labels and milestones, dependency updates, the security suite, and a clearer top bar14import type { TeamRole, TeamVisibility } from "./teams";
The contracts no longer describe g1t's own agents, and workspaces can keep their AI providers. Every consumer had already stopped using them, so the TypeScript and Rust contracts drop the workspace-agent, ability, look, skill-library, context, runner-agent and mention modules, the chat and docs RPCs agents posted and read through, the folio agent methods, the agent_waiting notification, agent.asked and memory.changed events, AI credit, token and gateway billing types, model routes and sessions, team agents, agent tokens, plan, review, message and confidence types, command rules, cost caps and confidence rules. The agents:run and models:* scopes are no longer offered by any preset, OAuth default or permission form, but a stored token or grant that names them still reads; and the removed operations are gone from the scope table, so the API's check that every operation has exactly one scope is strict again. What stored data needs in order to parse (old run and credential kinds, an agent team lead, retired rules and webhook events, old guardrail and integration settings) still parses, and a run's token is still PrincipalKind::Agent, which now means a run's token and the @g1t rows written before. The customize, marketplace, skills and claude-plugin contracts stay only until the mobile app drops its Customize screens.15import type { AgentRef, Verdict } from "./work";
Fixes from the page sweep16
17/** What every `package.*` event names. */
18export type PackageEventData = {
19 packageId: string;
20 workspace: string;
21 ecosystem: string;
22 name: string;
23 repoId: string | null;
24};
25
Events: review requests, assignments, stops and deployments are published26/** What `deployment.succeeded` and `deployment.failed` carry. */
27export type DeploymentEventData = {
28 deploymentId: string;
29 projectId: string;
30 repoId: string;
31 workspace: string;
32 project: string;
33 kind: "production" | "preview";
34 branch: string | null;
35 number: number | null;
36 commit: string;
37 path: string;
38 error: string | null;
39 recovered: boolean;
40 /** A username, or `g1t`. */
41 triggeredBy: string;
42};
43
Merge Actions: cross-repo workflows and actions, release and deployment triggers, step timeouts44/** What every `release.*` event carries. */
45export type ReleaseEventData = {
46 releaseId: string;
47 repoId: string;
48 tagName: string;
49 release: Release;
50 /** On `release.edited`: what the title and notes were before. */
51 changes?: { name?: { from: string | null }; body?: { from: string } };
52 /** Set when a workflow job's token made the change: the run's id. */
53 causedByJob?: string;
54};
55
Fixes from the page sweep56/** The payload of the `repo.collaborator_*` events. */
57export type RepoCollaboratorData = {
58 repoId: string;
59 namespace: string;
60 name: string;
61 username: string;
62 role: RepoRole | null;
63 previousRole: RepoRole | null;
64};
Teams and CODEOWNERS, labels and milestones, dependency updates, the security suite, and a clearer top bar65/** A team asked to review a pull request. */
66export type TeamRequested = { team: string; notified: string[]; assigned: string[] };
67
68/** The payload of the `team.*` events; each sets the fields that apply. */
@g1t welcomes you when you join a workspace, and that is the one introduction any agent makes. Identity now says when a person becomes a member, workspace.member_joined, by invitation, by an invite code, or by creating the workspace, and webhooks can hear it; the agents service hears it too, and for anyone who joined, never the creator, the workspace's @g1t opens your direct message and says in its own voice who it is, what to ask it, how agents answer, and where things are, once per person per workspace and charged to @g1t like any reply, with a fixed welcome when no model can be used. The agents, workspaces, authentication and webhooks guides say so.69/** How someone came to be a member of a workspace (`workspace.member_joined`). */
70export type JoinedHow = "invitation" | "created" | "joined";
71
72/** The payload of `workspace.member_joined`. Mirrors `MemberJoined` in events.rs. */
73export type MemberJoinedData = {
74 workspaceId: string;
75 /** The workspace's slug. */
76 workspace: string;
77 userId: string;
78 username: string;
79 role: "owner" | "member";
80 how: JoinedHow;
81};
82
Teams and CODEOWNERS, labels and milestones, dependency updates, the security suite, and a clearer top bar83export type TeamChangedData = {
84 workspace: string;
85 teamId: string;
86 team: string;
87 name: string;
88 visibility: TeamVisibility | null;
89 parent?: string;
90 changes?: string[];
91 username?: string;
92 role?: TeamRole;
93 previousRole?: TeamRole;
94 repoId?: string;
95 repo?: string;
96 repoRole?: RepoRole;
97 previousRepoRole?: RepoRole;
98};
99
Fixes from the page sweep100export type EventPayloads = {
101 "repo.created": { repoId: string; namespace: string; name: string; isPrivate: boolean };
102 "repo.forked": { repoId: string; sourceRepoId: string; pullId: string };
103 /**
104 * A repository's description, topics or visibility changed.
105 * `visibilityChanged` says whether it went public or private, which
106 * `repo.visibility_changed` also announces on its own.
107 */
108 "repo.updated": { repoId: string; namespace: string; name: string; isPrivate: boolean; visibilityChanged: boolean };
109 "repo.visibility_changed": { repoId: string; isPrivate: boolean };
110 /**
111 * A repository's name changed within its workspace `namespace`, from
112 * `from` to `to`, keeping its id. A path change like `repo.transferred`:
113 * services move rows kept under its path to its *current* path (see
114 * `repoMove`, `currentMovedPath`).
115 */
116 "repo.renamed": { repoId: string; namespace: string; from: string; to: string };
117 /**
118 * A repository was deleted. It is hidden and git refuses it, but it can
119 * be restored until `purgeAfter`: services stop what runs for it and hide
120 * it, and keep their rows until `repo.purged`.
121 */
122 "repo.deleted": {
123 repoId: string;
124 namespace: string;
125 name: string;
126 isPrivate: boolean;
127 purgeAfter: string;
128 /** It went with its workspace (`workspace.deleting`); deployments leaves it to that. */
129 withWorkspace?: boolean;
130 };
131 /** A deleted repository is back, as it was. Services start again what they stopped. */
132 "repo.restored": {
133 repoId: string;
134 namespace: string;
135 name: string;
136 isPrivate: boolean;
137 /** It came back with its workspace (`workspace.restored`). */
138 withWorkspace?: boolean;
139 };
140 /**
141 * A deleted repository is gone for good, its git data with it. Services
142 * drop every row they keep for it, except a workspace's history (ledgers,
143 * invoices, the audit log).
144 */
145 "repo.purged": { repoId: string; namespace: string; name: string };
146 /**
147 * A repository was archived (read-only: pushes, merges, agents and
148 * workflows refused; issues and pull requests locked; deployments keep
149 * serving), or unarchived.
150 */
151 "repo.archived": { repoId: string; namespace: string; name: string; archived: true };
152 "repo.unarchived": { repoId: string; namespace: string; name: string; archived: false };
153 /** The default branch is now `to`; `renamed` when `from` was renamed to it. */
154 "repo.default_branch_changed": { repoId: string; from: string; to: string; renamed: boolean };
155 /** A branch was renamed. Pull requests from it follow. */
156 "branch.renamed": { repoId: string; from: string; to: string; defaultBranch: boolean };
157 /** An account was made, or changed what its profile shows. Ask identity for the profile. */
158 "user.updated": { username: string };
Merge account deletion: soft delete for 30 days, staff restore and purge, ghost for what remains (identity 0037)159 /**
160 * An account was deleted, by the person or by g1t's staff; staff can
161 * restore it until `purgeAfter`. Its sessions, tokens and keys have ended
162 * and it has left every workspace. Services stop what they do for it and
163 * keep their rows; `user.restored` undoes that, and `user.deleted` follows
164 * once `purgeAfter` passes.
165 */
166 "user.deleting": { userId: string; username: string; byStaff: boolean; purgeAfter: string };
167 /** Staff brought a deleted account back. Services undo what they did on `user.deleting`. */
168 "user.restored": { userId: string; username: string };
169 /**
170 * An account is gone for good. Services drop what they keep for it alone
171 * and show what it wrote as `ghost` (`GHOST_USERNAME`, `GHOST_ID`).
172 * Ledgers, invoices and audit logs keep its username, which is never given
173 * to anyone again.
174 */
175 "user.deleted": { userId: string; username: string };
Fixes from the page sweep176 /** A workspace was made, or its name, description or icon changed. */
177 "workspace.updated": { workspaceId: string; slug: string };
@g1t welcomes you when you join a workspace, and that is the one introduction any agent makes. Identity now says when a person becomes a member, workspace.member_joined, by invitation, by an invite code, or by creating the workspace, and webhooks can hear it; the agents service hears it too, and for anyone who joined, never the creator, the workspace's @g1t opens your direct message and says in its own voice who it is, what to ask it, how agents answer, and where things are, once per person per workspace and charged to @g1t like any reply, with a fixed welcome when no model can be used. The agents, workspaces, authentication and webhooks guides say so.178 /**
179 * A person became a member of a workspace. `how` says by which door;
180 * the workspace's creator is `created`, so a listener that greets new
181 * members leaves them out (the agents service's @g1t welcomes everyone
182 * else, once). Never for an agent or a token.
183 */
184 "workspace.member_joined": MemberJoinedData;
Fixes from the page sweep185 /** Someone, or g1t staff, made an invite. Never the code or the address. */
186 "invite.created": { inviteId: string; inviterId: string | null; workspaceId: string | null; bound: boolean };
187 /** An invite was used: by a new account, or by an account joining a workspace. */
188 "invite.redeemed": {
189 inviteId: string;
190 userId: string;
191 inviterId: string | null;
192 workspaceId: string | null;
193 createdAccount: boolean;
194 };
195 /**
196 * One branch moved by a push. `ref` is the full ref, `after` the commit it
197 * points to now, and `defaultBranch` whether it is the default branch.
198 */
199 /**
Merge leftovers: plan activity filtered in the query, pushes counted by account, ghost during the deletion window, profile time zones (identity 0039)200 * `before` is where the ref pointed before; absent for a new branch or
201 * tag. `causedByJob` is set when a workflow job's token pushed: the run's id.
202 */
Merge branch 'mirroring' into artifacts-mode203 "git.push": {
204 repoId: string;
205 ref: string;
206 before?: string;
207 after: string;
208 defaultBranch: boolean;
209 causedByJob?: string;
Home says what people did as well as what agents did. Since you were last here now has a People column and an Agents column: who pushed how many commits to which projects, pull requests opened, merged and reviewed, issues opened and closed, docs edited, messages sent and deploys that went out, each line a link to where those are listed, with the agents' acceptance (first time, after review, didn't finish) kept as a row of their column; the sentence under the heading sums it up honestly, and says when a part of g1t could not be read, or that the span was quiet. Landed counts merged pull requests, commits pushed straight to a default branch, production deploys that went live, releases and packages, newest first; Running now adds workflow runs. Behind it, the events service answers an activity digest over a span in one round trip from its existing indexes, every push now records how many commits it carried, and chat counts the messages sent in the conversations you can read. The Home guide defines every line, and says how this scales.210 /**
211 * How many commits the push brought to the branch, along its
212 * first-parent line from `after` back to `before` (a merge commit is
213 * one), at most 50; one for a new branch. Absent when it was not
214 * counted: a tag, a branch deleted, a pull request landed, a push the
215 * store could not read back, or one from before this was recorded.
216 */
217 commits?: number;
Merge branch 'mirroring' into artifacts-mode218 };
Merge leftovers: plan activity filtered in the query, pushes counted by account, ghost during the deletion window, profile time zones (identity 0039)219 /**
Merge branch 'worktree-agent-a8b78c62188153aa3' into claude/cool-newton-7nm8r9220 * A branch or tag was deleted by a push. `before` is the commit it pointed
221 * to. `causedByJob` is set when a workflow job's token deleted it: the run's id.
222 */
223 "git.deleted": { repoId: string; ref: string; before: string; causedByJob?: string };
224 /**
Fixes from the page sweep225 * `author` is who opened it: g1t, for one its agent filed while at work,
226 * with `requestedBy` the person it was working for. Every issue and pull
227 * request event carries both.
228 */
229 "issue.opened": {
230 issueId: string;
231 repoId: string;
232 number: number;
233 title: string;
234 author?: { id: string; username: string };
235 requestedBy?: { id: string; username: string };
236 };
237 "issue.updated": { issueId: string; repoId: string; number: number };
Events: review requests, assignments, stops and deployments are published238 /** The people an issue is assigned to changed; `assignees` is the new set, `added` those newly assigned. */
239 "issue.assigned": { issueId: string; repoId: string; number: number; assignees: string[]; added?: string[] };
Fixes from the page sweep240 /** `resolvedBy` is the number of the pull request whose merge closed it. */
241 "issue.closed": {
242 issueId: string;
243 repoId: string;
244 number: number;
245 reason: "completed" | "not_planned";
246 resolvedBy?: number;
247 };
248 "issue.reopened": { issueId: string; repoId: string; number: number };
249 /**
250 * `issue` is the number of the issue the pull request is for. `author` is
251 * who opened it: g1t, for a change g1t made, with `requestedBy` the person
252 * who asked for it.
253 */
254 "pull.opened": {
255 pullId: string;
256 repoId: string;
257 number: number;
258 issue?: number;
259 agent: string;
260 author?: { id: string; username: string };
261 requestedBy?: { id: string; username: string };
262 };
The contracts no longer describe g1t's own agents, and workspaces can keep their AI providers. Every consumer had already stopped using them, so the TypeScript and Rust contracts drop the workspace-agent, ability, look, skill-library, context, runner-agent and mention modules, the chat and docs RPCs agents posted and read through, the folio agent methods, the agent_waiting notification, agent.asked and memory.changed events, AI credit, token and gateway billing types, model routes and sessions, team agents, agent tokens, plan, review, message and confidence types, command rules, cost caps and confidence rules. The agents:run and models:* scopes are no longer offered by any preset, OAuth default or permission form, but a stored token or grant that names them still reads; and the removed operations are gone from the scope table, so the API's check that every operation has exactly one scope is strict again. What stored data needs in order to parse (old run and credential kinds, an agent team lead, retired rules and webhook events, old guardrail and integration settings) still parses, and a run's token is still PrincipalKind::Agent, which now means a run's token and the @g1t rows written before. The customize, marketplace, skills and claude-plugin contracts stay only until the mobile app drops its Customize screens.263 "pull.ready": { pullId: string; repoId: string; number: number; issue?: number };
Fixes from the page sweep264 /** A push moved the head of a pull request that is ready for review. */
The contracts no longer describe g1t's own agents, and workspaces can keep their AI providers. Every consumer had already stopped using them, so the TypeScript and Rust contracts drop the workspace-agent, ability, look, skill-library, context, runner-agent and mention modules, the chat and docs RPCs agents posted and read through, the folio agent methods, the agent_waiting notification, agent.asked and memory.changed events, AI credit, token and gateway billing types, model routes and sessions, team agents, agent tokens, plan, review, message and confidence types, command rules, cost caps and confidence rules. The agents:run and models:* scopes are no longer offered by any preset, OAuth default or permission form, but a stored token or grant that names them still reads; and the removed operations are gone from the scope table, so the API's check that every operation has exactly one scope is strict again. What stored data needs in order to parse (old run and credential kinds, an agent team lead, retired rules and webhook events, old guardrail and integration settings) still parses, and a run's token is still PrincipalKind::Agent, which now means a run's token and the @g1t rows written before. The customize, marketplace, skills and claude-plugin contracts stay only until the mobile app drops its Customize screens.265 "pull.updated": { pullId: string; repoId: string; number: number; issue?: number; commit: string };
Fixes from the page sweep266 /** A merge was asked for while the pull request was behind; it has to catch up first. */
The contracts no longer describe g1t's own agents, and workspaces can keep their AI providers. Every consumer had already stopped using them, so the TypeScript and Rust contracts drop the workspace-agent, ability, look, skill-library, context, runner-agent and mention modules, the chat and docs RPCs agents posted and read through, the folio agent methods, the agent_waiting notification, agent.asked and memory.changed events, AI credit, token and gateway billing types, model routes and sessions, team agents, agent tokens, plan, review, message and confidence types, command rules, cost caps and confidence rules. The agents:run and models:* scopes are no longer offered by any preset, OAuth default or permission form, but a stored token or grant that names them still reads; and the removed operations are gone from the scope table, so the API's check that every operation has exactly one scope is strict again. What stored data needs in order to parse (old run and credential kinds, an agent team lead, retired rules and webhook events, old guardrail and integration settings) still parses, and a run's token is still PrincipalKind::Agent, which now means a run's token and the @g1t rows written before. The customize, marketplace, skills and claude-plugin contracts stay only until the mobile app drops its Customize screens.267 "pull.merge_requested": { pullId: string; repoId: string; number: number; issue?: number };
268 "pull.closed": { pullId: string; repoId: string; number: number; issue?: number };
Merge Actions: cross-repo workflows and actions, release and deployment triggers, step timeouts269 /** A closed pull request was opened again. `commit` is its head. */
The contracts no longer describe g1t's own agents, and workspaces can keep their AI providers. Every consumer had already stopped using them, so the TypeScript and Rust contracts drop the workspace-agent, ability, look, skill-library, context, runner-agent and mention modules, the chat and docs RPCs agents posted and read through, the folio agent methods, the agent_waiting notification, agent.asked and memory.changed events, AI credit, token and gateway billing types, model routes and sessions, team agents, agent tokens, plan, review, message and confidence types, command rules, cost caps and confidence rules. The agents:run and models:* scopes are no longer offered by any preset, OAuth default or permission form, but a stored token or grant that names them still reads; and the removed operations are gone from the scope table, so the API's check that every operation has exactly one scope is strict again. What stored data needs in order to parse (old run and credential kinds, an agent team lead, retired rules and webhook events, old guardrail and integration settings) still parses, and a run's token is still PrincipalKind::Agent, which now means a run's token and the @g1t rows written before. The customize, marketplace, skills and claude-plugin contracts stay only until the mobile app drops its Customize screens.270 "pull.reopened": { pullId: string; repoId: string; number: number; issue?: number; commit?: string };
Merge Actions: cross-repo workflows and actions, release and deployment triggers, step timeouts271 /** A pull request that was ready for review was turned back into a draft. */
The contracts no longer describe g1t's own agents, and workspaces can keep their AI providers. Every consumer had already stopped using them, so the TypeScript and Rust contracts drop the workspace-agent, ability, look, skill-library, context, runner-agent and mention modules, the chat and docs RPCs agents posted and read through, the folio agent methods, the agent_waiting notification, agent.asked and memory.changed events, AI credit, token and gateway billing types, model routes and sessions, team agents, agent tokens, plan, review, message and confidence types, command rules, cost caps and confidence rules. The agents:run and models:* scopes are no longer offered by any preset, OAuth default or permission form, but a stored token or grant that names them still reads; and the removed operations are gone from the scope table, so the API's check that every operation has exactly one scope is strict again. What stored data needs in order to parse (old run and credential kinds, an agent team lead, retired rules and webhook events, old guardrail and integration settings) still parses, and a run's token is still PrincipalKind::Agent, which now means a run's token and the @g1t rows written before. The customize, marketplace, skills and claude-plugin contracts stay only until the mobile app drops its Customize screens.272 "pull.converted_to_draft": { pullId: string; repoId: string; number: number; issue?: number };
Events: review requests, assignments, stops and deployments are published273 /** People were assigned to a pull request: `assignees` is the new set, `added` those newly assigned. */
274 "pull.assigned": { pullId: string; repoId: string; number: number; issue?: number; assignees: string[]; added: string[] };
275 /** Reviewers were asked for a pull request (`reviewers`), or no longer are. */
Teams and CODEOWNERS, labels and milestones, dependency updates, the security suite, and a clearer top bar276 "pull.review_requested": {
277 pullId: string;
278 repoId: string;
279 number: number;
280 issue?: number;
281 reviewers?: string[];
282 /** Teams asked: `team` is `workspace/slug`, `notified` who is told, `assigned` who review assignment picked. */
283 teams?: TeamRequested[];
284 /** Asked because they own files it changes (its CODEOWNERS file). */
285 codeOwners?: boolean;
286 };
287 "pull.review_request_removed": {
288 pullId: string;
289 repoId: string;
290 number: number;
291 issue?: number;
292 reviewers?: string[];
293 teams?: TeamRequested[];
294 };
Events: review requests, assignments, stops and deployments are published295 /** g1t stopped seeing a pull request through until a person steps in; `detail` says why. */
296 "pull.stalled": { pullId: string; repoId: string; number: number; issue?: number; detail: string };
297 /** A pull request g1t had stopped on is going again. */
298 "pull.resumed": { pullId: string; repoId: string; number: number; issue?: number };
Fixes from the page sweep299 /**
300 * The pull request's head or its target moved and the files both changed
301 * overlap: a sandbox should find out whether it still merges cleanly.
302 * `commit` is its head.
303 */
304 "pull.mergecheck": { pullId: string; repoId: string; number: number; issue?: number; commit: string };
305 /** Whether the pull request merges cleanly was settled. */
306 "pull.mergeability": { pullId: string; repoId: string; number: number; issue?: number };
The contracts no longer describe g1t's own agents, and workspaces can keep their AI providers. Every consumer had already stopped using them, so the TypeScript and Rust contracts drop the workspace-agent, ability, look, skill-library, context, runner-agent and mention modules, the chat and docs RPCs agents posted and read through, the folio agent methods, the agent_waiting notification, agent.asked and memory.changed events, AI credit, token and gateway billing types, model routes and sessions, team agents, agent tokens, plan, review, message and confidence types, command rules, cost caps and confidence rules. The agents:run and models:* scopes are no longer offered by any preset, OAuth default or permission form, but a stored token or grant that names them still reads; and the removed operations are gone from the scope table, so the API's check that every operation has exactly one scope is strict again. What stored data needs in order to parse (old run and credential kinds, an agent team lead, retired rules and webhook events, old guardrail and integration settings) still parses, and a run's token is still PrincipalKind::Agent, which now means a run's token and the @g1t rows written before. The customize, marketplace, skills and claude-plugin contracts stay only until the mobile app drops its Customize screens.307 "pull.merged": { pullId: string; repoId: string; number: number; issue?: number; commit: string };
Fixes from the page sweep308 /** A run of the acceptance checks finished. `commit` is what was checked. */
309 "checks.completed": {
310 pullId: string;
311 repoId: string;
312 number: number;
313 status: "passed" | "failed" | "errored";
314 commit: string;
315 };
Merge checks: statuses and check runs on every commit316 /** A status was set on a commit through the API. */
317 "status.created": StatusEventData;
318 /** A check run was reported on a commit through the API, completed, asked to run again, or had one of its buttons pressed (`requestedAction`). */
319 "check_run.created": CheckRunEventData;
320 "check_run.completed": CheckRunEventData;
321 "check_run.rerequested": CheckRunEventData;
322 "check_run.requested_action": CheckRunEventData;
323 /** A reporter's check runs on a commit all completed, or it was asked to run them again. */
324 "check_suite.completed": CheckSuiteEventData;
325 "check_suite.rerequested": CheckSuiteEventData;
The contracts no longer describe g1t's own agents, and workspaces can keep their AI providers. Every consumer had already stopped using them, so the TypeScript and Rust contracts drop the workspace-agent, ability, look, skill-library, context, runner-agent and mention modules, the chat and docs RPCs agents posted and read through, the folio agent methods, the agent_waiting notification, agent.asked and memory.changed events, AI credit, token and gateway billing types, model routes and sessions, team agents, agent tokens, plan, review, message and confidence types, command rules, cost caps and confidence rules. The agents:run and models:* scopes are no longer offered by any preset, OAuth default or permission form, but a stored token or grant that names them still reads; and the removed operations are gone from the scope table, so the API's check that every operation has exactly one scope is strict again. What stored data needs in order to parse (old run and credential kinds, an agent team lead, retired rules and webhook events, old guardrail and integration settings) still parses, and a run's token is still PrincipalKind::Agent, which now means a run's token and the @g1t rows written before. The customize, marketplace, skills and claude-plugin contracts stay only until the mobile app drops its Customize screens.326 /** A g1t agent finished reviewing a pull request; no verdict if it could not. No longer published: on older events only. */
Fixes from the page sweep327 "review.completed": {
328 pullId: string;
329 repoId: string;
330 number: number;
331 verdict?: "approve" | "request_changes";
332 };
333 /** A person was given a role on one repository directly, had it changed, or lost it. `role` is null once removed. */
334 "repo.collaborator_added": RepoCollaboratorData;
335 "repo.collaborator_removed": RepoCollaboratorData;
336 "repo.collaborator_role_changed": RepoCollaboratorData;
Teams and CODEOWNERS, labels and milestones, dependency updates, the security suite, and a clearer top bar337 /** A team of a workspace was created, changed (`changes` says what) or deleted. */
338 "team.created": TeamChangedData;
339 "team.edited": TeamChangedData;
340 "team.deleted": TeamChangedData;
341 /** Someone joined a team, had their role in it changed, or left it. */
342 "team.member_added": TeamChangedData;
343 "team.member_role_changed": TeamChangedData;
344 "team.member_removed": TeamChangedData;
345 /** A team was given a role on a repository, had it changed, or lost it. */
346 "team.repo_added": TeamChangedData;
347 "team.repo_role_changed": TeamChangedData;
348 "team.repo_removed": TeamChangedData;
Fixes from the page sweep349 /** A repository's merge queue gained, lost or settled an entry. */
350 "queue.changed": { repoId: string };
Merge branch 'worktree-agent-ab8033ab973f8d99a'351 /**
352 * A combined state in the merge queue failed. `pull` (also `number`)
353 * answers for it; `suspects` are the pull requests ahead it fails with,
354 * narrowed by building smaller combinations when `bisected`.
355 */
356 "integration.failed": {
357 repoId: string;
358 pullId: string;
359 number: number;
360 pull: number;
361 issue: number | null;
362 combination: number[];
363 check: { name: string; conclusion: string; url: string | null };
364 bisected: boolean;
365 suspects: number[];
366 otherPulls: number[];
367 commit: string | null;
368 };
369 /** A combined state in the merge queue passed. */
370 "integration.passed": {
371 repoId: string;
372 pullId: string;
373 number: number;
374 pull: number;
375 issue: number | null;
376 combination: number[];
377 commit: string | null;
378 };
379 /** A decision record was kept on an issue or pull request (`number`). */
380 "decision.recorded": {
381 repoId: string;
382 number: number;
383 issue: number | null;
384 decision: {
385 id: string;
386 issue: number | null;
387 pull: number | null;
388 sessionId: string | null;
389 actor: string | null;
390 kind: string;
391 confidence: "claimed" | "tested" | "approved";
392 summary: string;
393 evidence: Record<string, unknown>;
394 createdAt: string;
395 };
396 };
Fixes from the page sweep397 /** `number` is the issue or pull request commented on. */
398 "comment.created": {
399 commentId: string;
400 repoId: string;
401 number: number;
402 /** Set when the comment is on a pull request. */
403 pullId?: string;
404 /** Set when the comment is a review. */
405 verdict?: Verdict;
Cards you act on in chat; agents comment and review as themselves; names shown cleanly; commits on the calendar406 /**
407 * Set when one of the workspace's agents wrote it, as itself; the
408 * event's actor is then the person it acted for (`actingFor`).
409 */
410 agent?: AgentRef;
411 actingFor?: { id: string; username: string };
412 /** An agent's review: its verdict is advisory and counts toward nothing. */
413 advisory?: boolean;
Fixes from the page sweep414 };
Merge Actions: cross-repo workflows and actions, release and deployment triggers, step timeouts415 /** A comment's text changed; `changes.body.from` is what it said before. */
416 "comment.edited": {
417 commentId: string;
418 repoId: string;
419 number: number;
420 /** Set when the comment is on a pull request. */
421 pullId?: string;
422 changes: { body: { from: string } };
423 };
424 /** A comment was deleted; `comment` is the comment as it was. */
425 "comment.deleted": {
426 commentId: string;
427 repoId: string;
428 number: number;
429 /** Set when the comment was on a pull request. */
430 pullId?: string;
431 comment: {
432 id: string;
433 body: string;
434 author: { id: string; username: string };
435 createdAt: string;
436 path: string | null;
437 line: number | null;
438 };
439 };
Fixes from the page sweep440 "session.appended": { pullId: string; repoId: string; number: number; count: number };
441 /**
Events: review requests, assignments, stops and deployments are published442 * A build of a project finished, for production or one pull request's
443 * preview (`number`). `path` is the deployment's page on the site;
444 * `recovered`, on a success, says the build before it failed.
445 */
446 "deployment.succeeded": DeploymentEventData;
447 "deployment.failed": DeploymentEventData;
448 /**
Merge branch 'main' into worktree-agent-a69aeabc4b0deeb97449 * A deployment was made, wherever it runs: reported through the API, by
450 * a g1t Actions job with an `environment:`, or a g1t.page build. Its
451 * `payload` is left out: read the deployment for it.
452 */
Merge Actions: cross-repo workflows and actions, release and deployment triggers, step timeouts453 "deployment.created": { repoId: string; deployment: Omit<RepoDeployment, "payload">; causedByJob?: string };
454 /**
455 * A deployment has a new status; `deployment` is as it is now.
456 * `causedByJob` (as on every event a workflow job's token causes) is the
457 * run whose job made it, so no workflow starts for it.
458 */
Merge branch 'main' into worktree-agent-a69aeabc4b0deeb97459 "deployment_status.created": {
460 repoId: string;
461 deployment: Omit<RepoDeployment, "payload">;
462 deploymentStatus: DeploymentStatus;
Merge Actions: cross-repo workflows and actions, release and deployment triggers, step timeouts463 causedByJob?: string;
Merge branch 'main' into worktree-agent-a69aeabc4b0deeb97464 };
465 /**
Merge Actions: cross-repo workflows and actions, release and deployment triggers, step timeouts466 * A release changed, one event per GitHub release activity it amounts
467 * to: made (`created`; a published one is also `published`, and
468 * `released` or `prereleased`), a draft published, edited, made a draft
469 * again (`unpublished`) or deleted. `release` is as it is now (as it was,
470 * for `release.deleted`).
471 */
472 "release.created": ReleaseEventData;
473 "release.published": ReleaseEventData;
474 "release.released": ReleaseEventData;
475 "release.prereleased": ReleaseEventData;
476 "release.edited": ReleaseEventData;
477 "release.unpublished": ReleaseEventData;
478 "release.deleted": ReleaseEventData;
479 /**
Fixes from the page sweep480 * A package version was published, such as an image pushed by
481 * `docker push`. `tags` are the tags that now point to it; `repoId` (and
482 * the event's) is the repository the package is linked to, if any.
483 */
484 "package.published": PackageEventData & { version: string; digest: string; size: number; tags: string[] };
485 /** One version of a package was deleted, with the tags that pointed to it. */
486 "package.version_deleted": PackageEventData & { version: string; digest: string };
487 /** A package was deleted with every version it had. */
488 "package.deleted": PackageEventData;
489 /** A package became public or private. */
490 "package.visibility_changed": PackageEventData & { visibility: "public" | "private" };
491 /**
492 * A workspace's slug changed from `from` to `to`. Services that store a
493 * slug move their rows to the workspace's *current* slug (see
494 * `currentWorkspaceSlug`), so a repeated or late delivery after a second
495 * rename still lands in the right place.
496 */
497 "workspace.renamed": { workspaceId: string; from: string; to: string };
498 /**
499 * A repository moved from workspace `from` to `to`, keeping its id and
500 * name. Services that store its path or its workspace's slug move those
501 * rows to its *current* path (ask repos `path_by_id`), so a repeated or
502 * late delivery after a second transfer still lands in the right place.
503 */
504 "repo.transferred": { repoId: string; name: string; from: string; to: string };
505 /**
506 * A workspace is gone. Services drop what they keep for it alone; ledgers,
507 * invoices and the audit log stay under its slug, which is never reused.
508 */
509 "workspace.deleted": { workspaceId: string; slug: string };
510 /**
511 * An owner deleted a workspace; staff can restore it until `purgeAfter`,
512 * and nobody can reach it meanwhile. Services hide what they keep for it
513 * and stop what runs for it, keeping their rows: repos deletes its
514 * repositories softly (`repo.deleted` with `withWorkspace`), deployments
515 * pauses its apps, search drops it. `workspace.restored` undoes exactly
516 * that; `workspace.deleted` follows once `purgeAfter` passes. `by` is the
517 * owner's username.
518 */
519 "workspace.deleting": { workspaceId: string; slug: string; by: string; purgeAfter: string };
520 /**
521 * Staff brought a deleted workspace back with its members and tokens.
522 * Services undo what they did on `workspace.deleting`, and only that.
523 */
524 "workspace.restored": { workspaceId: string; slug: string };
525 /**
526 * A sandbox was stopped because it looked like it was mining: CPU pinned
527 * with little I/O and no progress, or a miner seen by name. For g1t's
528 * staff, in sudo; published with no `repoId` so it never reaches a
529 * repository's timeline or webhooks. `metrics` is what the sandbox
530 * measured (`Verdict` in crates/runner abuse.rs), or null if it could
531 * not say.
532 */
533 "abuse.flagged": {
534 workspace: string;
535 repo: string | null;
536 /** The agent run, when the sandbox had one. */
537 run: string | null;
538 /** What the sandbox was for: agent, checks, queue, actions, deploy... */
539 kind: string;
540 sandbox: string;
541 metrics: Record<string, unknown> | null;
542 };
Docs know what code they describe; a project's docs folder in Docs; Docs events; files on any S3 store543 /**
The artifacts service is services/artifacts, the Worker g1t-artifacts, bound as ARTIFACTS by the API, the site and the agents; its live rooms move to it with a Durable Object transfer from g1t-docs-service, and its database, bucket, indexes and queue keep their names. The git store's binding and settings are GITSTORE, its ops scripts gitstore-*, and workflow run artifacts keep their compatible API under run_artifacts modules. The deploy tool puts a Worker that has never deployed before the Workers in its stage that bind to it, and the deploy guide gives the cutover runbook.544 * Docs (services/artifacts): a page was made. Published with no `repoId`, so
Docs know what code they describe; a project's docs folder in Docs; Docs events; files on any S3 store545 * a page (which may be in a private space) never reaches a repository's
546 * timeline or webhooks; `actor` is the user's or agent's id. Readers
The artifacts service is services/artifacts, the Worker g1t-artifacts, bound as ARTIFACTS by the API, the site and the agents; its live rooms move to it with a Durable Object transfer from g1t-docs-service, and its database, bucket, indexes and queue keep their names. The git store's binding and settings are GITSTORE, its ops scripts gitstore-*, and workflow run artifacts keep their compatible API under run_artifacts modules. The deploy tool puts a Worker that has never deployed before the Workers in its stage that bind to it, and the deploy guide gives the cutover runbook.547 * check access with the artifacts service before showing anything of it.
Docs know what code they describe; a project's docs folder in Docs; Docs events; files on any S3 store548 */
549 "doc.page.created": DocPageEventData;
550 /**
551 * A page's content changed: at most once per page every ten minutes of
552 * editing (when its history records a version), and for every agent
553 * edit, accepted suggestion and restore. `authors` are member keys
554 * (`user:<id>`, `agent:<id>`) of everyone whose changes are in it.
555 */
556 "doc.page.updated": DocPageEventData & { versionId: string; kind: "edit" | "agent" | "suggestion" | "restore"; authors: string[] };
557 /** A page went to the trash (with every page under it; one event for the page asked about). */
558 "doc.page.archived": DocPageEventData;
559 /**
560 * A page became possibly out of date: a merged pull request or a push to
561 * a repository's default branch changed code it cites. `repoId` is in
562 * `data`, not on the event, for the same reason as above. `owners` are
563 * member keys; an agent that owns the page can update it
564 * (`stalePagesForAgent` in docs.ts).
565 */
566 "doc.page.stale": DocPageEventData & { repoId: string; repo: string; commit: string; pull: number | null; paths: string[]; owners: string[] };
Artifacts contracts: folios, their four kinds, dashboard datasets, folio events and the artifacts scopes are typed and validated the same in TypeScript and Rust, with nothing using them yet567 /**
The artifacts service is services/artifacts, the Worker g1t-artifacts, bound as ARTIFACTS by the API, the site and the agents; its live rooms move to it with a Durable Object transfer from g1t-docs-service, and its database, bucket, indexes and queue keep their names. The git store's binding and settings are GITSTORE, its ops scripts gitstore-*, and workflow run artifacts keep their compatible API under run_artifacts modules. The deploy tool puts a Worker that has never deployed before the Workers in its stage that bind to it, and the deploy guide gives the cutover runbook.568 * Artifacts (folios, services/artifacts): a folio was made. Like `doc.page.*`,
Artifacts contracts: folios, their four kinds, dashboard datasets, folio events and the artifacts scopes are typed and validated the same in TypeScript and Rust, with nothing using them yet569 * published with no `repoId`, never offered to webhooks, and readers check
The artifacts service is services/artifacts, the Worker g1t-artifacts, bound as ARTIFACTS by the API, the site and the agents; its live rooms move to it with a Durable Object transfer from g1t-docs-service, and its database, bucket, indexes and queue keep their names. The git store's binding and settings are GITSTORE, its ops scripts gitstore-*, and workflow run artifacts keep their compatible API under run_artifacts modules. The deploy tool puts a Worker that has never deployed before the Workers in its stage that bind to it, and the deploy guide gives the cutover runbook.570 * access with the artifacts service before showing anything of it.
Artifacts contracts: folios, their four kinds, dashboard datasets, folio events and the artifacts scopes are typed and validated the same in TypeScript and Rust, with nothing using them yet571 */
572 "folio.created": FolioEventData;
573 /** A folio's content changed: a version (`versionKind`) with everyone whose changes are in it. */
574 "folio.updated": FolioEventData & { versionId: string; versionKind: "edit" | "agent" | "suggestion" | "proposal" | "restore"; authors: string[] };
575 /** A folio went to the trash (with everything under it; one event for the folio asked about). */
576 "folio.trashed": FolioEventData;
577 "folio.restored": FolioEventData;
Merge remote-tracking branch 'origin/claude/cool-newton-7nm8r9' into claude/cool-newton-7nm8r9578 /**
579 * A folio was deleted for good from the trash (with everything under it;
580 * one event for each top that went): by someone with full access, by
581 * emptying the trash, or by the daily purge (`actor` null then).
582 */
583 "folio.deleted": FolioEventData;
Artifacts contracts: folios, their four kinds, dashboard datasets, folio events and the artifacts scopes are typed and validated the same in TypeScript and Rust, with nothing using them yet584 /** Someone was given access: who (member keys) and the role. Never content. */
585 "folio.shared": FolioEventData & { principals: string[]; role: "view" | "comment" | "edit" | "manage" };
586 /** Code a folio cites changed. The repository is in `data` as `owner/name` only. */
587 "folio.stale": FolioEventData & { repo: string; commit: string; pull: number | null; paths: string[]; owners: string[] };
Merge remote-tracking branch 'origin/claude/cool-newton-7nm8r9' into claude/cool-newton-7nm8r9588 /**
589 * A space was deleted (services/artifacts): everything in it went to the
590 * trash (`trashed` counts the artifacts; this one event stands for them
591 * all). Like `folio.*`, published with no `repoId` and never offered to
592 * webhooks; `name` is null for a members-only space.
593 */
594 "doc.space.deleted": { workspace: string; workspaceId: string; spaceId: string; name: string | null; kind: "workspace" | "team" | "private"; trashed: number };
Artifacts contracts: folios, their four kinds, dashboard datasets, folio events and the artifacts scopes are typed and validated the same in TypeScript and Rust, with nothing using them yet595};
596
597/**
598 * What every `folio.*` event carries. `title` is null unless every member
599 * of the workspace can read the folio, so a private folio's name never
600 * travels.
601 */
602export type FolioEventData = {
603 workspace: string;
604 workspaceId: string;
605 folioId: string;
606 kind: "doc" | "slides" | "design" | "dashboard";
607 spaceId: string | null;
608 title: string | null;
Docs know what code they describe; a project's docs folder in Docs; Docs events; files on any S3 store609};
610
611/** What every `doc.page.*` event carries. */
612export type DocPageEventData = {
613 workspace: string;
614 workspaceId: string;
615 pageId: string;
616 spaceId: string;
617 title: string;
618 /** The page's address on the site. */
619 path: string;
Fixes from the page sweep620};
621
622export type EventType = keyof EventPayloads;
623
624export type G1tEvent<T extends EventType = EventType> = {
625 [K in T]: {
626 id: string;
627 type: K;
628 /** The service that published it. */
629 source: string;
630 /** RFC 3339. */
631 time: string;
632 /** The repo the event concerns, used to scope timelines and deliveries. */
633 repoId: string | null;
634 /** The user or agent that caused it, if any. */
635 actor: string | null;
636 data: EventPayloads[K];
637 };
638}[T];
639
640/** What a publisher supplies; the bus fills in `id` and `time`. */
641export type NewEvent<T extends EventType = EventType> = {
642 [K in T]: Omit<G1tEvent<K>, "id" | "time">;
643}[T];
644
645export type EventQuery = {
646 repoId?: string;
647 types?: EventType[];
648 /** Return events older than this event id. */
649 before?: string;
Merge leftovers: plan activity filtered in the query, pushes counted by account, ghost during the deletion window, profile time zones (identity 0039)650 /** Only events by this account id. */
651 actor?: string;
652 /** Only events about these issues or pull requests (`number`, or the `issue` a comment or review is on). */
653 numbers?: number[];
654 /** Only events at or after this RFC 3339 time. */
655 since?: string;
Fixes from the page sweep656 limit?: number;
657};
658
Home says what people did as well as what agents did. Since you were last here now has a People column and an Agents column: who pushed how many commits to which projects, pull requests opened, merged and reviewed, issues opened and closed, docs edited, messages sent and deploys that went out, each line a link to where those are listed, with the agents' acceptance (first time, after review, didn't finish) kept as a row of their column; the sentence under the heading sums it up honestly, and says when a part of g1t could not be read, or that the span was quiet. Landed counts merged pull requests, commits pushed straight to a default branch, production deploys that went live, releases and packages, newest first; Running now adds workflow runs. Behind it, the events service answers an activity digest over a span in one round trip from its existing indexes, every push now records how many commits it carried, and chat counts the messages sent in the conversations you can read. The Home guide defines every line, and says how this scales.659/**
660 * `activity_digest`: what happened in some repositories, and to a
661 * workspace's artifacts, over `[from, until)`, counted by who did it. Home
662 * reads it for what people and agents did since you were last there.
663 * snake_case, as the Rust service reads it
664 * (`g1t_contracts::events::ActivityDigestArgs`).
665 */
666export type ActivityDigestArgs = {
667 /** By id; the caller has checked the viewer may read each. At most `MAX_DIGEST_REPOS` are read. */
668 repo_ids: string[];
669 /** The workspace's slug, for its `folio.*` events (which carry no repository); null leaves artifacts out. */
670 workspace: string | null;
671 /** RFC 3339, inclusive. */
672 from: string;
673 /** RFC 3339, exclusive. */
674 until: string;
675};
676
677/** The most repositories one digest reads. */
678export const MAX_DIGEST_REPOS = 50;
679
680/**
681 * How many times one actor did something. The actor is a member key:
682 * `user:<id>` for a person (or g1t, `user:usr_g1t_agent`), `agent:<id>` for
683 * one of the workspace's agents acting as itself, or `""` when the event
Merge main into rm-agents: mirroring removal, open signups, free-tier limits, the g1t CLI and runner fixes, with the agent removal kept. The CLI's table of operations is regenerated from the API without the agent, customize and AI credit operations; no CLI command used them.684 * named nobody.
Home says what people did as well as what agents did. Since you were last here now has a People column and an Agents column: who pushed how many commits to which projects, pull requests opened, merged and reviewed, issues opened and closed, docs edited, messages sent and deploys that went out, each line a link to where those are listed, with the agents' acceptance (first time, after review, didn't finish) kept as a row of their column; the sentence under the heading sums it up honestly, and says when a part of g1t could not be read, or that the span was quiet. Landed counts merged pull requests, commits pushed straight to a default branch, production deploys that went live, releases and packages, newest first; Running now adds workflow runs. Behind it, the events service answers an activity digest over a span in one round trip from its existing indexes, every push now records how many commits it carried, and chat counts the messages sent in the conversations you can read. The Home guide defines every line, and says how this scales.685 */
686export type ActorCount = { actor: string; count: number };
687
688/** Pushes by one actor, with the commits they brought. */
689export type PushesBy = { actor: string; count: number; commits: number };
690
691/** Pushes to a repository's branches (tags are not pushes here). A push whose commits were not counted counts as one commit. */
692export type PushDigest = {
693 count: number;
694 commits: number;
695 /** The branches pushed to, by name, sorted. */
696 branches: string[];
697 /** Most pushes first. */
698 by: PushesBy[];
699 /** Of those, the pushes straight to the default branch: what landed without a pull request. */
700 default_branch: { count: number; commits: number; by: PushesBy[]; last_at: string | null };
701};
702
703export type RepoDigest = {
704 repo_id: string;
705 pushes: PushDigest;
706 /** Pull requests opened, merged and closed without merging, each by who did it. */
707 pulls: { opened: ActorCount[]; merged: ActorCount[]; closed: ActorCount[] };
708 issues: { opened: ActorCount[]; closed: ActorCount[] };
709 /** `review.completed` (g1t's), and a comment with a verdict (a person's). */
710 reviews: ActorCount[];
711 /** Comments without a verdict; one by an agent as itself is the agent's. */
712 comments: ActorCount[];
713 /** Builds that finished, by who set them off; `production` is how many successes were production. */
714 deployments: { succeeded: ActorCount[]; failed: ActorCount[]; production: number };
715 /** Releases published, newest first, at most 50. */
716 releases: { tag: string; name: string | null; actor: string; at: string }[];
717 /** Package versions published, newest first, at most 50. */
718 packages: { ecosystem: string; name: string; version: string; actor: string; at: string }[];
719};
720
721/** A workspace's artifacts over the span. Never a title. */
722export type FolioDigest = {
723 created: ActorCount[];
724 /** Each folio whose content changed, once, with everyone whose changes are in it (member keys); at most 50. */
725 edited: { folio_id: string; kind: "doc" | "slides" | "design" | "dashboard" | string; authors: string[] }[];
726 /** How many folios changed, counting those past the cap. */
727 edited_count: number;
728};
729
730export type ActivityDigest = {
731 from: string;
732 until: string;
733 /** One per repository that had any event counted; none for a quiet one. */
734 repos: RepoDigest[];
735 /** When a workspace was named. */
736 folios: FolioDigest | null;
737 /** False when more events fell in the span than were read, or more repositories were named than are read, so counts are low. */
738 complete: boolean;
739};
740
Fixes from the page sweep741/** The event bus and its durable log. */
742export interface EventsApi {
743 publish(events: NewEvent[]): Promise<void>;
744 /** Newest first. */
745 list(query: EventQuery): Promise<G1tEvent[]>;
Home says what people did as well as what agents did. Since you were last here now has a People column and an Agents column: who pushed how many commits to which projects, pull requests opened, merged and reviewed, issues opened and closed, docs edited, messages sent and deploys that went out, each line a link to where those are listed, with the agents' acceptance (first time, after review, didn't finish) kept as a row of their column; the sentence under the heading sums it up honestly, and says when a part of g1t could not be read, or that the span was quiet. Landed counts merged pull requests, commits pushed straight to a default branch, production deploys that went live, releases and packages, newest first; Running now adds workflow runs. Behind it, the events service answers an activity digest over a span in one round trip from its existing indexes, every push now records how many commits it carried, and chat counts the messages sent in the conversations you can read. The Home guide defines every line, and says how this scales.746 /** A span of some repositories' and a workspace's artifacts' events, counted by who did it. */
747 activityDigest(args: ActivityDigestArgs): Promise<ActivityDigest>;
Fixes from the page sweep748}

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