The check run and JSON

The check run is written for two readers: a person who scans the title, and an agent loop that reads the JSON and fixes the findings without a human relay.

The check is named crocotaste and is posted by the Crocotaste GitHub App, so an agent can find it by name and verify it by app id.

Titles, by state

StateTitleConclusion
PassOn-system · 6 files · 42 tokens · 12 components · 9 decisions · 0 violationssuccess
Pass, checks onlyOn-system · checks only · 6 files · 42 tokens · 12 components · 9 decisions · 0 violationssuccess
Findings, drift only1 finding · 1 driftsuccess
Findings, a violation2 findings · 1 violation · 1 driftneutral
Neutral (our failure)Couldn't complete · re-run with @crocotaste reviewneutral
Neutral (balance)Review budget used · top up or upgradeneutral
SkippedSkipped · no UI files changedneutral
Skipped (too large)Skipped · too large to reviewneutral
Skipped (no system)Skipped · no design system foundneutral
Skipped (outsider)Skipped · ask a member for @crocotaste reviewneutral
RunningReviewing 6 files… ~60snone yet

The pass is always enumerated in the same order: files · tokens · components · decisions · violations. The number you trust is in the same position every time.

A check is only ever success or neutral, never failure, so a red check on your pull request belongs to somebody else. Green means on-system: a pass, or drift alone. A violation turns the check neutral until it is fixed or dismissed. Neutral never blocks a merge, even where you require the check, and findings are posted as a comment review, never request-changes: what blocks a merge stays your branch protection.

The JSON

A completed check's output.text ends with a fenced JSON block. Two checks carry none: the in-progress one, which has no body, and the Couldn't complete one, which publishes nothing rather than an empty result an agent might act on.

{
  "state": "findings",
  "grounding": {
    "hasDesignMd": true,
    "files": 6,
    "tokens": 42,
    "components": 12,
    "decisions": 9
  },
  "ai": "ok",
  "withheld": 0,
  "findings": [
    {
      "verdict": "VIOLATION",
      "path": "src/app/page.tsx",
      "line": 12,
      "message": "`#4ade80` is `--color-success` — use the token (tokens.css:18)",
      "citation": { "file": "tokens.css", "line": 18 },
      "fingerprint": "3f2a…"
    }
  ]
}
FieldMeaning
statepass, findings, neutral, skipped or too-large; the check's own state, not the pull request's
groundingwhat the review was checked against. files counts UI files reviewed, not files changed; hasDesignMd false means the system was parsed from code alone
aiwhat the model did with this push: ok (it read the diff), skipped (nothing new for it: the same lines as its last read, every line already reported, or an empty inventory; with the pull request's AI findings already spent, only when its lines are the ones last read), withheld (a read was due and did not happen: the review's included reads spent, an empty balance, two failed answers, or the pull request's AI findings already spent with new lines no model read; the pass is the checks' alone and carries no approval), failed, malformed or disabled; a skipped check carries skipped and the budget-used check withheld. withheld here is the model's status; the top-level withheld is the count of AI findings the cap held back
withheldAI findings the per-pull-request cap of 3 held back
findingsthe findings listed on this push, violations first
verdictVIOLATION or DRIFT
path, linethe added line in the new file, the same anchor as the inline comment
citationthe file and line in your references that the finding is proved against
fingerprinta stable hash, the same marker embedded in the inline comment

state: "neutral" covers both neutral titles, so an agent that needs to tell an exhausted balance from a failure should read the title. The wording of a failure is free to change; the states are not.

What an agent should do with it

Match findings to comments by fingerprint. It is stable across force-pushes and line shifts, and it is what stops a fix loop acting twice on one finding.

Re-read the check after your fix lands. findings is what was posted on this push, not everything known; when more exist, the summary above the JSON block says how many are not yet listed, and they post on later pushes as the listed ones are fixed or dismissed. An agent that never re-reads will believe it finished a batch early.

Treat withheld as work, not noise. Those findings were real; they were held back only because three per pull request is the ceiling.

Do not parse the message for structure. It names the value, then the token or component, then the source, but it is prose. citation and path/line are the structured fields.

Findings and verdicts explains what each verdict means and where a finding comes from.

Reading it

With the GitHub CLI, from inside the repository; gh fills in {owner} and {repo} itself:

gh api "repos/{owner}/{repo}/commits/$SHA/check-runs" \
  --jq '.check_runs[] | select(.name == "crocotaste") | .output.text' \
  | awk '/^```json$/{f=1;next} /^```$/{f=0} f'

That prints the JSON object alone, ready to pipe into jq. An empty result means the check has not completed yet, or it is the Couldn't complete one; when a review fails lists every state a check can end in.