2.9 KiB
GitHub PR status synchronization
Apply these rules to watch identity, PR lifecycle persistence, and batched lookup changes.
Paths and symbols refer to this package unless a path starts with apps/.
Watch identity
A github_pr_watches row is unique per session, repository, and branch.
Once a watch finds a PR, it remains that PR's synchronization handle.
Both the poller and on-demand synchronization iterate these watches.
On branch switches, re-point only a searching watch (pr_number=0) for the same repository.
Otherwise, add a watch for the new branch.
Apply this rule in resetPRWatchForBranchSwitch and syncPRWatchBranch.
Retain one searching watch per session/repository and one watch per discovered PR.
Lifecycle persistence
Watches cannot cover every task PR because sessions can disappear and users can link PRs by URL.
Keep the orphan sweep in service_pr_unwatched.go.
It reconciles unwatched github_task_prs rows and writes lifecycle fields,
the current head_sha, and stored workflow_attention when already present.
Exclude terminal and detached rows to bound the sweep.
Actions workflow reads belong to watched sync and feedback paths; the orphan
sweep does not collect new workflow evidence. Check and review aggregates belong
to the watch-driven path that fetches their evidence.
The REST PR response alone cannot supply those aggregates.
The backend is the only writer of github_task_prs.
The feedback read persists through SyncTaskPR in service_pr_feedback_sync.go.
Its github.task_pr.updated event updates every frontend surface.
Do not patch lifecycle fields only in a frontend store copy.
Keep both derivations on newPRStatus.
Persist inside the TTL cache's fetch closure so a cache hit causes no write.
Log persistence failures without failing the feedback read.
Use workspace-scoped ListTaskPRsByPRNumber to match the authorized credential scope.
resolveTerminalMergeState prevents a merged PR from leaving merged.
Do not extend this rule to closed: GitHub permits closed -> open.
Batched lookup budget
An alias with zero nodes definitively means no open PR on that branch.
Carry this result through branchBatchResult.ResolvedEmpty to applyBatchedSearchingWatch.
Do not repeat that lookup with client.FindPRByBranch.
After a definitive negative result, only the unqueried fork parent needs another lookup.
Cache fork identity with forkParentRepositoryForLookup per credential scope, owner, and repository.
Two or more open PRs are ambiguous, not a definitive negative result.
For ambiguity or an unresolved alias, retain the full fork-network fallback.
Throttle this production batched path with last_checked_at and PRSyncFreshnessWindow, as triggerPRDetection does.
For lookup changes, run service_pr_watch_batched_budget_test.go coverage.
Retain call-count assertions: a correct final PRStatus cannot detect duplicate API requests.