Skip to content

Watch CI with a script instead of a polling loop - #846

Merged
Jack-Edwards merged 4 commits into
stablefrom
chore/ci-watcher-polling
Aug 5, 2026
Merged

Watch CI with a script instead of a polling loop#846
Jack-Edwards merged 4 commits into
stablefrom
chore/ci-watcher-polling

Conversation

@Jack-Edwards

@Jack-Edwards Jack-Edwards commented Aug 5, 2026

Copy link
Copy Markdown
Member

The CI watcher was told to poll get_check_runs every thirty seconds. A foreground sleep does not run in this harness and the agent has no timer, so the interval it was asked for was one it could not take. The documented alternative was gh pr checks --watch, and gh was not installed, so that path was dead as well.

The mechanical half of watching CI now lives in .claude/scripts/ci-status.sh: it waits for checks to conclude, reports the outcome as an exit code, and on a failure prints the part of the log that explains it. The agent keeps the half that needs judgement — reading back from the symptom to the cause, reading the branch's version of the code the failure names, and deciding whether it is a defect, a wrong test, or the plan itself being wrong.

Exit codes separate a CI failure from the three setup problems that otherwise look like one: 0 passed, 1 failed, 3 no checks ever started, 4 gh not authenticated, 8 still pending when the watch ended. Reporting any of the last three as a failure sends an implementer hunting for a defect that does not exist.

crypter-triage-review named gh pr comment as the sole way to answer a finding with no thread, unreachable for the same reason gh was. It now names add_issue_comment alongside it.

Things worth knowing as a reviewer:

  • This adds a machine prerequisite: gh installed and authenticated. It carries its own credential, separate from the one the MCP server holds.
  • gh run view --log-failed returns roughly 1100 lines for a single failed job, mostly checkout and cleanup noise, and the failure is not at the tail. The script prints a window ending at the runner's ##[error] marker, which brings it down to about sixty lines. The marker itself is the symptom — the cause sits above it — and the agent is told so explicitly.
  • The check table previously listed Analyze (csharp) and Analyze (javascript) as separate rows. The matrix only expands when it runs; a docs-only diff reports one unexpanded Analyze.

Verified against this repository with gh 2.87.3: exit 0 on a green pull request (#845), exit 0 with skipped checks (#846), exit 4 unauthenticated, exit 64 on bad arguments and on an unknown pull request, the failing-run query against a commit with two failed workflows, and the log extraction against a real 1149-line failure log — where it surfaced the root cause, a Node version mismatch, that the ##[error] line did not mention.

n and others added 3 commits August 5, 2026 14:48
The CI watcher was told to poll for check runs every thirty seconds. A
foreground sleep does not run in this harness and the agent has no timer, so
the interval it was asked for was one it could not take. The documented way out
was gh pr checks --watch, and gh was not installed, so that path was dead too.

gh is now a hard dependency rather than an alternative offered where it happens
to exist. Watching is a single blocking --watch call, and the exit code
distinguishes a failure from a watch cut short before the round finished, which
would otherwise burn a fix attempt on a run that was merely still going.

Failure diagnosis reads the failing job's log through gh run view --log-failed
rather than scraping check run annotations. Annotations carry compiler
diagnostics well and test failures poorly, and the report this agent writes is
the only thing the implementer gets.

gh carries its own credential, separate from the MCP server's, so the agent
checks gh auth status first and names the missing login rather than failing
part way through with an authentication error.

crypter-triage-review named gh pr comment as the only way to answer a finding
with no thread, which was unreachable for the same reason. It now names the
MCP equivalent alongside it.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
An unauthenticated gh pr checks exits 4, which was outside the set of exit
codes the watcher was given. Left undocumented it reads as a non-zero exit and
therefore as a failing build, which sends the implementer looking for a defect
that is not there.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Waiting, reading exit codes, finding failing runs and cutting a log down to the
part that explains itself are all deterministic, and they were written as prose
for an agent to follow. Prose cannot be run, so the mistakes in it only surfaced
when a run went wrong: a polling interval the harness cannot take, an exit code
that reads as a failing build when it means nobody logged in, an instruction to
read the tail of a log whose last fifty lines are cleanup.

ci-status.sh does that half and can be tested. Exit codes separate a CI failure
from the three setup problems that otherwise look like one. On a failure it
prints the window of log ending at the runner's ##[error] marker, which turns a
1100-line dump into roughly sixty lines containing the cause.

The agent keeps the half that needs judgement: reading back from the symptom to
the cause, reading the branch's version of the code the failure names, deciding
whether it is a defect, a wrong test or the plan itself being wrong.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@Jack-Edwards Jack-Edwards changed the title Watch CI with gh instead of a polling loop Watch CI with a script instead of a polling loop Aug 5, 2026
Two skills offered a bare gh call as an alternative to the MCP server for
posting a review and commenting on a pull request. The MCP server does both, so
those were discretionary CLI invocations with nothing to recommend them.

The watcher's remaining direct call was fetching a fuller copy of a log the
script had already downloaded. The script now keeps each failing job's log and
prints its path, so reading further means opening a file rather than going back
to the network. Nothing outside ci-status.sh invokes gh now.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@Jack-Edwards
Jack-Edwards merged commit e74250b into stable Aug 5, 2026
13 checks passed
@Jack-Edwards
Jack-Edwards deleted the chore/ci-watcher-polling branch August 7, 2026 01:38
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