Skip to content
433 linesCodeBlameRaw

Pick any line to see why it is the way it is: the commit, the pull request and issue it came from, and what the agent was thinking.

Pull requests from branches1//! Rows as they come out of D1, and their conversion to contract types.
2
3use g1t_contracts::User;
4use g1t_contracts::repos::RepoPath;
5use g1t_contracts::work::{
Cards you act on in chat; agents comment and review as themselves; names shown cleanly; commits on the calendar6 AgentRef, AgentVerdict, CheckStatus, Comment, CommentKind, Issue, IssueReason, MilestoneRef, Pull, PullStatus, Runtime, SessionEntry,
Acceptance checks in sandboxes, line comments and review verdicts7 SessionEntryKind, State, Verdict,
Pull requests from branches8};
9use serde::Deserialize;
10
Git storage hardened, pages in tens of milliseconds, honest security alerts, and costs reconciled daily11/// An author or actor as stored: g1t itself when the id is its own (a
g1t is the stored author of what it opens; the person who asked is requested_by and keeps the author's rights12/// security update it opened, a merge its settings made), g1t's agent by
13/// its id (what it made or filed), a person otherwise.
Agents as a team: lifecycle, merge queue, billing and a new shell14pub(crate) fn user(id: String, username: String) -> User {
Git storage hardened, pages in tens of milliseconds, honest security alerts, and costs reconciled daily15 let kind = if g1t_contracts::system::is_system_id(&id) {
16 g1t_contracts::PrincipalKind::System
g1t is the stored author of what it opens; the person who asked is requested_by and keeps the author's rights17 } else if id == g1t_contracts::identity::AGENT_ID {
18 g1t_contracts::PrincipalKind::Agent
Git storage hardened, pages in tens of milliseconds, honest security alerts, and costs reconciled daily19 } else {
20 g1t_contracts::PrincipalKind::User
21 };
Pull requests from branches22 User {
23 id,
24 username,
Git storage hardened, pages in tens of milliseconds, honest security alerts, and costs reconciled daily25 kind,
Pull requests from branches26 ..User::default()
27 }
28}
29
g1t is the stored author of what it opens; the person who asked is requested_by and keeps the author's rights30/// Who asked g1t for the work, as stored beside its author: both columns,
31/// or nobody.
32pub(crate) fn requester(id: Option<String>, username: Option<String>) -> Option<User> {
33 Some(user(id?, username?))
34}
35
Pull requests from branches36#[derive(Deserialize)]
37pub struct IssueRow {
38 pub id: String,
39 pub repo_id: String,
40 pub number: u32,
41 pub title: String,
42 pub body: String,
43 /// JSON array of label names.
44 pub labels: String,
45 pub state: State,
46 pub reason: Option<IssueReason>,
47 pub resolved_by: Option<u32>,
48 pub author_id: String,
49 pub author_name: String,
g1t is the stored author of what it opens; the person who asked is requested_by and keeps the author's rights50 #[serde(default)]
51 pub requested_by_id: Option<String>,
52 #[serde(default)]
53 pub requested_by_name: Option<String>,
Pull requests from branches54 pub created_at: String,
55 pub updated_at: String,
56 pub closed_at: Option<String>,
57 pub pull_count: u32,
58 pub comment_count: u32,
Agents as a team: lifecycle, merge queue, billing and a new shell59 /// JSON array of usernames.
60 pub assignees: String,
61 /// JSON array of issue numbers.
62 pub blocked_by: String,
63 /// JSON of who queued it for a g1t agent, if anyone has.
64 pub queued_by: Option<String>,
65 pub agent: Option<String>,
Teams and CODEOWNERS, labels and milestones, dependency updates, the security suite, and a clearer top bar66 /// The number of its milestone, and that milestone's title.
67 #[serde(default)]
68 pub milestone: Option<u32>,
69 #[serde(default)]
70 pub milestone_title: Option<String>,
Pull requests from branches71}
72
Teams and CODEOWNERS, labels and milestones, dependency updates, the security suite, and a clearer top bar73/// A milestone as an issue or pull request names it, from its number and
74/// title as read beside it.
75pub(crate) fn milestone_ref(number: Option<u32>, title: Option<String>) -> Option<MilestoneRef> {
76 Some(MilestoneRef { number: number?, title: title? })
77}
78
Pull requests from branches79impl From<IssueRow> for Issue {
80 fn from(row: IssueRow) -> Self {
81 Issue {
82 id: row.id,
83 repo_id: row.repo_id,
84 number: row.number,
85 title: row.title,
86 body: row.body,
87 labels: serde_json::from_str(&row.labels).unwrap_or_default(),
88 state: row.state,
89 reason: row.reason,
90 resolved_by: row.resolved_by,
91 author: user(row.author_id, row.author_name),
g1t is the stored author of what it opens; the person who asked is requested_by and keeps the author's rights92 requested_by: requester(row.requested_by_id, row.requested_by_name),
Pull requests from branches93 created_at: row.created_at,
94 updated_at: row.updated_at,
95 closed_at: row.closed_at,
96 pull_count: row.pull_count,
97 comment_count: row.comment_count,
Agents as a team: lifecycle, merge queue, billing and a new shell98 assignees: serde_json::from_str(&row.assignees).unwrap_or_default(),
99 blocked_by: serde_json::from_str(&row.blocked_by).unwrap_or_default(),
100 queued: row.queued_by.is_some(),
101 agent: row.agent,
Teams and CODEOWNERS, labels and milestones, dependency updates, the security suite, and a clearer top bar102 milestone: milestone_ref(row.milestone, row.milestone_title),
Pull requests from branches103 }
104 }
105}
106
Agents as a team: lifecycle, merge queue, billing and a new shell107/// The remembered assessment of a pull request, read beside its row.
Pull requests from branches108#[derive(Deserialize)]
Agents as a team: lifecycle, merge queue, billing and a new shell109pub struct Snapshot {
110 pub stage: Option<g1t_contracts::work::Stage>,
111 pub stage_detail: Option<String>,
112 #[serde(default)]
113 pub revisions: u32,
114 /// Whether g1t is seeing it through at all.
115 #[serde(default)]
116 pub managed: u32,
117}
118
Thirteen MCP tools and classic token scopes; agents rate their confidence and can be put on an issue in one step119/// A pull request's columns, with its confidence (confidence.rs) beside
120/// them: what every read of a [`PullRow`] selects.
Teams and CODEOWNERS, labels and milestones, dependency updates, the security suite, and a clearer top bar121pub const PULL_COLUMNS: &str = "pulls.*,
122 (SELECT detail FROM pull_confidence WHERE pull_confidence.pull_id = pulls.id) AS confidence,
123 (SELECT title FROM milestones
124 WHERE milestones.repo_id = pulls.repo_id AND milestones.number = pulls.milestone) AS milestone_title";
Thirteen MCP tools and classic token scopes; agents rate their confidence and can be put on an issue in one step125
Agents as a team: lifecycle, merge queue, billing and a new shell126#[derive(Deserialize)]
Pull requests from branches127pub struct PullRow {
128 pub id: String,
129 pub repo_id: String,
130 pub number: u32,
131 pub issue_number: Option<u32>,
132 pub title: String,
133 pub body: Option<String>,
134 pub agent: String,
135 pub runtime: Runtime,
136 pub status: PullStatus,
137 pub fork_repo_id: Option<String>,
138 pub fork_namespace: Option<String>,
139 pub fork_name: Option<String>,
140 pub source_branch: Option<String>,
141 pub head_commit: Option<String>,
142 pub merge_base: Option<String>,
143 pub merged_by: Option<String>,
144 pub merged_at: Option<String>,
145 pub superseded_by: Option<u32>,
Acceptance checks in sandboxes, line comments and review verdicts146 pub check_status: Option<CheckStatus>,
Agents as a team: lifecycle, merge queue, billing and a new shell147 /// JSON array of changed files; `None` until first worked out.
148 pub files: Option<String>,
149 /// JSON arrays of usernames.
150 pub assignees: String,
151 pub reviewers: String,
Teams and CODEOWNERS, labels and milestones, dependency updates, the security suite, and a clearer top bar152 /// JSON array of `workspace/team`.
153 #[serde(default)]
154 pub team_reviewers: Option<String>,
Pull requests from branches155 pub author_id: String,
156 pub author_name: String,
g1t is the stored author of what it opens; the person who asked is requested_by and keeps the author's rights157 #[serde(default)]
158 pub requested_by_id: Option<String>,
159 #[serde(default)]
160 pub requested_by_name: Option<String>,
Pull requests from branches161 pub created_at: String,
162 pub updated_at: String,
Thirteen MCP tools and classic token scopes; agents rate their confidence and can be put on an issue in one step163 /// JSON of its confidence, once worked out.
164 #[serde(default)]
165 pub confidence: Option<String>,
Teams and CODEOWNERS, labels and milestones, dependency updates, the security suite, and a clearer top bar166 /// JSON array of label names.
167 #[serde(default)]
168 pub labels: Option<String>,
169 #[serde(default)]
170 pub milestone: Option<u32>,
171 #[serde(default)]
172 pub milestone_title: Option<String>,
173 /// The branch it merges into; NULL for the default branch.
174 #[serde(default)]
175 pub base_branch: Option<String>,
Merge rulesets: branch and tag rules, agent-first, enforced on push and merge176 #[serde(default)]
177 pub head_pushed_by: Option<String>,
178 #[serde(default)]
179 pub head_pushed_at: Option<String>,
Pull requests from branches180}
181
182impl From<PullRow> for Pull {
183 fn from(row: PullRow) -> Self {
184 Pull {
185 id: row.id,
186 repo_id: row.repo_id,
187 number: row.number,
188 issue: row.issue_number,
189 title: row.title,
190 body: row.body,
191 agent: row.agent,
192 runtime: row.runtime,
193 status: row.status,
194 fork: row
195 .fork_namespace
196 .zip(row.fork_name)
197 .map(|(namespace, name)| RepoPath { namespace, name }),
198 fork_repo_id: row.fork_repo_id,
199 branch: row.source_branch,
200 head_commit: row.head_commit,
201 merge_base: row.merge_base,
202 merged_by: row.merged_by,
203 merged_at: row.merged_at,
204 superseded_by: row.superseded_by,
Acceptance checks in sandboxes, line comments and review verdicts205 check_status: row.check_status,
Agents as a team: lifecycle, merge queue, billing and a new shell206 files: row
207 .files
208 .as_deref()
209 .and_then(|files| serde_json::from_str(files).ok())
210 .unwrap_or_default(),
211 assignees: serde_json::from_str(&row.assignees).unwrap_or_default(),
212 reviewers: serde_json::from_str(&row.reviewers).unwrap_or_default(),
Teams and CODEOWNERS, labels and milestones, dependency updates, the security suite, and a clearer top bar213 team_reviewers: row
214 .team_reviewers
215 .as_deref()
216 .and_then(|teams| serde_json::from_str(teams).ok())
217 .unwrap_or_default(),
Pull requests from branches218 author: user(row.author_id, row.author_name),
g1t is the stored author of what it opens; the person who asked is requested_by and keeps the author's rights219 requested_by: requester(row.requested_by_id, row.requested_by_name),
Pull requests from branches220 created_at: row.created_at,
221 updated_at: row.updated_at,
Thirteen MCP tools and classic token scopes; agents rate their confidence and can be put on an issue in one step222 confidence: row
223 .confidence
224 .as_deref()
225 .and_then(|detail| serde_json::from_str(detail).ok()),
Teams and CODEOWNERS, labels and milestones, dependency updates, the security suite, and a clearer top bar226 labels: row
227 .labels
228 .as_deref()
229 .and_then(|labels| serde_json::from_str(labels).ok())
230 .unwrap_or_default(),
231 milestone: milestone_ref(row.milestone, row.milestone_title),
232 base: row.base_branch,
Merge rulesets: branch and tag rules, agent-first, enforced on push and merge233 head_pushed_by: row.head_pushed_by,
234 head_pushed_at: row.head_pushed_at,
Pull requests from branches235 }
236 }
237}
238
239#[derive(Deserialize)]
240pub struct CommentRow {
241 pub id: String,
Agents as a team: lifecycle, merge queue, billing and a new shell242 pub kind: CommentKind,
Pull requests from branches243 pub author_id: String,
244 pub author_name: String,
245 pub body: String,
Acceptance checks in sandboxes, line comments and review verdicts246 pub path: Option<String>,
247 pub line: Option<u32>,
248 pub verdict: Option<Verdict>,
Pull requests from branches249 pub created_at: String,
Merge Actions: cross-repo workflows and actions, release and deployment triggers, step timeouts250 #[serde(default)]
251 pub edited_at: Option<String>,
252 /// The issue or pull request it is on, where the query reads it.
253 #[serde(default)]
254 pub number: u32,
Cards you act on in chat; agents comment and review as themselves; names shown cleanly; commits on the calendar255 /// One of the workspace's agents that wrote it, as itself, and whom it
256 /// acted for (migrations/0033_agent_comments.sql).
257 #[serde(default)]
258 pub agent_id: Option<String>,
259 #[serde(default)]
260 pub agent_handle: Option<String>,
261 #[serde(default)]
262 pub agent_name: Option<String>,
263 #[serde(default)]
264 pub agent_avatar_seed: Option<String>,
265 #[serde(default)]
266 pub acting_for_id: Option<String>,
267 #[serde(default)]
268 pub acting_for_name: Option<String>,
269 /// An agent review's verdict, kept apart from `verdict`, which every
270 /// rule about approvals reads: so it is advisory.
271 #[serde(default)]
272 pub agent_verdict: Option<String>,
273}
274
275impl CommentRow {
276 /// Who answers for it: whoever an agent acted for, or its author.
277 pub fn answerable_id(&self) -> &str {
278 self.acting_for_id.as_deref().unwrap_or(&self.author_id)
279 }
280
281 /// Whether it carries a verdict, a person's or an agent's.
282 pub fn has_verdict(&self) -> bool {
283 self.verdict.is_some() || self.agent_verdict.is_some()
284 }
Pull requests from branches285}
286
287impl From<CommentRow> for Comment {
288 fn from(row: CommentRow) -> Self {
Cards you act on in chat; agents comment and review as themselves; names shown cleanly; commits on the calendar289 let agent = match (row.agent_id, row.agent_handle) {
290 (Some(id), Some(handle)) => Some(AgentRef {
291 display_name: row.agent_name.unwrap_or_else(|| handle.clone()),
292 avatar_seed: row.agent_avatar_seed.unwrap_or_else(|| handle.clone()),
293 id,
294 handle,
295 }),
296 _ => None,
297 };
298 let advisory_verdict = row.agent_verdict.as_deref().and_then(AgentVerdict::parse);
299 let mut author = user(row.author_id, row.author_name);
300 if agent.is_some() {
301 author.kind = g1t_contracts::PrincipalKind::Agent;
302 }
Pull requests from branches303 Comment {
304 id: row.id,
Agents as a team: lifecycle, merge queue, billing and a new shell305 kind: row.kind,
Cards you act on in chat; agents comment and review as themselves; names shown cleanly; commits on the calendar306 author,
Pull requests from branches307 body: row.body,
Acceptance checks in sandboxes, line comments and review verdicts308 path: row.path,
309 line: row.line,
Cards you act on in chat; agents comment and review as themselves; names shown cleanly; commits on the calendar310 // A person's verdict, or for showing, an agent's advisory one.
311 verdict: row.verdict.or(advisory_verdict.and_then(AgentVerdict::verdict)),
Pull requests from branches312 created_at: row.created_at,
Merge Actions: cross-repo workflows and actions, release and deployment triggers, step timeouts313 edited_at: row.edited_at,
Cards you act on in chat; agents comment and review as themselves; names shown cleanly; commits on the calendar314 acting_for: agent.as_ref().and(requester(row.acting_for_id, row.acting_for_name)),
315 advisory: agent.is_some() && advisory_verdict.is_some(),
316 agent,
Pull requests from branches317 }
318 }
319}
320
321#[derive(Deserialize)]
322pub struct SessionRow {
323 pub seq: u32,
324 pub kind: SessionEntryKind,
325 pub text: String,
326 pub tool: Option<String>,
327 pub commit: Option<String>,
328 pub at: String,
329}
330
331impl From<SessionRow> for SessionEntry {
332 fn from(row: SessionRow) -> Self {
333 SessionEntry {
334 seq: row.seq,
335 kind: row.kind,
336 text: row.text,
337 tool: row.tool,
338 commit: row.commit,
339 at: row.at,
340 }
341 }
342}
343
Acceptance checks in sandboxes, line comments and review verdicts344/// A pull request whose head a push moved.
345#[derive(Deserialize)]
346pub struct MovedRow {
347 pub id: String,
348 pub repo_id: String,
349 pub number: u32,
350 pub issue_number: Option<u32>,
351 pub status: PullStatus,
g1t is the stored author of what it opens; the person who asked is requested_by and keeps the author's rights352 pub author_id: String,
353 pub author_name: String,
354 #[serde(default)]
355 pub requested_by_id: Option<String>,
356 #[serde(default)]
357 pub requested_by_name: Option<String>,
Acceptance checks in sandboxes, line comments and review verdicts358}
359
Pull requests from branches360/// A single number selected as `n`.
361#[derive(Deserialize)]
362pub struct NumberRow {
363 pub n: u32,
364}
365
366/// A single string selected as `value`.
367#[derive(Deserialize)]
368pub struct ValueRow {
369 pub value: String,
370}
g1t is the stored author of what it opens; the person who asked is requested_by and keeps the author's rights371
372/// Rows as the database holds them, for tests of the rules that read them.
373#[cfg(test)]
374pub(crate) mod stored {
375 use super::*;
376
377 /// A pull request g1t made in a fork, read back as stored: g1t as its
378 /// author, and `requested_by` the person who asked, if anyone did.
379 pub(crate) fn pull(author: (&str, &str), requested_by: Option<(&str, &str)>) -> Pull {
380 let row: PullRow = serde_json::from_value(serde_json::json!({
381 "id": "pr_1", "repo_id": "rep_1", "number": 14, "issue_number": 12, "title": "Fix it",
382 "body": null, "agent": "g1t", "runtime": "hosted", "status": "open",
383 "fork_repo_id": "rep_f", "fork_namespace": "pulls", "fork_name": "pr_1",
384 "source_branch": null, "head_commit": null, "merge_base": null, "merged_by": null,
385 "merged_at": null, "superseded_by": null, "check_status": null, "files": null,
386 "assignees": "[]", "reviewers": "[]",
387 "author_id": author.0, "author_name": author.1,
388 "requested_by_id": requested_by.map(|(id, _)| id),
389 "requested_by_name": requested_by.map(|(_, name)| name),
390 "created_at": "", "updated_at": ""
391 }))
392 .unwrap();
393 row.into()
394 }
395
396 /// g1t's agent, as an author is stored.
397 pub(crate) const G1T: (&str, &str) = (g1t_contracts::identity::AGENT_ID, "g1t");
398 /// The person who asked g1t for the work.
399 pub(crate) const ASKER: (&str, &str) = ("usr_1", "syntaqx");
400}
401
402#[cfg(test)]
403mod tests {
404 use super::stored::{ASKER, G1T, pull};
405 use super::*;
406 use g1t_contracts::PrincipalKind;
407
408 #[test]
409 fn g1t_s_pull_request_reads_back_as_g1t_s_requested_by_the_person() {
410 let made = pull(G1T, Some(ASKER));
411 assert_eq!((made.author.username.as_str(), made.author.kind), ("g1t", PrincipalKind::Agent));
412 let asked = made.requested_by.as_ref().expect("who asked is kept");
413 assert_eq!((asked.id.as_str(), asked.username.as_str(), asked.kind), ("usr_1", "syntaqx", PrincipalKind::User));
414 assert_eq!(made.owner().id, "usr_1");
415 }
416
417 #[test]
418 fn anyone_else_s_reads_back_as_theirs_alone() {
419 let own = pull(ASKER, None);
420 assert_eq!(own.author.kind, PrincipalKind::User);
421 assert!(own.requested_by.is_none());
422 assert_eq!(own.owner().id, "usr_1");
423 // Half a requester is nobody.
424 assert!(requester(Some("usr_1".into()), None).is_none());
425 }
426
427 #[test]
428 fn g1t_s_own_work_reads_back_as_g1t_itself() {
429 let own = pull(("g1t", "g1t"), None);
430 assert_eq!(own.author.kind, PrincipalKind::System);
431 assert!(own.requested_by.is_none());
432 }
433}

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