Skip to content

Review Desk: PR board with GitHub-driven columns; worktrees out of bb storage - #2

Merged
ishandhanani merged 5 commits into
mainfrom
review-desk/pr-board
Nov 2, 2026
Merged

ishandhanani merged 5 commits into
mainfrom
review-desk/pr-board

Conversation

@ishandhanani

@ishandhanani ishandhanani commented Oct 12, 2026 •

Copy link
Copy Markdown
Owner

Problem

Review Desk opened one PR at a time from a flat "Recent" list. There was no place to see every PR you are pushing forward and where each one stands. On bb 0.46 the PR page was also broken: the brief, guide, and chat failed with HTTP 409: Workspace path is inside bb-managed storage but is not a workspace of this project, because the PR worktrees lived under the plugin's host data dir and bb now refuses to spawn threads into an unmanaged path inside its own storage.

What changes

The Reviews page is a board. Paste a PR link and it becomes a card under Unreviewed (nobody has approved), Changes requested (a reviewer asked for changes), or Babysit (approved by you or others, now watching CI until it merges). The column follows GitHub: a CHANGES_REQUESTED decision or latest review wins, then any approval (the decision, or a reviewer's latest review; gh reports a missing decision as an empty string on repositories without required reviews). Drag a card to hold it in another column; it follows GitHub again once GitHub's state changes (board_stages stores the stage together with the auto stage it was dragged from, and applyPr clears the pin when the auto stage moves on). Merged and closed PRs leave the columns and fold into a strip under them with Remove and Remove all.

Each card: title, owner/repo #N, author, last GitHub activity, and chips for what is in the way: checks passed/total (red when one fails), unresolved threads, approvals, reviewers asking for changes, merge conflicts, and your unsent comments. A Babysit card leads with CI: a bar of passed checks, the failing checks by name linking to their runs, one verdict chip (merge conflicts, CI failing, CI running, needs a required review, still a draft, or ready to merge), and when the last commit was pushed. Clicking a card opens the existing PR page. Columns wrap into a grid: 2x2 beside bb's side panel, 3 across when wide. The board lives in board.tsx (BoardPage takes an onOpen callback) with timeAgo and describeError in lib/format.ts, so the board and the review page no longer share one file.

Sync. Open PRs sync when the board opens if they are more than ten minutes stale, on Refresh, and on the boardRefresh cron (default */15 * * * *, empty turns it off). A sync skips the git fetch when the head did not move (repo_prepare gained fetch: false). New RPCs board_move and board_refresh; reviews_list carries the card fields. CLI: bb review-desk board | move <id> <stage|auto> | refresh.

Worktrees move out of bb storage to ~/.review-desk/worktrees on the repository's machine (setting worktreesDir). A clean legacy worktree is removed on the way out, done PRs are migrated too, and the server forgets environments bound to a moved path so the next spawn creates new ones.

Removing a card removes its worktree (new host RPC repo_remove_worktree), unless it has local changes, which are kept and logged. On the development host 8 of 10 worktrees (2.4 GB) belonged to PRs already taken off the board.

SDK. @get-bb/plugin-sdk repinned 0.4.47 to 0.6.39 (bb plugin types). The composer pills use insert; useComposerView, insertMention, and updateText are gone from the SDK.

Validation

On a bb 0.46.0 server with ai-dynamo/dynamo #15599, #15600, and #15164 on the board:

  • npx tsc -p . clean against SDK 0.6.39; bb plugin build and bb plugin reload clean; the board-refresh schedule shows in bb plugin list.
  • Columns (2026-10-24): #15599 (CHANGES_REQUESTED with 3 approvals) in Changes requested, #15600 (approved, 2 failing checks) and #16616 (approved, CI green) in Babysit with "CI failing (2)" naming both checks and "Ready to merge" respectively, #15661 (closed) in the merged-or-closed strip, two SGLang PRs without approvals in Unreviewed.
  • Headless Chromium: drag #16616 to Unreviewed shows the card there with "Dragged here · GitHub says Babysit"; unpin returns it; bb review-desk board agrees at each step. Clicking a card opens the PR page; Back returns to the board. The strip expands to list the closed PR with Remove and Remove all.
  • bb review-desk refresh: 2 open PRs in 2.8 s; worktrees migrated to ~/.review-desk/worktrees, legacy dir empty.
  • After the move, brief_write on #15600 spawned the helper (status writing, then ready) where it failed with the 409 before.
  • Remove on a freshly added PR deleted its worktree under ~/.review-desk/worktrees; the two PRs left on the board kept theirs.

bb plugin types repinned @get-bb/plugin-sdk from 0.4.47 to the running bb's
0.6.39; tsc against the new declarations flagged the removed composer view
and insertMention/updateText methods, replaced in the next commit.
…of bb storage

The Reviews page is now a board of the pull requests you track. Paste a link
and the PR becomes a card under Unreviewed, Changes requested, Approved, or
Done (merged or closed). The column follows GitHub: the review decision, or
the latest review per reviewer when the repository has no required reviews
(gh reports that as an empty decision); REVIEW_REQUIRED stays Unreviewed even
with approvals because a required reviewer is still missing. Drag a card to
hold it elsewhere; it follows GitHub again once GitHub's state changes
(board_stages keeps the stage with the auto stage it was dragged from).

Cards show the title, owner/repo #N, author, last GitHub activity, and chips
for what is in the way: checks passed/total (red when one fails), unresolved
threads, approvals, reviewers asking for changes, merge conflicts, and
pending comments. Clicking a card opens the PR page as before. Columns wrap
into a grid (2x2 beside bb's side panel, 4 across when wide).

Sync: the board syncs open PRs when it opens if they are more than ten
minutes stale, on Refresh, and on the boardRefresh cron (default every 15
minutes); a sync skips the git fetch when the head did not move. New RPCs
board_move and board_refresh; reviews_list carries the card fields. CLI:
bb review-desk board | move <id> <stage|auto> | refresh.

Worktrees now live under ~/.review-desk/worktrees (setting worktreesDir)
instead of the plugin's host data dir: bb 0.46 refuses to spawn a thread into
an unmanaged path inside its own storage (HTTP 409), which broke the brief,
guide, and chat. repo_prepare takes fetch: false to keep a worktree in place
without the network, removes a clean legacy worktree on the way out, and the
server forgets environments bound to a moved path.

Composer pills use the current insert API (useComposerView, insertMention,
and updateText are gone from the SDK).

Validated on this server with ai-dynamo/dynamo#15599, #15600, #15164: columns,
drag and unpin round trip in a headless browser, refresh in 3 s, worktree
migration, and a brief written by the helper after the move.
@coderabbitai

coderabbitai Bot commented Oct 12, 2026 •

Copy link
Copy Markdown

Important

Draft PR not reviewed

Draft PRs are not automatically reviewed by default.

  • Trigger a manual review

To automatically review draft PRs, update your CodeRabbit configuration:

reviews:
  auto_review:
    drafts: true
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

Columns are now Unreviewed, Changes requested, and Babysit. Any approval
(the decision, or a reviewer's latest review) puts an open PR in Babysit:
approved by you or others, now watching CI until it merges. A Babysit card
leads with CI: a bar of passed checks, the failing checks by name linking to
their runs, one verdict chip (merge conflicts, CI failing, CI running, needs
a required review, still a draft, or ready to merge), and when the last
commit was pushed. Merged and closed PRs leave the columns (stage null) and
fold into a strip under them with Remove and Remove all.

The board moves out of app.tsx into board.tsx (BoardPage takes an onOpen
callback) and timeAgo/describeError into lib/format.ts, so the board and the
review page stop sharing one file. The summary gains failingChecks and
lastCommitAt; board_move refuses a merged or closed PR; refresh syncs open
PRs and only keeps the worktrees of the others in place.
A clean worktree goes with the card; one with local changes is kept and
logged. Eight of ten worktrees on this host (2.4 GB) belonged to PRs no
longer on the board.
@ishandhanani
ishandhanani merged commit d77661e into main Nov 2, 2026
1 check passed
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