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. | 1 | import type { AgentLook } from "./agent-look"; |
| Merge checks: statuses and check runs on every commit | 2 | import type { ChecksApi } from "./checks"; |
| Teams and CODEOWNERS, labels and milestones, dependency updates, the security suite, and a clearer top bar | 3 | import type { CodeownersReport, PullCodeOwners } from "./codeowners"; |
| Projects live: fixes from walking them end to end | 4 | import type { User, Viewer } from "./identity"; |
| Catching up with main takes seconds when the two sides touched different files | 5 | import type { PullBranchUpdate, RepoPath } from "./repos"; |
| Projects live: fixes from walking them end to end | 6 | import type { Result } from "./result"; |
| Merge rulesets: branch and tag rules, agent-first, enforced on push and merge | 7 | import type { MergeRules, RulesApi } from "./rules"; |
| Projects live: fixes from walking them end to end | 8 | |
| 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 | */ | |
| 14 | export type State = "open" | "closed"; | |
| 15 | ||
| 16 | /** Why an issue was closed. */ | |
| 17 | export 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 | */ | |
| 26 | export 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 rights | 40 | /** 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 end | 41 | author: User; |
| g1t is the stored author of what it opens; the person who asked is requested_by and keeps the author's rights | 42 | /** |
| 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 end | 47 | /** 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-agent | 67 | * that is still in progress in a fork, such as `g1t`. |
| Projects live: fixes from walking them end to end | 68 | */ |
| 69 | agent: string | null; | |
| Teams and CODEOWNERS, labels and milestones, dependency updates, the security suite, and a clearer top bar | 70 | /** The milestone it is in, if any. */ |
| 71 | milestone?: MilestoneRef | null; | |
| Projects live: fixes from walking them end to end | 72 | }; |
| 73 | ||
| g1t is the stored author of what it opens; the person who asked is requested_by and keeps the author's rights | 74 | /** |
| Teams and CODEOWNERS, labels and milestones, dependency updates, the security suite, and a clearer top bar | 75 | * 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 | */ | |
| 78 | export 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. */ | |
| 90 | export 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 | */ | |
| 96 | export 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. */ | |
| 115 | export type MilestoneDetail = { milestone: Milestone; issues: Issue[]; pulls: Pull[] }; | |
| 116 | ||
| 117 | /** How `setLabels` changes an item's labels. */ | |
| 118 | export 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 rights | 121 | * 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 | */ | |
| 126 | export function workOwner(item: Pick<Pull, "author" | "requestedBy">): User { | |
| 127 | return item.requestedBy ?? item.author; | |
| 128 | } | |
| 129 | ||
| Projects live: fixes from walking them end to end | 130 | /** `draft` is still being worked on; `open` is ready for review. */ |
| 131 | export type PullStatus = "draft" | "open" | "merged" | "closed"; | |
| 132 | ||
| 133 | /** Where the agent runs: on g1t's sandboxes, or in someone's own session. */ | |
| 134 | export 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 | */ | |
| 140 | export 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-agent | 185 | * Those whose review was asked for: usernames, and `g1t` when a g1t |
| Projects live: fixes from walking them end to end | 186 | * agent was asked. |
| 187 | */ | |
| 188 | reviewers: string[]; | |
| Teams and CODEOWNERS, labels and milestones, dependency updates, the security suite, and a clearer top bar | 189 | /** |
| 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 rights | 203 | /** Who opened it: a person, or g1t (`kind` `agent`, username `g1t`) for a change g1t made. */ |
| Projects live: fixes from walking them end to end | 204 | author: User; |
| g1t is the stored author of what it opens; the person who asked is requested_by and keeps the author's rights | 205 | /** |
| 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 end | 211 | /** 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 step | 215 | /** |
| 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 merge | 221 | /** 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 step | 224 | }; |
| 225 | ||
| 226 | /** How sure g1t is that an agent's change is right. */ | |
| 227 | export 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 | */ | |
| 236 | export 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. */ | |
| 251 | export type AgentStartStatus = "started" | "queued" | "not_started"; | |
| 252 | ||
| 253 | /** Whether the agent started, and if not, why and what fixes it. */ | |
| 254 | export 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 end | 265 | }; |
| 266 | ||
| g1t is one name: its agent's work, commits and comments show as @g1t, and nobody can claim g1t or g1t-agent | 267 | /** 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 step | 268 | export 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 incidents | 275 | /** |
| 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 step | 280 | export type DelegateInput = { |
| 281 | title: string; | |
| 282 | body: string; | |
| 283 | labels?: string[]; | |
| Fast pages, required checks on the branch, self-hosted runners, honest incidents | 284 | /** 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 step | 285 | checks?: string[]; |
| 286 | }; | |
| 287 | ||
| Projects live: fixes from walking them end to end | 288 | /** One file a pull request changes, and by how much. */ |
| 289 | export 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 | */ | |
| 296 | export 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 incidents | 305 | /** |
| 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 end | 310 | export type CheckStatus = "queued" | "running" | "passed" | "failed" | "errored"; |
| 311 | ||
| Fast pages, required checks on the branch, self-hosted runners, honest incidents | 312 | /** How one command went, in a run recorded before checks were workflows. */ |
| Projects live: fixes from walking them end to end | 313 | export 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 incidents | 324 | * 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 end | 326 | */ |
| 327 | export 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. */ | |
| 342 | export 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 | */ | |
| 348 | export 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 timeouts | 368 | /** 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 calendar | 370 | /** |
| 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 calendar | 389 | * is `/<workspace>/-/agents/<handle>`. |
| 390 | */ | |
| 391 | export 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 end | 398 | }; |
| 399 | ||
| Cards you act on in chat; agents comment and review as themselves; names shown cleanly; commits on the calendar | 400 | /** An agent's review: all of them advisory. */ |
| 401 | export 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. */ | |
| 404 | export 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. | 407 | export 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 calendar | 409 | } |
| 410 | ||
| Projects live: fixes from walking them end to end | 411 | export 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. */ | |
| 420 | export 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 rights | 428 | /** 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 end | 429 | author: User; |
| 430 | /** Username of whoever wrote the checks: the issue's author. */ | |
| 431 | requestedBy: string; | |
| 432 | repo: RepoPath; | |
| 433 | number: number; | |
| 434 | }; | |
| 435 | ||
| 436 | export type CheckReport = { results?: CheckResult[]; error?: string; skip?: boolean }; | |
| 437 | ||
| 438 | export 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. */ | |
| 441 | export 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 | ||
| 453 | export type NewSessionEntry = Pick<SessionEntry, "kind" | "text"> & | |
| 454 | Partial<Pick<SessionEntry, "tool" | "commit">>; | |
| 455 | ||
| 456 | export type IssueDetail = { | |
| 457 | issue: Issue; | |
| 458 | /** Every pull request made against it, oldest first. */ | |
| 459 | pulls: Pull[]; | |
| 460 | comments: Comment[]; | |
| 461 | }; | |
| 462 | ||
| 463 | export 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 incidents | 468 | /** The latest record against its head: the merge queue taking it out. */ |
| Projects live: fixes from walking them end to end | 469 | 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 domains | 495 | /** |
| 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 incidents | 502 | /** Earlier records like `checks`, newest first, without their output. */ |
| Agents and memory, checks and conflicts, profiles, slug renames, custom domains | 503 | earlierChecks?: CheckRun[]; |
| Fast pages, required checks on the branch, self-hosted runners, honest incidents | 504 | /** |
| 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 bar | 509 | /** |
| 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 merge | 514 | /** |
| 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 incidents | 520 | }; |
| 521 | ||
| 522 | /** Where a required check stands on a commit; `expected` when nothing has reported it yet. */ | |
| 523 | export type RequiredState = "success" | "failure" | "pending" | "expected"; | |
| 524 | ||
| 525 | /** One check a branch's protection requires, as it stands on a commit. */ | |
| 526 | export 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 domains | 533 | }; |
| 534 | ||
| Fast pages, required checks on the branch, self-hosted runners, honest incidents | 535 | /** A check name reported on a repository's commits lately, for choosing required checks. */ |
| 536 | export 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 domains | 544 | /** |
| Fast pages, required checks on the branch, self-hosted runners, honest incidents | 545 | * 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 | */ | |
| 549 | export 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 | ||
| 555 | const 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 domains | 572 | * 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 | */ | |
| 576 | export type Mergeable = "clean" | "conflicting" | "unknown" | "checking"; | |
| 577 | ||
| 578 | /** What a sandbox needs to find out whether a pull request merges cleanly. */ | |
| 579 | export 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 rights | 594 | /** 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 domains | 595 | author: User; |
| Projects live: fixes from walking them end to end | 596 | }; |
| 597 | ||
| 598 | /** What a workflow run (or another tool) says about a commit. */ | |
| 599 | export 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 commit | 606 | /** 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 end | 610 | }; |
| 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 | */ | |
| 621 | export type Stage = | |
| 622 | | "working" | |
| 623 | | "checking" | |
| 624 | | "reviewing" | |
| 625 | | "revising" | |
| 626 | | "catching_up" | |
| 627 | | "answering" | |
| 628 | | "queued" | |
| 629 | | "ready" | |
| 630 | | "needs_you"; | |
| 631 | ||
| 632 | export 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. */ | |
| 641 | export 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 rights | 645 | /** 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 end | 646 | 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. */ | |
| 662 | export 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 | */ | |
| 669 | export type PlanStatus = "planning" | "ready" | "failed" | "applied"; | |
| 670 | ||
| 671 | /** One issue a plan proposes. */ | |
| 672 | export 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 incidents | 677 | /** 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 end | 679 | /** 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. */ | |
| 691 | export 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. */ | |
| 714 | export 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. */ | |
| 723 | export 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 | */ | |
| 734 | export 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 incidents | 741 | * 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 end | 748 | * 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 incidents | 760 | /** Whether someone who may merge can bypass required checks that have not passed. */ |
| Projects live: fixes from walking them end to end | 761 | 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 step | 775 | /** |
| 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 bar | 780 | /** |
| 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 end | 786 | /** 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. */ | |
| 793 | export type RepoSettingsInput = Omit<RepoSettings, "updatedBy" | "updatedAt">; | |
| 794 | ||
| 795 | /** The next step for a pull request g1t is seeing through, already claimed. */ | |
| 796 | export type Advance = | |
| 797 | | { action: "none" } | |
| 798 | | { action: "review" | "revise" | "catch_up"; job: LifecycleJob }; | |
| 799 | ||
| 800 | /** What a sandbox needs to review a pull request. */ | |
| 801 | export 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 rights | 815 | /** 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 end | 816 | 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 tier | 817 | /** |
| 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 end | 828 | }; |
| 829 | ||
| 830 | export type OpenIssueInput = { | |
| 831 | title: string; | |
| 832 | body: string; | |
| 833 | labels?: string[]; | |
| Fast pages, required checks on the branch, self-hosted runners, honest incidents | 834 | /** Deprecated: commands, added to the body under "Definition of done". */ |
| Projects live: fixes from walking them end to end | 835 | checks?: string[]; |
| Teams and CODEOWNERS, labels and milestones, dependency updates, the security suite, and a clearer top bar | 836 | /** The number of the milestone to put it in. Needs the Triage role. */ |
| 837 | milestone?: number; | |
| Projects live: fixes from walking them end to end | 838 | }; |
| 839 | ||
| 840 | export 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 bar | 846 | /** The number of the milestone to put it in; 0 takes it out. */ |
| 847 | milestone?: number; | |
| Projects live: fixes from walking them end to end | 848 | }; |
| 849 | ||
| 850 | export 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 bar | 864 | /** 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 ready | 866 | /** |
| 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 end | 871 | }; |
| 872 | ||
| Fast pages, required checks on the branch, self-hosted runners, honest incidents | 873 | /** One repository's pull requests from `pullsForRepos`, newest first. */ |
| 874 | export 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 end | 882 | /** Issues, pull requests, comments and sessions. */ |
| Merge checks: statuses and check runs on every commit | 883 | export interface WorkApi extends RulesApi, ChecksApi { |
| Projects live: fixes from walking them end to end | 884 | 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 step | 885 | /** |
| g1t is one name: its agent's work, commits and comments show as @g1t, and nobody can claim g1t or g1t-agent | 886 | * 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 step | 887 | * 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 end | 891 | /** 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 bar | 895 | filter?: { state?: State; label?: string; milestone?: number }, |
| Projects live: fixes from walking them end to end | 896 | ): 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 bar | 902 | /** 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 end | 939 | /** 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 timeouts | 947 | /** |
| 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 calendar | 957 | /** |
| 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 end | 990 | |
| 991 | /** | |
| Fast pages, required checks on the branch, self-hosted runners, honest incidents | 992 | * 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 end | 994 | */ |
| 995 | startChecks(pullId: string): Promise<Result<CheckJob>>; | |
| 996 | /** | |
| Fast pages, required checks on the branch, self-hosted runners, honest incidents | 997 | * 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 end | 999 | */ |
| 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 domains | 1005 | /** |
| 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 end | 1013 | |
| 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 incidents | 1040 | /** 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 end | 1042 | /** 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 bar | 1044 | /** 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 end | 1046 | /** |
| 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 bar | 1065 | 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 incidents | 1071 | /** |
| 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 end | 1077 | 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-agent | 1080 | * for; each list given replaces the whole set. Asking for `g1t`'s |
| Projects live: fixes from walking them end to end | 1081 | * 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 bar | 1087 | 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 end | 1096 | ): Promise<Result<Pull>>; |
| Catching up with main takes seconds when the two sides touched different files | 1097 | /** |
| 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 end | 1105 | /** 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 timeouts | 1108 | /** 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 end | 1112 | /** |
| 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 merge | 1129 | /** Merge although required checks have not passed, where the rule requiring them allows it. */ |
| Projects live: fixes from walking them end to end | 1130 | ignoreChecks?: boolean; |
| Merge rulesets: branch and tag rules, agent-first, enforced on push and merge | 1131 | /** Merge past rules a ruleset lets the actor bypass. Recorded as a bypass. */ |
| 1132 | bypassRules?: boolean; | |
| Projects live: fixes from walking them end to end | 1133 | }, |
| 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 domains | 1142 | /** |
| 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 project | 1147 | /** |
| 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 end | 1153 | |
| 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 | */ | |
| 1195 | export 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 bar | 1199 | /** The branch it merges into, which it is compared from. */ |
| 1200 | baseBranch: string | null; | |
| Projects live: fixes from walking them end to end | 1201 | } { |
| Teams and CODEOWNERS, labels and milestones, dependency updates, the security suite, and a clearer top bar | 1202 | 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 end | 1204 | 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 bar | 1209 | baseBranch, |
| Projects live: fixes from walking them end to end | 1210 | }; |
| 1211 | } | |
| 1212 | ||
| 1213 | ||
| 1214 | /** Where a pull request in a merge queue stands. */ | |
| 1215 | /** Where one issue of an applied plan stands. */ | |
| 1216 | export 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. */ | |
| 1232 | export 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 | ||
| 1252 | export type QueueState = "waiting" | "testing" | "passed" | "failed" | "landed" | "removed"; | |
| 1253 | ||
| 1254 | /** One pull request's place in a merge queue. */ | |
| 1255 | export 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. */ | |
| 1276 | export type QueueView = { | |
| 1277 | enabled: boolean; | |
| 1278 | active: QueueEntry[]; | |
| 1279 | /** Newest first. */ | |
| 1280 | recent: QueueEntry[]; | |
| 1281 | }; | |
| 1282 | ||
| 1283 | export 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. */ | |
| 1293 | export 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 incidents | 1301 | /** Always empty: the state is checked by the merge_group workflows run on it. */ |
| Projects live: fixes from walking them end to end | 1302 | checks: string[]; |
| Fast pages, required checks on the branch, self-hosted runners, honest incidents | 1303 | /** Always empty, as `checks`. */ |
| Projects live: fixes from walking them end to end | 1304 | contractChecks: string[]; |
| 1305 | actor: User; | |
| 1306 | }; | |
| Agents and memory, checks and conflicts, profiles, slug renames, custom domains | 1307 | |
| 1308 | // --- A person's work --------------------------------------------------------- | |
| 1309 | // Mirrors the `Authored*` types in `crates/contracts/src/work.rs`. | |
| 1310 | ||
| 1311 | export type AuthoredKind = "issue" | "pull"; | |
| 1312 | /** `closed` takes in merged pull requests too; `merged` is only those. */ | |
| 1313 | export type AuthoredState = "open" | "closed" | "merged"; | |
| 1314 | /** `created` is newest first, `updated` most recently changed, `oldest` oldest first. */ | |
| 1315 | export type AuthoredSort = "created" | "updated" | "oldest"; | |
| 1316 | ||
| 1317 | /** The most items one `byAuthor` page holds. */ | |
| 1318 | export const AUTHORED_PAGE = 25; | |
| 1319 | ||
| 1320 | export 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 | ||
| 1331 | export 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. */ | |
| 1353 | export type AuthoredCounts = { | |
| 1354 | pullsMerged: number; | |
| 1355 | pullsOpen: number; | |
| 1356 | pulls: number; | |
| 1357 | issues: number; | |
| 1358 | issuesOpen: number; | |
| 1359 | }; | |
| 1360 | ||
| 1361 | export 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 project | 1369 | |
| 1370 | // Mirrors `Contributions` in `crates/contracts/src/work.rs`. | |
| 1371 | ||
| 1372 | /** How many days `contributions` covers: today and the 364 before it. */ | |
| 1373 | export 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 calendar | 1376 | export 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 project | 1384 | |
| 1385 | /** A person's year, as far as the viewer may see. */ | |
| 1386 | export 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.