Repair the GitHub code-review onboarding - #473
Merged
Merged
Conversation
Listing repos cost one `/search/issues` call per repo, fired concurrently, purely to decorate each row with an exact open-PR count. GitHub allows 30 search requests a minute and secondary-rate-limits bursts, so any account past a handful of repos got a 403, `listRepos` rejected, and the connect card fell into its error state — every time, so the connection looked permanently broken. The picker now reads from the one list call it was already making. The open-PR count is gone; the push timestamp that explains the ordering rides along on that same response for free.
The walkthrough read Connect GitHub, then Pick your repos, and the picker's helper called each repo "its own permission". That describes a GitHub App, where repo selection happens after install. We ship a personal access token: repo access is decided while the token is being created, and picking a repo afterwards grants nothing. The connect step now walks a person through a fine-grained token scoped to the repositories they want reviewed, and the picker is honestly a watch-list over what that token already reaches — "Choose what gets reviewed", with narrowing pointed back at GitHub where it really happens.
The card's mount effect read its state with no rejection path, so a read that threw left the query on `loading` — which renders the disconnected body. A person with a working GitHub connection was told they had never connected one, with a Connect button that could only lead them through the same failure again. A rejected read now becomes the card's own error state, reported through the error sink with a refId, and says plainly that GitHub could not be reached with this token.
Each reviewer's system prompt ended with "Reply with JSON and nothing
else", and those same prompts install the reviewers as ordinary chat
agents. Asking one of them anything in a room got a raw
`{"summary": ..., "findings": []}` back. The same contract also sat
inside the review workflow's own prompt, where it contradicted the
instruction to write one prose review and post it through the GitHub
tool.
A reviewer definition now carries its lens alone. `reviewerReportPrompt`
appends the contract on the one path that parses JSON back — the review
run's pass turns, which now receive the system prompt to use rather than
reaching for the definition's.
"6 your token can reach · 3 picked" was missing its subject.
Contributor
Author
|
Reviewed against CL-7189's four defects and the diff. Verified against acceptance criteria — all satisfied:
Ran the full touched-file test set (chat-ui, chat, code-review, github-tools, workflow-catalog, last-30-days-research) — all green. Commit messages: no prefixes, no tracker refs, all subject/body lines within 72 chars. No findings. No code changes needed. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Driving the Code review template end to end: the connect card said "Connect GitHub" over a connection that had already stored a credential, the walkthrough described a permission model we do not have, and the reviewers answered in raw JSON. Four defects, each with its own commit.
Fixes CL-7189.
The connect kept failing
listReposdecorated every repo row with an exact open-PR count from/search/issues— one call per repo, fired concurrently offPromise.all. GitHub allows 30 search requests a minute and secondary-rate-limits bursts, so any account past a handful of repos got a 403, the wholelistReposrejected, andreadGithubStatereturned{ok:false}, leaving the card in its error state. Reconnecting hit the same wall.The picker now reads entirely from the one
/user/reposcall. The count is gone;pushed_atrides along on that response for free and explains the ordering, so a row still says something ("updated 2h ago") without a second request.A failed read looked like "never connected"
ConnectGithubBlockContainer's mount effect had no rejection path, so a read that threw left the query onloading— which renders the disconnected body. That is how a working connection ends up under a Connect button. A rejection now becomes the card's own error state, throughreportErrorwith a quotable refId.The steps described a GitHub App
Connect GitHub → Pick your repos → Start reviewing, with the picker's helper calling each repo "its own permission you can turn off later", is the GitHub App flow, where repo selection happens after install. With a PAT the access is settled while the token is created, and picking a repo afterwards grants nothing.
Per the owner ruling — PAT only, App stays out of scope — the connect step now walks through a fine-grained token scoped to the repositories you want reviewed, and step two is honestly a watch-list over what that token already reaches: "Choose what gets reviewed", with narrowing pointed back at GitHub.
Reviewers posted JSON into the room
REVIEWER_REPORT_CONTRACT("Reply with JSON and nothing else") was concatenated into everyReviewerDefinition.systemPrompt, and those prompts are what installs the reviewers as chat agents. The contract was also inside the review workflow's prompt, contradicting its own instruction to write one prose review and post it throughgithub_post_pr_review.A definition now carries its lens alone;
reviewerReportPromptappends the contract on the single path that parses JSON back, andReviewerTurnreceives the system prompt to use rather than reaching for the definition's.Checks
bun run checkpasses apart from@corbits/tool-registry-publish, whose five failures reproduce identically onmain— its fixtures commit asfreshness@test, which a local git hook's author allowlist rejects.