Skip to content

fix(pstack): watch-pr --status-only reports a head with no checks instead of retrying - #769

Open
deanrie wants to merge 1 commit into
cursor:mainfrom
deanrie:pstack/watch-pr-no-checks
Open

deanrie wants to merge 1 commit into
cursor:mainfrom
deanrie:pstack/watch-pr-no-checks

Conversation

@deanrie

@deanrie deanrie commented Oct 22, 2026

Copy link
Copy Markdown

Fixes #750.

Problem

On a PR in a repository with no CI or check apps, watch-pr --status-only never prints a status. resolveChecks throws a retryable ChecksUnavailable when both gh pr checks and the GraphQL rollup come back empty, readSnapshot has no state for that case, and runSimple sends --status-only through pollUntilTerminal with the full --max-query-errors budget. So the caller sees RETRY: GitHub status query failed; retrying in 60s at 60, 120 and 240 s and then nothing. Babysit's check mode calls --status-only and expects one status line, so the check stalls for minutes.

Change

  • readSnapshot gains noChecks: "report" | "retry". With "report" an empty check set becomes a new ci-none CI state (source: "none", no checks, merge assessment still read so the GitHub-side verdict is kept). The default keeps today's retry: a freshly pushed head has no checks yet either, and polling must not call it ready.
  • runSimple passes "report" only for --status-only, and clamps maxQueryErrors to 1 for that mode, so a status read ends on the first query error instead of sleeping through the backoff schedule. Polling mode is unchanged.
  • --pretty renders ci-none as no checks reported; the --status-only help text says it reads GitHub once.

This follows the shape of the two downstream fixes linked in the issue (MaxFabian25/pstack-harness-adaptations #2 and #5), folded into one change against this tree. ci-none is not reachable from classifyPr / stack decisions, since only --status-only produces it; the exhaustive switch in render.ts covers it.

Tests

  • policy.test.ts: readSnapshot with noChecks: "report" yields ci-none with a merge assessment; the default still raises a retryable checks-unavailable error.
  • cli.test.ts: --status-only on a no-checks head prints one STATUS verdict with ci-none (JSON and --pretty); --status-only ends on the first query error without sleeping; plain polling on the same head still emits RETRY and sleeps.

bun test: 74 pass / 0 fail. tsc --strict clean. generate-pstack-harness-trees.mjs --check up to date. No overlap with #746 (git merge-tree clean).

…tead of retrying for minutes

On a PR in a repository with no CI or check apps, resolveChecks throws a
retryable ChecksUnavailable when both gh pr checks and the GraphQL rollup
are empty, and --status-only went through pollUntilTerminal with the full
--max-query-errors budget. The result was RETRY lines at 60/120/240 s and
no status at all, which stalls babysit's check mode.

- readSnapshot gains noChecks: "report" | "retry". With "report" an empty
  check set becomes a new ci-none state (source "none", no checks, merge
  assessment still read); the default keeps today's retry, because a
  freshly pushed head has no checks yet either and polling must not call
  it ready.
- runSimple passes "report" for --status-only and clamps maxQueryErrors
  to 1 for that mode, so a status read ends on the first query error
  instead of sleeping through the backoff schedule.
- --pretty renders ci-none as "no checks reported"; --status-only help
  says it reads GitHub once.

Tests: readSnapshot report/retry, CLI --status-only on a no-checks head
(JSON and --pretty), first-error exit, and polling still emitting RETRY.
bun test 74/74, tsc clean, harness tree regenerated.

Fixes cursor#750.
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.

pstack: watch-pr --status-only retries for minutes on a repo with no checks

1 participant