flagon-io/g1t

public

Where people and agents ship software together. The open-source git platform for the whole job: issues, agents, checks and deploys to the edge.

g1t/services/work/src/rows.rs

334 lines10,907 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::{
Agents as a team: lifecycle, merge queue, billing and a new shell6 CheckStatus, Comment, CommentKind, Issue, IssueReason, 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>,
Work service in Rust, with RFC 3339 timestamps66}
67
Issues and pull requests replace intents and attempts68impl From<IssueRow> for Issue {
69 fn from(row: IssueRow) -> Self {
70 Issue {
Work service in Rust, with RFC 3339 timestamps71 id: row.id,
72 repo_id: row.repo_id,
73 number: row.number,
74 title: row.title,
Issues and pull requests replace intents and attempts75 body: row.body,
76 labels: serde_json::from_str(&row.labels).unwrap_or_default(),
77 state: row.state,
78 reason: row.reason,
79 resolved_by: row.resolved_by,
80 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 rights81 requested_by: requester(row.requested_by_id, row.requested_by_name),
Work service in Rust, with RFC 3339 timestamps82 created_at: row.created_at,
Issues and pull requests replace intents and attempts83 updated_at: row.updated_at,
84 closed_at: row.closed_at,
85 pull_count: row.pull_count,
86 comment_count: row.comment_count,
Agents as a team: lifecycle, merge queue, billing and a new shell87 assignees: serde_json::from_str(&row.assignees).unwrap_or_default(),
88 blocked_by: serde_json::from_str(&row.blocked_by).unwrap_or_default(),
89 queued: row.queued_by.is_some(),
90 agent: row.agent,
Work service in Rust, with RFC 3339 timestamps91 }
92 }
93}
94
Agents as a team: lifecycle, merge queue, billing and a new shell95/// The remembered assessment of a pull request, read beside its row.
Work service in Rust, with RFC 3339 timestamps96#[derive(Deserialize)]
Agents as a team: lifecycle, merge queue, billing and a new shell97pub struct Snapshot {
98 pub stage: Option<g1t_contracts::work::Stage>,
99 pub stage_detail: Option<String>,
100 #[serde(default)]
101 pub revisions: u32,
102 /// Whether g1t is seeing it through at all.
103 #[serde(default)]
104 pub managed: u32,
105}
106
Thirteen MCP tools and classic token scopes; agents rate their confidence and can be put on an issue in one step107/// A pull request's columns, with its confidence (confidence.rs) beside
108/// them: what every read of a [`PullRow`] selects.
109pub const PULL_COLUMNS: &str =
110 "pulls.*, (SELECT detail FROM pull_confidence WHERE pull_confidence.pull_id = pulls.id) AS confidence";
111
Agents as a team: lifecycle, merge queue, billing and a new shell112#[derive(Deserialize)]
Issues and pull requests replace intents and attempts113pub struct PullRow {
Work service in Rust, with RFC 3339 timestamps114 pub id: String,
115 pub repo_id: String,
116 pub number: u32,
Issues and pull requests replace intents and attempts117 pub issue_number: Option<u32>,
118 pub title: String,
119 pub body: Option<String>,
Work service in Rust, with RFC 3339 timestamps120 pub agent: String,
Issues and pull requests replace intents and attempts121 pub runtime: Runtime,
122 pub status: PullStatus,
Pull requests from branches123 pub fork_repo_id: Option<String>,
124 pub fork_namespace: Option<String>,
125 pub fork_name: Option<String>,
126 pub source_branch: Option<String>,
Work service in Rust, with RFC 3339 timestamps127 pub head_commit: Option<String>,
Issues and pull requests replace intents and attempts128 pub merge_base: Option<String>,
129 pub merged_by: Option<String>,
130 pub merged_at: Option<String>,
131 pub superseded_by: Option<u32>,
Acceptance checks in sandboxes, line comments and review verdicts132 pub check_status: Option<CheckStatus>,
Agents as a team: lifecycle, merge queue, billing and a new shell133 /// JSON array of changed files; `None` until first worked out.
134 pub files: Option<String>,
135 /// JSON arrays of usernames.
136 pub assignees: String,
137 pub reviewers: String,
Issues and pull requests replace intents and attempts138 pub author_id: String,
139 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 rights140 #[serde(default)]
141 pub requested_by_id: Option<String>,
142 #[serde(default)]
143 pub requested_by_name: Option<String>,
Work service in Rust, with RFC 3339 timestamps144 pub created_at: String,
145 pub updated_at: String,
Thirteen MCP tools and classic token scopes; agents rate their confidence and can be put on an issue in one step146 /// JSON of its confidence, once worked out.
147 #[serde(default)]
148 pub confidence: Option<String>,
Work service in Rust, with RFC 3339 timestamps149}
150
Issues and pull requests replace intents and attempts151impl From<PullRow> for Pull {
152 fn from(row: PullRow) -> Self {
153 Pull {
Work service in Rust, with RFC 3339 timestamps154 id: row.id,
155 repo_id: row.repo_id,
156 number: row.number,
Issues and pull requests replace intents and attempts157 issue: row.issue_number,
158 title: row.title,
159 body: row.body,
Work service in Rust, with RFC 3339 timestamps160 agent: row.agent,
161 runtime: row.runtime,
162 status: row.status,
Pull requests from branches163 fork: row
164 .fork_namespace
165 .zip(row.fork_name)
166 .map(|(namespace, name)| RepoPath { namespace, name }),
Work service in Rust, with RFC 3339 timestamps167 fork_repo_id: row.fork_repo_id,
Pull requests from branches168 branch: row.source_branch,
Work service in Rust, with RFC 3339 timestamps169 head_commit: row.head_commit,
Issues and pull requests replace intents and attempts170 merge_base: row.merge_base,
171 merged_by: row.merged_by,
172 merged_at: row.merged_at,
173 superseded_by: row.superseded_by,
Acceptance checks in sandboxes, line comments and review verdicts174 check_status: row.check_status,
Agents as a team: lifecycle, merge queue, billing and a new shell175 files: row
176 .files
177 .as_deref()
178 .and_then(|files| serde_json::from_str(files).ok())
179 .unwrap_or_default(),
180 assignees: serde_json::from_str(&row.assignees).unwrap_or_default(),
181 reviewers: serde_json::from_str(&row.reviewers).unwrap_or_default(),
Issues and pull requests replace intents and attempts182 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 rights183 requested_by: requester(row.requested_by_id, row.requested_by_name),
Work service in Rust, with RFC 3339 timestamps184 created_at: row.created_at,
185 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 step186 confidence: row
187 .confidence
188 .as_deref()
189 .and_then(|detail| serde_json::from_str(detail).ok()),
Work service in Rust, with RFC 3339 timestamps190 }
191 }
192}
193
194#[derive(Deserialize)]
Issues and pull requests replace intents and attempts195pub struct CommentRow {
196 pub id: String,
Agents as a team: lifecycle, merge queue, billing and a new shell197 pub kind: CommentKind,
Issues and pull requests replace intents and attempts198 pub author_id: String,
199 pub author_name: String,
200 pub body: String,
Acceptance checks in sandboxes, line comments and review verdicts201 pub path: Option<String>,
202 pub line: Option<u32>,
203 pub verdict: Option<Verdict>,
Issues and pull requests replace intents and attempts204 pub created_at: String,
205}
206
207impl From<CommentRow> for Comment {
208 fn from(row: CommentRow) -> Self {
209 Comment {
210 id: row.id,
Agents as a team: lifecycle, merge queue, billing and a new shell211 kind: row.kind,
Issues and pull requests replace intents and attempts212 author: user(row.author_id, row.author_name),
213 body: row.body,
Acceptance checks in sandboxes, line comments and review verdicts214 path: row.path,
215 line: row.line,
216 verdict: row.verdict,
Issues and pull requests replace intents and attempts217 created_at: row.created_at,
218 }
219 }
220}
221
222#[derive(Deserialize)]
Work service in Rust, with RFC 3339 timestamps223pub struct SessionRow {
224 pub seq: u32,
225 pub kind: SessionEntryKind,
226 pub text: String,
227 pub tool: Option<String>,
228 pub commit: Option<String>,
229 pub at: String,
230}
231
232impl From<SessionRow> for SessionEntry {
233 fn from(row: SessionRow) -> Self {
234 SessionEntry {
235 seq: row.seq,
236 kind: row.kind,
237 text: row.text,
238 tool: row.tool,
239 commit: row.commit,
240 at: row.at,
241 }
242 }
243}
Issues and pull requests replace intents and attempts244
Acceptance checks in sandboxes, line comments and review verdicts245/// A pull request whose head a push moved.
246#[derive(Deserialize)]
247pub struct MovedRow {
248 pub id: String,
249 pub repo_id: String,
250 pub number: u32,
251 pub issue_number: Option<u32>,
252 pub status: PullStatus,
g1t is the stored author of what it opens; the person who asked is requested_by and keeps the author's rights253 pub author_id: String,
254 pub author_name: String,
255 #[serde(default)]
256 pub requested_by_id: Option<String>,
257 #[serde(default)]
258 pub requested_by_name: Option<String>,
Acceptance checks in sandboxes, line comments and review verdicts259}
260
Issues and pull requests replace intents and attempts261/// A single number selected as `n`.
262#[derive(Deserialize)]
263pub struct NumberRow {
264 pub n: u32,
265}
266
267/// A single string selected as `value`.
268#[derive(Deserialize)]
269pub struct ValueRow {
270 pub value: String,
271}
g1t is the stored author of what it opens; the person who asked is requested_by and keeps the author's rights272
273/// Rows as the database holds them, for tests of the rules that read them.
274#[cfg(test)]
275pub(crate) mod stored {
276 use super::*;
277
278 /// A pull request g1t made in a fork, read back as stored: g1t as its
279 /// author, and `requested_by` the person who asked, if anyone did.
280 pub(crate) fn pull(author: (&str, &str), requested_by: Option<(&str, &str)>) -> Pull {
281 let row: PullRow = serde_json::from_value(serde_json::json!({
282 "id": "pr_1", "repo_id": "rep_1", "number": 14, "issue_number": 12, "title": "Fix it",
283 "body": null, "agent": "g1t", "runtime": "hosted", "status": "open",
284 "fork_repo_id": "rep_f", "fork_namespace": "pulls", "fork_name": "pr_1",
285 "source_branch": null, "head_commit": null, "merge_base": null, "merged_by": null,
286 "merged_at": null, "superseded_by": null, "check_status": null, "files": null,
287 "assignees": "[]", "reviewers": "[]",
288 "author_id": author.0, "author_name": author.1,
289 "requested_by_id": requested_by.map(|(id, _)| id),
290 "requested_by_name": requested_by.map(|(_, name)| name),
291 "created_at": "", "updated_at": ""
292 }))
293 .unwrap();
294 row.into()
295 }
296
297 /// g1t's agent, as an author is stored.
298 pub(crate) const G1T: (&str, &str) = (g1t_contracts::identity::AGENT_ID, "g1t");
299 /// The person who asked g1t for the work.
300 pub(crate) const ASKER: (&str, &str) = ("usr_1", "syntaqx");
301}
302
303#[cfg(test)]
304mod tests {
305 use super::stored::{ASKER, G1T, pull};
306 use super::*;
307 use g1t_contracts::PrincipalKind;
308
309 #[test]
310 fn g1t_s_pull_request_reads_back_as_g1t_s_requested_by_the_person() {
311 let made = pull(G1T, Some(ASKER));
312 assert_eq!((made.author.username.as_str(), made.author.kind), ("g1t", PrincipalKind::Agent));
313 let asked = made.requested_by.as_ref().expect("who asked is kept");
314 assert_eq!((asked.id.as_str(), asked.username.as_str(), asked.kind), ("usr_1", "syntaqx", PrincipalKind::User));
315 assert_eq!(made.owner().id, "usr_1");
316 }
317
318 #[test]
319 fn anyone_else_s_reads_back_as_theirs_alone() {
320 let own = pull(ASKER, None);
321 assert_eq!(own.author.kind, PrincipalKind::User);
322 assert!(own.requested_by.is_none());
323 assert_eq!(own.owner().id, "usr_1");
324 // Half a requester is nobody.
325 assert!(requester(Some("usr_1".into()), None).is_none());
326 }
327
328 #[test]
329 fn g1t_s_own_work_reads_back_as_g1t_itself() {
330 let own = pull(("g1t", "g1t"), None);
331 assert_eq!(own.author.kind, PrincipalKind::System);
332 assert!(own.requested_by.is_none());
333 }
334}