Skip to content

feat(github): PR status and claims as a library - #705

Merged
kixelated merged 7 commits into
mainfrom
quest/m0/github-readers
Nov 13, 2026
Merged

kixelated merged 7 commits into
mainfrom
quest/m0/github-readers

Conversation

@kixelated

@kixelated kixelated commented Nov 13, 2026 •

Copy link
Copy Markdown
Collaborator

Finishes quest/m0/github-readers.md: a host with no checkout, git, or Node APIs, such as a Cloudflare Worker, can now read a PR's status and a quest's claims with Quest's own code, through a new quest/github export.

Summary

  • Client split. Requests, GraphQL, paging, retries, rate limits, and the deadline move from src/cli/github.ts to src/github/client.ts. The CLI keeps PR arguments, git remotes, and token resolution (GitHubInputError, pullRequest, readRemote, gitHubDependencies). repositoryPath moves into the client too.
  • PR status. pullRequestStatus and everything it calls (summary, classifyCheck, ejection reader, review record, enabledHead/headBefore, requiredOf/unreported) move to src/github/status.ts. The read side of holds (readSnapshot, readHoldStatus, starterHeld, ago) moves to src/github/hold.ts. The quest land markers it reads (LAND_CHECK, pin/pinned, EJECTED, Reason) move to src/github/land.ts. src/cli/status.ts keeps only statusLines, and src/cli/hold.ts keeps taking, releasing, and landing.
  • Claims. src/github/claims.ts holds OpenPull, Claim, Holdings, openPullRequests, pullsFrom, mergedPull, and a new held(github, { upstream, fork? }, branches). When a source passes no tips, it reads them through GitHub's matching-refs API (claimBranches). It reads the sources' tips and their open PRs concurrently. The CLI's held now delegates to it, passing tips it read with git ls-remote as before. Only finding the upstream through remotes, and the branches-only case off GitHub, stay in the CLI.
  • Signals. src/github/signals.ts and src/github/online-review.ts (from src/cli/): pullRequestStatus reads feat(merge): hold a head an unanswered finding or newer maintainer decision signals #652's signals, so they live in the library.
  • Export. package.json exports ./github (src/github/index.ts), type-checked by tsc -p src/github with types: [] and the WebWorker lib, so a stray node: import or process fails just check.
  • src/github/models.ts (the PR body's ## Models parser) moves to src/cli/models-record.ts, since it imports the CLI's model routing.
  • hosts (and type Host) is now exported from ./core. main.ts imports it from there.
  • Deletes the quest and updates the one quest that named the moved models.ts.

quest status, quest wait, quest unblocked --unclaimed, and quest start all call the moved code, so the CLI and a hosted caller cannot disagree.

Public API

  • New export quest/github: GitHub, GitHubDeadline, GitHubGraphQLError, GitHubDependencies, Repository, PullRequest, pullRequestStatus with Status and its parts, HoldFact/HoldReport, and held, claimBranches, openPullRequests with Claim, Holdings, OpenPull, Source, Sources.
  • quest/core adds hosts and Host.
  • No CLI output or wire change. The package stays private, so a consumer pins a commit (github:moq-dev/quest#<sha>).

Choices made without asking

  • held takes repositories as { owner, repo } rather than owner/repo strings, as the rest of the client does.
  • statusLines stays in the CLI: a hosted caller has no consumer for the plain-line format yet.
  • ago lives in src/github/hold.ts, its main consumer; quest start's describe imports it from there.
  • The CLI still reads the fork's tips through git rather than the API: same answer (verified below), and no extra requests.

Validation

  • just check and just test pass (39 files, 1314 tests). A new test/claims.test.ts covers the library held: tips read through matching-refs for the upstream and the fork, the earliest open PR across both holding the claim, an upstream branch at a merged PR's head holding nothing, and no ref reads when tips are passed.
  • Real surface: quest status for #652, #698, #701, and #705, and quest unblocked --unclaimed --json (stdout and stderr), were byte-identical between origin/main and this branch.
  • Worker-shaped differential: bundled src/github with bun build --target=browser --conditions=workerd (no node: imports in the bundle). It ran with only fetch and a token, and the result matched the CLI:
  • Note: a plain browser bundle (no workerd/worker condition) picks decode-named-character-reference's DOM build through ../core's Markdown parser and fails on document. Workers resolve the workerd condition to the non-DOM file, so a Worker is unaffected.

Conflicts

Merged main after moq-dev/quest#652 landed, carrying its edits into the moved modules: signals on Status and pullRequestStatus in src/github/status.ts, the unanswered_signal reason in src/github/land.ts, and the signal line in statusLines. Since pullRequestStatus now reads signals, src/cli/signals.ts and src/cli/online-review.ts (which use only the client) move to src/github/, and ./github exports type Signal. quest status 652 printed the same output on main and on the merged branch.

Follow-ups

None recommended.

Models

  • Size: M
  • Implementer: Claude Code, claude-opus-5-5, medium effort
  • Implementer: Claude Code, claude-opus-5-5, medium effort (iterate, M)

🤖 Generated with Claude Code

(Written by Claude Opus 5.5 with medium)

Review

Rewritten by quest review after each round.

  • Head: 70f2c9d

  • Base: origin/main at e31952e

  • Reviewer: Codex, gpt-6.1-sol, high effort

  • Session: 01a1d6d5-2826-7382-bbe0-1ee3b62abec9, round 3

  • Score: 10/10, Code inspection found no actionable regressions in the incremental merge integration, which preserves main’s signal checks and the GitHub readers’ independence from Node; builds and tests were not run as instructed.

  • Rounds: 3; findings 0: fixed 0, refuted 0, open 0

  • Findings: none

  • Reviewer: Codex, gpt-6.1-sol, medium effort, shadow

  • Session: 01a1d6d5-2826-7fb1-a482-222dac5f866f

  • Rounds: 1; findings 0: fixed 0, refuted 0, open 0

@kixelated kixelated changed the title PR status and claims as a library feat(github): PR status and claims as a library Nov 13, 2026
@kixelated
kixelated marked this pull request as ready for review November 13, 2026 21:35
@coderabbitai

coderabbitai Bot commented Nov 13, 2026 •

Copy link
Copy Markdown

Warning

Review limit reached

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

Next included review available in 45 minutes.

Check out review usage here.

View limit details

Limit details: You’ve used the included review currently available.

Learn how review limits work.

Review configuration:

Run configuration

  • Source mode: Auto
  • Repository: Unavailable
  • Branch: Unavailable
  • File: No configuration file from this repository applied
  • Commit: Unavailable
  • Layers: Organization UI
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: c2d5912b-3bd7-4095-a1ab-b67e4bb1634b
Commits

Reviewing files that changed from the base of the PR and between e31952e and 70f2c9d.

Files selected for processing: 51

  • package.json
  • quest/m0/github-readers.md
  • quest/m0/routing-evidence/writer-ab.md
  • src/cli/claims.ts
  • src/cli/github.ts
  • src/cli/hold.ts
  • src/cli/land-apply.ts
  • src/cli/land-bump.ts
  • src/cli/land-checks.ts
  • src/cli/land-fixer.ts
  • src/cli/land-halt.ts
  • src/cli/land-head.ts
  • src/cli/land-queue.ts
  • src/cli/land-serve.ts
  • src/cli/land-watch-fix.ts
  • src/cli/land-watch.ts
  • src/cli/land.ts
  • src/cli/main.ts
  • src/cli/models-record.ts
  • src/cli/review-record.ts
  • src/cli/review.ts
  • src/cli/start.ts
  • src/cli/status.ts
  • src/cli/usage.ts
  • src/cli/wait.ts
  • src/core/index.ts
  • src/github/claims.ts
  • src/github/client.ts
  • src/github/hold.ts
  • src/github/index.ts
  • src/github/land.ts
  • src/github/online-review.ts
  • src/github/signals.ts
  • src/github/status.ts
  • src/github/tsconfig.json
  • test/claims.test.ts
  • test/github.test.ts
  • test/hold.test.ts
  • test/land-bump.test.ts
  • test/land-fixer-diagnostics.test.ts
  • test/land-watch.test.ts
  • test/land.test.ts
  • test/move.test.ts
  • test/online-review.test.ts
  • test/review.test.ts
  • test/signals.test.ts
  • test/start.test.ts
  • test/status.test.ts
  • test/usage.test.ts
  • test/wait.test.ts
  • test/worktree.test.ts
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

Share

@pullfrog pullfrog 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.

ℹ️ No critical issues — one small latency suggestion inline.

Reviewed changes

Reviewed the full split of Quest's GitHub readers into src/github/ and the new quest/github export. Compared line by line against the old files, the moved code is verbatim. The only real logic changes are the extracted readSnapshot and the new library held/claimBranches. tsc -p src/github, root tsc, and the claims, status, start, github, and hold tests all pass locally.

  • Client split: the request, GraphQL, paging, retry, and deadline code moves to src/github/client.ts. The CLI keeps remotes, token resolution, and PR argument parsing.
  • PR status and holds: pullRequestStatus moves to src/github/status.ts. The read side of holds moves to src/github/hold.ts, and Labels.read() now delegates to readSnapshot. The quest land markers move to src/github/land.ts.
  • Claims library: held(github, { upstream, fork? }, branches) reads tips through git/matching-refs/heads/quest/ when a source passes none. The CLI's held wraps it and keeps the off-GitHub branch. Fork detection now uses the case-insensitive same() instead of an exact compare, which is a small fix rather than a regression.
  • Export and type isolation: ./github is in package.json, and src/github/tsconfig.json uses types: [] with the WebWorker lib, so a node: import fails just check.
  • Relocations: src/github/models.ts moves to src/cli/models-record.ts, and hosts/Host are now exported from ./core. The remaining CLI hunks only rewire imports.

Pullfrog  | Fix all ➔ | Fix 👍s ➔ | View workflow run | Using claude-opus-5-5 | 𝕏

Comment thread src/github/claims.ts Resolved
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
pullfrog[bot]
pullfrog Bot previously approved these changes Nov 13, 2026

@pullfrog pullfrog 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.

✅ No new issues found.

Reviewed changes

Reviewed the single commit since the prior pullfrog review.

  • Parallelized held reads: the library held in src/github/claims.ts now reads the upstream and fork tips and lists their open PRs in one Promise.all. Result order is unchanged: all keeps the [upstream, fork] order, so pushTo still picks the last source. This addresses the earlier latency suggestion.

Pullfrog  | View workflow run | Using claude-sonnet-5-5 | 𝕏

…d modules

signals.ts and online-review.ts move to src/github, since pullRequestStatus now
reads signals and both use only the client.

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

@pullfrog pullfrog 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.

✅ No new issues found.

Reviewed changes

Reviewed the merge of main since the prior pullfrog review. It carries #652's signals into the moved modules. tsc -p src/github, the root tsc, and the signals, online-review, status, land, hold, and claims tests all pass locally.

  • Moved signal readers: src/cli/signals.ts and src/cli/online-review.ts now live in src/github/. The only change in each is the import path ./github → ./client, so neither pulls in Node APIs.
  • Carried pullRequestStatus signals: Status.signals and the readSignals call, including the head-changed guard, are in src/github/status.ts. unanswered_signal is added to Reason in src/github/land.ts, and ./github exports type Signal.
  • Rewired importers: the CLI modules (hold, land, land-fixer, land-watch, land-watch-fix, usage) and the tests now import from ../github/signals and ../github/online-review. No stale src/cli/ copies remain.

Pullfrog  | View workflow run | Using claude-opus-5-5 | 𝕏

@kixelated
kixelated added this pull request to the merge queue Nov 13, 2026
Merged via the queue into main with commit 2aa603e Nov 13, 2026
19 checks passed
@kixelated
kixelated deleted the quest/m0/github-readers branch November 13, 2026 23:14
kixelated added a commit that referenced this pull request Nov 13, 2026
Follows #705's moves into src/github/ and keeps serve's deletions; adds a host-independent tests follow-up quest.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
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