Fetch CI failure logs for a PR, detect the project toolchain, and diagnose the root cause. Outputs a structured diagnosis with the failure category, affected files, and suggested fix strategy. Use when a PR has failing CI and you need to understand why.
Instrucciones de origen · Vista previa de solo lectura
name
td-diagnose-ci
description
Fetch CI failure logs for a PR, detect the project toolchain, and diagnose the root cause. Outputs a structured diagnosis with the failure category, affected files, and suggested fix strategy. Use when a PR has failing CI and you need to understand why.
argument-hint
<repo> <PR number>
user-invocable
true
type
skill
mandatory
false
triggers
["diagnose CI","diagnose CI failure","why is CI failing","check CI logs"]
Read the failing test, update to match new dep API
7
prek/formatter
Files were modified by following hooks, prek exited with code 1
Run npx prek run --all-files locally, commit the formatted files
8
Biome formatting
biome check diff output
Run npx biome check --write --unsafe, commit changes
Python/tox failures
#
Category
Detection string in logs
Suggested fix
1
Dependency resolution
ResolutionFailure, Could not find a version, conflicting
Update version constraints in pyproject.toml
2
Import error
ImportError, ModuleNotFoundError, cannot import name
Updated dep renamed/moved a module — update import path
3
Type check failure
mypy errors with [code] suffixes
Fix type annotations
4
Lint violation
ruff errors with rule codes (F401, E501)
Fix the code
5
Test failure
FAILED tests/, AssertionError
Read the failing test, update assertions
6
Lock file conflict
uv.lock mismatch, pip resolution error
Regenerate: uv lock
7
pre-commit failure
pre-commit.ci - pr failing
Run pre-commit run --all-files, commit fixes
Cross-ecosystem failures
#
Category
Detection string in logs
Suggested fix
1
GitHub Actions version
Node.js 16 actions are deprecated
Update action version SHA in workflow YAML
2
Merge conflict
merge conflict in PR status
Should have been caught by td-rebase-pr
3
Infra/flaky
Transient network errors, runner timeouts
Re-trigger: gh run rerun RUN_ID --repo OWNER/REPO --failed
Step 5 — Check if failure is pre-existing
Before blaming the dependency update, check if the same failure exists
on the base branch:
Check the last 3 push-triggered runs (scheduled/cron runs may behave
differently):
gh run list --repo OWNER/REPO --branch BASE_BRANCH --event push --limit 3 \
--json conclusion --jq '.[].conclusion'
If the base branch is consistently failing, this is a pre-existing
failure, not caused by the dependency update. Note this in the
diagnosis.
Step 6 — Get the PR diff
gh pr diff PR_NUMBER --repo OWNER/REPO
Understand what the bot changed. This constrains what files should be
touched by a fix — per Shatakshi's guidance: avoid modifying anything
beyond the files already touched by the bot unless absolutely necessary.
Note in the diagnosis which files the bot changed.
Step 7 — Assess fix complexity
Analyze the PR diff, failure diagnosis, and PR metadata to determine if
this is safe to auto-fix.
7a. Gather signals
Version bumps: Parse the diff for version changes in package.json,
pyproject.toml, setup.cfg, or requirements*.txt. A major version
bump is:
npm: first non-zero number changed (e.g., ^5.9.3 → ^6.0.0)
Python: first number changed (e.g., >=2.1 → >=3.0)
PR metadata: Check for review comments and blocking labels:
Zero major version bumps (or exactly one with a lockfile/config-only fix)
Failure matches a known pattern from Step 4
Fix touches 3 or fewer files
Fix does NOT change: test assertions, CI/workflow config, or source logic
Fix stays within lockfile, config files, or formatting-only changes
Not pre-existing on main (Step 5)
No existing human review comments or reviews on the PR
No blocking labels (do-not-merge, needs-discussion, breaking, wontfix, on-hold)
The fix is one of these safe categories ONLY: lockfile regeneration, formatter/linter auto-fix, removing unused imports, or adding a type annotation on a single line
NEEDS HUMAN REVIEW — ANY of these:
Multiple major version bumps in one PR
Any major version bump that requires source code changes (not just
lockfile/config)
Failure doesn't match any known pattern
Pre-existing failure on the base branch
Fix would touch more than 3 files
Fix requires changing test assertions or expected values
gh pr comment PR_NUMBER --repo OWNER/REPO --body "$(cat <<'EOF'
## skill-guardian: diagnose-ci
This PR was analyzed automatically and **cannot be auto-fixed**.
**Reason:** <reason from 7b — list all triggered conditions by number>
**Diagnosis summary:**
- <failure 1 category>: <one-line description>
- <failure 2 category>: <one-line description>
**Major version bumps:** <list if any, e.g., typescript 5→6, wdio 8→9>
**Suggested action:** A maintainer should review this PR. <specific
guidance based on the reason — e.g., "Consider splitting the major
version bumps into separate PRs" or "The base branch is failing
independently — fix main first">
_Automated by [skill-guardian](https://github.com/ansible/team-devtools) · diagnose-ci_
EOF
)"
Step 8 — Output
## CI Diagnosis
**Repo:** OWNER/REPO
**PR:** #NUMBER — TITLE
**Toolchain:** TypeScript / Python-tox / Python-uv / Unknown
**Pre-existing:** yes / no
### Failure 1: check_name (failed step: step_name)
**Category:** <category from pattern table>
**Error:** <key error line from logs>
**File(s):** <file:line if identifiable>
**Suggested fix:** <specific fix from pattern table>
### Failure 2: check_name (failed step: step_name)
**Category:** <category from pattern table>
**Error:** <key error line from logs>
**File(s):** <file:line if identifiable>
**Suggested fix:** <specific fix from pattern table>
### Bot changed files
- pnpm-lock.yaml
- ...
### Fix scope
<which files need to change — should stay within bot's diff if possible>
### Assessment
**Verdict:** AUTO-FIXABLE / NEEDS HUMAN REVIEW
**Triggered rules:** <list by number, e.g., "#1 multiple major bumps, #2 source code changes required">
**Major bumps:** <list, e.g., "typescript 5→6, @wdio/cli 8→9">
**Files fix would touch:** <count>
**Human reviews on PR:** <count>
**Blocking labels:** <list or "none">
**PR comment posted:** yes / no / already exists
Each failed check gets its own numbered section with its own category,
error, and suggested fix. A PR may have multiple independent failures
(e.g., lint fails for one reason, tests fail for a different reason).
If no pattern matches:
### Root cause
**Category:** unknown
**Error:** <raw error lines>
### Suggested fix
Manual investigation needed. Error does not match known patterns.