docs(skills): cluster CI failures before pulling artifacts

Move the artifact-download guidance out of the generic dialectic loop and
into triage, where it now runs per error-message cluster instead of per
failing job: group the failing jobs by their actual failing line, fetch one
representative's artifacts per cluster, and run the dialectic per cluster.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
Kevin Veen-Birkenbach
2026-08-01 14:55:38 +02:00
parent 545c213f88
commit 8f231d49e7
2 changed files with 19 additions and 20 deletions

View File

@@ -26,13 +26,6 @@ operator holds.
git history; the running containers (exec, logs, inspect through whatever git history; the running containers (exec, logs, inspect through whatever
make or CLI helpers the project exposes); CI logs and artifacts; tests; docs. make or CLI helpers the project exposes); CI logs and artifacts; tests; docs.
Cite `file:line` and command output — never a bare assertion. Cite `file:line` and command output — never a bare assertion.
**Download the artifacts before theorising.** When the failure comes from a
CI run, list its artifacts and fetch every one that could carry the failure
(`gh run download <run> -n <name> -D <dir>`, or the equivalent for the CI in
use). A job log routinely holds only the *path* of a report while the payload
— assertion text, expected vs received, server logs, diagnostic dumps — lives
in the artifact. Theorising from the log alone while an unread artifact
contains the answer is the single most expensive mistake in this loop.
2. **Antithesis.** Spawn MULTIPLE independent skeptics (parallel subagents or a 2. **Antithesis.** Spawn MULTIPLE independent skeptics (parallel subagents or a
workflow) whose only job is to REFUTE the thesis. Each re-inspects the workflow) whose only job is to REFUTE the thesis. Each re-inspects the
sources itself and defaults to "refuted" on any concrete hole. Give diverse sources itself and defaults to "refuted" on any concrete hole. Give diverse

View File

@@ -17,27 +17,33 @@ root cause is proven.
whose conclusion is failure, cancelled, or timed-out. A downstream aggregate whose conclusion is failure, cancelled, or timed-out. A downstream aggregate
job that fails only because an upstream job did is not a separate root cause — job that fails only because an upstream job did is not a separate root cause —
note it and move on. note it and move on.
2. **Download the run's artifacts.** Before investigating, list the run's 2. **Cluster the failures by error message.** Group the failing jobs by their
artifacts and fetch every one belonging to a failing job — reports, rescue actual failing line, not by job name. Jobs whose messages differ in anything
diagnostics, inventories, container logs. The job log usually names an but the interpolated identifiers (host, app, port, path) belong in separate
clusters.
3. **Download artifacts per cluster.** For each cluster, fetch every artifact of
one representative job: reports, rescue diagnostics, inventories, container
logs. Pull a second member's artifacts only when the representative's
evidence does not explain the whole cluster. The job log usually names an
artifact path and nothing more; the assertion text, the server-side artifact path and nothing more; the assertion text, the server-side
exception and the state dumps are inside the artifact. Do this even when the exception and the state dumps are inside the artifact. Do this even when the
log looks conclusive, because a log that explains the symptom rarely log looks conclusive, because a log that explains the symptom rarely
explains the cause. explains the cause.
3. **Dialectic per failing job.** For EACH failing job, invoke the `dialectic` 4. **Dialectic per cluster.** For EACH cluster, invoke the `dialectic` skill:
skill: form a thesis about the root cause from evidence (the job log, its form a thesis about the root cause from evidence (the job log, its artifacts,
artifacts, the code at the run's commit, git history), attack it with the code at the run's commit, git history), attack it with independent
independent skeptics, and iterate to a ~99% thesis. The jobs are independent, skeptics, and iterate to a ~99% thesis. The clusters are independent, so run
so run their investigations in parallel where the tooling allows. their investigations in parallel where the tooling allows.
4. **Distinguish shared vs hidden causes.** When several jobs share one root 5. **Distinguish shared vs hidden causes.** A cluster is a hypothesis, not a
cause, fix it once. When a job hides a second failure behind the first, keep proof: if the dialectic shows one cluster splitting into two causes, split it.
going until the job is actually green, not just past the first error. When a job hides a second failure behind the first, keep going until the job
5. **Fix at the root.** Apply the real fix in the repository for each proven root is actually green, not just past the first error.
6. **Fix at the root.** Apply the real fix in the repository for each proven root
cause. Never mask a failure — no retry-until-pass, no disabling the check, no cause. Never mask a failure — no retry-until-pass, no disabling the check, no
soft-skip. If a failure is genuinely external (upstream outage, flaky infra), soft-skip. If a failure is genuinely external (upstream outage, flaky infra),
confirm that with evidence and surface it honestly instead of fixing around confirm that with evidence and surface it honestly instead of fixing around
it. it.
6. **Follow the run.** While the run is still in progress, re-check it 7. **Follow the run.** While the run is still in progress, re-check it
periodically and triage each newly failed job as it appears. The run is done periodically and triage each newly failed job as it appears. The run is done
only when it has finished and every failure has a verified fix. only when it has finished and every failure has a verified fix.