Skip to content

feat(cli): report a PR's state with quest status - #162

Merged
kixelated merged 5 commits into
mainfrom
quest/m0/helpers/status
Oct 21, 2026
Merged

kixelated merged 5 commits into
mainfrom
quest/m0/helpers/status

Conversation

@kixelated

@kixelated kixelated commented Oct 21, 2026 •

Copy link
Copy Markdown
Collaborator

Completes quest/m0/helpers/status.md.

Problem

Agents chained gh api .../reviews|comments|reactions and reviewThreads GraphQL queries to read a PR's state, often right after quest wait returned (219 of 396 audited sessions).

Behavior

quest status <pr> takes the same argument as quest wait (a GitHub PR URL, or a number in origin) and prints, plain or --json:

  • URL, state (open/closed/merged), draft, head SHA, mergeable, merge-state, review-decision
  • auto-merge (method, who, when) and merge-queue entry (state, position, enqueued at), or -
  • the head's check rollup with passed/failing/pending counts, then one line per failing or pending check with required/optional (from isRequired(pullRequestNumber:)), result, details URL, and name
  • each reviewer's latest submitted review, marked current or stale against the head
  • reactions on the PR and its reviews, named reacted:<content> as quest wait names them
  • unresolved review threads with node ID, current/outdated, last commenter, latest comment URL, and path:line

It is one GraphQL query; long check, review, and thread lists page with @include so later pages fetch only the connections that still have more. A push between pages fails with "rerun" rather than mixing heads. It exits 0 for any PR state, 2 for invalid arguments, and 1 for other failures.

Live output on kixelated/quest#128:

url https://github.com/kixelated/quest/pull/128
state open
draft false
head 0ade9d977d54c6f48152410532c58e9ea78db3d0
mergeable conflicting
merge-state dirty
review-decision -
auto-merge -
merge-queue -
checks success passed=14 failing=0 pending=0
review stale commented kixelated 2026-10-16T06:14:04Z https://github.com/kixelated/quest/pull/128#pullrequestreview-5543745302
review current commented chatgpt-codex-connector 2026-10-16T17:57:16Z https://github.com/kixelated/quest/pull/128#pullrequestreview-5551703054
thread PRRT_kwDOUhuoys6tUUV2 current chatgpt-codex-connector https://github.com/kixelated/quest/pull/128#discussion_r4297708263 src/cli/gate.ts:115
...

Shared GitHub client

As the epic plan asked, the first second GitHub caller extracts the client: src/cli/github.ts now holds PR-argument parsing, auth, the rate-limited request with same-origin pagination, GraphQL error handling, and the JSON helpers. quest wait uses it unchanged in behavior. WaitInputError became GitHubInputError, and WaitDependencies became GitHubDependencies. A deadline inside the client throws GitHubDeadline, which quest wait already turns into WaitTimeout with its resume cursor.

Skills and docs

  • merge: read the PR's state with quest status <pr>, including after each quest wait wakes, and confirm a dequeue or disabled auto-merge with it.
  • iterate: names quest status for checks, reviews by head, and unresolved threads.
  • complete: confirms a dequeue or disabled auto-merge with quest status.
  • ready: summarizes the reviews and CI from quest status <pr> (user-approved addition).
  • README gains a "Read a pull request's state" section matching --help.
  • The epic's plan now names src/cli/github.ts as the shared client.

