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.
| Merge rulesets: branch and tag rules, agent-first, enforced on push and merge | 1 | import type { RepoPath } from "./repos"; |
| 2 | import type { Result } from "./result"; | |
| 3 | import type { User, Viewer } from "./identity"; | |
| 4 | ||
| 5 | /** | |
| 6 | * Rulesets: what may happen to a repository's branches and tags, and what a | |
| 7 | * pull request needs before it merges. A ruleset belongs to a repository or | |
| 8 | * to a workspace (and through it to the repositories it selects), targets | |
| 9 | * branches or tags by name, is `active`, `evaluate` (a dry run that records | |
| 10 | * what it would have refused) or `disabled`, lists who may bypass it, and | |
| 11 | * holds rules. Rulesets stack: every rule of each holds. | |
| 12 | * | |
| 13 | * Mirrors `crates/contracts/src/rules.rs`. Rulesets travel in the shape the | |
| 14 | * API shows them, `snake_case`, so an export imports anywhere unchanged. | |
| 15 | */ | |
| 16 | ||
| 17 | export const DEFAULT_BRANCH = "~DEFAULT_BRANCH"; | |
| 18 | export const ALL = "~ALL"; | |
| 19 | export const MAX_RULESETS = 75; | |
| 20 | ||
| 21 | export type Enforcement = "active" | "evaluate" | "disabled"; | |
| 22 | export type Target = "branch" | "tag"; | |
| 23 | export type Level = "repository" | "workspace"; | |
| 24 | export type AppliesTo = "everyone" | "agents" | "people"; | |
| 25 | export type BypassActorKind = "role" | "team" | "user" | "token" | "g1t"; | |
| 26 | export type BypassMode = "always" | "pull_requests"; | |
| 27 | export type MergeMethod = "merge" | "squash" | "rebase"; | |
| Merge checks: statuses and check runs on every commit | 28 | export type Integration = "actions" | "deployments" | "security" | "g1t" | "api"; |
| Merge rulesets: branch and tag rules, agent-first, enforced on push and merge | 29 | export type PatternOperator = "starts_with" | "ends_with" | "contains" | "regex"; |
| 30 | ||
| 31 | export type Weekday = "mon" | "tue" | "wed" | "thu" | "fri" | "sat" | "sun"; | |
| 32 | ||
| 33 | export type RefCondition = { include: string[]; exclude: string[] }; | |
| 34 | export type RepositoryCondition = { | |
| 35 | include: string[]; | |
| 36 | exclude: string[]; | |
| 37 | visibility: "any" | "public" | "private"; | |
| 38 | topics: string[]; | |
| 39 | }; | |
| 40 | export type Conditions = { ref_name: RefCondition; repository?: RepositoryCondition }; | |
| 41 | export type BypassActor = { kind: BypassActorKind; value: string; mode: BypassMode }; | |
| 42 | ||
| 43 | export type PullRequestParameters = { | |
| 44 | required_approvals: number; | |
| 45 | count_agent_approvals: boolean; | |
| 46 | dismiss_stale_reviews_on_push: boolean; | |
| 47 | require_code_owner_review: boolean; | |
| 48 | require_last_push_approval: boolean; | |
| 49 | allowed_merge_methods: MergeMethod[]; | |
| 50 | /** Only the ruleset made from branch protection that did not refuse pushes. */ | |
| 51 | allow_direct_pushes?: boolean; | |
| 52 | }; | |
| 53 | export type RulesetCheck = { context: string; integration?: Integration }; | |
| 54 | export type StatusChecksParameters = { | |
| 55 | checks: RulesetCheck[]; | |
| 56 | strict: boolean; | |
| 57 | paths: string[]; | |
| 58 | allow_bypass_on_merge: boolean; | |
| 59 | }; | |
| 60 | export type MergeQueueParameters = { | |
| 61 | merge_method: MergeMethod; | |
| 62 | max_entries_to_build: number; | |
| 63 | min_entries_to_merge: number; | |
| 64 | min_entries_wait_minutes: number; | |
| 65 | check_response_timeout_minutes: number; | |
| 66 | }; | |
| 67 | export type PatternParameters = { name: string; operator: PatternOperator; pattern: string; negate: boolean }; | |
| 68 | export type WeeklyWindow = { days: Weekday[]; start: string; end: string }; | |
| 69 | export type Period = { start: string; end?: string | null; reason: string }; | |
| 70 | export type MergeWindowParameters = { | |
| 71 | time_zone: string; | |
| 72 | windows: WeeklyWindow[]; | |
| 73 | freezes: Period[]; | |
| 74 | exceptions: Period[]; | |
| 75 | }; | |
| 76 | ||
| 77 | /** Every rule type, with its parameters. */ | |
| 78 | export type Rule = | |
| 79 | | { type: "creation"; parameters: Record<string, never> } | |
| 80 | | { type: "update"; parameters: Record<string, never> } | |
| 81 | | { type: "deletion"; parameters: Record<string, never> } | |
| 82 | | { type: "non_fast_forward"; parameters: Record<string, never> } | |
| 83 | | { type: "required_linear_history"; parameters: Record<string, never> } | |
| 84 | | { type: "required_signatures"; parameters: Record<string, never> } | |
| 85 | | { type: "pull_request"; parameters: PullRequestParameters } | |
| 86 | | { type: "required_status_checks"; parameters: StatusChecksParameters } | |
| 87 | | { type: "merge_queue"; parameters: MergeQueueParameters } | |
| 88 | | { type: "required_deployments"; parameters: { environments: string[] } } | |
| 89 | | { type: "commit_message_pattern"; parameters: PatternParameters } | |
| 90 | | { type: "commit_author_email_pattern"; parameters: PatternParameters } | |
| 91 | | { type: "committer_email_pattern"; parameters: PatternParameters } | |
| 92 | | { type: "branch_name_pattern"; parameters: PatternParameters } | |
| 93 | | { type: "tag_name_pattern"; parameters: PatternParameters } | |
| 94 | | { type: "file_path_restriction"; parameters: { restricted_file_paths: string[] } } | |
| 95 | | { type: "file_extension_restriction"; parameters: { restricted_file_extensions: string[] } } | |
| 96 | | { type: "max_file_size"; parameters: { max_file_size_mb: number } } | |
| 97 | | { type: "max_file_path_length"; parameters: { max_file_path_length: number } } | |
| 98 | | { type: "max_files_changed"; parameters: { max_files: number } } | |
| 99 | | { type: "secret_scanning"; parameters: Record<string, never> } | |
| 100 | | { type: "path_review"; parameters: { paths: string[]; required_approvals: number; team?: string | null } } | |
| 101 | | { type: "merge_window"; parameters: MergeWindowParameters } | |
| The contracts no longer describe g1t's own agents, and workspaces can keep their AI providers. Every consumer had already stopped using them, so the TypeScript and Rust contracts drop the workspace-agent, ability, look, skill-library, context, runner-agent and mention modules, the chat and docs RPCs agents posted and read through, the folio agent methods, the agent_waiting notification, agent.asked and memory.changed events, AI credit, token and gateway billing types, model routes and sessions, team agents, agent tokens, plan, review, message and confidence types, command rules, cost caps and confidence rules. The agents:run and models:* scopes are no longer offered by any preset, OAuth default or permission form, but a stored token or grant that names them still reads; and the removed operations are gone from the scope table, so the API's check that every operation has exactly one scope is strict again. What stored data needs in order to parse (old run and credential kinds, an agent team lead, retired rules and webhook events, old guardrail and integration settings) still parses, and a run's token is still PrincipalKind::Agent, which now means a run's token and the @g1t rows written before. The customize, marketplace, skills and claude-plugin contracts stay only until the mobile app drops its Customize screens. | 102 | | { type: "agent_auto_merge"; parameters: { allowed: boolean } }; |
| 103 | ||
| 104 | /** | |
| 105 | * Rule types no longer offered, which were about g1t's own agents. A stored | |
| 106 | * ruleset that has one still reads: the rule is left out. Mirrors | |
| 107 | * `RETIRED_RULES` in `crates/contracts/src/rules.rs`. | |
| 108 | */ | |
| 109 | export const RETIRED_RULES: readonly string[] = ["confidence_threshold", "cost_cap"]; | |
| Merge rulesets: branch and tag rules, agent-first, enforced on push and merge | 110 | |
| 111 | export type RuleType = Rule["type"]; | |
| 112 | export type RuleEntry = Rule & { applies_to: AppliesTo }; | |
| 113 | ||
| 114 | /** What a ruleset says: what is created, changed, exported and imported. */ | |
| 115 | export type RulesetSpec = { | |
| 116 | name: string; | |
| 117 | enforcement: Enforcement; | |
| 118 | target: Target; | |
| 119 | conditions: Conditions; | |
| 120 | bypass_actors: BypassActor[]; | |
| 121 | rules: RuleEntry[]; | |
| 122 | }; | |
| 123 | ||
| 124 | export type Ruleset = RulesetSpec & { | |
| 125 | id: string; | |
| 126 | level: Level; | |
| 127 | workspace: string; | |
| 128 | repo_id?: string; | |
| 129 | repository?: string; | |
| 130 | /** `branch_protection` for the one made from branch protection settings. */ | |
| 131 | source?: string; | |
| 132 | created_by: string; | |
| 133 | created_at: string; | |
| 134 | updated_by: string; | |
| 135 | updated_at: string; | |
| 136 | }; | |
| 137 | ||
| 138 | export type RulesetSummary = { | |
| 139 | id: string; | |
| 140 | name: string; | |
| 141 | level: Level; | |
| 142 | enforcement: Enforcement; | |
| 143 | bypass_actors: BypassActor[]; | |
| 144 | }; | |
| 145 | ||
| 146 | export type EffectiveRule = RuleEntry & { | |
| 147 | ruleset_id: string; | |
| 148 | ruleset_name: string; | |
| 149 | level: Level; | |
| 150 | enforcement: Enforcement; | |
| 151 | }; | |
| 152 | ||
| 153 | export type EffectiveRules = { | |
| 154 | name: string; | |
| 155 | target: Target; | |
| 156 | default_branch: boolean; | |
| 157 | rules: EffectiveRule[]; | |
| 158 | rulesets: RulesetSummary[]; | |
| 159 | }; | |
| 160 | ||
| 161 | export type RuleVerdict = "pass" | "fail" | "bypass"; | |
| 162 | export type Action = "push" | "merge" | "create_ref" | "delete_ref" | "rename_ref" | "commit"; | |
| 163 | ||
| 164 | export type Violation = { | |
| 165 | rule: string; | |
| 166 | ruleset_id: string; | |
| 167 | ruleset_name: string; | |
| 168 | enforcement: Enforcement; | |
| 169 | message: string; | |
| 170 | remedy: string; | |
| 171 | }; | |
| 172 | ||
| 173 | export type Evaluation = { | |
| 174 | id: string; | |
| 175 | repo_id: string; | |
| 176 | workspace: string; | |
| 177 | ruleset_id: string; | |
| 178 | ruleset_name: string; | |
| 179 | enforcement: Enforcement; | |
| 180 | action: Action; | |
| 181 | git_ref: string; | |
| 182 | actor: string; | |
| 183 | actor_kind: string; | |
| 184 | verdict: RuleVerdict; | |
| 185 | violations: Violation[]; | |
| 186 | number: number | null; | |
| 187 | sha: string | null; | |
| 188 | repository: string; | |
| 189 | created_at: string; | |
| 190 | }; | |
| 191 | ||
| 192 | export type Insights = { | |
| 193 | days: number; | |
| 194 | total: number; | |
| 195 | passed: number; | |
| 196 | blocked: number; | |
| 197 | would_block: number; | |
| 198 | bypassed: number; | |
| 199 | by_ruleset: { | |
| 200 | ruleset_id: string; | |
| 201 | ruleset_name: string; | |
| 202 | enforcement: Enforcement; | |
| 203 | total: number; | |
| 204 | blocked: number; | |
| 205 | would_block: number; | |
| 206 | bypassed: number; | |
| 207 | }[]; | |
| 208 | by_rule: { rule: string; count: number }[]; | |
| 209 | }; | |
| 210 | ||
| 211 | export type EvaluationPage = { evaluations: Evaluation[]; next: string | null; insights: Insights }; | |
| 212 | ||
| 213 | /** What a pull request's merge box shows of the rules of its base. */ | |
| 214 | export type MergeRules = { | |
| 215 | unmet: Violation[]; | |
| 216 | bypassable: Violation[]; | |
| 217 | evaluate: Violation[]; | |
| 218 | rulesets: RulesetSummary[]; | |
| 219 | merge_queue: boolean; | |
| 220 | /** What the active rules ask, as they stack. */ | |
| 221 | required_approvals: number; | |
| 222 | strict: boolean; | |
| 223 | allow_bypass_on_merge: boolean; | |
| 224 | }; | |
| 225 | ||
| 226 | /** Whose rulesets: a repository's or a workspace's. */ | |
| 227 | export type RulesetOwner = { repo: RepoPath } | { workspace: string }; | |
| 228 | ||
| 229 | export type EvaluationFilter = { | |
| 230 | ruleset_id?: string; | |
| 231 | verdict?: RuleVerdict; | |
| 232 | problems_only?: boolean; | |
| 233 | before?: string; | |
| 234 | limit?: number; | |
| 235 | }; | |
| 236 | ||
| 237 | export interface RulesApi { | |
| 238 | listRulesets(owner: RulesetOwner, viewer: Viewer, includeParents?: boolean): Promise<Result<Ruleset[]>>; | |
| 239 | getRuleset(owner: RulesetOwner, id: string, viewer: Viewer): Promise<Result<Ruleset>>; | |
| 240 | /** Creates one (no `id`) or replaces one. */ | |
| 241 | saveRuleset(actor: User, owner: RulesetOwner, ruleset: RulesetSpec, id?: string): Promise<Result<Ruleset>>; | |
| 242 | deleteRuleset(actor: User, owner: RulesetOwner, id: string): Promise<Result<boolean>>; | |
| 243 | effectiveRules(repo: RepoPath, name: string, viewer: Viewer, target?: Target): Promise<Result<EffectiveRules>>; | |
| 244 | ruleEvaluations(owner: RulesetOwner, viewer: Viewer, filter?: EvaluationFilter): Promise<Result<EvaluationPage>>; | |
| 245 | } |
This file's history is long; its oldest lines are credited to the oldest commit read.