Repository navigation
fix(poteto-mode): treat check-less PRs as ci-clean in watch-pr - #510
izeigerman wants to merge 1 commit into
Conversation
gh pr checks exits 1 with empty output when a branch has no checks, and the GraphQL rollup is empty too, so resolveChecks threw ChecksUnavailable and the poll loop retried forever on repos with no CI. An empty read is now a valid answer gated by gh's own 'no checks reported' message; any other empty read still throws so the watcher fails closed.
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes using high effort and found 1 potential issue.
Bugbot Autofix is ON, but it could not run because the branch was deleted or merged before autofix could start.
Reviewed by Cursor Bugbot for commit c640a0f. Configure here.
| (fast.kind === "unusable" && | ||
| [0, 1, 8].includes(fast.exitCode) && | ||
| /no checks reported/.test(fast.stderr)); | ||
| if (noChecksReported) return { source: "gh-pr-checks", checks: [] }; |
There was a problem hiding this comment.
Empty checks emit premature READY
High Severity · Logic Bug
resolveChecks treats GitHub's no checks reported answer as a stable empty CheckRead, and readSnapshot then maps that through an allowed merge assessment to ci-clean. The same gh pr checks message also appears while workflows have not registered yet, so watch-pr can emit READY before CI starts.
Additional Locations (1)
Reviewed by Cursor Bugbot for commit c640a0f. Configure here.
|
Read through this against |


Why
watch-prnever reaches a verdict on repositories with no CI configured.gh pr checksexits 1 with empty output when a branch has no checks, the GraphQL rollup is empty too, soresolveChecksthrewChecksUnavailable, which is retryable, and the poll loop retried until its deadline. A repo without checks is a stable fact, not a transient failure.resolveChecksnow returns an empty read when gh itself answered with its "no checks reported" message. Any other empty read, such as a credential failure, still throws, so the watcher fails closed.readSnapshotmaps an empty read through the merge assessment, so a check-less PR classifies asci-cleanwhen GitHub allows the merge and asci-github-rejectedwhen GitHub refuses it.Scope
skills/poteto-mode/scripts/watch-pr/github.ts:resolveChecksreturns an emptyCheckReadon gh's "no checks reported" signal.skills/poteto-mode/scripts/watch-pr/policy.ts:readSnapshothandles the empty read.skills/poteto-mode/scripts/watch-pr/types.ts:CheckRead.checksandCiBase.allaccept an empty list.skills/poteto-mode/scripts/watch-pr/github.test.ts,policy.test.ts: the fail-closed case keeps passing, plus new tests for the empty read and the ready classification.skills/poteto-mode/references/bugbot-triage.md: one candidate learning from the run that found this.Blast Radius
Watchers on repos with CI never hit the new path, because their fast path returns a non-empty check list. Watchers on check-less repos go from hanging to a verdict. Nothing else reads the relaxed fields.
Verification
bun run typecheckandbun test watch-prpass with 40 tests, including the kept fail-closed case. Live against a real check-less PR (izeigerman/hawkeye#8), the watcher previously retried oncould not read PR checksevery 60 seconds and now emits its verdict in one pass.Note
Low Risk
Scoped to poteto-mode watch-pr check resolution; repos with real CI keep the non-empty fast path, and non–no-checks empty reads still error.
Overview
watch-prno longer hangs on repos with no CI. Whengh pr checksand GraphQL rollup are both empty but stderr matches GitHub’s stable “no checks reported” signal (exit 0/1/8),resolveChecksreturns an emptyCheckReadinstead of throwing retryableChecksUnavailable. Other empty reads (e.g. credential errors) still throw so the watcher fails closed.Policy and types follow the empty read:
readSnapshotroutes zero checks through the existing merge assessment →ci-cleanwhen GitHub allows merge, orci-github-rejectedwhen it refuses.CheckRead.checksandCiBase.allare typed as plain arrays so an empty list is valid.Tests cover the new empty-read path and ready classification; the credential failure case is unchanged. bugbot-triage adds a candidate pattern: verify review comments that contradict invariants stated in the same diff before dismissing.
Reviewed by Cursor Bugbot for commit c640a0f. Bugbot is set up for automated code reviews on this repo. Configure here.