Skip to content

g1t/services/work/src/rows.rs

379 lines12,716 bytesCodeBlame

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.

Work service in Rust, with RFC 3339 timestamps1//! 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::{
Teams and CODEOWNERS, labels and milestones, dependency updates, the security suite, and a clearer top bar6 CheckStatus, Comment, CommentKind, Issue, IssueReason, MilestoneRef, Pull, PullStatus, Runtime, SessionEntry,
Acceptance checks in sandboxes, line comments and review verdicts7 SessionEntryKind, State, Verdict,
Work service in Rust, with RFC 3339 timestamps8};
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 };
Issues and pull requests replace intents and attempts22 User {
23 id,
24 username,
Git storage hardened, pages in tens of milliseconds, honest security alerts, and costs reconciled daily25 kind,
Issues and pull requests replace intents and attempts26 ..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
Work service in Rust, with RFC 3339 timestamps36#[derive(Deserialize)]
Issues and pull requests replace intents and attempts37pub struct IssueRow {
Work service in Rust, with RFC 3339 timestamps38 pub id: String,
39 pub repo_id: String,
40 pub number: u32,
41 pub title: String,
Issues and pull requests replace intents and attempts42 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>,
Work service in Rust, with RFC 3339 timestamps48 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>,
Work service in Rust, with RFC 3339 timestamps54 pub created_at: String,
Issues and pull requests replace intents and attempts55 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>,
Work service in Rust, with RFC 3339 timestamps71}
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
Issues and pull requests replace intents and attempts79impl From<IssueRow> for Issue {
80 fn from(row: IssueRow) -> Self {
81 Issue {
Work service in Rust, with RFC 3339 timestamps82 id: row.id,
83 repo_id: row.repo_id,
84 number: row.number,
85 title: row.title,
Issues and pull requests replace intents and attempts86 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),
Work service in Rust, with RFC 3339 timestamps93 created_at: row.created_at,
Issues and pull requests replace intents and attempts94 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),
Work service in Rust, with RFC 3339 timestamps103 }
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.
Work service in Rust, with RFC 3339 timestamps108#[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)]
Issues and pull requests replace intents and attempts127pub struct PullRow {
Work service in Rust, with RFC 3339 timestamps128 pub id: String,
129 pub repo_id: String,
130 pub number: u32,
Issues and pull requests replace intents and attempts131 pub issue_number: Option<u32>,
132 pub title: String,
133 pub body: Option<String>,
Work service in Rust, with RFC 3339 timestamps134 pub agent: String,
Issues and pull requests replace intents and attempts135 pub runtime: Runtime,
136 pub status: PullStatus,
Pull requests from branches137 pub fork_repo_id: Option<String>,
138 pub fork_namespace: Option<String>,
139 pub fork_name: Option<String>,
140 pub source_branch: Option<String>,
Work service in Rust, with RFC 3339 timestamps141 pub head_commit: Option<String>,
Issues and pull requests replace intents and attempts142 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>,
Issues and pull requests replace intents and attempts155 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>,
Work service in Rust, with RFC 3339 timestamps161 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>,
Work service in Rust, with RFC 3339 timestamps180}
181
Issues and pull requests replace intents and attempts182impl From<PullRow> for Pull {
183 fn from(row: PullRow) -> Self {
184 Pull {
Work service in Rust, with RFC 3339 timestamps185 id: row.id,
186 repo_id: row.repo_id,
187 number: row.number,
Issues and pull requests replace intents and attempts188 issue: row.issue_number,
189 title: row.title,
190 body: row.body,
Work service in Rust, with RFC 3339 timestamps191 agent: row.agent,
192 runtime: row.runtime,
193 status: row.status,
Pull requests from branches194 fork: row
195 .fork_namespace
196 .zip(row.fork_name)
197 .map(|(namespace, name)| RepoPath { namespace, name }),
Work service in Rust, with RFC 3339 timestamps198 fork_repo_id: row.fork_repo_id,
Pull requests from branches199 branch: row.source_branch,
Work service in Rust, with RFC 3339 timestamps200 head_commit: row.head_commit,
Issues and pull requests replace intents and attempts201 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(),
Issues and pull requests replace intents and attempts218 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),
Work service in Rust, with RFC 3339 timestamps220 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,
Work service in Rust, with RFC 3339 timestamps235 }
236 }
237}
238
239#[derive(Deserialize)]
Issues and pull requests replace intents and attempts240pub struct CommentRow {
241 pub id: String,
Agents as a team: lifecycle, merge queue, billing and a new shell242 pub kind: CommentKind,
Issues and pull requests replace intents and attempts243 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>,
Issues and pull requests replace intents and attempts249 pub created_at: String,
250}
251
252impl From<CommentRow> for Comment {
253 fn from(row: CommentRow) -> Self {
254 Comment {
255 id: row.id,
Agents as a team: lifecycle, merge queue, billing and a new shell256 kind: row.kind,
Issues and pull requests replace intents and attempts257 author: user(row.author_id, row.author_name),
258 body: row.body,
Acceptance checks in sandboxes, line comments and review verdicts259 path: row.path,
260 line: row.line,
261 verdict: row.verdict,
Issues and pull requests replace intents and attempts262 created_at: row.created_at,
263 }
264 }
265}
266
267#[derive(Deserialize)]
Work service in Rust, with RFC 3339 timestamps268pub struct SessionRow {
269 pub seq: u32,
270 pub kind: SessionEntryKind,
271 pub text: String,
272 pub tool: Option<String>,
273 pub commit: Option<String>,
274 pub at: String,
275}
276
277impl From<SessionRow> for SessionEntry {
278 fn from(row: SessionRow) -> Self {
279 SessionEntry {
280 seq: row.seq,
281 kind: row.kind,
282 text: row.text,
283 tool: row.tool,
284 commit: row.commit,
285 at: row.at,
286 }
287 }
288}
Issues and pull requests replace intents and attempts289
Acceptance checks in sandboxes, line comments and review verdicts290/// A pull request whose head a push moved.
291#[derive(Deserialize)]
292pub struct MovedRow {
293 pub id: String,
294 pub repo_id: String,
295 pub number: u32,
296 pub issue_number: Option<u32>,
297 pub status: PullStatus,
g1t is the stored author of what it opens; the person who asked is requested_by and keeps the author's rights298 pub author_id: String,
299 pub author_name: String,
300 #[serde(default)]
301 pub requested_by_id: Option<String>,
302 #[serde(default)]
303 pub requested_by_name: Option<String>,
Acceptance checks in sandboxes, line comments and review verdicts304}
305
Issues and pull requests replace intents and attempts306/// A single number selected as `n`.
307#[derive(Deserialize)]
308pub struct NumberRow {
309 pub n: u32,
310}
311
312/// A single string selected as `value`.
313#[derive(Deserialize)]
314pub struct ValueRow {
315 pub value: String,
316}
g1t is the stored author of what it opens; the person who asked is requested_by and keeps the author's rights317
318/// Rows as the database holds them, for tests of the rules that read them.
319#[cfg(test)]
320pub(crate) mod stored {
321 use super::*;
322
323 /// A pull request g1t made in a fork, read back as stored: g1t as its
324 /// author, and `requested_by` the person who asked, if anyone did.
325 pub(crate) fn pull(author: (&str, &str), requested_by: Option<(&str, &str)>) -> Pull {
326 let row: PullRow = serde_json::from_value(serde_json::json!({
327 "id": "pr_1", "repo_id": "rep_1", "number": 14, "issue_number": 12, "title": "Fix it",
328 "body": null, "agent": "g1t", "runtime": "hosted", "status": "open",
329 "fork_repo_id": "rep_f", "fork_namespace": "pulls", "fork_name": "pr_1",
330 "source_branch": null, "head_commit": null, "merge_base": null, "merged_by": null,
331 "merged_at": null, "superseded_by": null, "check_status": null, "files": null,
332 "assignees": "[]", "reviewers": "[]",
333 "author_id": author.0, "author_name": author.1,
334 "requested_by_id": requested_by.map(|(id, _)| id),
335 "requested_by_name": requested_by.map(|(_, name)| name),
336 "created_at": "", "updated_at": ""
337 }))
338 .unwrap();
339 row.into()
340 }
341
342 /// g1t's agent, as an author is stored.
343 pub(crate) const G1T: (&str, &str) = (g1t_contracts::identity::AGENT_ID, "g1t");
344 /// The person who asked g1t for the work.
345 pub(crate) const ASKER: (&str, &str) = ("usr_1", "syntaqx");
346}
347
348#[cfg(test)]
349mod tests {
350 use super::stored::{ASKER, G1T, pull};
351 use super::*;
352 use g1t_contracts::PrincipalKind;
353
354 #[test]
355 fn g1t_s_pull_request_reads_back_as_g1t_s_requested_by_the_person() {
356 let made = pull(G1T, Some(ASKER));
357 assert_eq!((made.author.username.as_str(), made.author.kind), ("g1t", PrincipalKind::Agent));
358 let asked = made.requested_by.as_ref().expect("who asked is kept");
359 assert_eq!((asked.id.as_str(), asked.username.as_str(), asked.kind), ("usr_1", "syntaqx", PrincipalKind::User));
360 assert_eq!(made.owner().id, "usr_1");
361 }
362
363 #[test]
364 fn anyone_else_s_reads_back_as_theirs_alone() {
365 let own = pull(ASKER, None);
366 assert_eq!(own.author.kind, PrincipalKind::User);
367 assert!(own.requested_by.is_none());
368 assert_eq!(own.owner().id, "usr_1");
369 // Half a requester is nobody.
370 assert!(requester(Some("usr_1".into()), None).is_none());
371 }
372
373 #[test]
374 fn g1t_s_own_work_reads_back_as_g1t_itself() {
375 let own = pull(("g1t", "g1t"), None);
376 assert_eq!(own.author.kind, PrincipalKind::System);
377 assert!(own.requested_by.is_none());
378 }
379}

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