Skip to content
1,392 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.

Agents have faces, and are never mistaken for people. Every agent wears a little bot face drawn from a look it owns, shape, colour, eyes, mouth, antenna, accessory and pattern, chosen in its builder and on its Profile tab with a live preview, Shuffle and a way back to the face its seed gives it; the face blinks on its own time, breathes, narrows its eyes while the agent works, shuts them asleep and bounces when it finishes, all of it still for anyone who asked for less motion. Wherever an agent shows, in chat, in a list, on a mention, on a review or a commit, its avatar carries an agent marker, and the people reading it are told so. In Chat, direct messages are two lists: People, and Agents, which also holds the agents you haven't talked to yet; a conversation with both a person and an agent in it is marked in the list, named in the conversation's header, spelled out by the composer and explained once the first time it opens. Agents keep their look in the agents service, which every service passes along. The chat and agents guides say so, and CONTRIBUTING makes the shared avatar the only way to draw an agent.1import type { AgentLook } from "./agent-look";
Merge checks: statuses and check runs on every commit2import type { ChecksApi } from "./checks";
Teams and CODEOWNERS, labels and milestones, dependency updates, the security suite, and a clearer top bar3import type { CodeownersReport, PullCodeOwners } from "./codeowners";
Projects live: fixes from walking them end to end4import type { User, Viewer } from "./identity";
Catching up with main takes seconds when the two sides touched different files5import type { PullBranchUpdate, RepoPath } from "./repos";
Projects live: fixes from walking them end to end6import type { Result } from "./result";
Merge rulesets: branch and tag rules, agent-first, enforced on push and merge7import type { MergeRules, RulesApi } from "./rules";
Projects live: fixes from walking them end to end8
9/**
10 * The filter on lists of issues and pull requests. An open pull request is
11 * a draft or one ready for review; a closed one was merged or closed
12 * without merging.
13 */
14export type State = "open" | "closed";
15
16/** Why an issue was closed. */
17export type IssueReason = "completed" | "not_planned";
18
19/**
20 * Something that should change in a repository: a bug, a feature, a
21 * question. Opened by a person, an agent or an integration. Pull requests
22 * are made against it; the one that is merged resolves it.
23 *
24 * Issues and pull requests share one sequence of numbers per repository.
25 */
26export type Issue = {
27 id: string;
28 repoId: string;
29 /** Shown as `#12`. */
30 number: number;
31 title: string;
32 /** Markdown. Also what an agent is given to work from. */
33 body: string;
34 labels: string[];
35 state: State;
36 /** Set when closed. */
37 reason: IssueReason | null;
38 /** The number of the pull request whose merge closed this issue. */
39 resolvedBy: number | null;
g1t is the stored author of what it opens; the person who asked is requested_by and keeps the author's rights40 /** Who opened it: a person, an integration, or g1t (`kind` `agent`) for one its agent filed while at work. */
Projects live: fixes from walking them end to end41 author: User;
g1t is the stored author of what it opens; the person who asked is requested_by and keeps the author's rights42 /**
43 * For an issue g1t's agent filed: the person it was working for. They may
44 * manage it as its author could. See `workOwner`.
45 */
46 requestedBy: User | null;
Projects live: fixes from walking them end to end47 /** RFC 3339. */
48 createdAt: string;
49 /** RFC 3339. */
50 updatedAt: string;
51 /** RFC 3339. */
52 closedAt: string | null;
53 /** Pull requests made against this issue, in any state. */
54 pullCount: number;
55 commentCount: number;
56 /** Usernames of the people it is assigned to. */
57 assignees: string[];
58 /** The numbers of the issues that have to be merged before this one is worked on. */
59 blockedBy: number[];
60 /**
61 * Whether a g1t agent takes it as soon as it can: at once, or when what it
62 * is blocked by has merged.
63 */
64 queued: boolean;
65 /**
66 * The agent working on it now: the one behind its newest pull request
g1t is one name: its agent's work, commits and comments show as @g1t, and nobody can claim g1t or g1t-agent67 * that is still in progress in a fork, such as `g1t`.
Projects live: fixes from walking them end to end68 */
69 agent: string | null;
Teams and CODEOWNERS, labels and milestones, dependency updates, the security suite, and a clearer top bar70 /** The milestone it is in, if any. */
71 milestone?: MilestoneRef | null;
Projects live: fixes from walking them end to end72};
73
g1t is the stored author of what it opens; the person who asked is requested_by and keeps the author's rights74/**
Teams and CODEOWNERS, labels and milestones, dependency updates, the security suite, and a clearer top bar75 * A label of a repository: a name, a color and what it means. Issues and
76 * pull requests carry labels by name; names are lowercase.
77 */
78export type Label = {
79 name: string;
80 /** Six hex digits, without `#`. */
81 color: string;
82 description: string;
83 /** How many issues carry it, open or closed. */
84 issues: number;
85 /** How many pull requests carry it, in any state. */
86 pulls: number;
87};
88
89/** A milestone, as an issue or pull request names it. */
90export type MilestoneRef = { number: number; title: string };
91
92/**
93 * A goal, with an optional due date, that issues and pull requests are
94 * gathered under. Its progress is how many of them are closed.
95 */
96export type Milestone = {
97 /** Numbered from 1 in each repository, apart from issues. */
98 number: number;
99 title: string;
100 /** Markdown. */
101 description: string;
102 /** `YYYY-MM-DD`. */
103 dueOn: string | null;
104 state: State;
105 /** Open issues and pull requests in it. */
106 openItems: number;
107 /** Closed issues, and merged or closed pull requests, in it. */
108 closedItems: number;
109 createdAt: string;
110 updatedAt: string;
111 closedAt: string | null;
112};
113
114/** One milestone and what is in it, newest first. */
115export type MilestoneDetail = { milestone: Milestone; issues: Issue[]; pulls: Pull[] };
116
117/** How `setLabels` changes an item's labels. */
118export type LabelChange = "set" | "add" | "remove";
119
120/**
g1t is the stored author of what it opens; the person who asked is requested_by and keeps the author's rights121 * Whose an issue or a pull request is to answer for: whoever asked g1t for
122 * it, or its author. They may change, close and steer it, are never asked to
123 * review it and cannot approve it, and see it as theirs. Mirrors
124 * `Pull::owner` in the Rust contracts.
125 */
126export function workOwner(item: Pick<Pull, "author" | "requestedBy">): User {
127 return item.requestedBy ?? item.author;
128}
129
Projects live: fixes from walking them end to end130/** `draft` is still being worked on; `open` is ready for review. */
131export type PullStatus = "draft" | "open" | "merged" | "closed";
132
133/** Where the agent runs: on g1t's sandboxes, or in someone's own session. */
134export type Runtime = "hosted" | "external";
135
136/**
137 * A proposed change. It is made either in a fork created for it, which is
138 * how agents work, or on a branch pushed to the repository itself.
139 */
140export type Pull = {
141 id: string;
142 repoId: string;
143 /** Shown as `#12`. */
144 number: number;
145 /** The number of the issue this is for, if any. */
146 issue: number | null;
147 title: string;
148 /** Markdown: what changed and why. Set when marked ready. */
149 body: string | null;
150 /** A label for the agent doing the work, e.g. `claude-code`. */
151 agent: string;
152 runtime: Runtime;
153 status: PullStatus;
154 /** The fork holding the change, unless it is on a branch. */
155 fork: RepoPath | null;
156 /** The fork's repository id. */
157 forkRepoId: string | null;
158 /** The branch of the repository holding the change, unless it is in a fork. */
159 branch: string | null;
160 headCommit: string | null;
161 /**
162 * For a merged pull request, what the branch pointed to before the merge.
163 * Comparing against it shows what the pull request changed.
164 */
165 mergeBase: string | null;
166 /** Username of whoever merged it. */
167 mergedBy: string | null;
168 /** RFC 3339. */
169 mergedAt: string | null;
170 /**
171 * Set on a pull request closed because another one for the same issue was
172 * merged: that one's number.
173 */
174 supersededBy: number | null;
175 /**
176 * Where the latest run of the issue's acceptance checks stands, if there
177 * has been one against the current head.
178 */
179 checkStatus: CheckStatus | null;
180 /** The files it changes, as of its latest push. */
181 files: ChangedFile[];
182 /** Usernames of the people it is assigned to. */
183 assignees: string[];
184 /**
g1t is one name: its agent's work, commits and comments show as @g1t, and nobody can claim g1t or g1t-agent185 * Those whose review was asked for: usernames, and `g1t` when a g1t
Projects live: fixes from walking them end to end186 * agent was asked.
187 */
188 reviewers: string[];
Teams and CODEOWNERS, labels and milestones, dependency updates, the security suite, and a clearer top bar189 /**
190 * Teams whose review was asked for, as `workspace/slug`. A team stays here
191 * after review assignment picks people from it, who are in `reviewers`.
192 */
193 teamReviewers?: string[];
194 /** The labels it carries, by name. */
195 labels?: string[];
196 /** The milestone it is in, if any. */
197 milestone?: MilestoneRef | null;
198 /**
199 * The branch it merges into. Lists and `getPull` name it; null only in
200 * what services pass between themselves, for the default branch.
201 */
202 base?: string | null;
g1t is the stored author of what it opens; the person who asked is requested_by and keeps the author's rights203 /** Who opened it: a person, or g1t (`kind` `agent`, username `g1t`) for a change g1t made. */
Projects live: fixes from walking them end to end204 author: User;
g1t is the stored author of what it opens; the person who asked is requested_by and keeps the author's rights205 /**
206 * For a change g1t made: the person who asked for it, by assigning an issue
207 * or handing g1t the work. They answer for it as its author would. See
208 * `workOwner`.
209 */
210 requestedBy: User | null;
Projects live: fixes from walking them end to end211 /** RFC 3339. */
212 createdAt: string;
213 /** RFC 3339. */
214 updatedAt: string;
Thirteen MCP tools and classic token scopes; agents rate their confidence and can be put on an issue in one step215 /**
216 * How sure g1t is of a g1t agent's change, from what it can observe, once
217 * the agent has finished it. Absent before then, and on changes g1t is
218 * not seeing through.
219 */
220 confidence?: Confidence | null;
Merge rulesets: branch and tag rules, agent-first, enforced on push and merge221 /** Who last moved its head (a user id), and when; absent until a push after rulesets arrived. */
222 headPushedBy?: string;
223 headPushedAt?: string;
Thirteen MCP tools and classic token scopes; agents rate their confidence and can be put on an issue in one step224};
225
226/** How sure g1t is that an agent's change is right. */
227export type ConfidenceLevel = "low" | "medium" | "high";
228
229/**
230 * How sure g1t is of a change an agent made, worked out from what can be
231 * observed: its checks, how often it was sent back, the reviewer agent's
232 * verdict, whether it touched tests, its size, where it reached, how close
233 * it came to its guardrails, and what it asked without an answer. The
234 * agent's own word can only lower it.
235 */
236export type Confidence = {
237 level: ConfidenceLevel;
238 /** A few words each, most telling first: what lowered it, or for `high`, what it rests on. */
239 reasons: string[];
240 /** What the agent said of its own change, if it said. */
241 selfReported: ConfidenceLevel | null;
242 /** What the agent said it was unsure about. */
243 uncertainAbout: string[];
244 /** The agent run it was worked out after. */
245 runId: string | null;
246 /** RFC 3339. */
247 assessedAt: string;
248};
249
250/** What became of the agent when an issue was opened and handed to it in one step. */
251export type AgentStartStatus = "started" | "queued" | "not_started";
252
253/** Whether the agent started, and if not, why and what fixes it. */
254export type AgentStart = {
255 status: AgentStartStatus;
256 /**
257 * Why it did not start: `not_paid`, `trial_used`, `limit`, `paused`,
258 * `issue_cap`, `billing_unavailable` or `no_model`; `waiting` when queued.
259 */
260 code: string | null;
261 /** What happened, in a sentence or two, with what to do. */
262 message: string | null;
263 /** Where the fix is: the workspace's billing or model settings. */
264 fixUrl: string | null;
Projects live: fixes from walking them end to end265};
266
g1t is one name: its agent's work, commits and comments show as @g1t, and nobody can claim g1t or g1t-agent267/** An issue opened and handed to g1t in one step. The issue exists whatever became of the agent. */
Thirteen MCP tools and classic token scopes; agents rate their confidence and can be put on an issue in one step268export type Delegated = {
269 issue: Issue;
270 /** The pull request the agent opened, when it started. */
271 pull: Pull | null;
272 agent: AgentStart;
273};
274
Fast pages, required checks on the branch, self-hosted runners, honest incidents275/**
276 * What to put an agent on: an issue's title, and what to do in plain words,
277 * with what done means if you like (a "Definition of done" section). What
278 * has to pass before it merges is the branch's required checks.
279 */
Thirteen MCP tools and classic token scopes; agents rate their confidence and can be put on an issue in one step280export type DelegateInput = {
281 title: string;
282 body: string;
283 labels?: string[];
Fast pages, required checks on the branch, self-hosted runners, honest incidents284 /** Deprecated: commands, added to the body under "Definition of done". */
Thirteen MCP tools and classic token scopes; agents rate their confidence and can be put on an issue in one step285 checks?: string[];
286};
287
Projects live: fixes from walking them end to end288/** One file a pull request changes, and by how much. */
289export type ChangedFile = { path: string; additions: number; deletions: number };
290
291/**
292 * Another pull request in progress that changes some of the same files. Two
293 * for the same issue are alternatives; two for different issues are heading
294 * for a conflict.
295 */
296export type Overlap = {
297 number: number;
298 title: string;
299 /** The number of the issue the other pull request is for. */
300 issue: number | null;
301 /** The files both change. */
302 paths: string[];
303};
304
Fast pages, required checks on the branch, self-hosted runners, honest incidents305/**
306 * On a pull request, `failed` means the merge queue took it out, until its
307 * head moves. The other states are from runs of commands written on issues,
308 * which g1t no longer runs.
309 */
Projects live: fixes from walking them end to end310export type CheckStatus = "queued" | "running" | "passed" | "failed" | "errored";
311
Fast pages, required checks on the branch, self-hosted runners, honest incidents312/** How one command went, in a run recorded before checks were workflows. */
Projects live: fixes from walking them end to end313export type CheckResult = {
314 command: string;
315 passed: boolean;
316 /** Null when the command was stopped for taking too long. */
317 exitCode: number | null;
318 /** What the command printed; the end of it, when there was a lot. */
319 output: string;
320 durationMs: number;
321};
322
323/**
Fast pages, required checks on the branch, self-hosted runners, honest incidents324 * A record against a pull request's head: the merge queue taking it out,
325 * with why, or an earlier run of commands written on its issue.
Projects live: fixes from walking them end to end326 */
327export type CheckRun = {
328 id: string;
329 /** The commit that was checked. */
330 headCommit: string;
331 status: CheckStatus;
332 results: CheckResult[];
333 /** Why the checks could not be run, when `status` is `errored`. */
334 error: string | null;
335 /** RFC 3339. */
336 createdAt: string;
337 /** RFC 3339. */
338 finishedAt: string | null;
339};
340
341/** A reviewer's decision on a pull request. */
342export type Verdict = "approve" | "request_changes";
343
344/**
345 * A comment on an issue or a pull request. On a pull request it can sit on
346 * one line of the change, and it can carry a reviewer's verdict.
347 */
348export type Comment = {
349 id: string;
350 /**
351 * Something a person or an agent wrote, or something that happened: an
352 * assignment, a review asked for, a close.
353 */
354 kind: "comment" | "event";
355 author: User;
356 /**
357 * Markdown. For an event, what its author did, as the rest of a sentence
358 * that starts with their name: "assigned ana".
359 */
360 body: string;
361 /** The file commented on, for a comment on a line. */
362 path: string | null;
363 /** The line of that file, as numbered after the change. */
364 line: number | null;
365 verdict: Verdict | null;
366 /** RFC 3339. */
367 createdAt: string;
Merge Actions: cross-repo workflows and actions, release and deployment triggers, step timeouts368 /** When its text was last edited, RFC 3339; absent if it never was. */
369 editedAt?: string;
Cards you act on in chat; agents comment and review as themselves; names shown cleanly; commits on the calendar370 /**
371 * Set when one of the workspace's agents wrote it, as itself. `author`
372 * is then the agent (its id, its handle as `username`, kind `agent`):
373 * show it by `agent.displayName` with an Agent badge, never as a person.
374 */
375 agent?: AgentRef;
376 /** Who the agent acted for, whose access capped it. Set with `agent`. */
377 actingFor?: User;
378 /**
379 * An agent's review. Its `verdict` (none for a review that only
380 * comments) is shown but advisory: it never counts toward required
381 * approvals or code owners, and never blocks a merge.
382 */
383 advisory?: boolean;
384};
385
386/**
387 * One of a workspace's own agents as a comment or review it wrote shows
Agents have faces, and are never mistaken for people. Every agent wears a little bot face drawn from a look it owns, shape, colour, eyes, mouth, antenna, accessory and pattern, chosen in its builder and on its Profile tab with a live preview, Shuffle and a way back to the face its seed gives it; the face blinks on its own time, breathes, narrows its eyes while the agent works, shuts them asleep and bounces when it finishes, all of it still for anyone who asked for less motion. Wherever an agent shows, in chat, in a list, on a mention, on a review or a commit, its avatar carries an agent marker, and the people reading it are told so. In Chat, direct messages are two lists: People, and Agents, which also holds the agents you haven't talked to yet; a conversation with both a person and an agent in it is marked in the list, named in the conversation's header, spelled out by the composer and explained once the first time it opens. Agents keep their look in the agents service, which every service passes along. The chat and agents guides say so, and CONTRIBUTING makes the shared avatar the only way to draw an agent.388 * it: Margo (@margo), with the face drawn from `avatarSeed` or chosen as `look`. Its page
Cards you act on in chat; agents comment and review as themselves; names shown cleanly; commits on the calendar389 * is `/<workspace>/-/agents/<handle>`.
390 */
391export type AgentRef = {
392 id: string;
393 handle: string;
394 displayName: string;
395 avatarSeed: string;
Agents have faces, and are never mistaken for people. Every agent wears a little bot face drawn from a look it owns, shape, colour, eyes, mouth, antenna, accessory and pattern, chosen in its builder and on its Profile tab with a live preview, Shuffle and a way back to the face its seed gives it; the face blinks on its own time, breathes, narrows its eyes while the agent works, shuts them asleep and bounces when it finishes, all of it still for anyone who asked for less motion. Wherever an agent shows, in chat, in a list, on a mention, on a review or a commit, its avatar carries an agent marker, and the people reading it are told so. In Chat, direct messages are two lists: People, and Agents, which also holds the agents you haven't talked to yet; a conversation with both a person and an agent in it is marked in the list, named in the conversation's header, spelled out by the composer and explained once the first time it opens. Agents keep their look in the agents service, which every service passes along. The chat and agents guides say so, and CONTRIBUTING makes the shared avatar the only way to draw an agent.396 /** Its chosen face (./agent-look.ts), when it has one. */
397 look?: AgentLook | null;
Projects live: fixes from walking them end to end398};
399
Cards you act on in chat; agents comment and review as themselves; names shown cleanly; commits on the calendar400/** An agent's review: all of them advisory. */
401export type AgentVerdict = "comment" | "approve" | "request_changes";
402
403/** How many comments and reviews one agent may write on one issue or pull request an hour. */
404export const AGENT_COMMENTS_PER_HOUR = 5;
405
406/** An agent as its comments name it, from the agents service's record of it. */
Agents have faces, and are never mistaken for people. Every agent wears a little bot face drawn from a look it owns, shape, colour, eyes, mouth, antenna, accessory and pattern, chosen in its builder and on its Profile tab with a live preview, Shuffle and a way back to the face its seed gives it; the face blinks on its own time, breathes, narrows its eyes while the agent works, shuts them asleep and bounces when it finishes, all of it still for anyone who asked for less motion. Wherever an agent shows, in chat, in a list, on a mention, on a review or a commit, its avatar carries an agent marker, and the people reading it are told so. In Chat, direct messages are two lists: People, and Agents, which also holds the agents you haven't talked to yet; a conversation with both a person and an agent in it is marked in the list, named in the conversation's header, spelled out by the composer and explained once the first time it opens. Agents keep their look in the agents service, which every service passes along. The chat and agents guides say so, and CONTRIBUTING makes the shared avatar the only way to draw an agent.407export function agentRef(agent: { id: string; handle: string; display_name: string; avatar_seed: string; look?: AgentLook | null }): AgentRef {
408 return { id: agent.id, handle: agent.handle, displayName: agent.display_name, avatarSeed: agent.avatar_seed, look: agent.look ?? null };
Cards you act on in chat; agents comment and review as themselves; names shown cleanly; commits on the calendar409}
410
Projects live: fixes from walking them end to end411export type NewComment = {
412 /** May be empty when approving. */
413 body: string;
414 path?: string;
415 line?: number;
416 verdict?: Verdict;
417};
418
419/** What a sandbox needs to carry out a check run. */
420export type CheckJob = {
421 runId: string;
422 /** Lets the sandbox, and nothing else, report this run's results. */
423 token: string;
424 commands: string[];
425 /** The repository holding the commit: the fork, or the repository itself. */
426 source: RepoPath;
427 commit: string;
g1t is the stored author of what it opens; the person who asked is requested_by and keeps the author's rights428 /** Who the pull request is for (`workOwner`: whoever asked g1t for it, or its author), and so can read its source. */
Projects live: fixes from walking them end to end429 author: User;
430 /** Username of whoever wrote the checks: the issue's author. */
431 requestedBy: string;
432 repo: RepoPath;
433 number: number;
434};
435
436export type CheckReport = { results?: CheckResult[]; error?: string; skip?: boolean };
437
438export type SessionEntryKind = "prompt" | "message" | "tool_call" | "tool_result" | "note";
439
440/** One step of an agent's session: the "why" behind a pull request's commits. */
441export type SessionEntry = {
442 seq: number;
443 kind: SessionEntryKind;
444 text: string;
445 /** For tool calls and results. */
446 tool: string | null;
447 /** The fork's head commit when this entry was recorded, if known. */
448 commit: string | null;
449 /** RFC 3339. */
450 at: string;
451};
452
453export type NewSessionEntry = Pick<SessionEntry, "kind" | "text"> &
454 Partial<Pick<SessionEntry, "tool" | "commit">>;
455
456export type IssueDetail = {
457 issue: Issue;
458 /** Every pull request made against it, oldest first. */
459 pulls: Pull[];
460 comments: Comment[];
461};
462
463export type PullDetail = {
464 pull: Pull;
465 /** The issue it is for, if any. */
466 issue: Issue | null;
467 comments: Comment[];
Fast pages, required checks on the branch, self-hosted runners, honest incidents468 /** The latest record against its head: the merge queue taking it out. */
Projects live: fixes from walking them end to end469 checks: CheckRun | null;
470 /** Other pull requests in progress that change the same files. */
471 overlaps: Overlap[];
472 /**
473 * Whether the branch it would merge into has moved on without it, so that
474 * it has to catch up before it can merge.
475 */
476 behind: boolean;
477 /** Whether a g1t agent is reviewing it right now. */
478 reviewPending: boolean;
479 /**
480 * Where it stands on its way to being merged, for a pull request g1t is
481 * seeing through. Null on anyone else's.
482 */
483 lifecycle: Lifecycle | null;
484 /**
485 * A merge was asked for while it was behind: g1t is bringing it up to
486 * date and will then land it.
487 */
488 landing: boolean;
489 /** Why g1t stopped working on it, if it did. */
490 stalled: string | null;
491 /** Messages people sent the agent while it worked, oldest first. */
492 messages: AgentMessage[];
493 /** What workflow runs said about its head commit, one per workflow. */
494 statuses?: CommitStatus[];
Agents and memory, checks and conflicts, profiles, slug renames, custom domains495 /**
496 * Whether it merges cleanly into the branch it targets, worked out ahead
497 * of time whenever either side moves.
498 */
499 mergeable?: Mergeable;
500 /** When `mergeable` is `conflicting`: the files that conflict. */
501 conflicts?: string[];
Fast pages, required checks on the branch, self-hosted runners, honest incidents502 /** Earlier records like `checks`, newest first, without their output. */
Agents and memory, checks and conflicts, profiles, slug renames, custom domains503 earlierChecks?: CheckRun[];
Fast pages, required checks on the branch, self-hosted runners, honest incidents504 /**
505 * The checks the default branch's protection requires, each as it stands
506 * on the head commit. Empty when none are required.
507 */
508 requiredChecks?: RequiredCheck[];
Teams and CODEOWNERS, labels and milestones, dependency updates, the security suite, and a clearer top bar509 /**
510 * Who owns the files it changes (the CODEOWNERS file of the branch it
511 * merges into) and whose approval is still needed. Absent without one.
512 */
513 codeOwners?: PullCodeOwners | null;
Merge rulesets: branch and tag rules, agent-first, enforced on push and merge514 /**
515 * The rules of the branch it merges into it does not meet yet, for whoever
516 * is looking: what refuses the merge, what they may bypass, and what rulesets
517 * in evaluate would refuse. Absent once it is closed or merged.
518 */
519 rules?: MergeRules | null;
Fast pages, required checks on the branch, self-hosted runners, honest incidents520};
521
522/** Where a required check stands on a commit; `expected` when nothing has reported it yet. */
523export type RequiredState = "success" | "failure" | "pending" | "expected";
524
525/** One check a branch's protection requires, as it stands on a commit. */
526export type RequiredCheck = {
527 /** A workflow's name, such as `CI`, or another status's context. */
528 name: string;
529 state: RequiredState;
530 description: string | null;
531 /** Where to see more: the workflow run, for one a workflow reported. */
532 targetUrl: string | null;
Agents and memory, checks and conflicts, profiles, slug renames, custom domains533};
534
Fast pages, required checks on the branch, self-hosted runners, honest incidents535/** A check name reported on a repository's commits lately, for choosing required checks. */
536export type SeenCheck = {
537 name: string;
538 /** The events it was reported for, such as `pull_request`; empty for a status that names none. */
539 events: string[];
540 /** RFC 3339. */
541 lastSeen: string;
542};
543
Agents and memory, checks and conflicts, profiles, slug renames, custom domains544/**
Fast pages, required checks on the branch, self-hosted runners, honest incidents545 * A status context's check name: `CI / pull_request` is the `CI` check,
546 * reported for a `pull_request` event. A context that does not end in an
547 * event, such as `g1t / deploy`, is its own name. As the work service reads it.
548 */
549export function checkName(context: string): string {
550 const at = context.lastIndexOf(" / ");
551 if (at <= 0) return context;
552 return STATUS_EVENTS.has(context.slice(at + 3)) ? context.slice(0, at) : context;
553}
554
555const STATUS_EVENTS = new Set([
556 "push",
557 "pull_request",
558 "pull_request_target",
559 "pull_request_review",
560 "merge_group",
561 "workflow_dispatch",
562 "workflow_run",
563 "workflow_call",
564 "schedule",
565 "release",
566 "issues",
567 "issue_comment",
568 "repository_dispatch",
569]);
570
571/**
Agents and memory, checks and conflicts, profiles, slug renames, custom domains572 * Whether a pull request merges cleanly into the branch it targets:
573 * `unknown` when it was never worked out or could not be, `checking` while
574 * a probe merges the two.
575 */
576export type Mergeable = "clean" | "conflicting" | "unknown" | "checking";
577
578/** What a sandbox needs to find out whether a pull request merges cleanly. */
579export type MergecheckJob = {
580 pullId: string;
581 /** Lets the sandbox, and nothing else, report this probe. */
582 token: string;
583 repo: RepoPath;
584 number: number;
585 defaultBranch: string;
586 /** The default branch's commit to merge into. */
587 base: string;
588 /** The repository holding the change: its fork, or the repository. */
589 source: RepoPath;
590 /** The branch of `source` holding it. */
591 branch: string;
592 /** The change's commit. */
593 head: string;
g1t is the stored author of what it opens; the person who asked is requested_by and keeps the author's rights594 /** Who the pull request is for (`workOwner`: whoever asked g1t for it, or its author), and so can read its source. */
Agents and memory, checks and conflicts, profiles, slug renames, custom domains595 author: User;
Projects live: fixes from walking them end to end596};
597
598/** What a workflow run (or another tool) says about a commit. */
599export type CommitStatus = {
600 /** What reported it, such as `CI / push`. */
601 context: string;
602 state: "pending" | "success" | "failure" | "error";
603 description: string | null;
604 targetUrl: string | null;
605 updatedAt: string;
Merge checks: statuses and check runs on every commit606 /** The integration that reported it: `actions`, `deployments`, `security`, `g1t` or `api`. */
607 source?: string;
608 /** Set on the status a check run stands as: the check run's id. */
609 checkRunId?: string;
Projects live: fixes from walking them end to end610};
611
612/**
613 * A step on the way from an assigned issue to a pull request that is ready
614 * to merge. g1t takes each one without being asked: `working` (the agent is
615 * making the change), `checking`, `reviewing`, `revising` (the agent is
616 * addressing failed checks or a review), `catching_up` (merging in the
617 * branch it would land on), `answering` (woken to answer another agent),
618 * then `ready` for a person to merge. `needs_you`
619 * means g1t has stopped and a person decides what happens next.
620 */
621export type Stage =
622 | "working"
623 | "checking"
624 | "reviewing"
625 | "revising"
626 | "catching_up"
627 | "answering"
628 | "queued"
629 | "ready"
630 | "needs_you";
631
632export type Lifecycle = {
633 stage: Stage;
634 /** One sentence saying what is happening, or why it stopped. */
635 detail: string;
636 /** How many times the agent has been sent back to revise it. */
637 revisions: number;
638};
639
640/** What the runner needs to carry out a step of a pull request's lifecycle. */
641export type LifecycleJob = {
642 pullId: string;
643 repo: RepoPath;
644 number: number;
g1t is the stored author of what it opens; the person who asked is requested_by and keeps the author's rights645 /** Who the pull request belongs to (`workOwner`: whoever asked g1t for it, or its author). Sandboxes act as them. */
Projects live: fixes from walking them end to end646 author: User;
647 /** The repository holding the change: its fork, or the repository itself. */
648 source: RepoPath;
649 /** The branch of the source holding the change; its default branch when null. */
650 branch: string | null;
651 defaultBranch: string;
652 title: string;
653 description: string;
654 issue: Issue | null;
655 /** For a revision: the failed checks or the review to address. */
656 feedback: string;
657 /** For a revision: which one this is, from 1. */
658 round: number;
659};
660
661/** An agent woken to answer what other agents sent it while it was not at work. */
662export type Wake = { job: LifecycleJob; messages: AgentMessage[] };
663
664/**
665 * `planning` while an agent reads the repository and writes it; `ready` for
666 * a person to read and apply; `failed` if it could not be written;
667 * `applied` once its issues are open.
668 */
669export type PlanStatus = "planning" | "ready" | "failed" | "applied";
670
671/** One issue a plan proposes. */
672export type PlannedIssue = {
673 title: string;
674 /** Markdown: what to change, where, and why. */
675 body: string;
676 labels: string[];
Fast pages, required checks on the branch, self-hosted runners, honest incidents677 /** What is true once it is done, in plain words; added to the issue's body under "Definition of done". */
678 done: string[];
Projects live: fixes from walking them end to end679 /** The files it will most likely change. */
680 files: string[];
681 /**
682 * The positions, counting from 1, of earlier issues in the plan that have
683 * to be merged first.
684 */
685 dependsOn: number[];
686 /** Its number, once the plan has been applied and it was kept. */
687 number: number | null;
688};
689
690/** An outcome someone wrote, and the issues an agent proposes to get there. */
691export type Plan = {
692 id: string;
693 repoId: string;
694 /** The outcome wanted, as written. */
695 brief: string;
696 status: PlanStatus;
697 /** The agent's account of how it split the work. */
698 summary: string;
699 issues: PlannedIssue[];
700 /** Why it could not be written, when `status` is `failed`. */
701 error: string | null;
702 author: User;
703 /** RFC 3339. */
704 createdAt: string;
705 /** RFC 3339. */
706 finishedAt: string | null;
707 /** Once applied: where each issue it opened stands now, in plan order. */
708 progress: IssueProgress[];
709 /** Questions and handoffs between its pull requests' agents, newest first. */
710 exchanges: AgentMessage[];
711};
712
713/** What a sandbox needs to write a plan. */
714export type PlanJob = {
715 planId: string;
716 /** Lets the sandbox, and nothing else, report this plan. */
717 token: string;
718 brief: string;
719 repo: RepoPath;
720};
721
722/** An issue waiting for a g1t agent that can be given one now. */
723export type ReadyIssue = {
724 repo: RepoPath;
725 number: number;
726 /** Who queued it, on whose say-so the agent works. */
727 actor: User;
728};
729
730/**
731 * How a repository wants its pull requests handled. A repository that has
732 * changed nothing has the defaults.
733 */
734export type RepoSettings = {
735 /**
736 * Land a g1t agent's pull request without a person once it is ready:
737 * checks passed and approved as the settings below require.
738 */
739 autoMerge: boolean;
740 /**
Fast pages, required checks on the branch, self-hosted runners, honest incidents741 * The checks that must pass on a pull request's head before it may merge
742 * into the default branch, by name: a workflow's name (`CI`) or another
743 * status's context (`g1t / deploy`). The same for people and agents, and
744 * for the merge queue.
745 */
746 requiredChecks: string[];
747 /**
Projects live: fixes from walking them end to end748 * Refuse to merge a pull request that does not contain the default
749 * branch's latest commits, so that what merges is what was checked. When
750 * off, merging one that is behind brings it up to date first.
751 */
752 requireUpToDate: boolean;
753 /**
754 * How many approving reviews a pull request needs before it may merge. A
755 * reviewer who has since asked for changes blocks it.
756 */
757 requiredApprovals: number;
758 /** Whether a g1t agent's approval counts towards `requiredApprovals`. */
759 countAgentApprovals: boolean;
Fast pages, required checks on the branch, self-hosted runners, honest incidents760 /** Whether someone who may merge can bypass required checks that have not passed. */
Projects live: fixes from walking them end to end761 allowIgnoringChecks: boolean;
762 /** Whether a g1t agent's pull request is reviewed by a second agent unasked. */
763 agentReview: boolean;
764 /**
765 * How many times a g1t agent is sent back to its pull request before a
766 * person is asked instead.
767 */
768 maxRevisions: number;
769 /**
770 * Merge through a queue: pull requests are tested together with those
771 * ahead of them, and only a combination that passed reaches the default
772 * branch.
773 */
774 mergeQueue: boolean;
Thirteen MCP tools and classic token scopes; agents rate their confidence and can be put on an issue in one step775 /**
776 * Ask a person before merging a g1t agent's change whose confidence is
777 * low: auto-merge and the merge queue leave it until a person approves it.
778 */
779 holdLowConfidence: boolean;
Teams and CODEOWNERS, labels and milestones, dependency updates, the security suite, and a clearer top bar780 /**
781 * Refuse to merge until the code owners of every file it changes have
782 * approved, as many as each section asks. People only; `g1t` only where
783 * the file names `@g1t`.
784 */
785 requireCodeOwnerReview?: boolean;
Projects live: fixes from walking them end to end786 /** Username of the member who last changed the settings, if anyone has. */
787 updatedBy: string | null;
788 /** RFC 3339. */
789 updatedAt: string | null;
790};
791
792/** The settings a member can change. */
793export type RepoSettingsInput = Omit<RepoSettings, "updatedBy" | "updatedAt">;
794
795/** The next step for a pull request g1t is seeing through, already claimed. */
796export type Advance =
797 | { action: "none" }
798 | { action: "review" | "revise" | "catch_up"; job: LifecycleJob };
799
800/** What a sandbox needs to review a pull request. */
801export type ReviewJob = {
802 runId: string;
803 /** Lets the sandbox, and nothing else, report this review. */
804 token: string;
805 /** The repository holding the commit: the fork, or the repository itself. */
806 source: RepoPath;
807 commit: string;
808 repo: RepoPath;
809 defaultBranch: string;
810 number: number;
811 title: string;
812 description: string;
813 /** The issue the pull request is for, which says what it should achieve. */
814 issue: Issue | null;
g1t is the stored author of what it opens; the person who asked is requested_by and keeps the author's rights815 /** Who the pull request is for (`workOwner`: whoever asked g1t for it, or its author), and so can read its source. */
Projects live: fixes from walking them end to end816 author: User;
Auto model routing: the cheapest tier that can do each piece of work, a retry goes up a tier, and each run records its tier817 /**
818 * The files it changes, as of its latest push: how large the change is,
819 * which decides the model that reviews it.
820 */
821 files: ChangedFile[];
822 /**
823 * What among them runs, configures or guards things (CI workflows,
824 * secrets, infrastructure), once each. Any sends the review to the
825 * larger model.
826 */
827 sensitive: string[];
Projects live: fixes from walking them end to end828};
829
830export type OpenIssueInput = {
831 title: string;
832 body: string;
833 labels?: string[];
Fast pages, required checks on the branch, self-hosted runners, honest incidents834 /** Deprecated: commands, added to the body under "Definition of done". */
Projects live: fixes from walking them end to end835 checks?: string[];
Teams and CODEOWNERS, labels and milestones, dependency updates, the security suite, and a clearer top bar836 /** The number of the milestone to put it in. Needs the Triage role. */
837 milestone?: number;
Projects live: fixes from walking them end to end838};
839
840export type UpdateIssueInput = {
841 title?: string;
842 body?: string;
843 labels?: string[];
844 /** Usernames of the people it is assigned to; replaces the whole set. */
845 assignees?: string[];
Teams and CODEOWNERS, labels and milestones, dependency updates, the security suite, and a clearer top bar846 /** The number of the milestone to put it in; 0 takes it out. */
847 milestone?: number;
Projects live: fixes from walking them end to end848};
849
850export type OpenPullInput = {
851 /** The number of the issue this is for. */
852 issue?: number;
853 /** Defaults to the issue's title; required without an issue. */
854 title?: string;
855 /** What changed and why. Usually set later, when a draft is marked ready. */
856 body?: string;
857 /**
858 * A branch of the repository that already holds the change. The pull
859 * request is then ready for review at once and has no fork.
860 */
861 branch?: string;
862 agent: string;
863 runtime: Runtime;
Teams and CODEOWNERS, labels and milestones, dependency updates, the security suite, and a clearer top bar864 /** The branch to merge into: the default branch when left out. */
865 base?: string;
Open a pull request as a draft: it can't merge, and agents' review routines wait, until it is marked ready866 /**
867 * Opened from a branch as a draft, still being worked on: it can't merge,
868 * and agents' review routines wait, until it is marked ready.
869 */
870 draft?: boolean;
Projects live: fixes from walking them end to end871};
872
Fast pages, required checks on the branch, self-hosted runners, honest incidents873/** One repository's pull requests from `pullsForRepos`, newest first. */
874export type RepoPulls = {
875 repoId: string;
876 /** Draft and open. */
877 open: Pull[];
878 /** Merged and closed. */
879 closed: Pull[];
880};
881
Projects live: fixes from walking them end to end882/** Issues, pull requests, comments and sessions. */
Merge checks: statuses and check runs on every commit883export interface WorkApi extends RulesApi, ChecksApi {
Projects live: fixes from walking them end to end884 openIssue(actor: User, repo: RepoPath, input: OpenIssueInput): Promise<Result<Issue>>;
Thirteen MCP tools and classic token scopes; agents rate their confidence and can be put on an issue in one step885 /**
g1t is one name: its agent's work, commits and comments show as @g1t, and nobody can claim g1t or g1t-agent886 * Opens an issue to put g1t on at once: refused, with nothing
Thirteen MCP tools and classic token scopes; agents rate their confidence and can be put on an issue in one step887 * opened, unless `actor` may put agents to work in `repo`. The runner's
888 * `delegate` calls it, then starts the agent.
889 */
890 delegateIssue(actor: User, repo: RepoPath, input: DelegateInput): Promise<Result<Issue>>;
Projects live: fixes from walking them end to end891 /** Newest first. */
892 listIssues(
893 repo: RepoPath,
894 viewer: Viewer,
Teams and CODEOWNERS, labels and milestones, dependency updates, the security suite, and a clearer top bar895 filter?: { state?: State; label?: string; milestone?: number },
Projects live: fixes from walking them end to end896 ): Promise<Result<Issue[]>>;
897 getIssue(repo: RepoPath, number: number, viewer: Viewer): Promise<Result<IssueDetail>>;
898 /** The author or a member of the workspace may. */
899 updateIssue(actor: User, repo: RepoPath, number: number, input: UpdateIssueInput): Promise<Result<Issue>>;
900 closeIssue(actor: User, repo: RepoPath, number: number, reason?: IssueReason): Promise<Result<Issue>>;
901 reopenIssue(actor: User, repo: RepoPath, number: number): Promise<Result<Issue>>;
Teams and CODEOWNERS, labels and milestones, dependency updates, the security suite, and a clearer top bar902 /** A repository's labels, by name, each with how many issues and pull requests carry it. */
903 listLabels(repo: RepoPath, viewer: Viewer): Promise<Result<Label[]>>;
904 /**
905 * Creates a label, or with `name` changes one; renaming it renames it on
906 * everything that carries it. Needs the Triage role.
907 */
908 saveLabel(
909 actor: User,
910 repo: RepoPath,
911 label: { name?: string; newName?: string; color?: string; description?: string },
912 ): Promise<Result<Label>>;
913 /** Removes a label from the repository and everything carrying it. */
914 deleteLabel(actor: User, repo: RepoPath, name: string): Promise<Result<boolean>>;
915 /** Adds the default labels the repository does not have yet; returns them all. */
916 addDefaultLabels(actor: User, repo: RepoPath): Promise<Result<Label[]>>;
917 /**
918 * The labels of an issue or a pull request, replaced, added to or taken
919 * from. Labels the repository lacks are created for someone with the
920 * Triage role. Returns its labels now.
921 */
922 setLabels(
923 actor: User,
924 repo: RepoPath,
925 number: number,
926 labels: string[],
927 change?: LabelChange,
928 ): Promise<Result<string[]>>;
929 /** Open ones by due date, then closed ones; both unless `state` says. */
930 listMilestones(repo: RepoPath, viewer: Viewer, state?: State): Promise<Result<Milestone[]>>;
931 getMilestone(repo: RepoPath, number: number, viewer: Viewer): Promise<Result<MilestoneDetail>>;
932 /** Creates a milestone, or with `number` changes the fields given. Needs the Triage role. */
933 saveMilestone(
934 actor: User,
935 repo: RepoPath,
936 milestone: { number?: number; title?: string; description?: string; dueOn?: string; state?: State },
937 ): Promise<Result<Milestone>>;
938 deleteMilestone(actor: User, repo: RepoPath, number: number): Promise<Result<boolean>>;
Projects live: fixes from walking them end to end939 /** How many issues and pull requests are open. */
940 counts(repo: RepoPath, viewer: Viewer): Promise<Result<{ issues: number; pulls: number }>>;
941
942 /**
943 * On an issue or a pull request. On a pull request it may name a line of
944 * the change and carry a verdict; nobody can give a verdict on their own.
945 */
946 addComment(actor: User, repo: RepoPath, number: number, comment: NewComment): Promise<Result<Comment>>;
Merge Actions: cross-repo workflows and actions, release and deployment triggers, step timeouts947 /**
948 * Changes a comment's text. Its author may, and so may anyone with the
949 * Maintain role or higher; notes of what happened cannot be changed.
950 */
951 editComment(actor: User, repo: RepoPath, commentId: string, body: string): Promise<Result<Comment>>;
952 /**
953 * Deletes a comment: its author, or anyone with the Maintain role or
954 * higher. A review that gave a verdict cannot be deleted, only edited.
955 */
956 deleteComment(actor: User, repo: RepoPath, commentId: string): Promise<Result<boolean>>;
Cards you act on in chat; agents comment and review as themselves; names shown cleanly; commits on the calendar957 /**
958 * One of the workspace's agents comments on an issue or a pull request
959 * as itself, on behalf of `actingFor`: the person whose access caps it.
960 * The checks a person's comment has apply to them (verified, can read
961 * the repository, not archived). At most `AGENT_COMMENTS_PER_HOUR`
962 * comments and reviews per agent per issue or pull request
963 * (`conflict` past it). Publishes `comment.created` with `agent`. For
964 * the agents service only: never reachable with a person's token.
965 */
966 workspaceAgentComment(
967 repo: RepoPath,
968 number: number,
969 agent: AgentRef,
970 actingFor: User,
971 body: string,
972 ): Promise<Result<Comment>>;
973 /**
974 * One of the workspace's agents reviews a pull request as itself, on
975 * behalf of `actingFor`. Advisory: the verdict is shown but never counts
976 * toward required approvals or code owners, and never blocks a merge.
977 * Refused on a draft and on a closed or merged pull request (`conflict`);
978 * `body` may be empty only when approving. Same checks and limit as
979 * `workspaceAgentComment`. Publishes `comment.created` with `agent`,
980 * `advisory` and the verdict.
981 */
982 workspaceAgentReview(
983 repo: RepoPath,
984 number: number,
985 agent: AgentRef,
986 actingFor: User,
987 verdict: AgentVerdict,
988 body: string,
989 ): Promise<Result<Comment>>;
Projects live: fixes from walking them end to end990
991 /**
Fast pages, required checks on the branch, self-hosted runners, honest incidents992 * Always refused now: a pull request's checks are the workflows run on
993 * it. Kept for a runner from before.
Projects live: fixes from walking them end to end994 */
995 startChecks(pullId: string): Promise<Result<CheckJob>>;
996 /**
Fast pages, required checks on the branch, self-hosted runners, honest incidents997 * What a sandbox says about a run from before checks were workflows: so
998 * one still finishing is recorded.
Projects live: fixes from walking them end to end999 */
1000 reportChecks(runId: string, token: string, report: CheckReport): Promise<Result<CheckRun>>;
1001 /** Begins a review by a g1t agent. For the runner service. */
1002 startReview(pullId: string): Promise<Result<ReviewJob>>;
1003 /** Records that a review could not be written. For the runner service. */
1004 failReview(runId: string, token: string, error: string): Promise<Result<boolean>>;
Agents and memory, checks and conflicts, profiles, slug renames, custom domains1005 /**
1006 * Claims the probe of whether a pull request merges cleanly that a
1007 * `pull.mergecheck` event asked for. Refused when it is no longer wanted
1008 * or the repository has as many running as it may. For the runner service.
1009 */
1010 startMergecheck(pullId: string): Promise<Result<MergecheckJob>>;
1011 /** Records that a probe could not be carried out. For the runner service. */
1012 failMergecheck(pullId: string, token: string, error: string): Promise<Result<Mergeable>>;
Projects live: fixes from walking them end to end1013
1014 /**
1015 * Works out the next step for a pull request g1t is seeing through and,
1016 * if there is one to take now, claims it, so that it is taken once
1017 * however often this is called. For the runner service.
1018 */
1019 advance(pullId: string): Promise<Advance>;
1020 /** Records that a step could not be carried out, so a person is asked. */
1021 stall(pullId: string, reason: string): Promise<boolean>;
1022 /** Ids of the open pull requests g1t is seeing through. */
1023 managedPulls(repoId?: string): Promise<string[]>;
1024
1025 /** A repository's merge queue: what is in it, in order, and what recently left. */
1026 queue(repo: RepoPath, viewer: Viewer): Promise<Result<QueueView>>;
1027 /**
1028 * The next batch of combined states to test for a repository, one per
1029 * entry; empty while a batch is being tested or nothing waits.
1030 */
1031 queueBuild(repoId: string): Promise<QueueJob[]>;
1032 /** Reports that a combined state could not be built or checked. */
1033 failQueue(entryId: string, token: string, error: string): Promise<Result<QueueState>>;
1034 /** Sends the agent working on a pull request a message, for its next step. */
1035 messageAgent(actor: User, repo: RepoPath, number: number, body: string): Promise<Result<AgentMessage>>;
1036 /** Takes a pull request out of the merge queue. Members only. */
1037 removeFromQueue(actor: User, repo: RepoPath, number: number): Promise<Result<Pull>>;
1038
1039 getSettings(repo: RepoPath, viewer: Viewer): Promise<Result<RepoSettings>>;
Fast pages, required checks on the branch, self-hosted runners, honest incidents1040 /** The check names reported on the repository's commits in the last 30 days, most recent first. */
1041 seenChecks(repo: RepoPath, viewer: Viewer): Promise<Result<SeenCheck[]>>;
Projects live: fixes from walking them end to end1042 /** Members of the repository's workspace only. */
1043 updateSettings(actor: User, repo: RepoPath, settings: RepoSettingsInput): Promise<Result<RepoSettings>>;
Teams and CODEOWNERS, labels and milestones, dependency updates, the security suite, and a clearer top bar1044 /** The CODEOWNERS file at a branch (the default when left out), checked. Needs Read. */
1045 codeownersErrors(repo: RepoPath, viewer: Viewer, ref?: string | null): Promise<Result<CodeownersReport>>;
Projects live: fixes from walking them end to end1046 /**
1047 * What the runner needs to bring a pull request up to date because a
1048 * merge of it was asked for. Null if none was.
1049 */
1050 catchUpJob(pullId: string): Promise<LifecycleJob | null>;
1051 /**
1052 * Claims a short step for the agent on a pull request to answer the
1053 * questions and handoffs it was sent while not at work, and hands them
1054 * over, marked read. Null when there is nothing waiting or it cannot
1055 * take a step now.
1056 */
1057 wakeForMessages(pullId: string): Promise<Wake | null>;
1058
1059 /**
1060 * Opens a pull request: a draft with a fork to push to, or, given a
1061 * branch, one ready for review.
1062 */
1063 openPull(actor: User, repo: RepoPath, input: OpenPullInput): Promise<Result<Pull>>;
1064 /** Newest first. */
Teams and CODEOWNERS, labels and milestones, dependency updates, the security suite, and a clearer top bar1065 listPulls(
1066 repo: RepoPath,
1067 viewer: Viewer,
1068 state?: State,
1069 filter?: { label?: string; milestone?: number; base?: string },
1070 ): Promise<Result<Pull[]>>;
Fast pages, required checks on the branch, self-hosted runners, honest incidents1071 /**
1072 * The newest `limit` open and closed pull requests of each repository,
1073 * in one call. Repositories the viewer cannot read, and forks, are left
1074 * out: ask those with `listPulls`.
1075 */
1076 pullsForRepos(repoIds: string[], viewer: Viewer, limit: number): Promise<RepoPulls[]>;
Projects live: fixes from walking them end to end1077 getPull(repo: RepoPath, number: number, viewer: Viewer): Promise<Result<PullDetail>>;
1078 /**
1079 * Changes who a pull request is assigned to and whose review is asked
g1t is one name: its agent's work, commits and comments show as @g1t, and nobody can claim g1t or g1t-agent1080 * for; each list given replaces the whole set. Asking for `g1t`'s
Projects live: fixes from walking them end to end1081 * review does not by itself start one: the runner's `review` does.
1082 */
1083 updatePull(
1084 actor: User,
1085 repo: RepoPath,
1086 number: number,
Teams and CODEOWNERS, labels and milestones, dependency updates, the security suite, and a clearer top bar1087 changes: {
1088 assignees?: string[];
1089 reviewers?: string[];
1090 labels?: string[];
1091 /** 0 takes it out of its milestone. */
1092 milestone?: number;
1093 /** The branch it merges into. Needs the Write role. */
1094 base?: string;
1095 },
Projects live: fixes from walking them end to end1096 ): Promise<Result<Pull>>;
Catching up with main takes seconds when the two sides touched different files1097 /**
1098 * Brings a pull request up to date with the default branch in seconds,
1099 * without a sandbox, when the two changed different files: the merge
1100 * commit is pushed to its branch as `actor`, who must be whoever opened
1101 * it (for a fork) or a member (for a branch). Otherwise `needs_agent`, and
1102 * nothing is pushed: the runner's `update` is the way on.
1103 */
1104 catchUpPull(actor: User, repo: RepoPath, number: number): Promise<Result<PullBranchUpdate>>;
Projects live: fixes from walking them end to end1105 /** Marks a draft ready for review and sets its description. */
1106 readyPull(actor: User, repo: RepoPath, number: number, summary: string): Promise<Result<Pull>>;
1107 closePull(actor: User, repo: RepoPath, number: number): Promise<Result<Pull>>;
Merge Actions: cross-repo workflows and actions, release and deployment triggers, step timeouts1108 /** Opens a closed pull request again, as the draft it was if it was closed as one. Never a merged one. */
1109 reopenPull(actor: User, repo: RepoPath, number: number): Promise<Result<Pull>>;
1110 /** Turns an open pull request back into a draft; it leaves the merge queue. */
1111 convertPullToDraft(actor: User, repo: RepoPath, number: number): Promise<Result<Pull>>;
Projects live: fixes from walking them end to end1112 /**
1113 * Lands the pull request on the repository's default branch. Unless
1114 * `keepIssueOpen`, that resolves the issue it was for: the issue closes
1115 * naming this pull request, and the others still in progress for it close
1116 * as superseded. Only members of the repository's workspace may merge.
1117 *
1118 * If the default branch has moved, the pull request is brought up to date
1119 * first and lands when that is done; it comes back still open, and
1120 * `PullDetail.landing` is true meanwhile. A repository that requires pull
1121 * requests to be up to date refuses instead.
1122 */
1123 mergePull(
1124 actor: User,
1125 repo: RepoPath,
1126 number: number,
1127 options?: {
1128 keepIssueOpen?: boolean;
Merge rulesets: branch and tag rules, agent-first, enforced on push and merge1129 /** Merge although required checks have not passed, where the rule requiring them allows it. */
Projects live: fixes from walking them end to end1130 ignoreChecks?: boolean;
Merge rulesets: branch and tag rules, agent-first, enforced on push and merge1131 /** Merge past rules a ruleset lets the actor bypass. Recorded as a bypass. */
1132 bypassRules?: boolean;
Projects live: fixes from walking them end to end1133 },
1134 ): Promise<Result<Pull>>;
1135 /**
1136 * Drafts and open pull requests the viewer started, most recently active
1137 * first, each with where it stands if g1t is seeing it through.
1138 */
1139 listActivePulls(
1140 viewer: Viewer,
1141 ): Promise<{ pull: Pull; issue: Issue | null; lifecycle: Lifecycle | null }[]>;
Agents and memory, checks and conflicts, profiles, slug renames, custom domains1142 /**
1143 * The issues and pull requests a person opened, a page at a time, only
1144 * on repositories the viewer may read. Not found for no such account.
1145 */
1146 byAuthor(username: string, viewer: Viewer, filter?: AuthoredFilter): Promise<Result<Authored>>;
Chat controls, public profiles, shadcn selects, and no Docs tab in a project1147 /**
1148 * What a person did each day of the last year (issues and pull requests
1149 * opened, reviews given), only on repositories the viewer may read: the
1150 * calendar on their profile. Not found for no such account.
1151 */
1152 contributions(username: string, viewer: Viewer): Promise<Result<Contributions>>;
Projects live: fixes from walking them end to end1153
1154 /**
1155 * Records an outcome to plan for. Members only. For the runner service,
1156 * which starts the sandbox in which an agent writes the plan.
1157 */
1158 startPlan(actor: User, repo: RepoPath, brief: string): Promise<Result<PlanJob>>;
1159 /** Records that a plan could not be written. For the runner service. */
1160 failPlan(planId: string, token: string, error: string): Promise<Result<boolean>>;
1161 /** Members only. */
1162 getPlan(repo: RepoPath, viewer: Viewer, id: string): Promise<Result<Plan>>;
1163 /** Newest first. Members only. */
1164 listPlans(repo: RepoPath, viewer: Viewer): Promise<Result<Plan[]>>;
1165 /**
1166 * Opens a plan's issues, each blocked by the ones it depends on. With
1167 * `assign`, each is queued for a g1t agent. `keep` holds the positions,
1168 * from 1, of the issues to open; all of them when absent. Once.
1169 */
1170 applyPlan(
1171 actor: User,
1172 repo: RepoPath,
1173 id: string,
1174 options?: { assign?: boolean; keep?: number[] },
1175 ): Promise<Result<Plan>>;
1176 /** Asks for a g1t agent to take an issue as soon as it can, or withdraws that. */
1177 queueIssue(actor: User, repo: RepoPath, number: number, queued: boolean): Promise<Result<boolean>>;
1178 /** Issues waiting for a g1t agent that can be given one now. For the runner. */
1179 readyIssues(repoId?: string): Promise<ReadyIssue[]>;
1180
1181 /** Open issues assigned to the viewer, most recently changed first. */
1182 listAssignedIssues(viewer: Viewer): Promise<Issue[]>;
1183
1184 appendSession(actor: User, repo: RepoPath, number: number, entries: NewSessionEntry[]): Promise<Result<{ count: number }>>;
1185 readSession(repo: RepoPath, number: number, viewer: Viewer, afterSeq?: number): Promise<Result<SessionEntry[]>>;
1186}
1187
1188/**
1189 * What to pass `ReposApi.compare` to see what a pull request changes.
1190 *
1191 * A fork is compared as a whole. A branch is compared by name while the
1192 * pull request is open, and by the commit it was merged or closed at
1193 * afterwards, so later pushes to the branch do not change the record.
1194 */
1195export function pullComparison(pull: Pull): {
1196 repoId: string;
1197 base: string | null;
1198 head: string | null;
Teams and CODEOWNERS, labels and milestones, dependency updates, the security suite, and a clearer top bar1199 /** The branch it merges into, which it is compared from. */
1200 baseBranch: string | null;
Projects live: fixes from walking them end to end1201} {
Teams and CODEOWNERS, labels and milestones, dependency updates, the security suite, and a clearer top bar1202 const baseBranch = pull.base ?? null;
1203 if (pull.forkRepoId) return { repoId: pull.forkRepoId, base: pull.mergeBase, head: null, baseBranch };
Projects live: fixes from walking them end to end1204 const settled = pull.status === "merged" || pull.status === "closed";
1205 return {
1206 repoId: pull.repoId,
1207 base: pull.mergeBase,
1208 head: (settled && pull.headCommit) || pull.branch,
Teams and CODEOWNERS, labels and milestones, dependency updates, the security suite, and a clearer top bar1209 baseBranch,
Projects live: fixes from walking them end to end1210 };
1211}
1212
1213
1214/** Where a pull request in a merge queue stands. */
1215/** Where one issue of an applied plan stands. */
1216export type IssueProgress = {
1217 number: number;
1218 title: string;
1219 /**
1220 * `blocked`, `waiting` (for an agent), `open`, a lifecycle stage,
1221 * `landed` or `closed`.
1222 */
1223 state: string;
1224 detail: string;
1225 /** The issues it is waiting on that are still open. */
1226 blockedBy: number[];
1227 pull: number | null;
1228 agent: string | null;
1229};
1230
1231/** A message a person sent an agent at work on a pull request. */
1232export type AgentMessage = {
1233 id: string;
1234 author: string;
1235 body: string;
1236 createdAt: string;
1237 /** When the agent received it; null until then. */
1238 deliveredAt: string | null;
1239 /** `message` from a person; from an agent a `question`, `handoff` or `answer`. */
1240 kind: "message" | "question" | "handoff" | "answer";
1241 /** The pull request whose agent sent it, when an agent did. */
1242 fromNumber: number | null;
1243 /** The pull request it was sent to. */
1244 toNumber: number;
1245 /** The reply to a question or handoff, once there is one. */
1246 answer: string | null;
1247 declined: boolean;
1248 /** For the sending agent: what to expect when the one it asked is not at work. */
1249 hint?: string;
1250};
1251
1252export type QueueState = "waiting" | "testing" | "passed" | "failed" | "landed" | "removed";
1253
1254/** One pull request's place in a merge queue. */
1255export type QueueEntry = {
1256 id: string;
1257 number: number;
1258 title: string;
1259 agent: string;
1260 state: QueueState;
1261 /** The pull requests merged ahead of it in the state being tested, in order. */
1262 ahead: number[];
1263 baseCommit: string | null;
1264 combinedCommit: string | null;
1265 error: string | null;
1266 results: CheckResult[];
1267 /** Username of whoever merged it into the queue: a person, or `g1t`. */
1268 enqueuedBy: string;
1269 /** RFC 3339. */
1270 createdAt: string;
1271 /** RFC 3339. */
1272 finishedAt: string | null;
1273};
1274
1275/** A repository's merge queue: what is in it, in order, and what recently left. */
1276export type QueueView = {
1277 enabled: boolean;
1278 active: QueueEntry[];
1279 /** Newest first. */
1280 recent: QueueEntry[];
1281};
1282
1283export type QueueStackItem = {
1284 number: number;
1285 title: string;
1286 /** The repository holding the change, and its branch. */
1287 source: RepoPath;
1288 branch: string;
1289 commit: string;
1290};
1291
1292/** What a sandbox needs to build and check one combined state. */
1293export type QueueJob = {
1294 entryId: string;
1295 token: string;
1296 repo: RepoPath;
1297 defaultBranch: string;
1298 baseCommit: string;
1299 branch: string;
1300 stack: QueueStackItem[];
Fast pages, required checks on the branch, self-hosted runners, honest incidents1301 /** Always empty: the state is checked by the merge_group workflows run on it. */
Projects live: fixes from walking them end to end1302 checks: string[];
Fast pages, required checks on the branch, self-hosted runners, honest incidents1303 /** Always empty, as `checks`. */
Projects live: fixes from walking them end to end1304 contractChecks: string[];
1305 actor: User;
1306};
Agents and memory, checks and conflicts, profiles, slug renames, custom domains1307
1308// --- A person's work ---------------------------------------------------------
1309// Mirrors the `Authored*` types in `crates/contracts/src/work.rs`.
1310
1311export type AuthoredKind = "issue" | "pull";
1312/** `closed` takes in merged pull requests too; `merged` is only those. */
1313export type AuthoredState = "open" | "closed" | "merged";
1314/** `created` is newest first, `updated` most recently changed, `oldest` oldest first. */
1315export type AuthoredSort = "created" | "updated" | "oldest";
1316
1317/** The most items one `byAuthor` page holds. */
1318export const AUTHORED_PAGE = 25;
1319
1320export type AuthoredFilter = {
1321 kind?: AuthoredKind;
1322 state?: AuthoredState;
1323 /** `namespace/name`. */
1324 repo?: string;
1325 sort?: AuthoredSort;
1326 /** The `next` of the page before. */
1327 before?: string;
1328 limit?: number;
1329};
1330
1331export type AuthoredItem = {
1332 kind: AuthoredKind;
1333 repo: RepoPath;
1334 number: number;
1335 title: string;
1336 /** A merged pull request is closed. */
1337 state: State;
1338 /** A pull request's own status; null on an issue. */
1339 status: PullStatus | null;
1340 /** Why an issue was closed. */
1341 reason: IssueReason | null;
1342 draft: boolean;
1343 merged: boolean;
1344 /** RFC 3339. */
1345 createdAt: string;
1346 /** RFC 3339. */
1347 updatedAt: string;
1348 /** RFC 3339. */
1349 mergedAt: string | null;
1350};
1351
1352/** Over every repository the viewer may read, whatever the filters. */
1353export type AuthoredCounts = {
1354 pullsMerged: number;
1355 pullsOpen: number;
1356 pulls: number;
1357 issues: number;
1358 issuesOpen: number;
1359};
1360
1361export type Authored = {
1362 items: AuthoredItem[];
1363 /** Pass as `before` for the next page; null on the last. */
1364 next: string | null;
1365 counts: AuthoredCounts;
1366 /** The repositories they worked in that the viewer may read, most work first. */
1367 repos: { repo: RepoPath; count: number }[];
1368};
Chat controls, public profiles, shadcn selects, and no Docs tab in a project1369
1370// Mirrors `Contributions` in `crates/contracts/src/work.rs`.
1371
1372/** How many days `contributions` covers: today and the 364 before it. */
1373export const CONTRIBUTION_DAYS = 365;
1374
1375/** One day with something on it; days with nothing are left out. */
Cards you act on in chat; agents comment and review as themselves; names shown cleanly; commits on the calendar1376export type ContributionDay = {
1377 /** `YYYY-MM-DD`, UTC. */
1378 date: string;
1379 /** Everything that day, commits included. */
1380 count: number;
1381 /** How many of `count` are commits they pushed to a default branch. */
1382 commits?: number;
1383};
Chat controls, public profiles, shadcn selects, and no Docs tab in a project1384
1385/** A person's year, as far as the viewer may see. */
1386export type Contributions = {
1387 /** Oldest first. */
1388 days: ContributionDay[];
1389 total: number;
1390 /** The first day counted, `YYYY-MM-DD`; the last is today (UTC). */
1391 from: string;
1392};

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