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

Icons are cached at the edge1/**
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";
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look11import type { RepoRole } from "./access";
Merge checks: statuses and check runs on every commit12import type { CheckRunEventData, CheckSuiteEventData, StatusEventData } from "./checks";
Merge branch 'mirroring' into artifacts-mode13import type { RepoMirror } from "./mirrors";
Merge branch 'main' into worktree-agent-a69aeabc4b0deeb9714import type { DeploymentStatus, RepoDeployment } from "./deployments";
Teams and CODEOWNERS, labels and milestones, dependency updates, the security suite, and a clearer top bar15import type { TeamRole, TeamVisibility } from "./teams";
Cards you act on in chat; agents comment and review as themselves; names shown cleanly; commits on the calendar16import type { AgentRef, Confidence, Verdict } from "./work";
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look17
Packages, with a container registry on g1t.sh; workspaces deleted whole and kept 30 days; Members for every member18/** What every `package.*` event names. */
19export type PackageEventData = {
20 packageId: string;
21 workspace: string;
22 ecosystem: string;
23 name: string;
24 repoId: string | null;
25};
26
Events: review requests, assignments, stops and deployments are published27/** What `deployment.succeeded` and `deployment.failed` carry. */
28export type DeploymentEventData = {
29 deploymentId: string;
30 projectId: string;
31 repoId: string;
32 workspace: string;
33 project: string;
34 kind: "production" | "preview";
35 branch: string | null;
36 number: number | null;
37 commit: string;
38 path: string;
39 error: string | null;
40 recovered: boolean;
41 /** A username, or `g1t`. */
42 triggeredBy: string;
43};
44
Merge Actions: cross-repo workflows and actions, release and deployment triggers, step timeouts45/** What every `release.*` event carries. */
46export type ReleaseEventData = {
47 releaseId: string;
48 repoId: string;
49 tagName: string;
50 release: Release;
51 /** On `release.edited`: what the title and notes were before. */
52 changes?: { name?: { from: string | null }; body?: { from: string } };
53 /** Set when a workflow job's token made the change: the run's id. */
54 causedByJob?: string;
55};
56
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look57/** The payload of the `repo.collaborator_*` events. */
58export type RepoCollaboratorData = {
59 repoId: string;
60 namespace: string;
61 name: string;
62 username: string;
63 role: RepoRole | null;
64 previousRole: RepoRole | null;
65};
Teams and CODEOWNERS, labels and milestones, dependency updates, the security suite, and a clearer top bar66/** A team asked to review a pull request. */
67export type TeamRequested = { team: string; notified: string[]; assigned: string[] };
68
69/** 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.70/** How someone came to be a member of a workspace (`workspace.member_joined`). */
71export type JoinedHow = "invitation" | "created" | "joined";
72
73/** The payload of `workspace.member_joined`. Mirrors `MemberJoined` in events.rs. */
74export type MemberJoinedData = {
75 workspaceId: string;
76 /** The workspace's slug. */
77 workspace: string;
78 userId: string;
79 username: string;
80 role: "owner" | "member";
81 how: JoinedHow;
82};
83
Teams and CODEOWNERS, labels and milestones, dependency updates, the security suite, and a clearer top bar84export type TeamChangedData = {
85 workspace: string;
86 teamId: string;
87 team: string;
88 name: string;
89 visibility: TeamVisibility | null;
90 parent?: string;
91 changes?: string[];
92 username?: string;
93 role?: TeamRole;
94 previousRole?: TeamRole;
95 repoId?: string;
96 repo?: string;
97 repoRole?: RepoRole;
98 previousRepoRole?: RepoRole;
99};
100
Icons are cached at the edge101export type EventPayloads = {
102 "repo.created": { repoId: string; namespace: string; name: string; isPrivate: boolean };
103 "repo.forked": { repoId: string; sourceRepoId: string; pullId: string };
104 /**
Search across all of g1t, Explore, and a command palette105 * A repository's description, topics or visibility changed.
106 * `visibilityChanged` says whether it went public or private, which
107 * `repo.visibility_changed` also announces on its own.
108 */
109 "repo.updated": { repoId: string; namespace: string; name: string; isPrivate: boolean; visibilityChanged: boolean };
110 "repo.visibility_changed": { repoId: string; isPrivate: boolean };
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look111 /**
112 * A repository's name changed within its workspace `namespace`, from
113 * `from` to `to`, keeping its id. A path change like `repo.transferred`:
114 * services move rows kept under its path to its *current* path (see
115 * `repoMove`, `currentMovedPath`).
116 */
117 "repo.renamed": { repoId: string; namespace: string; from: string; to: string };
118 /**
119 * A repository was deleted. It is hidden and git refuses it, but it can
120 * be restored until `purgeAfter`: services stop what runs for it and hide
121 * it, and keep their rows until `repo.purged`.
122 */
Packages, with a container registry on g1t.sh; workspaces deleted whole and kept 30 days; Members for every member123 "repo.deleted": {
124 repoId: string;
125 namespace: string;
126 name: string;
127 isPrivate: boolean;
128 purgeAfter: string;
129 /** It went with its workspace (`workspace.deleting`); deployments leaves it to that. */
130 withWorkspace?: boolean;
131 };
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look132 /** A deleted repository is back, as it was. Services start again what they stopped. */
Packages, with a container registry on g1t.sh; workspaces deleted whole and kept 30 days; Members for every member133 "repo.restored": {
134 repoId: string;
135 namespace: string;
136 name: string;
137 isPrivate: boolean;
138 /** It came back with its workspace (`workspace.restored`). */
139 withWorkspace?: boolean;
140 };
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look141 /**
142 * A deleted repository is gone for good, its git data with it. Services
143 * drop every row they keep for it, except a workspace's history (ledgers,
144 * invoices, the audit log).
145 */
146 "repo.purged": { repoId: string; namespace: string; name: string };
147 /**
148 * A repository was archived (read-only: pushes, merges, agents and
149 * workflows refused; issues and pull requests locked; deployments keep
150 * serving), or unarchived.
151 */
152 "repo.archived": { repoId: string; namespace: string; name: string; archived: true };
153 "repo.unarchived": { repoId: string; namespace: string; name: string; archived: false };
154 /** The default branch is now `to`; `renamed` when `from` was renamed to it. */
155 "repo.default_branch_changed": { repoId: string; from: string; to: string; renamed: boolean };
156 /** A branch was renamed. Pull requests from it follow. */
157 "branch.renamed": { repoId: string; from: string; to: string; defaultBranch: boolean };
Search across all of g1t, Explore, and a command palette158 /** An account was made, or changed what its profile shows. Ask identity for the profile. */
159 "user.updated": { username: string };
Merge account deletion: soft delete for 30 days, staff restore and purge, ghost for what remains (identity 0037)160 /**
161 * An account was deleted, by the person or by g1t's staff; staff can
162 * restore it until `purgeAfter`. Its sessions, tokens and keys have ended
163 * and it has left every workspace. Services stop what they do for it and
164 * keep their rows; `user.restored` undoes that, and `user.deleted` follows
165 * once `purgeAfter` passes.
166 */
167 "user.deleting": { userId: string; username: string; byStaff: boolean; purgeAfter: string };
168 /** Staff brought a deleted account back. Services undo what they did on `user.deleting`. */
169 "user.restored": { userId: string; username: string };
170 /**
171 * An account is gone for good. Services drop what they keep for it alone
172 * and show what it wrote as `ghost` (`GHOST_USERNAME`, `GHOST_ID`).
173 * Ledgers, invoices and audit logs keep its username, which is never given
174 * to anyone again.
175 */
176 "user.deleted": { userId: string; username: string };
Search across all of g1t, Explore, and a command palette177 /** A workspace was made, or its name, description or icon changed. */
178 "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.179 /**
180 * A person became a member of a workspace. `how` says by which door;
181 * the workspace's creator is `created`, so a listener that greets new
182 * members leaves them out (the agents service's @g1t welcomes everyone
183 * else, once). Never for an agent or a token.
184 */
185 "workspace.member_joined": MemberJoinedData;
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look186 /** Someone, or g1t staff, made an invite. Never the code or the address. */
187 "invite.created": { inviteId: string; inviterId: string | null; workspaceId: string | null; bound: boolean };
188 /** An invite was used: by a new account, or by an account joining a workspace. */
189 "invite.redeemed": {
190 inviteId: string;
191 userId: string;
192 inviterId: string | null;
193 workspaceId: string | null;
194 createdAccount: boolean;
195 };
196 /** Someone asked for access while registration is invite-only. The address is not in the event. */
197 "waitlist.requested": { entryId: string };
Search across all of g1t, Explore, and a command palette198 /**
Icons are cached at the edge199 * One branch moved by a push. `ref` is the full ref, `after` the commit it
200 * points to now, and `defaultBranch` whether it is the default branch.
201 */
g1t is the stored author of what it opens; the person who asked is requested_by and keeps the author's rights202 /**
Merge leftovers: plan activity filtered in the query, pushes counted by account, ghost during the deletion window, profile time zones (identity 0039)203 * `before` is where the ref pointed before; absent for a new branch or
204 * tag. `causedByJob` is set when a workflow job's token pushed: the run's id.
205 */
Merge branch 'mirroring' into artifacts-mode206 "git.push": {
207 repoId: string;
208 ref: string;
209 before?: string;
210 after: string;
211 defaultBranch: boolean;
212 causedByJob?: string;
213 /** Set when it was copied in from the remote a mirror follows, not made on g1t. */
214 mirrored?: boolean;
215 /** The repository's mirror state when it landed; absent for one that leads. */
216 mirror?: RepoMirror;
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.217 /**
218 * How many commits the push brought to the branch, along its
219 * first-parent line from `after` back to `before` (a merge commit is
220 * one), at most 50; one for a new branch. Absent when it was not
221 * counted: a tag, a branch deleted, a pull request landed, a push the
222 * store could not read back, or one from before this was recorded.
223 */
224 commits?: number;
Merge branch 'mirroring' into artifacts-mode225 };
Merge leftovers: plan activity filtered in the query, pushes counted by account, ghost during the deletion window, profile time zones (identity 0039)226 /**
g1t is the stored author of what it opens; the person who asked is requested_by and keeps the author's rights227 * `author` is who opened it: g1t, for one its agent filed while at work,
228 * with `requestedBy` the person it was working for. Every issue and pull
229 * request event carries both.
230 */
231 "issue.opened": {
232 issueId: string;
233 repoId: string;
234 number: number;
235 title: string;
236 author?: { id: string; username: string };
237 requestedBy?: { id: string; username: string };
238 };
Icons are cached at the edge239 "issue.updated": { issueId: string; repoId: string; number: number };
Events: review requests, assignments, stops and deployments are published240 /** The people an issue is assigned to changed; `assignees` is the new set, `added` those newly assigned. */
241 "issue.assigned": { issueId: string; repoId: string; number: number; assignees: string[]; added?: string[] };
Icons are cached at the edge242 /** `resolvedBy` is the number of the pull request whose merge closed it. */
243 "issue.closed": {
244 issueId: string;
245 repoId: string;
246 number: number;
247 reason: "completed" | "not_planned";
248 resolvedBy?: number;
249 };
250 "issue.reopened": { issueId: string; repoId: string; number: number };
g1t is the stored author of what it opens; the person who asked is requested_by and keeps the author's rights251 /**
252 * `issue` is the number of the issue the pull request is for. `author` is
253 * who opened it: g1t, for a change g1t made, with `requestedBy` the person
254 * who asked for it.
255 */
256 "pull.opened": {
257 pullId: string;
258 repoId: string;
259 number: number;
260 issue?: number;
261 agent: string;
262 author?: { id: string; username: string };
263 requestedBy?: { id: string; username: string };
264 };
Thirteen MCP tools and classic token scopes; agents rate their confidence and can be put on an issue in one step265 /** `confidence`, on a g1t agent's change once g1t has worked it out, is on every pull request event. */
266 "pull.ready": { pullId: string; repoId: string; number: number; issue?: number; confidence?: Confidence };
Icons are cached at the edge267 /** A push moved the head of a pull request that is ready for review. */
Thirteen MCP tools and classic token scopes; agents rate their confidence and can be put on an issue in one step268 "pull.updated": { pullId: string; repoId: string; number: number; issue?: number; commit: string; confidence?: Confidence };
Icons are cached at the edge269 /** A merge was asked for while the pull request was behind; it has to catch up first. */
Thirteen MCP tools and classic token scopes; agents rate their confidence and can be put on an issue in one step270 "pull.merge_requested": { pullId: string; repoId: string; number: number; issue?: number; confidence?: Confidence };
271 "pull.closed": { pullId: string; repoId: string; number: number; issue?: number; confidence?: Confidence };
Merge Actions: cross-repo workflows and actions, release and deployment triggers, step timeouts272 /** A closed pull request was opened again. `commit` is its head. */
273 "pull.reopened": { pullId: string; repoId: string; number: number; issue?: number; commit?: string; confidence?: Confidence };
274 /** A pull request that was ready for review was turned back into a draft. */
275 "pull.converted_to_draft": { pullId: string; repoId: string; number: number; issue?: number; confidence?: Confidence };
Events: review requests, assignments, stops and deployments are published276 /** People were assigned to a pull request: `assignees` is the new set, `added` those newly assigned. */
277 "pull.assigned": { pullId: string; repoId: string; number: number; issue?: number; assignees: string[]; added: string[] };
278 /** 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 bar279 "pull.review_requested": {
280 pullId: string;
281 repoId: string;
282 number: number;
283 issue?: number;
284 reviewers?: string[];
285 /** Teams asked: `team` is `workspace/slug`, `notified` who is told, `assigned` who review assignment picked. */
286 teams?: TeamRequested[];
287 /** Asked because they own files it changes (its CODEOWNERS file). */
288 codeOwners?: boolean;
289 };
290 "pull.review_request_removed": {
291 pullId: string;
292 repoId: string;
293 number: number;
294 issue?: number;
295 reviewers?: string[];
296 teams?: TeamRequested[];
297 };
Events: review requests, assignments, stops and deployments are published298 /** g1t stopped seeing a pull request through until a person steps in; `detail` says why. */
299 "pull.stalled": { pullId: string; repoId: string; number: number; issue?: number; detail: string };
300 /** A pull request g1t had stopped on is going again. */
301 "pull.resumed": { pullId: string; repoId: string; number: number; issue?: number };
Agents and memory, checks and conflicts, profiles, slug renames, custom domains302 /**
303 * The pull request's head or its target moved and the files both changed
304 * overlap: a sandbox should find out whether it still merges cleanly.
305 * `commit` is its head.
306 */
307 "pull.mergecheck": { pullId: string; repoId: string; number: number; issue?: number; commit: string };
308 /** Whether the pull request merges cleanly was settled. */
309 "pull.mergeability": { pullId: string; repoId: string; number: number; issue?: number };
Icons are cached at the edge310 /** Another agent asked the agent on a pull request, which was not at work, a question or handed it work. */
311 "agent.asked": { pullId: string; repoId: string; number: number; issue?: number };
Thirteen MCP tools and classic token scopes; agents rate their confidence and can be put on an issue in one step312 "pull.merged": { pullId: string; repoId: string; number: number; issue?: number; commit: string; confidence?: Confidence };
Icons are cached at the edge313 /** A run of the acceptance checks finished. `commit` is what was checked. */
314 "checks.completed": {
315 pullId: string;
316 repoId: string;
317 number: number;
318 status: "passed" | "failed" | "errored";
319 commit: string;
320 };
Merge checks: statuses and check runs on every commit321 /** A status was set on a commit through the API. */
322 "status.created": StatusEventData;
323 /** A check run was reported on a commit through the API, completed, asked to run again, or had one of its buttons pressed (`requestedAction`). */
324 "check_run.created": CheckRunEventData;
325 "check_run.completed": CheckRunEventData;
326 "check_run.rerequested": CheckRunEventData;
327 "check_run.requested_action": CheckRunEventData;
328 /** A reporter's check runs on a commit all completed, or it was asked to run them again. */
329 "check_suite.completed": CheckSuiteEventData;
330 "check_suite.rerequested": CheckSuiteEventData;
Icons are cached at the edge331 /** A g1t agent finished reviewing a pull request; no verdict if it could not. */
332 "review.completed": {
333 pullId: string;
334 repoId: string;
335 number: number;
336 verdict?: "approve" | "request_changes";
337 };
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look338 /** A person was given a role on one repository directly, had it changed, or lost it. `role` is null once removed. */
339 "repo.collaborator_added": RepoCollaboratorData;
340 "repo.collaborator_removed": RepoCollaboratorData;
341 "repo.collaborator_role_changed": RepoCollaboratorData;
Teams and CODEOWNERS, labels and milestones, dependency updates, the security suite, and a clearer top bar342 /** A team of a workspace was created, changed (`changes` says what) or deleted. */
343 "team.created": TeamChangedData;
344 "team.edited": TeamChangedData;
345 "team.deleted": TeamChangedData;
346 /** Someone joined a team, had their role in it changed, or left it. */
347 "team.member_added": TeamChangedData;
348 "team.member_role_changed": TeamChangedData;
349 "team.member_removed": TeamChangedData;
350 /** A team was given a role on a repository, had it changed, or lost it. */
351 "team.repo_added": TeamChangedData;
352 "team.repo_role_changed": TeamChangedData;
353 "team.repo_removed": TeamChangedData;
Icons are cached at the edge354 /** A repository's merge queue gained, lost or settled an entry. */
355 "queue.changed": { repoId: string };
356 /** `number` is the issue or pull request commented on. */
357 "comment.created": {
358 commentId: string;
359 repoId: string;
360 number: number;
361 /** Set when the comment is on a pull request. */
362 pullId?: string;
363 /** Set when the comment is a review. */
364 verdict?: Verdict;
Cards you act on in chat; agents comment and review as themselves; names shown cleanly; commits on the calendar365 /**
366 * Set when one of the workspace's agents wrote it, as itself; the
367 * event's actor is then the person it acted for (`actingFor`).
368 */
369 agent?: AgentRef;
370 actingFor?: { id: string; username: string };
371 /** An agent's review: its verdict is advisory and counts toward nothing. */
372 advisory?: boolean;
Icons are cached at the edge373 };
Merge Actions: cross-repo workflows and actions, release and deployment triggers, step timeouts374 /** A comment's text changed; `changes.body.from` is what it said before. */
375 "comment.edited": {
376 commentId: string;
377 repoId: string;
378 number: number;
379 /** Set when the comment is on a pull request. */
380 pullId?: string;
381 changes: { body: { from: string } };
382 };
383 /** A comment was deleted; `comment` is the comment as it was. */
384 "comment.deleted": {
385 commentId: string;
386 repoId: string;
387 number: number;
388 /** Set when the comment was on a pull request. */
389 pullId?: string;
390 comment: {
391 id: string;
392 body: string;
393 author: { id: string; username: string };
394 createdAt: string;
395 path: string | null;
396 line: number | null;
397 };
398 };
Icons are cached at the edge399 "session.appended": { pullId: string; repoId: string; number: number; count: number };
Agents and memory, checks and conflicts, profiles, slug renames, custom domains400 /**
Events: review requests, assignments, stops and deployments are published401 * A build of a project finished, for production or one pull request's
402 * preview (`number`). `path` is the deployment's page on the site;
403 * `recovered`, on a success, says the build before it failed.
404 */
405 "deployment.succeeded": DeploymentEventData;
406 "deployment.failed": DeploymentEventData;
407 /**
Merge branch 'main' into worktree-agent-a69aeabc4b0deeb97408 * A deployment was made, wherever it runs: reported through the API, by
409 * a g1t Actions job with an `environment:`, or a g1t.page build. Its
410 * `payload` is left out: read the deployment for it.
411 */
Merge Actions: cross-repo workflows and actions, release and deployment triggers, step timeouts412 "deployment.created": { repoId: string; deployment: Omit<RepoDeployment, "payload">; causedByJob?: string };
413 /**
414 * A deployment has a new status; `deployment` is as it is now.
415 * `causedByJob` (as on every event a workflow job's token causes) is the
416 * run whose job made it, so no workflow starts for it.
417 */
Merge branch 'main' into worktree-agent-a69aeabc4b0deeb97418 "deployment_status.created": {
419 repoId: string;
420 deployment: Omit<RepoDeployment, "payload">;
421 deploymentStatus: DeploymentStatus;
Merge Actions: cross-repo workflows and actions, release and deployment triggers, step timeouts422 causedByJob?: string;
Merge branch 'main' into worktree-agent-a69aeabc4b0deeb97423 };
424 /**
Merge Actions: cross-repo workflows and actions, release and deployment triggers, step timeouts425 * A release changed, one event per GitHub release activity it amounts
426 * to: made (`created`; a published one is also `published`, and
427 * `released` or `prereleased`), a draft published, edited, made a draft
428 * again (`unpublished`) or deleted. `release` is as it is now (as it was,
429 * for `release.deleted`).
430 */
431 "release.created": ReleaseEventData;
432 "release.published": ReleaseEventData;
433 "release.released": ReleaseEventData;
434 "release.prereleased": ReleaseEventData;
435 "release.edited": ReleaseEventData;
436 "release.unpublished": ReleaseEventData;
437 "release.deleted": ReleaseEventData;
438 /**
Packages, with a container registry on g1t.sh; workspaces deleted whole and kept 30 days; Members for every member439 * A package version was published, such as an image pushed by
440 * `docker push`. `tags` are the tags that now point to it; `repoId` (and
441 * the event's) is the repository the package is linked to, if any.
442 */
443 "package.published": PackageEventData & { version: string; digest: string; size: number; tags: string[] };
444 /** One version of a package was deleted, with the tags that pointed to it. */
445 "package.version_deleted": PackageEventData & { version: string; digest: string };
446 /** A package was deleted with every version it had. */
447 "package.deleted": PackageEventData;
448 /** A package became public or private. */
449 "package.visibility_changed": PackageEventData & { visibility: "public" | "private" };
450 /**
Agents and memory, checks and conflicts, profiles, slug renames, custom domains451 * A workspace's slug changed from `from` to `to`. Services that store a
452 * slug move their rows to the workspace's *current* slug (see
453 * `currentWorkspaceSlug`), so a repeated or late delivery after a second
454 * rename still lands in the right place.
455 */
456 "workspace.renamed": { workspaceId: string; from: string; to: string };
Agents get guardrails, run credentials, an audit log, a context hub, repository instructions and mentions; security upkeep; snake_case API457 /**
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look458 * A repository moved from workspace `from` to `to`, keeping its id and
459 * name. Services that store its path or its workspace's slug move those
460 * rows to its *current* path (ask repos `path_by_id`), so a repeated or
461 * late delivery after a second transfer still lands in the right place.
462 */
463 "repo.transferred": { repoId: string; name: string; from: string; to: string };
464 /**
465 * A workspace is gone. Services drop what they keep for it alone; ledgers,
466 * invoices and the audit log stay under its slug, which is never reused.
467 */
468 "workspace.deleted": { workspaceId: string; slug: string };
469 /**
Packages, with a container registry on g1t.sh; workspaces deleted whole and kept 30 days; Members for every member470 * An owner deleted a workspace; staff can restore it until `purgeAfter`,
471 * and nobody can reach it meanwhile. Services hide what they keep for it
472 * and stop what runs for it, keeping their rows: repos deletes its
473 * repositories softly (`repo.deleted` with `withWorkspace`), deployments
474 * pauses its apps, search drops it. `workspace.restored` undoes exactly
475 * that; `workspace.deleted` follows once `purgeAfter` passes. `by` is the
476 * owner's username.
477 */
478 "workspace.deleting": { workspaceId: string; slug: string; by: string; purgeAfter: string };
479 /**
480 * Staff brought a deleted workspace back with its members and tokens.
481 * Services undo what they did on `workspace.deleting`, and only that.
482 */
483 "workspace.restored": { workspaceId: string; slug: string };
484 /**
Agents get guardrails, run credentials, an audit log, a context hub, repository instructions and mentions; security upkeep; snake_case API485 * A memory was added, changed, reviewed or forgotten. No text: ask the
486 * work service for it by id. `repoId` is the project's, or null for the
487 * workspace's memory. `status` is `deleted` once forgotten.
488 */
489 "memory.changed": { memoryId: string; workspace: string; status: "candidate" | "kept" | "dismissed" | "deleted" };
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look490 /**
491 * A sandbox was stopped because it looked like it was mining: CPU pinned
492 * with little I/O and no progress, or a miner seen by name. For g1t's
493 * staff, in sudo; published with no `repoId` so it never reaches a
494 * repository's timeline or webhooks. `metrics` is what the sandbox
495 * measured (`Verdict` in crates/runner abuse.rs), or null if it could
496 * not say.
497 */
498 "abuse.flagged": {
499 workspace: string;
500 repo: string | null;
501 /** The agent run, when the sandbox had one. */
502 run: string | null;
503 /** What the sandbox was for: agent, checks, queue, actions, deploy... */
504 kind: string;
505 sandbox: string;
506 metrics: Record<string, unknown> | null;
507 };
Docs know what code they describe; a project's docs folder in Docs; Docs events; files on any S3 store508 /**
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.509 * 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 store510 * a page (which may be in a private space) never reaches a repository's
511 * 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.512 * 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 store513 */
514 "doc.page.created": DocPageEventData;
515 /**
516 * A page's content changed: at most once per page every ten minutes of
517 * editing (when its history records a version), and for every agent
518 * edit, accepted suggestion and restore. `authors` are member keys
519 * (`user:<id>`, `agent:<id>`) of everyone whose changes are in it.
520 */
521 "doc.page.updated": DocPageEventData & { versionId: string; kind: "edit" | "agent" | "suggestion" | "restore"; authors: string[] };
522 /** A page went to the trash (with every page under it; one event for the page asked about). */
523 "doc.page.archived": DocPageEventData;
524 /**
525 * A page became possibly out of date: a merged pull request or a push to
526 * a repository's default branch changed code it cites. `repoId` is in
527 * `data`, not on the event, for the same reason as above. `owners` are
528 * member keys; an agent that owns the page can update it
529 * (`stalePagesForAgent` in docs.ts).
530 */
531 "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 yet532 /**
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.533 * 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 yet534 * 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.535 * 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 yet536 */
537 "folio.created": FolioEventData;
538 /** A folio's content changed: a version (`versionKind`) with everyone whose changes are in it. */
539 "folio.updated": FolioEventData & { versionId: string; versionKind: "edit" | "agent" | "suggestion" | "proposal" | "restore"; authors: string[] };
540 /** A folio went to the trash (with everything under it; one event for the folio asked about). */
541 "folio.trashed": FolioEventData;
542 "folio.restored": FolioEventData;
Merge branch 'customize' into main: Customize replaces the Marketplace, the Artifacts trash and spaces changes, the Security-free cleanup, with the desktop app's own title bar kept in the shell.543 /**
544 * A folio was deleted for good from the trash (with everything under it;
545 * one event for each top that went): by someone with full access, by
546 * emptying the trash, or by the daily purge (`actor` null then).
547 */
548 "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 yet549 /** Someone was given access: who (member keys) and the role. Never content. */
550 "folio.shared": FolioEventData & { principals: string[]; role: "view" | "comment" | "edit" | "manage" };
551 /** Code a folio cites changed. The repository is in `data` as `owner/name` only. */
552 "folio.stale": FolioEventData & { repo: string; commit: string; pull: number | null; paths: string[]; owners: string[] };
Merge branch 'customize' into main: Customize replaces the Marketplace, the Artifacts trash and spaces changes, the Security-free cleanup, with the desktop app's own title bar kept in the shell.553 /**
554 * A space was deleted (services/artifacts): everything in it went to the
555 * trash (`trashed` counts the artifacts; this one event stands for them
556 * all). Like `folio.*`, published with no `repoId` and never offered to
557 * webhooks; `name` is null for a members-only space.
558 */
559 "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 yet560};
561
562/**
563 * What every `folio.*` event carries. `title` is null unless every member
564 * of the workspace can read the folio, so a private folio's name never
565 * travels.
566 */
567export type FolioEventData = {
568 workspace: string;
569 workspaceId: string;
570 folioId: string;
571 kind: "doc" | "slides" | "design" | "dashboard";
572 spaceId: string | null;
573 title: string | null;
Docs know what code they describe; a project's docs folder in Docs; Docs events; files on any S3 store574};
575
576/** What every `doc.page.*` event carries. */
577export type DocPageEventData = {
578 workspace: string;
579 workspaceId: string;
580 pageId: string;
581 spaceId: string;
582 title: string;
583 /** The page's address on the site. */
584 path: string;
Icons are cached at the edge585};
586
587export type EventType = keyof EventPayloads;
588
589export type G1tEvent<T extends EventType = EventType> = {
590 [K in T]: {
591 id: string;
592 type: K;
593 /** The service that published it. */
594 source: string;
595 /** RFC 3339. */
596 time: string;
597 /** The repo the event concerns, used to scope timelines and deliveries. */
598 repoId: string | null;
599 /** The user or agent that caused it, if any. */
600 actor: string | null;
601 data: EventPayloads[K];
602 };
603}[T];
604
605/** What a publisher supplies; the bus fills in `id` and `time`. */
606export type NewEvent<T extends EventType = EventType> = {
607 [K in T]: Omit<G1tEvent<K>, "id" | "time">;
608}[T];
609
610export type EventQuery = {
611 repoId?: string;
612 types?: EventType[];
613 /** Return events older than this event id. */
614 before?: string;
Merge leftovers: plan activity filtered in the query, pushes counted by account, ghost during the deletion window, profile time zones (identity 0039)615 /** Only events by this account id. */
616 actor?: string;
617 /** Only events about these issues or pull requests (`number`, or the `issue` a comment or review is on). */
618 numbers?: number[];
619 /** Only events at or after this RFC 3339 time. */
620 since?: string;
Icons are cached at the edge621 limit?: number;
622};
623
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.624/**
625 * `activity_digest`: what happened in some repositories, and to a
626 * workspace's artifacts, over `[from, until)`, counted by who did it. Home
627 * reads it for what people and agents did since you were last there.
628 * snake_case, as the Rust service reads it
629 * (`g1t_contracts::events::ActivityDigestArgs`).
630 */
631export type ActivityDigestArgs = {
632 /** By id; the caller has checked the viewer may read each. At most `MAX_DIGEST_REPOS` are read. */
633 repo_ids: string[];
634 /** The workspace's slug, for its `folio.*` events (which carry no repository); null leaves artifacts out. */
635 workspace: string | null;
636 /** RFC 3339, inclusive. */
637 from: string;
638 /** RFC 3339, exclusive. */
639 until: string;
640};
641
642/** The most repositories one digest reads. */
643export const MAX_DIGEST_REPOS = 50;
644
645/**
646 * How many times one actor did something. The actor is a member key:
647 * `user:<id>` for a person (or g1t, `user:usr_g1t_agent`), `agent:<id>` for
648 * one of the workspace's agents acting as itself, or `""` when the event
649 * named nobody (a push copied in by a mirror).
650 */
651export type ActorCount = { actor: string; count: number };
652
653/** Pushes by one actor, with the commits they brought. */
654export type PushesBy = { actor: string; count: number; commits: number };
655
656/** Pushes to a repository's branches (tags are not pushes here). A push whose commits were not counted counts as one commit. */
657export type PushDigest = {
658 count: number;
659 commits: number;
660 /** The branches pushed to, by name, sorted. */
661 branches: string[];
662 /** Most pushes first. */
663 by: PushesBy[];
664 /** Of those, the pushes straight to the default branch: what landed without a pull request. */
665 default_branch: { count: number; commits: number; by: PushesBy[]; last_at: string | null };
666};
667
668export type RepoDigest = {
669 repo_id: string;
670 pushes: PushDigest;
671 /** Pull requests opened, merged and closed without merging, each by who did it. */
672 pulls: { opened: ActorCount[]; merged: ActorCount[]; closed: ActorCount[] };
673 issues: { opened: ActorCount[]; closed: ActorCount[] };
674 /** `review.completed` (g1t's), and a comment with a verdict (a person's). */
675 reviews: ActorCount[];
676 /** Comments without a verdict; one by an agent as itself is the agent's. */
677 comments: ActorCount[];
678 /** Builds that finished, by who set them off; `production` is how many successes were production. */
679 deployments: { succeeded: ActorCount[]; failed: ActorCount[]; production: number };
680 /** Releases published, newest first, at most 50. */
681 releases: { tag: string; name: string | null; actor: string; at: string }[];
682 /** Package versions published, newest first, at most 50. */
683 packages: { ecosystem: string; name: string; version: string; actor: string; at: string }[];
684};
685
686/** A workspace's artifacts over the span. Never a title. */
687export type FolioDigest = {
688 created: ActorCount[];
689 /** Each folio whose content changed, once, with everyone whose changes are in it (member keys); at most 50. */
690 edited: { folio_id: string; kind: "doc" | "slides" | "design" | "dashboard" | string; authors: string[] }[];
691 /** How many folios changed, counting those past the cap. */
692 edited_count: number;
693};
694
695export type ActivityDigest = {
696 from: string;
697 until: string;
698 /** One per repository that had any event counted; none for a quiet one. */
699 repos: RepoDigest[];
700 /** When a workspace was named. */
701 folios: FolioDigest | null;
702 /** False when more events fell in the span than were read, or more repositories were named than are read, so counts are low. */
703 complete: boolean;
704};
705
Icons are cached at the edge706/** The event bus and its durable log. */
707export interface EventsApi {
708 publish(events: NewEvent[]): Promise<void>;
709 /** Newest first. */
710 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.711 /** A span of some repositories' and a workspace's artifacts' events, counted by who did it. */
712 activityDigest(args: ActivityDigestArgs): Promise<ActivityDigest>;
Icons are cached at the edge713}

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