Skip to main content

ai-review-max-turns

Triage a red Claude-powered CI review check. Use when an AI review job fails or flakes: tell a real unpublished finding from turn-budget or ceiling overruns and infra reruns via subtype + is_error.

Informações da origem

Repositório
laurigates/claude-plugins
Última atividade na origem
26 de setembro de 2026 às 23:17
Idioma detectado do SKILL.md
inglês
Estrelas
60
Forks
6

Opções de instalação

Por padrão, está selecionado o prompt que primeiro revisa a origem. Você pode mudar para um comando direto ou baixar uma cópia local.

Revise os arquivos de origem

Leia o SKILL.md e os arquivos complementares exibidos pelo SkillsMP antes de decidir se vai instalar.

Explorador de arquivos
2 arquivos

Exibindo SKILL.md

SKILL.md
Instruções da origem · Visualização somente leitura
name
ai-review-max-turns
description
Triage a red Claude-powered CI review check. Use when an AI review job fails or flakes: tell a real unpublished finding from turn-budget or ceiling overruns and infra reruns via subtype + is_error.
allowed-tools
Bash, Read, Grep, Glob, TodoWrite
created
2026-09-02T00:00:00.000Z
modified
2026-10-09T00:00:00.000Z
reviewed
2026-09-23T00:00:00.000Z
# A Red AI-Review CI Check Has Five Very Different Causes — Separate Them Before Acting A growing class of CI checks are **Claude-powered reviewers** — a workflow that runs the Claude Code action over the PR diff and reports findings as a pass/fail check. They are usually a family of `reusable-quality-*`, `reusable-security-*`, and `reusable-a11y-*` workflows, surfaced on the PR as checks named `typescript / analyze`, `secrets / scan`, `owasp / scan`, `aria / analyze`, `wcag / analyze`, and the like. ## When to Use This Skill | Use this skill when... | Use something else when... | |---|---| | The red check is Claude-powered (`owasp / scan`, `secrets / scan`, `aria`/`wcag`, …) | A deterministic check failed and you need its error → `github-actions-inspection` | | Deciding whether that red is a finding or noise | The failure is real and needs a code fix pushed → `git-plugin:git-fix-pr` | | The AI review stays green but re-runs on every push — see [REFERENCE.md](REFERENCE.md) | | ## The five causes They go red for five reasons that demand **opposite** responses. Reading one as another is the whole hazard: | Cause | Tell | Response | |---|---|---| | **Budget exhaustion** — the run died mid-flight | `error_max_turns` in the log; `is_error: true` | Ignore the failure; it says nothing about the code | | **Turn-ceiling overrun** — the run *finished*, the wrapper failed the job | `is_error: false`, `subtype: "success"`, **no** `Found N` line, and `##[error]Claude reported a successful result after N turns, exceeding the configured maximum of M` | Ignore the failure; the scan completed and found nothing | | **A real finding it could not publish** | `is_error: false`, `subtype: "success"`, a `::error::Found N …` line, **and no PR comment** | Investigate the code by hand — the check found something | | **Result flagged errored despite completing** | `subtype: "success"` **and** `is_error: true`, low `num_turns`, 0 denials, no `Found N` line, no `result` string | Rerun the identical commit once; a pass means it was infra | | **Bot-actor refusal** — the action refused to start Claude | No execution file, no `is_error`, no `num_turns`; the log says `non-human actor: <name> (type: Bot)`; when a workflow pushed with `github.token`, also `run_attempt` ≥ 2 with `actor` ≠ `triggering_actor` | Ignore the failure; fix the workflow with `allowed_bots`, or push with a PAT or App token | > **The law: the red X is never the discriminator, and neither is `is_error` > on its own.** Rule out Cause 5 first: a refused run has nothing to read. Then > read `subtype` and `is_error` together. `error_max_turns` means > the run died mid-flight. `subtype: "success"` means it finished, and a > finished run can still report `is_error: true` (Cause 4), so > `is_error` alone does not separate a run that died from one that finished. > Among finished runs reading `is_error: false`, the **finding count** decides: > a `Found N` line means the check is trying to tell you something through a > blocked channel; its absence alongside a turn-count error means the wrapper > failed a scan that had nothing to say. Read `subtype` and `is_error`, then the finding count, before forming any theory. Stopping at `is_error` sends a turn-ceiling overrun to the hand-audit response, and files Cause 4 under budget exhaustion, whose upstream fix (raise `max_turns`) cannot help a five-turn run. ```sh url=$(gh pr checks <pr> -R <owner>/<repo> --json name,link \ --jq '.[]|select(.name=="<check>")|.link') runid=$(echo "$url" | sed -E 's#.*/runs/([0-9]+)/.*#\1#') gh run view "$runid" --log-failed 2>&1 | grep -iE '"is_error"|"subtype"|error_max_turns|num_turns|non-human actor' ``` **Cause 1 (budget exhaustion)** — when the log shows `error_max_turns`, open [references/budget-exhaustion.md](references/budget-exhaustion.md) for the rotating-failure tell, why not to blind-rerun, the `mergeStateStatus` check, and the upstream fix. **Cause 2 (turn-ceiling overrun)** — when a `subtype: "success"` run logs `exceeding the configured maximum`, open [references/turn-ceiling-overrun.md](references/turn-ceiling-overrun.md) for the grep, the evidence, where the turns went (including a base-branch restore that parks a PR's `.claude/` edits in `.claude-pr/`), and the upstream fix. **Cause 4 (errored despite completing)** — when `subtype: "success"` and `is_error: true` appear together, open [references/errored-despite-completing.md](references/errored-despite-completing.md) for the full signature, the grep, and the rerun-once rule. **Cause 5 (bot-actor refusal)** — when the step fails with no execution file and the log says `non-human actor`, open [references/bot-actor-refusal.md](references/bot-actor-refusal.md) for the approval-hold mechanism, the `allowed_bots` fix, and a scan counting them across a repo's failed runs. ## Cause 3 — a real finding the check cannot publish These workflows are told `Leave a PR comment with findings` but are granted no comment tool, so every attempt is denied and the prose is discarded — while `fail-on-critical` still fails the build off the count in `structured_output`. The result is a gate that **blocks a merge on a finding nobody can read.** ```sh gh run view --job <job-id> --log | grep -E '"is_error"|"subtype"|permission_denials_count|critical security' gh pr view <n> --json comments --jq '.comments | length' # 0 = it could not publish gh api repos/<o>/<r>/check-runs/<job-id> --jq .output # all null = nothing to read ``` `permission_denials_count` in double digits is the signature: the model retries the blocked call, which also burns budget. **Do not treat an unreadable finding as a false positive.** Read the analyzed files yourself against the check's own category list. The finding is often in *pre-existing* code the scan read alongside the diff — but not always. A worked case where the finding was real is in [references/unpublished-finding.md](references/unpublished-finding.md). **The count is not stable.** Same commit, different answer. Never treat a delta between runs as evidence a fix worked. ## The trap under all five: a check that never ran looks exactly like a pass Before using a sibling PR as a "it's green there" control, check the **duration**. These workflows carry `file-patterns` filters, so a PR touching no matching files completes in **4–6 seconds** having analyzed nothing — and reports `pass`. ```sh gh pr checks <n> | grep -E "owasp|code-smell" # 4s pass = skipped, not clean gh run list --workflow security.yml --branch main -L 5 # empty = PR-triggered only, no main baseline ``` A green tick from a skipped run is not a control. This is `never-fabricate-test-identifiers.md`'s known-good control applied to CI: if the "passing" comparison never executed, you have no baseline, and `pr-merge-hazards.md`'s merge-over-red test ("same check already fails on `main`") cannot be satisfied. ### No history at all: the workflow has ≤1 historical run The control above presumes some earlier run exists. A newly added workflow may have none, and its only run can be the failing one: ```sh gh run list --workflow <file>.yml -L 12 # only the failing run, or nothing ``` When the workflow has ≤1 historical run, state it in the triage: no baseline exists, so "is this normal for this check?" cannot be answered from history. An empty `gh run list` reads as *nothing to see*; it means there is nothing to compare against. Rerunning the identical commit then becomes the primary discriminator rather than a follow-up (a deterministic failure repeats, a flake does not), alongside reading the changed files against the check's own criteria. Evidence (thelma#1524) is in [references/errored-despite-completing.md](references/errored-despite-completing.md). ## When it bites - Large PRs that outrun a per-file reviewer's turn budget, and repos that mark these checks **required**: [references/budget-exhaustion.md](references/budget-exhaustion.md) § When it bites. - Any security-category scan whose red you are tempted to wave through on the strength of green deterministic gates. Cause 3 looks identical from the outside and is exactly where that reflex is most expensive. ## Rationale A red check on valid code is worse than no check: it reads as a real finding, so it pulls a reviewer into chasing a non-existent defect and erodes trust in the AI-review signal. But the inverse error is worse still — treating every AI-review red as flakiness waves through the findings that are real and merely unpublishable. Ruling out the bot-actor refusal, then reading `subtype`, `is_error` and the finding count together, separates all five. Same instinct as `github-actions-plugin:multirepo-ci-cd`: diagnose against what CI actually did (read the run), not against the surface red. ## Related - [REFERENCE.md](REFERENCE.md) — the *green* runaway: a `synchronize`-triggered review loop with no round counter, why draft does not stop it, the kill switches and their blast radius, and where the per-run cost actually lives - `.claude/rules/pr-merge-hazards.md` §4 — `UNSTABLE` vs `BLOCKED`, and the two checks required before merging over red - `laurigates/.claude/rules/ci-cd-workflows.md` — the three *green*-but-inert modes of these same workflows (empty secret, workflow anti-tampering, skipped by filter); this skill covers the *red* modes - `~/.claude/rules/diagnose-at-the-failure-point.md` — measure at the failure point rather than accepting the framing the error hands you - `github-actions-plugin:multirepo-ci-cd` — portfolio-wide CI diagnosis discipline
Ver no GitHub