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 branch 'worktree-agent-a6a121745e81f639f' | 1 | //! What g1t adds around a pull request for many agents working at once: |
| 2 | //! which files it changes, which other pull requests are changing the same | |
| The work, events, webhooks, actions, repos and packages services no longer run g1t's own agents. Work drops the 35 calls that queued issues for g1t, delegated them, messaged and reviewed through the agent, planned, captured memories automatically, rated confidence and capped agent spend, and its pull request lifecycle no longer revises or reviews: a pull request only advances to a merge by the repository's auto-merge setting. Merging a pull request that is behind now catches it up itself, through the repository's branch update, and lands it when the push arrives; when it can't be caught up cleanly the merge says to merge the base in and try again. Recording a session on a pull request, memory recall and remember, overlaps, the merge queue and required checks stay as they were. | 3 | //! files, and whether it has fallen behind. |
| Merge branch 'worktree-agent-a6a121745e81f639f' | 4 | |
| 5 | use std::collections::HashSet; | |
| 6 | ||
| The work, events, webhooks, actions, repos and packages services no longer run g1t's own agents. Work drops the 35 calls that queued issues for g1t, delegated them, messaged and reviewed through the agent, planned, captured memories automatically, rated confidence and capped agent spend, and its pull request lifecycle no longer revises or reviews: a pull request only advances to a merge by the repository's auto-merge setting. Merging a pull request that is behind now catches it up itself, through the repository's branch update, and lands it when the push arrives; when it can't be caught up cleanly the merge says to merge the base in and try again. Recording a session on a pull request, memory recall and remember, overlaps, the merge queue and required checks stay as they were. | 7 | use g1t_contracts::repos::{BehindArgs, Comparison, GetByIdArgs, Repo, RepoPath}; |
| Merge branch 'worktree-agent-a6a121745e81f639f' | 8 | use g1t_contracts::work::*; |
| The work, events, webhooks, actions, repos and packages services no longer run g1t's own agents. Work drops the 35 calls that queued issues for g1t, delegated them, messaged and reviewed through the agent, planned, captured memories automatically, rated confidence and capped agent spend, and its pull request lifecycle no longer revises or reviews: a pull request only advances to a merge by the repository's auto-merge setting. Merging a pull request that is behind now catches it up itself, through the repository's branch update, and lands it when the push arrives; when it can't be caught up cleanly the merge says to merge the base in and try again. Recording a session on a pull request, memory recall and remember, overlaps, the merge queue and required checks stay as they were. | 9 | use g1t_contracts::{FailureCode, Outcome}; |
| Merge branch 'worktree-agent-a6a121745e81f639f' | 10 | use serde::Deserialize; |
| 11 | use worker::Result; | |
| 12 | ||
| The work, events, webhooks, actions, repos and packages services no longer run g1t's own agents. Work drops the 35 calls that queued issues for g1t, delegated them, messaged and reviewed through the agent, planned, captured memories automatically, rated confidence and capped agent spend, and its pull request lifecycle no longer revises or reviews: a pull request only advances to a merge by the repository's auto-merge setting. Merging a pull request that is behind now catches it up itself, through the repository's branch update, and lands it when the push arrives; when it can't be caught up cleanly the merge says to merge the base in and try again. Recording a session on a pull request, memory recall and remember, overlaps, the merge queue and required checks stay as they were. | 13 | use crate::Work; |
| Merge branch 'worktree-agent-a6a121745e81f639f' | 14 | use crate::rows::{PULL_COLUMNS, PullRow}; |
| 15 | ||
| 16 | /// Beyond this a change is too large for per-file bookkeeping to be useful. | |
| 17 | const MAX_FILES: usize = 300; | |
| The work, events, webhooks, actions, repos and packages services no longer run g1t's own agents. Work drops the 35 calls that queued issues for g1t, delegated them, messaged and reviewed through the agent, planned, captured memories automatically, rated confidence and capped agent spend, and its pull request lifecycle no longer revises or reviews: a pull request only advances to a merge by the repository's auto-merge setting. Merging a pull request that is behind now catches it up itself, through the repository's branch update, and lands it when the push arrives; when it can't be caught up cleanly the merge says to merge the base in and try again. Recording a session on a pull request, memory recall and remember, overlaps, the merge queue and required checks stay as they were. | 18 | /// g1t's agent, which wrote reviews and pull requests before g1t stopped |
| 19 | /// hosting agents: shown as `g1t`, which nobody can register or sign in as. | |
| Merge branch 'worktree-agent-a6a121745e81f639f' | 20 | pub(crate) use g1t_contracts::identity::{AGENT_ID, AGENT_NAME}; |
| 21 | ||
| 22 | #[derive(Deserialize)] | |
| 23 | struct OtherRow { | |
| 24 | number: u32, | |
| 25 | title: String, | |
| 26 | issue_number: Option<u32>, | |
| 27 | files: Option<String>, | |
| 28 | } | |
| 29 | ||
| 30 | impl Work { | |
| 31 | pub(crate) async fn pull_by_id(&self, id: &str) -> Result<Option<Pull>> { | |
| 32 | Ok(self | |
| 33 | .db | |
| 34 | .prepare(format!("SELECT {PULL_COLUMNS} FROM pulls WHERE id = ?")) | |
| 35 | .bind(&[id.into()])? | |
| 36 | .first::<PullRow>(None) | |
| 37 | .await? | |
| 38 | .map(Pull::from)) | |
| 39 | } | |
| 40 | ||
| 41 | /// Works out which files a pull request changes and records them, so | |
| 42 | /// that overlaps between pull requests can be found without comparing | |
| 43 | /// every one of them each time. | |
| 44 | pub(crate) async fn refresh_files(&self, pull: &Pull) -> Result<Vec<ChangedFile>> { | |
| 45 | // Its owner (whoever asked g1t for it, or its author) can read both | |
| 46 | // the repository and the pull request's source. | |
| 47 | let viewer = self.owner_viewer(pull).await?; | |
| 48 | let compared: Outcome<Comparison> = | |
| 49 | g1t_kit::call(&self.repos, "compare", &pull.comparison(&viewer)).await?; | |
| 50 | let files: Vec<ChangedFile> = match compared { | |
| 51 | Outcome::Ok(comparison) => comparison | |
| 52 | .files | |
| 53 | .into_iter() | |
| 54 | .take(MAX_FILES) | |
| 55 | .map(|file| ChangedFile { | |
| 56 | path: file.path, | |
| 57 | additions: file.additions, | |
| 58 | deletions: file.deletions, | |
| 59 | }) | |
| 60 | .collect(), | |
| 61 | // Nothing pushed yet, or nothing to compare against. | |
| 62 | Outcome::Fail(_) => Vec::new(), | |
| 63 | }; | |
| 64 | self.db | |
| 65 | .prepare("UPDATE pulls SET files = ? WHERE id = ?") | |
| 66 | .bind(&[ | |
| 67 | serde_json::to_string(&files)?.into(), | |
| 68 | pull.id.as_str().into(), | |
| 69 | ])? | |
| 70 | .run() | |
| 71 | .await?; | |
| 72 | Ok(files) | |
| 73 | } | |
| 74 | ||
| 75 | /// Other pull requests in progress that change files this one changes. | |
| 76 | pub(crate) async fn overlaps(&self, pull: &Pull) -> Result<Vec<Overlap>> { | |
| 77 | if pull.files.is_empty() { | |
| 78 | return Ok(Vec::new()); | |
| 79 | } | |
| 80 | let mine: HashSet<&str> = pull.files.iter().map(|file| file.path.as_str()).collect(); | |
| 81 | let others = match self.prefetched_pull(&pull.id) { | |
| 82 | Some(found) => found.rows::<OtherRow>(crate::prefetch::Slot::Others)?, | |
| 83 | None => self.other_pulls(pull).await?, | |
| 84 | }; | |
| 85 | Ok(others | |
| 86 | .into_iter() | |
| 87 | .filter_map(|other| { | |
| 88 | let files: Vec<ChangedFile> = | |
| 89 | serde_json::from_str(other.files.as_deref().unwrap_or("[]")).ok()?; | |
| 90 | let paths: Vec<String> = files | |
| 91 | .into_iter() | |
| 92 | .map(|file| file.path) | |
| 93 | .filter(|path| mine.contains(path.as_str())) | |
| 94 | .collect(); | |
| 95 | (!paths.is_empty()).then_some(Overlap { | |
| 96 | number: other.number, | |
| 97 | title: other.title, | |
| 98 | issue: other.issue_number, | |
| 99 | paths, | |
| 100 | }) | |
| 101 | }) | |
| 102 | .collect()) | |
| 103 | } | |
| 104 | ||
| 105 | /// The other pull requests in progress in its repository. | |
| 106 | async fn other_pulls(&self, pull: &Pull) -> Result<Vec<OtherRow>> { | |
| 107 | self | |
| 108 | .db | |
| 109 | .prepare( | |
| 110 | "SELECT number, title, issue_number, files FROM pulls | |
| 111 | WHERE repo_id = ? AND id != ? AND status IN ('draft', 'open') | |
| 112 | ORDER BY number LIMIT 200", | |
| 113 | ) | |
| 114 | .bind(&[pull.repo_id.as_str().into(), pull.id.as_str().into()])? | |
| 115 | .all() | |
| 116 | .await? | |
| 117 | .results::<OtherRow>() | |
| 118 | } | |
| 119 | ||
| 120 | /// Whether the branch a pull request would merge into has commits the | |
| 121 | /// pull request does not, so that it must catch up before it can merge. | |
| 122 | pub(crate) async fn is_behind(&self, repo_id: &str, pull: &Pull) -> Result<bool> { | |
| 123 | if !pull.status.is_active() || pull.head_commit.is_none() { | |
| 124 | return Ok(false); | |
| 125 | } | |
| 126 | let asked = BehindArgs { | |
| 127 | source_id: pull | |
| 128 | .fork_repo_id | |
| 129 | .clone() | |
| 130 | .unwrap_or_else(|| repo_id.to_owned()), | |
| 131 | branch: pull.branch.clone(), | |
| Teams and CODEOWNERS, labels and milestones, dependency updates, the security suite, and a clearer top bar | 132 | target_branch: pull.base.clone().filter(|base| !base.is_empty()), |
| Merge branch 'worktree-agent-a6a121745e81f639f' | 133 | }; |
| 134 | self.timing.rpc(g1t_kit::call(&self.repos, "behind", &asked)).await | |
| 135 | } | |
| 136 | ||
| The work, events, webhooks, actions, repos and packages services no longer run g1t's own agents. Work drops the 35 calls that queued issues for g1t, delegated them, messaged and reviewed through the agent, planned, captured memories automatically, rated confidence and capped agent spend, and its pull request lifecycle no longer revises or reviews: a pull request only advances to a merge by the repository's auto-merge setting. Merging a pull request that is behind now catches it up itself, through the repository's branch update, and lands it when the push arrives; when it can't be caught up cleanly the merge says to merge the base in and try again. Recording a session on a pull request, memory recall and remember, overlaps, the merge queue and required checks stay as they were. | 137 | /// Where a pull request lives, for a tool that knows only its id (its |
| 138 | /// fork is named after it). | |
| 139 | pub(crate) async fn locate_pull(&self, a: LocatePullArgs) -> Result<Outcome<LocatedPull>> { | |
| 140 | let missing = || Outcome::fail(FailureCode::NotFound, "Pull request not found."); | |
| 141 | let Some(pull) = self.pull_by_id(&a.id).await? else { | |
| 142 | return Ok(missing()); | |
| Merge branch 'worktree-agent-a6a121745e81f639f' | 143 | }; |
| 144 | let repo: Outcome<Repo> = g1t_kit::call( | |
| 145 | &self.repos, | |
| 146 | "get_by_id", | |
| 147 | &GetByIdArgs { | |
| 148 | id: pull.repo_id.clone(), | |
| The work, events, webhooks, actions, repos and packages services no longer run g1t's own agents. Work drops the 35 calls that queued issues for g1t, delegated them, messaged and reviewed through the agent, planned, captured memories automatically, rated confidence and capped agent spend, and its pull request lifecycle no longer revises or reviews: a pull request only advances to a merge by the repository's auto-merge setting. Merging a pull request that is behind now catches it up itself, through the repository's branch update, and lands it when the push arrives; when it can't be caught up cleanly the merge says to merge the base in and try again. Recording a session on a pull request, memory recall and remember, overlaps, the merge queue and required checks stay as they were. | 149 | viewer: a.viewer, |
| Merge branch 'worktree-agent-a6a121745e81f639f' | 150 | }, |
| 151 | ) | |
| 152 | .await?; | |
| The work, events, webhooks, actions, repos and packages services no longer run g1t's own agents. Work drops the 35 calls that queued issues for g1t, delegated them, messaged and reviewed through the agent, planned, captured memories automatically, rated confidence and capped agent spend, and its pull request lifecycle no longer revises or reviews: a pull request only advances to a merge by the repository's auto-merge setting. Merging a pull request that is behind now catches it up itself, through the repository's branch update, and lands it when the push arrives; when it can't be caught up cleanly the merge says to merge the base in and try again. Recording a session on a pull request, memory recall and remember, overlaps, the merge queue and required checks stay as they were. | 153 | let Outcome::Ok(repo) = repo else { |
| 154 | return Ok(missing()); | |
| Merge branch 'worktree-agent-a6a121745e81f639f' | 155 | }; |
| The work, events, webhooks, actions, repos and packages services no longer run g1t's own agents. Work drops the 35 calls that queued issues for g1t, delegated them, messaged and reviewed through the agent, planned, captured memories automatically, rated confidence and capped agent spend, and its pull request lifecycle no longer revises or reviews: a pull request only advances to a merge by the repository's auto-merge setting. Merging a pull request that is behind now catches it up itself, through the repository's branch update, and lands it when the push arrives; when it can't be caught up cleanly the merge says to merge the base in and try again. Recording a session on a pull request, memory recall and remember, overlaps, the merge queue and required checks stay as they were. | 156 | Ok(Outcome::Ok(LocatedPull { |
| 157 | repo: RepoPath { | |
| 158 | namespace: repo.namespace, | |
| 159 | name: repo.name, | |
| Merge branch 'worktree-agent-a6a121745e81f639f' | 160 | }, |
| 161 | number: pull.number, | |
| 162 | title: pull.title, | |
| The work, events, webhooks, actions, repos and packages services no longer run g1t's own agents. Work drops the 35 calls that queued issues for g1t, delegated them, messaged and reviewed through the agent, planned, captured memories automatically, rated confidence and capped agent spend, and its pull request lifecycle no longer revises or reviews: a pull request only advances to a merge by the repository's auto-merge setting. Merging a pull request that is behind now catches it up itself, through the repository's branch update, and lands it when the push arrives; when it can't be caught up cleanly the merge says to merge the base in and try again. Recording a session on a pull request, memory recall and remember, overlaps, the merge queue and required checks stay as they were. | 163 | status: pull.status, |
| Merge branch 'worktree-agent-a6a121745e81f639f' | 164 | })) |
| 165 | } | |
| 166 | } |
This file's history is long; its oldest lines are credited to the oldest commit read.