# CI Triage

> Decision tree for a red CI run. Use BEFORE retrying — blind re-runs burn the shared GitHub rate limit and hide real bugs.

- Skill: `earayu/ci-triage` (Agent Skill)
- Install (CLI): `npx skillmds@latest add earayu/ci-triage`
- Raw SKILL.md: https://api.skillmd.com/api/skills/earayu/ci-triage/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: AI & ML
- Author: earayu (https://skillmd.com/u/earayu)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/earayu/ci-triage

---


# CI Failure Triage

Use this skill whenever a PR's CI goes red.

## 1. Get the signal, not the whole log

Never dump a full failed-run log into context (10-50KB+). Use the
wrapper's key-line extraction (`github.ci.failed_log_signal_patterns`,
capped by `failed_log_max_lines`). Pull the raw log only when a human
explicitly asks.

## 2. Classify the failure

| Symptom | Class | Action |
|---|---|---|
| `psycopg2 ... Connection refused` / `port 5432` / "Apply migrations" | runner infra (postgres OOM/contention) | Do NOT loop-retry. Escalate / wait off-peak / evidence-based admin override. |
| kube-apiserver readiness 500 / kube-proxy CrashLoop / node not-ready | runner infra (kind cluster) | Same. |
| `test_openapi_route_coverage_matrix... AssertionError: N == M` | matrix drift | `git merge origin/<default>` into branch (brings updated matrix). Proven fix. |
| `Type error` / `tsc` / `Would reformat` / ruff | real code | Fix precisely. Don't retry. |
| compose/kind smoke ✅ but lint-and-unit ❌ on an FE-only PR | code clean → infra | Treat the red as infra; pursue the infra path. |

## 3. Don't double-trigger

If a monitor/PM script or another agent is already auto-rerunning, do
NOT also push an empty commit or `gh run rerun`. Coordinate so exactly
one owner pulls the trigger. Empty-commit retrigger re-runs ALL checks
→ waste + runner contention.

## 4. Persistent failure = escalate, not loop

≥3 failures of the same check across reruns is NOT a transient flake.
Pull the real log, name the root cause, escalate (SRE / off-peak
retry / evidence-based admin override) instead of an infinite loop.

## 5. i18n / contract sync gotcha

When you i18n a user-facing string (raw → `t('...')`), grep
contract/snapshot tests for the raw string before merging — they may
assert on it and turn main red after merge.

