Skip to content

feat: lead pull request and issue pages with a status box, like security alerts - #744

Merged
penso merged 5 commits into
worktree/detailed-viewfrom
worktree/detail-status-box
Oct 20, 2026
Merged

penso merged 5 commits into
worktree/detailed-viewfrom
worktree/detail-status-box

Conversation

@penso

@penso penso commented Oct 20, 2026

Copy link
Copy Markdown
Owner

Stacked on #736 (single-click open, list-switch reset, Windows native probe fix); review the commits after it.

Summary

  • Pull request and issue pages read like security alerts (variant D of the native mockups). The 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. 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, blockers, and the newest agent run, with Dispatch / Review / Open agent / Merge in its footer. Merge lists its methods inline under the button. The overview's facts fold into one line above the description.
  • Security alerts open in a resizable pane beside the list, like issues: the list keeps the room, the page sits in a 520 px pane whose left edge drags to resize it or drags it shut. Folding the list away still gives the page the whole section. The pane's bounds, handle, and drag arithmetic moved into a shared orchestrator::pane module both sections use.
  • An issue or pull request several checkouts read is listed once. The same repository on two hosts listed each GitHub item twice, and selecting one lit both. One row is kept per item (the copy with an agent run when only another has one); its Project cell says how many hosts list it, the backend pills count it once, and the row's page, Start agent, and dispatch go to the checkout that row shows. The dispatch dialog's host tiles still offer every connected host.
  • The accent tints only the open row. A row the arrow keys moved to with no page open wears the neutral hover tint, so the last row clicked no longer looks open after its page closes.

QA

  • cargo test -p herdr-gpui --locked orchestrator — 144 passed, including tests/status.rs (status box under the title, Next steps and stops at the end, failing checks / review / merge rows from the fixture) and tests/twins.rs (dedupe keeps the copy with a run; two hosts' copies are one row; page goes to the shown checkout)
  • cargo test -p herdr-gpui --locked security:: — 59 passed, including pane_resize.rs (520 px default, list fills the rest, dragging widens by the drag, dragging shut closes)
  • just ci — passed locally (macOS arm64)
  • Open a pull request with failing checks: the status box names them; Merge ▾ shows the methods inline and the confirmation still opens
  • Open an issue with no runs: "No agent yet" row and Dispatch agent in the box
  • Step with the header's up/down buttons through a long list; the list scrolls to follow
  • Security: open an alert, drag the pane edge wider and narrower, then nearly shut; fold the list away and back
  • With the same repository connected on two hosts, each issue shows once with "· 2 hosts"; Start agent offers both hosts in the dispatch dialog
  • Close a page: its row loses the accent; arrow keys still show where the selection is
  • Narrow window: header tags and title wrap, status rows truncate their detail

No screenshots yet: capturing the real window needs input on a shared display. Native visual check pending.

penso added 5 commits October 19, 2026 23:21
…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.
@penso

penso commented Oct 20, 2026

Copy link
Copy Markdown
Owner Author

just ci ran locally and passed on 095e169 (macOS arm64).

@penso
penso merged commit a7ec01f into worktree/detailed-view Oct 20, 2026
18 checks passed
@penso
penso deleted the worktree/detail-status-box branch October 20, 2026 15:32
@greptile-apps

greptile-apps Bot commented Oct 20, 2026 •

Copy link
Copy Markdown

RetriggerView in GreptileConfidence Score: 4/5

[Medium impact] The changes affect item lists and detail pages across the Issues, Pull requests, and Security sections.

The PR appears safe to merge, with non-blocking fixes for checkout consistency, child arrows, pane sizing, and skipped-check text.

Findings

  1. P2 Page reads the wrong copy ▶
  2. P2 Children lack a collapse arrow ▶
  3. P2 Pane outgrows the window ▶
  4. P2 Skipped checks look missing ▶

Summary

Adds status boxes and list navigation to issue and pull request pages, combines duplicate rows across checkouts, and gives security pages a resizable pane.

Non-blocking fixes:

  • Issue and pull-request pages lead with a status box.
  • Issues and pull requests from several checkouts appear once in the list.
  • Security pages open in a resizable pane beside the alert list.
  • Only the row with an open page gets the accent tint.

Review used source inspection. No tests or native-window captures were run.

Diagram

%%{init: {'theme': 'neutral'}}%%
flowchart LR
  A[Checkout snapshots] --> B[Build and sort rows]
  B --> C[Keep one row per item]
  C --> D[Choose shown checkout]
  D --> E[Status and actions]
  A --> F[First matching item]
  F --> G[Page text and branch name]
Loading

Reviews (1) · Last reviewed commit: "fix: tint a pull request or issue row wi..." · Reviewed by Greptile

Comment on lines 65 to +70
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,

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Page reads the wrong copy

repo_of now selects the checkout shown by the row, but item() still returns the first checkout's copy. If the two hosts have different snapshots and the second host supplies the kept row, its page shows the first host's title, description, and branches. The dispatch dialog also names its branch from that first copy while sending the second copy's prompt. Resolve the item from the chosen checkout too.

Comment on lines +579 to +588
match at.get(&key) {
Some(&index) => {
let first = &mut kept[index];
if first.run.is_none() && row.run.is_some() {
// The tree shape stays the first copy's: its children
// follow it.
*first = ItemRow {
depth: first.depth,
children: first.children,
..row

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Children lack a collapse arrow

dedupe keeps the first parent's children value even when later copies contribute child rows. If one host lists parent P without children and another lists P with child C, the result can show C under P while P.children remains None. Users then have no arrow to collapse that child. Rebuild the child markers after combining the copies, and test copies with different trees.

Comment on lines +125 to +127
.debug_selector(|| "security-pane".into())
.flex_none()
.w(px(self.security.pane_width))

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Pane outgrows the window

The security pane uses its saved width without checking the current window width. A user can widen it to 1,000 px in a large window, then shrink the window to its supported 640 px minimum. The pane stays 1,000 px wide because Resize::of applies its limit only during a handle drag. The list loses its space and part of the page extends outside the window. Limit the rendered width to the available space while keeping the saved width as the user's preference.

Comment on lines +136 to +140
Some(Outcome::Skipped) | None => Row {
icon: "icons/pass.svg",
hue: muted,
title: "No checks reported".into(),
detail: None,

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Skipped checks look missing

When every reported check is skipped, checks_outcome() returns None, so this row says "No checks reported" and drops the details. The checks do exist; pr.checks() already describes them as skipped. Distinguish an empty check list from an all-skipped list and show that summary.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant