agentleFS
noltenolte/claude-shared/skills/workflow-health-triage/SKILL.md

workflow-health-triage

Skill0 starsChanged 3 months agoMITView on GitHub

Triages a failing GitHub Actions workflow run on `develop` or `main` per `spec/project/workflow-health/`. Classifies the failure into one of `defect` / `flake` / `infra` / `stale pin` / `secret drift` / `other`, dispatches the most specialised Claude agent that matches the classification, records the classification plus the dispatched agent's name in the eventual fix PR's Risk / rollout notes, and verifies the standard `fix/`-PR flow. Invoke when the user asks to \"triage this red workflow\", \"classify this CI failure\", or equivalent German-language requests. Don't use to silence checks via `continue-on-error` shortcuts or by removing required-checks entries (forbidden by spec); don't use to bypass branch protection (`enforce_admins` on develop has no exception path); don't use to merge a fix PR (use `pull-request-merge`). Supports resume on re-invocation per `spec/claude/resumable-work/`.

  • Reads credentials

The file

We split this skill into the rules it gives an agent

8 rules. About 0 are common, 1 is distinctive, and 7 are very specific to this project.

  • ≈0

    Common · estimate

    Many files like this have a rule of this kind.

  • ≈1

    Distinctive · estimate

    This author's own choices. Worth a look.

  • 7

    Very specific

    Tied to their project's names, files or tools. Probably skip.

  • Common
  • Distinctive
  • Very specific
  1. Very specific:

    Hard: never call gh run rerun <id> more than once before a recorded classification exists.

    line 82
  2. Very specific:

    If the user wants the skill to open the fix PR itself, dispatch pull-request-create with these two lines pre-populated in the Risk / …

    line 102
  3. Very specific:

    After the fix PR opens, the skill stops.

    line 106
  4. Very specific:

    Read examples/01-defect-classification-dispatch.md when triaging a failure that classifies as defect and dispatches to a specialised agent.

    line 120
  5. Very specific:

    Read examples/02-stale-pin-portfolio-gap.md when the failure root-causes to a stale pin in the portfolio plumbing.

    line 121
  6. Very specific:

    Read examples/03-flake-no-fix-record-only.md when the failure classifies as flake and the skill records the classification without opening …

    line 122
  7. Distinctive:

    Always: prefer a plugin-distributed specialised agent over the generalist when one matches.

    line 136
  8. Very specific:

    When spec/project/workflow-health/ disagrees with this skill, the spec wins.

    line 137

≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.

Keep what fits and drop the rest. Your version, ready for your agents.
Files
SKILL.md

Workflow Health Triage

Implements spec/project/workflow-health/ §Triage before remediation and §Specialised-agent dispatch for remediation. The skill is the generalist that classifies a failure and dispatches the hands-on fix to the most specialised available Claude agent; it never performs the fix itself when a matching specialised agent exists.

Why this is a skill, not an agent

  • Externally-visible mutations gate on user confirmation. Classification ambiguity, agent-dispatch confirmation, and the fix-PR title / body are mid-flow user dialogues; an agent's fire-and-forget shape would miss them.
  • Orchestrator pattern (per skill-vs-agent). The work itself is classify, dispatch, verify; the dispatched specialised agent does the editing. The orchestrator stays in the main thread and chains other skills (pull-request-create for the fix PR, optionally pull-request-merge after CI is green).
  • Per-classification user gating. At least three of the six classes (defect, flake, secret drift) need a human "yes that's the right call" before the dispatcher commits to a remediation lane.
  • Counter-dimension considered: a narrow agent could handle the classification step in isolation and gain context-window protection, but every downstream lane (PR creation, agent dispatch, verification) is interactive—keeping the whole flow in one skill is simpler than splitting at the classification boundary.

User-language policy

Detect the user's language and respond in it. All git, gh, and Agent(subagent_type=…) invocations stay English so the audit trail (PR titles, classification labels, agent names) is grep-able portfolio-wide.

Preconditions

Before any classification:

  • Confirm the working directory is a git repository and gh auth status reports authenticated.
  • Confirm spec/project/workflow-health/<canonical_language>.md is reachable — in the current project or, when absent there, at ${CLAUDE_PLUGIN_ROOT}/spec/project/workflow-health/<canonical_language>.md (the copy shipped inside the installed nolte-shared plugin). If neither is reachable, stop and report—without it the classifications are ad-hoc; this skill is the spec's implementer, not its replacement.
  • The user supplies the failing workflow run (a gh run view <id> URL, a workflow file name like release-publish.yml, or "the red one on develop"). If nothing is supplied, run gh run list --status failure --branch develop --limit 5 and ask which run to triage.

Operations

1. Inspect the failing run

Run in parallel:

  • gh run view <id> --json name,headBranch,headSha,event,status,conclusion,workflowName,url,jobs
  • gh api repos/<owner>/<repo>/actions/runs/<id>/jobs --jq '.jobs[] | {name, conclusion, html_url}'
  • gh run view <id> --log-failed (capture the failing-step output for classification)
  • git log --oneline -1 <headSha> (resolve the commit under the run)

Tooling (optional GitHub MCP): the GitHub reads above are Actions / workflow-run reads. When a connected GitHub MCP server exposes an actions read toolset, prefer it and verify the exact tool names against the pinned server version, per spec/claude/mcp-tool-preference/; the reference hosted endpoint exposes no actions toolset, so these reads stay on gh (a documented OQ-D coverage gap). gh stays authoritative and the fallback is never removed.

Confirm the run is on develop or main (the spec's scope) and is conclusion: failure. If it's still in_progress, stop and ask the user to wait for completion before triage. If it's cancelled, classify as other with a one-line note and stop—unless the lane's recent runs (gh run list --workflow <file> --limit 20) are majority-cancelled: then the lane delivers no verdict at all, and the subject is the lane, not the run. Route it to spec/project/workflow-health/ §"Cancellation rates" and its two-cause fork: measure the median wait (started_at − created_at, jobs with no needs: only) beside the runtime per ${CLAUDE_PLUGIN_ROOT}/skills/cicd-pipeline-design/references/slot-capacity-measurement.md; wait that dominates runtime is a capacity finding for cicd-pipeline-design, runtime above the trigger cadence is the cadence remedy, runtime far below it is churn. Stop after naming which of the three applies; the remediation isn't a fix/ PR from this skill.

2. Classify before any re-run

Walk the table top-down and stop at the first match. The rows are ordered by specificity rather than by the spec's class order, so a narrow signal is tested before the broader rows that would also capture it; every row still resolves to one of the spec's six classes:

Signal in the failed-step outputClassification
Push rejected with refusing to allow a GitHub App to create or update workflow ... without 'workflows' permissioninfra — evaluate this row first. Both the defect row (the rejection names a workflow file the diff modified) and the secret drift row (it is a 403) would otherwise capture it, and neither is right: it is a deterministic platform constraint, not a repository defect and not an expired credential
Failing step references a file the head commit's diff modifieddefect
Re-run of the same headSha would produce green (no infra signal, no code change in the failing step's surface)flake
HTTP 5xx, rate-limit, registry-unreachable, GitHub status incidentinfra
uses: pin in the workflow points to a nolte/gh-plumbing (or other reusable) tag, and a newer tag exists with the relevant fixstale pin
Token, deploy key, or OIDC trust expired or rotated; failure references 401, 403, expired, unauthorizedsecret drift
None of the aboveother (with a short note explaining why)

Confirm the chosen class with the user before proceeding—at minimum for defect, flake, and secret drift, where misclassification has the highest cost. Apply the classification by writing it to a scratch note that becomes the seed of the fix PR's Risk / rollout notes.

Hard: never call gh run rerun <id> more than once before a recorded classification exists; repeated blind re-runs are drift per spec/project/workflow-health/ §Triage before remediation.

3. Dispatch the most specialised available agent

The set of available agents changes over time; never freeze a snapshot of "which agents exist" inside this skill body. Resolve the dispatch target dynamically each invocation:

  1. Resolve the candidate set. Glob agents/*.md (plus .claude/agents/*.md (project-distributed; additionally ~/.claude/agents/*.md for user-level agents) for the project-distributed half), then Read the description: line of every candidate. Build a (name, description) table; the table is the runtime inventory.
  2. Match classification to candidate. Walk the candidates and pick the one whose description most closely matches the (classification, failing-artefact-area) pair: a defect in a markdown spec/skill/agent file maps to whichever agent's description names "spec-conformant authoring" or the equivalent; a defect in a workflow YAML maps to whichever agent's description names "workflow YAML" or "GitHub Actions"; a documentation defect maps to whichever agent names an audience-targeted documentation responsibility; and so on. The match is on the description's stated responsibility, not on the agent's name.
  3. Recognise the no-fix classifications. flake and secret drift produce no agent dispatch by design — the work is documenting the flake in the project's flake registry (FLAKES.md or the flake-labelled issue set, whichever the repository uses) for flake, or rotating the credential outside Claude for secret drift. The skill produces only the fix PR that re-references the rotated credential.
  4. No match is a portfolio gap. When the candidate walk produces no plausible match and the failure class has occurred three or more times historically (use gh run list --status failure --branch develop --limit 50 plus a quick grep to estimate), surface this as a portfolio gap per spec/project/workflow-health/ §Specialised-agent dispatch — the user is asked whether to author a new agent (via claude-plugin-developer) before the fix PR opens. When a match exists, dispatch with Agent(subagent_type="<plugin>:<agent>") and pass the classification, the run URL, the failing-step excerpt, and the fix-PR-title hint. The classification is a hypothesis about the cause, so the dispatch brief MUST authorise refutation per spec/claude/dispatch-brief/: tell the agent it may refute the classification, and treat a returned refutation (contradicting evidence plus what it did instead) as a first-class result — re-classify rather than force the fix — not a failed dispatch. Wait for the agent's report.

The dynamic-lookup design means a new specialised agent that lands in agents/ becomes dispatchable immediately, without a coordinated edit to this skill — and a renamed or removed agent stops being a target the next time the skill runs, with no stale snapshot to mislead the dispatch.

4. Verify the fix PR carries the audit trail

Whether the editing was done by a specialised agent or the generalist, the resulting fix PR MUST carry both pieces of evidence in its Risk / rollout notes section per the pull-request-workflow spec:

  • Triage classification verbatim (one of the six labels above, with a one-line note for other)
  • Dispatched agent name (the literal subagent_type argument), or the literal phrase "no matching specialised agent—generalist remediation"

If the user wants the skill to open the fix PR itself, dispatch pull-request-create with these two lines pre-populated in the Risk / rollout notes; the user still confirms the title and body before push, per the pull-request-create spec's externally-visible-action gate.

5. Verify the standard PR gate

After the fix PR opens, the skill stops. The actual merge belongs to pull-request-merge, which re-validates the gate. The skill MUST NOT:

  • merge the fix PR itself (out of scope; pull-request-merge owns that)
  • pass --admin anywhere (enforce_admins: true on develop has no exception)
  • waive a still-failing required check on the fix PR (the spec forbids continue-on-error masking and required-check removal)

Report back the run ID, the classification, the dispatched agent name (or "generalist"), the fix-PR URL, and a one-line "next action: invoke pull-request-merge after CI is green".

Old patterns

Earlier revisions of this skill enumerated specific agent names inline (for example workflow-yaml-fixer, claude-plugin-developer, audience-doc-author) as the dispatch table. That snapshot rotted whenever a new agent landed or an existing one renamed; the runtime-Glob design in Operation 3 replaces it. The historical mapping is preserved here only so a reader who recognises the prior wording can spot the transition: defect in workflow YAML used to fall back to generalist (no matching agent), defect in spec / skill / agent files used to dispatch claude-plugin-developer, defect in documentation used to dispatch audience-doc-author. Use the runtime lookup in Operation 3 instead of this snapshot.

Examples

  • Read examples/01-defect-classification-dispatch.md when triaging a failure that classifies as defect and dispatches to a specialised agent.
  • Read examples/02-stale-pin-portfolio-gap.md when the failure root-causes to a stale pin in the portfolio plumbing.
  • Read examples/03-flake-no-fix-record-only.md when the failure classifies as flake and the skill records the classification without opening a fix PR.

Resumability

Per spec/claude/resumable-work/, this skill is resumable: true. State is persisted to .resume/workflow-health-triage/<run-id>.yml after every successful user-approval gate and after each named phase boundary. On re-invocation, scan that directory for files with status: in_progress whose inputs: snapshot matches the current invocation; if one matches, prompt the operator with Resume run <run_id> from phase <phase> (last checkpoint <last_checkpoint_at>)? [resume / start-new / discard]. The state-file envelope (schema_version, run_id, inputs, phase, decisions[], status, ...) and the fail-closed semantics on schema or YAML errors are load-bearing in the spec; don't duplicate those rules here.

Hard rules

  • Never re-run a failed required workflow run more than once before a recorded triage classification exists; the spec calls repeated blind re-runs drift.
  • Never classify a failure as flake without reproducible evidence (re-run of the same headSha returned green and no infra signal explains the first failure).
  • Never mask a failure: don't propose continue-on-error: true on a required job, don't propose removing a check from the required-checks set in .github/settings.yml without a tracking Issue, don't propose repointing a nolte/gh-plumbing pin from a tag to a branch.
  • Never bypass branch protection on the fix PR; enforce_admins: true on develop has no exception path.
  • Never dispatch a specialised agent with a classification the spec doesn't list. The closed set is defect / flake / infra / stale pin / secret drift / other.
  • Never open a fix PR whose Risk / rollout notes don't carry the classification and the dispatched agent name (or the explicit "no matching specialised agent" note).
  • Always prefer a plugin-distributed specialised agent over the generalist when one matches; the spec's §Specialised-agent dispatch makes this a SHOULD that this skill upgrades to a hard contract for the dispatch step.
  • When spec/project/workflow-health/ disagrees with this skill, the spec wins. Propose updating this skill rather than silently diverging.

Gotchas

Per spec/claude/skill-management/ §Gotchas—concrete corrections to non-obvious environment facts the executing agent would otherwise get wrong.

  • GITHUB_TOKEN-cascade failures aren't defect. A release-drafter.yml that doesn't fire after an automerge.yaml squash-merge, or a release-cd-refresh-master.yml that doesn't fire after release-publish.yml, is the documented infra class per spec/project/workflow-health/ §Known platform constraints—and the remediation is upstream in nolte/gh-plumbing, not in the consumer repo. Don't open a fix PR against the consumer's workflow YAML; document the infra classification and reference the nolte/gh-plumbing tracking Issue.
  • A workflow-file push rejection reads like secret drift and isn't. refusing to allow a GitHub App to create or update workflow ... without 'workflows' permission is a 403-flavoured rejection, so the secret drift row matches it on the surface. It's the second constraint in spec/project/workflow-health/ §Known platform constraints: GITHUB_TOKEN is a GitHub App identity and can never write under .github/workflows/, and the permissions: block has no workflows scope to grant. Rotating a credential fixes nothing. Classify infra and route to the App-token remediation, whose installation needs workflows: write on top of contents: write. It surfaces intermittently, only when the pushed diff happens to touch a workflow file, so a green history doesn't rule it out.
  • pascalgn/automerge-action exits 0 on mergeResult: 'merge_failed'. A automerge.yaml run with conclusion success whose log carries mergeResult: 'merge_failed' or Failed to merge PR: is a stale pin failure (the reusable's MERGE_METHOD default doesn't match the repo's allowed strategy in some pre-fix versions). Triage the automerge.yaml uses: tag, not the workflow YAML itself.
  • Renovate-generated bump PRs for nolte/gh-plumbing aren't automerged in this portfolio. A stale pin remediation that proposes to enable Renovate automerge for nolte/gh-plumbing violates workflow-health §Upstream drift and the AC against it. The remediation is a human-acknowledged Renovate PR, not an automerge rule.
  • flake without reproducible evidence is defect. A "let's just re-run and hope" reflex is exactly what the spec forbids. If the same headSha doesn't re-run cleanly green and no infra signal explains the first failure, the class is defect and the work is a fix, not a tracking entry.

Multi-model testing

Examples and operations in this skill are verified on Claude Sonnet as the default model; spot-checked on Haiku for cost-sensitive runs; Opus is appropriate for high-stakes audits that require deeper reasoning. The skill body has no model-specific assumptions beyond standard tool-call semantics.

Download now (ZIP)

Does it work?

Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.

No reviews yet

People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.

  • It worked
  • Partly
  • It didn't
What did you use it for? e.g. Reviewing pull requests in a Rails app

Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.

Your trail

Files you open will collect here, so you can find them again.

Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.

Now do this for your own.

Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.