cmux NEXT Inspector Changes: every pull request the chat touched or named, in any repository

Merged
TE
15d ago
+512-107

Second of three pieces for the Inspector's Changes card (after #23786's rows; next, the cached status path).

What

Changes showed one pull request in a chat that had driven dozens (Leo: "THERE SHOULD BE A LOT MORE CHANGES IN THIS CHAT"). It only read gh pr create output and a few gh pr verbs. Now summary/transcriptPullRequests.ts reads the whole transcript, across every repository:

  • gh pr create and glaeda-gh post pr output: pull requests the chat opened, with their --title. Only a real create counts (tested on the command without its quoted text), so rg "gh pr create" or glaeda-gh post pr-comment opens nothing.
  • Each gh pr <verb>, gh-merge-green or glaeda-gh … pr call names one pull request: its first argument after the flags and their values (a URL, owner/repo#N or a number). A number is in that call's own -R owner/repo, else the chat folder's repository. A merge, close or reopen sets the state of that pull request only.
  • Pull request URLs in any successful command count as touched. Other owner/repo#N text in a command is only a mention, since it may be an issue. Quoted text and heredoc bodies are data and are skipped (a comment's body names other pull requests). The line that opens a heredoc is still read, and <<< and shifts are not heredocs.
  • With replies: true (the Inspector only), the agent's replies are read too: URLs, owner/repo#N, repo #N for a repository the transcript or folder names, PR #N, and a bare #N in the folder's repository. A #N inside a code block is ignored.
  • Mentions show in Changes once the App has read them as pull requests (the next PR reads every row's status from the App's cache). Until then only the header's pull request has a status, so mentions stay hidden. The summary card never lists mentions.
  • Each pull request is listed once, ordered by where the chat last touched or named it, open ones first.

Cost: each row's findings are kept per row object (a WeakMap), so a growing transcript reads only its new or changed rows. The composer's pull request bars and the summary card never read replies.

API: transcriptPullRequests(rows, { folder, replies }); sessionSummary(rows, repository) takes the folder's repository for the Inspector. The summary card and the composer's bars call it as before.

Changelog

  • Changed: The Inspector's Changes card lists every pull request the chat opened, merged, checked or named, in any repository, not only the ones it opened in this one.

Tests

  • New webviews/test/transcript-pull-requests.test.ts:
    • cross-repo glaeda-gh … pr calls and URLs;
    • owner/repo#N and docs/guide.md#3 in commands counted only as mentions;
    • creates with titles, plus rg "gh pr create" and post pr-comment opening nothing;
    • --interval 10 not read as a number;
    • a merge settling only its own call's pull request (folder vs -R, chained calls);
    • reply mentions: URL, owner/repo#N, repo #N, PR#N, bare #N, a fenced #333333, an unknown repository, replies off;
    • dedupe across all forms;
    • quoted, heredoc, <<< and shift text;
    • the per-row cache shared between readers;
    • the summary card leaving mentions out.
  • webviews/test/chat-inspector-changes.test.tsx: the order tests now put ended pull requests newer than open ones (the review's note on #23786) and check ordering by last touch.

Observed / Not run

  • Ran scripts/web-lint.sh (passed), prepush-gate.py (no new violations) and cmux-ci compile-check --app at 719d4e7dc7c (passed).
  • Not run locally: bun test (local test runs are not allowed on this Mac); CI's webview tests run them.

No capture: webview-only change to what the list contains, with no change to how it looks; the gallery state from #23786 still covers the rows.

Agent session: cosmic-gray

🤖 Generated with Claude Code