Decisions made without asking (routine; recommended option taken)

  1. review-decision is reported even though the decided list did not name it. It is GitHub's own value. Without it, an approval followed by a comment-only review would look like commented only.
  2. "Latest review" means the latest submitted review of any state, including commented. Pending reviews (the viewer's unsubmitted draft) are excluded. A deleted account groups as -.
  3. Check classification: neutral and skipped runs pass, matching quest/m0/helpers/wait-checks.md. Commit statuses error/failure fail and pending/expected are pending. Passing checks are counted but not listed.
  4. Thread fields: the URL is the latest comment's URL, paired with its author. An outdated thread reports its original line and is marked outdated.
  5. Reactions are the newest 100 per PR or review, the same as quest wait, and are not paged.
  6. JSON keys are camelCase, so the object matches the exported Status type.
  7. Plain format: the record type comes first and free text (check name, path) comes last. Missing values print as -. Reaction lines include their time.

Validation

  • nix develop -c just check: passed
  • nix develop -c just test: passed (vitest 232 + Worker 249, shell hook suites, lifecycle checks on both builds)
  • New test/status.test.ts uses recorded responses for stale and current reviews, required and optional failing checks, commit statuses, a queued PR with auto-merge, resolved and unresolved threads, multi-connection pagination, a head change between pages, GraphQL errors, a missing PR, and a bad PR argument.
  • Ran live against kixelated/quest#128 and kixelated/quest#158 (merged).

Limitations and follow-ups

  • Expect merge conflicts with kixelated/quest#161 (required checks in quest wait) in src/cli/wait.ts, src/cli/main.ts, and the merge/complete skills. That PR should read checks through GitHub.graphql in src/cli/github.ts. It could also share check classification with status.ts, so the two commands agree on what passes.

(Written by Claude Opus 5.5)

🤖 Generated with Claude Code

kixelated and others added 2 commits October 21, 2026 10:21
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
`quest status <pr>` prints a pull request's head, draft and open state,
failing and pending checks with requiredness, mergeability, auto-merge,
merge-queue state, each reviewer's latest review marked current or stale,
reactions, and unresolved review threads with node IDs, plain or --json,
from one paged GraphQL query.

Extract the GitHub client from `quest wait` into src/cli/github.ts so both
commands share PR parsing, auth, rate-limit retry, and same-origin paging.
Point the merge, iterate, and complete skills at it, and finish
quest/m0/helpers/status.md.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@kixelated

Copy link
Copy Markdown
Collaborator Author

Outcome: quest/m0/helpers/status.md is implemented and deleted in this PR. just check and just test passed locally in the Nix shell. Seven routine decisions are recorded in the description; none needed the user. Expect conflicts with #161 in src/cli/wait.ts, src/cli/main.ts, and the merge/complete skills. The GitHub client now lives in src/cli/github.ts.

(Written by Claude Opus 5.5)

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 21, 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-21T19:23:06.586756Z 18b7a89 New commits
🔒 Security Review ✅ Completed 2026-10-21T19:28:30.785355Z 18b7a89 New commits
ℹ️ 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.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@kixelated

Copy link
Copy Markdown
Collaborator Author

@codex review

(Written by Claude Opus 5.5)

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. 🚀

Reviewed commit: 741f0322f4

ℹ️ 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".

@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: be1615b702

ℹ️ 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 thread src/cli/status.ts
Comment on lines +213 to +215
const reviewer = actor(row.author);
const commit = row.commit === null ? null : string(object(row.commit).oid);
latest.delete(reviewer);

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 separate reviews from deleted accounts

When a PR contains reviews from multiple deleted accounts, GitHub returns null for each author, so actor(row.author) produces "-" for all of them and the reviewer-keyed map silently overwrites every review except the last. This violates the command's one-latest-review-per-reviewer contract and can hide a changes-requested review; use a review-specific fallback key when the author is unavailable rather than grouping all anonymous authors together.

Useful? React with 👍 / 👎.

@kixelated

Copy link
Copy Markdown
Collaborator Author

Merge summary for quest status:

Enabling squash auto-merge on the current head.

(Written by Claude Opus 5.5)

@kixelated
kixelated merged commit 2f93530 into main Oct 21, 2026
14 checks passed
kixelated added a commit that referenced this pull request Oct 21, 2026
…st status

Move the checks query and the base branch's requirement reads onto the
shared GitHub client from #162, and classify each check with quest
status's classifyCheck so both commands agree on what passes.

Address Codex's review of 3ee919d:
- read every page of the branch's rules (per_page=100, following links)
- treat a required-workflows rule as requiring checks, so optional
  checks are not promoted before the workflow's checks start
- keep the app a required check is bound to, so another app's check of
  the same name does not count as the required one starting

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@kixelated
kixelated deleted the quest/m0/helpers/status branch October 21, 2026 21:05
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