feat(web): a coding agent watches its pull request's CI with gh and fixes what fails, where the installation grants the App the read
Merged
DA
8d ago+300+300+012345678901234567890123456789-66-66-01234567890123456789
Do not merge or enqueue: Dean reviews this one first.
What
Coding agents watch their own pull request's CI in the same turn with the gh CLI already authenticated at their sandbox's firewall, and fix what fails. No server watcher, no webhooks, no new state, no migration.
- The write token asks for the CI read only where it is granted. Dean added Actions: read, Checks: read, Commit statuses: read to the App; each installation still has to approve them, and a mint naming a permission the installation never granted fails whole. So
github-app.tsreads each installation'spermissionsoff the/user/installationslisting the mint already reads (no new request), andrepositoryWriteTokenaddschecks,statuses, andactionsread beside contents and pull requests write only where the installation grants all three (CI_READ_PERMISSIONS); otherwise it mints exactly as today. Planning's read token is unchanged. - The agent is told whether CI is readable through the seam that already composes its instructions:
host.promptnow readsrepositoryCiReadable(the same reach check, as far as the installation) and composes the instructions on it. A GitHub read that fails at session start is logged and reads as not readable, so the session still starts; the checkout refuses on its own terms when the sandbox opens. What the prompt said is kept in the session's prompt state beside its hash, so a step's context estimate composes the same text again. - Instructions (
coder-host/instructions.ts), one step after "open a pull request": where readable, watch withgh pr checks <n> --watch --fail-fast, check back on the backgrounded command rather than polling, read a failure withgh run view <run-id> --log-failed, fix, push, and watch again for at mostCODER.CI_FIX_ROUNDS(3, inbounds.ts) rounds; stop when every check passes or the repository runs no checks; say plainly when it stopped with a check failing; never mark the PR ready, merge, or close it. Where not readable: do not try, and say CI was not watched.
Tests
github-app.test.ts: the write mint names the three CI permissions for an installation that grants them and exactly today's body for one that does not, andrepositoryCiReadableanswers each; through the App's public seam over the existing GitHub HTTP fake, which now carries an installation'spermissions.coder-host.test.ts:host.promptsays CI is readable for a granting installation, not for a withholding one (different hashes), and not where GitHub cannot be read.coder-agent.test.ts: the instructions namegh pr checks, the round count fromCODER.CI_FIX_ROUNDS, and the never-merge rule where readable, and "CI was not watched" where not, in the shape of the existing instructions tests.
Verification
./scripts/check.sh exits 0 locally. CI could not verify the Mac; this PR changes no desktop or UI code, so there is no component to screenshot and no verify.sh evidence to attach (Dean waived verify.sh for this work).
š¤ Generated with Claude Code