Skip to content

feat: PR merge-state visibility — mergeable column + detail-on-highlight pane #1

Description

@sashml

Summary

Add PR merge-state visibility so a reviewer can judge whether an open PR is ready to
merge without leaving the terminal. Two related parts:

  1. A compact State column in every PR table (All PRs / Inbox / per-repo).
  2. A detail-on-highlight pane (d) showing the freshly computed merge state, CI
    check rollup, and recent commits (git log) for the highlighted PR.

Motivation / key constraint

GitHub computes mergeable lazily — it only runs the merge check when a PR is
accessed, and until then GraphQL returns UNKNOWN. ghdash's list views come from the
search API, which never triggers that computation, so a plain column would show
UNKNOWN for almost every row.

The fix: the list column is a best-effort hint, and the authoritative value comes from a
per-PR detail fetch when a row is highlighted — which also naturally carries the git
log and CI rollup. The two features are one coherent flow.

Change 1 — merge-state column

Before

┌ Navigation ──────────┐┌ All Open PRs (13) ─────────────────────────────────────┐
│  Inbox               ││ #      Title              Author   Repo         Updated │
│  All PRs (13)        ││ #62    feat(ui): page-lvl sashml   catalyst      7m ago  │
│▼ AITechCraft (18)    ││ #40    [Draft] feat(e2e)  sashml   catalyst      2h ago  │
│    zs-beads-rust [2] ││ #9     deps: bump         depbot   zs-beads-rust 1d ago  │
└──────────────────────┘└────────────────────────────────────────────────────────┘

After — new State column between # and Title

┌ Navigation ──────────┐┌ All Open PRs (13) ─────────────────────────────────────┐
│  Inbox               ││ #    State  Title           Author  Repo         Updated│
│  All PRs (13)        ││ #62  ✓ ok   feat(ui): page  sashml  catalyst      7m ago │
│▼ AITechCraft (18)    ││ #40  ✗ cf   [Draft] feat(e2  sashml  catalyst      2h ago │
│    zs-beads-rust [2] ││ #9   ?      deps: bump       depbot  zs-beads-rust 1d ago │
└──────────────────────┘└─────────────────────────────────────────────────────────┘
  legend:  ✓ ok = mergeable    ✗ cf = conflicting    ? = unknown (not yet computed)

Glyphs pair a shape/letter with color, so the signal survives colorblindness and
monochrome terminals.

Change 2 — detail-on-highlight pane (press d)

Highlight a PR and press d. A pane fetches the PR directly (forcing a fresh mergeable),
plus statusCheckRollup and the last 5 commits:

      ┌ PR #62 — feat(ui): page-level layout ─────────────────────────┐
      │ Merge: ✓ mergeable (CLEAN)       CI: ✓ passing                 │
      │                                                               │
      │ Recent commits:                                               │
      │   a1b2c3d  feat(ui): page-level layout           (7m ago)     │
      │   9f8e7d6  fix: sidebar overflow on narrow view  (1h ago)     │
      │   1122334  test: add layout snapshots            (3h ago)     │
      │                                                               │
      │ Press d or Esc to close                                       │
      └───────────────────────────────────────────────────────────────┘
  • Conflicting example → Merge: ✗ conflicting (DIRTY) CI: ✗ failing
  • Fetch is debounced ~200ms and cached per PR, so holding j/k never sprays
    API calls and nav stays responsive. r (refresh) clears the cache to recompute fresh.
  • Once detail resolves, the list column upgrades from ? to the authoritative value.

Implementation notes

  • New GraphQL: mergeable + mergeStateStatus on the search/repo PR queries; a new
    PR_DETAIL_QUERY (mergeable, mergeStateStatus, commits(last:5) + per-commit
    statusCheckRollup).
  • PullRequest gains mergeable / merge_state_status as Option<String> with
    #[serde(default)] so existing disk-cache entries still deserialize.
  • Detail lives in an in-memory pr_details map (kept out of disk cache on purpose, for
    freshness). Debounce is implemented in the event loop's tokio::select!.
  • New key d toggles the pane; status-bar hint updated.

Tracking (beads)

  • zombo-sash-eco-rpjg — merge-state column (implemented)
  • zombo-sash-eco-zkk5 — detail-on-highlight pane (implemented)
  • zombo-sash-eco-9h3o — CI/checks glyph in the list column (follow-up)
  • zombo-sash-eco-pp0u — filter/sort by merge state + legend (follow-up)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions