Skip to content

feat: auto-watch your PRs and review requests (prw watch --mine) - #16

Merged
devblac merged 2 commits into
mainfrom
feat/auto-watch
Oct 25, 2026
Merged

devblac merged 2 commits into
mainfrom
feat/auto-watch

Conversation

@devblac

@devblac devblac commented Oct 17, 2026

Copy link
Copy Markdown
Owner

Stacked PR — part of a series (11/11). Base is #15's branch, so this diff shows only this change. Merge in order; after each merge GitHub retargets the next one to main.

Description

Copying PR URLs into prw watch one at a time was the main friction in daily use. Two new flags subscribe to a GitHub search instead of a fixed list:

prw watch --mine               # author:@me, open, non-archived, all repos
prw watch --review-requested   # review-requested:@me (incl. your teams)

Changes

  • Client.SearchPullRequests (search API, paginated, capped at 300, skips issues, tracks incomplete_results).
  • Config: auto_watch list + per-PR source; both omitempty, so existing configs are unchanged.
  • watcher.SyncAutoWatch: adds matches (tagged with their source) under the config lock. Removal rules:
    • review-requested PRs that no longer match are dropped (request withdrawn/answered);
    • mine PRs are not dropped on absence — that means merged/closed, and prw run should still send the final notification (fix: safe concurrent config writes, isolated tests, auto-drop merged/closed PRs #9 logic) before dropping them;
    • incomplete or failed searches never remove anything; a source disabled mid-sync is skipped;
    • PRs watched by hand are never touched, and watching an auto-added PR by hand claims it.
  • prw run syncs on startup and every 5 minutes (search API has its own 30/min limit), and picks up watch --mine run in another terminal; run --once syncs too.
  • prw unwatch --mine|--review-requested disables the source and removes only the PRs it added.
  • prw list: auto-watch lines + ADDED BY column (source in --json); config show: auto_watch.
  • Owner/repo compared case-insensitively (as GitHub does) so search results can't duplicate PRs watched with different casing.

Testing

  • Unit: search parsing/pagination/cap/incomplete; config enable/disable/claim/case-insensitivity/omitempty; every sync rule; Run startup sync with an empty list, the 5-minute cadence, picking up a subscription enabled while running; command output/args/token. Race detector clean; mutation check: removing the removal guard fails 2 tests.
  • Live, against my real account: watch --mine found 18 open PRs across 7 repos, run --once checked all of them, unwatch --mine removed all 18.

Found while testing (not fixed here)

14 of those 18 PRs have no checks at all (repos without CI, and the stacked PRs in this series, whose base isn't main). prw reports them as pending forever, so prw wait / wait_for_ci would block until the timeout. Tracked as #18 in TASKS.md.

Checklist

  • Tests added or updated
  • go test -race ./... passes
  • go vet ./... passes
  • Documentation updated (README / CHANGELOG / TASKS)
  • Commit messages are clear

🤖 Generated with Claude Code

devblac and others added 2 commits October 17, 2026 17:19
Agents that open PRs need to check and wait for CI and read which
checks failed. Expose prw's CI aggregation as Model Context Protocol
tools over stdio:

- get_ci_status: state, check counts, failed checks with links.
- wait_for_ci: blocks until CI finishes (default 10m, max 1h), fails
  fast, follows new pushes, emits notifications/progress when the call
  has a progressToken, and honors notifications/cancelled (no response
  is sent for a cancelled request, per the spec). A timeout is a normal
  result (pending, timed_out=true) so the agent can call again.
- list_watched, watch_pr, unwatch_pr: manage the watch list via
  config.Update, so a running `prw run` picks changes up.

The protocol subset (initialize with version negotiation, ping,
tools/list, tools/call) is implemented directly: the official Go SDK
needs Go 1.25 and the module targets 1.22. Tool calls run
concurrently so pings and cancellations are handled during a long
wait; on stdin EOF in-flight calls finish before exit. One GitHub
client is shared so the ETag cache keeps repeated polling free.

Verified end-to-end over stdio against the real API, with the token
resolved from `gh auth token`.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Copying PR URLs into `prw watch` one by one was the main friction in
day-to-day use. `prw watch --mine` and `prw watch --review-requested`
subscribe to a GitHub search (author:@me / review-requested:@me, open,
non-archived) instead of a fixed list:

- Matches are added right away and tagged with their source;
  `prw run` (and `run --once`) re-runs the searches every 5 minutes,
  picking up subscriptions enabled while it is running.
- Review-request PRs are dropped when the request goes away; "mine"
  PRs are left for `prw run` to notify about and drop when merged or
  closed. Incomplete or failed searches never remove anything.
- PRs watched by hand are never touched; watching an auto-added PR by
  hand claims it. `prw unwatch --mine` disables the source and removes
  only the PRs it added.
- `prw list` shows auto-watch and an ADDED BY column (`source` in
  --json); `prw config show` shows auto_watch.

Also compare owner/repo case-insensitively, as GitHub does, so search
results can't duplicate PRs watched with different casing.

Verified live: 18 open PRs across 7 repos found and CI-checked, then
cleanly removed by `unwatch --mine`.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@devblac
devblac marked this pull request as ready for review October 17, 2026 22:15
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 17, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-10-17T22:18:22.771907Z 8cbc891 Draft marked ready
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 8cbc891856

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +100 to +103
if pr.Source == source && !matches[prKey(pr.Owner, pr.Repo, pr.Number)] {
result.Removed = append(result.Removed, pr)
changed = true
continue

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 Badge Preserve closed review requests for the lifecycle check

When a PR added by --review-requested is merged or closed while prw is stopped, the is:open search no longer returns it, so this removal path deletes it during startup synchronization. Watcher.Run and RunOnce reload the shortened list before checkAllPRs, meaning the PR is never fetched and its promised final merged/closed notification is lost. Distinguish withdrawn review requests from closed PRs, or retain absent entries until the lifecycle check confirms their state.

Useful? React with 👍 / 👎.

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