Repository navigation
Conversation
… lists Switching between the Pull requests and Issues lists kept the previous item's detail pane open, showing content that no longer belonged to the shown list. Changing lists now closes the pane and its merge menu, and stops following the old pull request's conversation. A row also needed a double-click to open, unlike the vulnerability list. One click now selects and opens it; the row's expander and Start agent controls still stop the press from reaching the row.
|
|
[Medium impact] The changes affect the app’s pull-request, issue, and security workflows. Fix the first-import race before merging; concurrent opens can prevent old runs from being carried over. FindingsSummaryThe PR makes issue and pull request rows open with one click and closes their pages when switching lists.
Diagram%%{init: {'theme': 'neutral'}}%%
flowchart TD
A[Open repository] --> B{Saved repository found?}
B -->|Yes| C[Show stored items and runs]
B -->|No| D[Detect repository]
C --> D
D --> E{App database exists?}
E -->|No| F[Import old database if present]
E -->|Yes| G[Open app database]
F --> G
G --> H[Sync items and checks]
Reviews (2) · Last reviewed commit: "Merge remote-tracking branch 'origin/mai..." · Reviewed by Greptile |
The list-switch assertions only closed an issue, so removing the pull request cleanup still passed. The new test opens a looked-up pull request with its merge menu open, switches to Issues, and checks that the detail, the merge menu, and the followed target are all cleared.
…tive probe cc727de stopped child rows that draw no fold chevron from reserving its column, and the headless row test was updated for it, but the native paint probe still subtracted ARROW_RESERVE. Windows native GUI jobs on main and every branch since failed with "child label width: actual 179px, expected 161px": exactly the 18px reserve.
…ity alerts The detail pane now reads like a security alert's page. Its header holds the crumbs with an "N of M" stepper (previous, next, open in the browser, close), colored tags for state, priority and branches, and a title that wraps instead of truncating. A status box leads the item's first page (the conversation for a pull request, the description for an issue): one row each for the checks (naming the failing ones), the review decision, the merge state, any blockers, and the newest agent run, with Dispatch, Review, Open agent and Merge in its footer. Merge lists its methods inline under the button instead of in a menu pinned to the old header's geometry. The overview's facts fold into one line above the description. The security page's tag moves to the shared Look so both pages draw it the same way.
… issues An open alert or report took everything but a fixed 320 px list, so its page was much wider than an issue's. The list now keeps the room and the page sits in a 520 px pane whose left edge drags to resize it, or shut, exactly as the Pull requests and Issues sections do. Folding the list away still gives the page the whole section. The pane's width bounds, handle, and drag arithmetic move out of the orchestrator view into a shared `pane` module both sections use.
The same repository checked out on two hosts listed each of its GitHub issues and pull requests twice, and selecting one lit both rows: the selection, the open item, and the repository a page and its actions go to were all looked up by item key, which the copies share. The merged list now keeps one row per item, where its first copy came, as the copy with an agent run when only another has one. Its Project cell says how many hosts list it, and the backend pills count it once. A row's page, Start agent, and dispatch now go to the checkout that row shows rather than the first one holding the key; the dispatch dialog's host tiles still offer every connected host to send the agent to.
…s open The accent lit both the open row and a row the arrow keys moved to, so the last row clicked still looked open after its page closed. The selected row without a page now wears the hover tint, keeping the selection visible without claiming a page.
feat: lead pull request and issue pages with a status box, like security alerts
The icon waited for a finished read to find a repository with Dependabot alerts or private reporting on. That read needs the GitHub sign-in, every host's workspaces, and every repository read in turn, so the icon came late, and never for an account with nothing turned on. The section already explains an empty read, so the icon is listed from the start and its count fills in when the read lands.
A workspace opened on a plain folder became a project that reported "This folder is not inside a Git repository" in a red banner, took a project pill, and counted toward the header's projects. Such a folder is no project: the view now leaves it out of the header, pills, project column, and banners, while other failures are still reported.
…its rows The Security section listed every report and alert with no way to narrow it, unlike Pull requests and Issues. It now has their search field and pills: the field matches summary, package, advisory, repository, reporter, severity, manifest, and alert number; one pill per source (reports, Dependabot) and per repository narrows to those picked. The cards, the list beside a page, and stepping with its N of M count all follow it. Every row, in the cards and beside a page, has Start agent, which opens the workspace's agent dialog with the fix or investigation prompt the page's own button writes. The pill, compact button, and search outline move onto the shared Look so both sections draw the same ones.
…list The compact list beside an open issue dropped the row's Start agent button with the author and comment columns. The action column now stays in both layouts, so an agent can be started on another issue without closing the page first.
GitHub's GraphQL API answers a GitHub App token without the Dependabot alerts permission with an empty listing, so such repositories read as "no open alerts". An empty listing is now checked against the REST alerts endpoint, which refuses such a token; a refusal reads as a new Alerts::Hidden state. The section names those repositories, the CLI prints and reports "hidden", and another host's sign-in is tried for them as it is for reports. Any other REST failure keeps the empty listing.
…restart The orchestrator's per-repository database moves from agent-launcher's data directory into the app's own state directory; agent-launcher's file is copied in (VACUUM INTO a private file) the first time a repository opens, and never written again. Schema version 2 adds each open pull request's last read review and checks, so they show before the first sync. A new app-wide cache (`cache/cache.sqlite3`, private like the databases) keeps which repository each checkout held, so the lists paint before git or SSH answer; a checkout that holds none any more drops what was shown. It also keeps the Security section's last read per set of GitHub logins: alerts and report titles and metadata, never a report's description or a token. A repository whose read fails keeps its last kept entry. The restored rows have no account or checkouts, so an item's page waits for the run's first read. The private file and directory checks move from the orchestrator store into `private_file`, shared by both databases. Syncing is unchanged: the existing timers read again right after the cached state is shown.
# Conflicts: # crates/herdr-gpui/src/sidebar/layout_tests.rs
|
@greptileai review |
| if let Some(legacy) = legacy.filter(|legacy| !path.exists() && legacy.is_file()) | ||
| && let Err(error) = Store::import(&legacy, &path) | ||
| { | ||
| tracing::warn!( | ||
| category = "orchestrator", | ||
| %error, | ||
| "Cannot carry over agent-launcher's database" | ||
| ); | ||
| } | ||
| let store = Store::open(&path)?; |
There was a problem hiding this comment.
Concurrent opens skip old runs
Opening the same repository in two windows during its first import can leave an empty database instead of its old runs and history. prepare(path) creates the destination before the copy starts. Another worker can see that file, skip the import, and create an empty database there. The first worker's copy then fails because the destination is no longer empty.
Both workers continue, and later launches skip the import because the file exists. Copy into a temporary file and publish it only after success, with coordination between workers.
| pub(super) fn repo_of(&self, key: &str) -> Option<usize> { | ||
| self.repos.iter().position(|repo| repo.item(key).is_some()) | ||
| self.lines | ||
| .iter() | ||
| .find_map(|line| match line { | ||
| rows::Line::Row(row) if self.row_item(row).key.canonical() == key => Some(row.repo), | ||
| _ => None, | ||
| }) | ||
| .or_else(|| self.repos.iter().position(|repo| repo.item(key).is_some())) |
There was a problem hiding this comment.
Page shows another checkout's text
repo_of now chooses the checkout shown by the row, but item still returns the first checkout's copy. When two checkouts have different reads of the same issue, filtering to the second project opens its page with the first project's title, description, and labels. This also happens when dedupe chooses the second copy because it has a run.
The page then combines one checkout's issue text with another checkout's runs. Read the item from the chosen checkout before falling back to other copies.
| let many_sources = sources.len() > 1; | ||
| if many_sources { |
There was a problem hiding this comment.
A selected filter disappears when it becomes the only pill in its group. The code keeps selected sources and repositories in the counts, but draws each group only when its length exceeds one. The filter stays active even though the user cannot see or turn it off, so Security can keep hiding items.
Draw a group whenever it has a selected pill, even if only one remains. Apply this to both source and repository pills, including the toolbar's final visibility check.
Summary
Switching between the Pull requests and Issues lists left the previous item's detail pane open with content from the other list. Changing lists now closes the pane and its merge menu, and stops following the old pull request's conversation.
A row needed a double-click to open its details; it now opens on a single click, like the vulnerability list. The row's expander and Start agent controls still only do their own action.
Fixes the Windows native GUI jobs failing on
mainand every branch: the native sidebar probe still subtracted the fold-chevron column that cc727de gave back to child rows (child label width: actual 179px, expected 161px).Includes feat: lead pull request and issue pages with a status box, like security alerts #744 (merged into this branch): pull request and issue pages lead with a security-style status box, security alerts open in a resizable pane, an item several checkouts list shows once, and only the open row wears the accent.
The Security icon is always in the activity bar. It waited for the first full read to find a repository with alerts on, which took a while at startup and never happened for an account with nothing turned on.
The Security section searches and filters like Issues: a search field, a pill per source (reports, Dependabot) and per repository, applied to the cards, the list beside a page, and stepping. Every row, in both lists, has Start agent, opening the workspace's agent dialog with the page's fix or investigation prompt.
Folders outside Git are left out of the pull request and issue lists: no red "not inside a Git repository" banner, project pill, or count in the header.
Issue rows keep Start agent while a page is open beside the list.
A sign-in that cannot read Dependabot alerts says so instead of "no open alerts": an empty GraphQL listing is checked against the REST endpoint, whose refusal reads as
hiddenin the section and the CLI.Instant restart. The orchestrator's database is now the app's own, in its state directory; agent-launcher's is copied in once per repository. Pull request reviews and checks are stored too (schema 2). A new private app cache (
cache/cache.sqlite3) keeps each checkout's repository, so lists paint before git/SSH answer, and the Security section's last read per GitHub sign-in (alerts and report titles, no descriptions or tokens). The existing timers sync right after.QA
cargo test -p herdr-gpui --locked orchestrator— 140 passed (updateda_click_opens_the_item_beside_the_listcovers single-click open and the pane closing on list switch)just cion 5ced939 (main merged) — passed (macOS arm64)security::tests::section::the_icon_is_listed_before_any_read— icon shown before a read and after one with alerts offsecurity::tests::filter— typing narrows to the matching alert and drops an empty source's pill; source and repository pills narrow, "nothing matches" shows; a row's Start agent does not open its page; the list beside a page has Start agent; stepping skips what the search hidesorchestrator::view::tests::outside_git::a_folder_outside_git_is_left_out_quietly— no banner or project pill, one project counted; fails without the fixswitching_lists_closes_the_open_pull_request— opens a looked-up PR with the merge menu open, switches to Issues, checks detail, merge menu, and followed target are cleared; fails if the cleanup is removedorchestrator::view::tests::row_start— Start agent sits in the list beside an open issue and opens the dispatch dialogsecurity::tests::unreadableand the CLIalerts_a_sign_in_cannot_read_say_so_rather_than_none— a REST refusal (403/404) reads as hidden, other failures keep the listing, the section names the repository, another account is preferredorchestrator::tests::restart— checks stored per repository and replaced whole; agent-launcher's database copied in once (private file, runs and checks kept, later legacy writes ignored); a cached repository is dropped when the folder is no longer onesecurity::tests::saved,cache::tests— the read is kept per sign-in, a failed repository keeps its last entry, no account or checkouts are kept, the run's own read wins over a late restore; cache entries round-trip and the file is privatecargo test -p herdr-gpui sidebar::— 270 passedjust test-sidebar(macOS) — sidebar-child probe passes; the run then fails at the workspace PR popover glyph check, which passes on Windows CI (main at 26443bc)No screenshots: capturing the real window needs input on a shared display; the visible changes (status box, icon, banner) are covered by headless tests and the QA steps above.