| name | pressure-testing-skills |
| description | Use when validating or hardening a SKILL.md, prompt, rule, or any agent-followed document — when you need proof it actually works, not just that it reads well. Runs a fresh subagent that follows the doc literally on a known-answer fixture, captures friction, and iterates to determinism before minimizing. Use after writing-skills produces a draft, or whenever a skill 'looks right' but hasn't been proven under an agent. |
Pressure-Testing Skills — amd-smi
Empirically prove a skill (or prompt/rule/checklist) works by making a fresh
subagent follow it literally on a fixture whose answers you already know, then
iterate on the failures until the run is deterministic. Reading a skill tells you
it's plausible. Only a literal run by a naive agent tells you it's correct.
Iron Law: A SKILL IS NOT DONE UNTIL A FRESH SUBAGENT, FOLLOWING IT VERBATIM ON
A KNOWN-ANSWER FIXTURE, CATCHES EVERY PLANTED ISSUE WITH ZERO GUESSING AND NO
BLOCKING FRICTION — WITHOUT INVENTING STEPS THE SKILL DIDN'T GIVE.
If the agent got the right answer by adding its own check, the skill failed —
that check belongs in the skill. If it "ran clean" but missed a planted issue,
the skill failed. If it had to guess which value to use, the skill failed.
REQUIRED BACKGROUND: you must understand writing-skills (structure, CSO,
token budget) and dispatching-parallel-agents (how to run subagents) first.
Why Literal + Naive + Known-Answer
The whole method rests on three constraints — drop any one and the test lies:
| Constraint | Drop it and… |
|---|
| Literal — agent runs the documented commands verbatim, invents nothing | A clever agent papers over gaps with its own reasoning; you ship a skill only experts can follow |
| Naive — fresh subagent, no prior context, no domain memory | Your own knowledge leaks in and the skill looks clearer than it is |
| Known-answer — fixture with a pre-written answer key | You can't tell "caught everything" from "got lucky / ran clean" |
The Loop
0. Build the fixture + answer key (the hardest and most important step)
1. Snapshot the skill to a stable temp path (vN)
2. Dispatch a FRESH, correctly-tooled subagent — follow vN verbatim, invent nothing
3. Collect: issues-caught-vs-answer-key AND friction log
4. Fix the ROOT CAUSE of each miss / friction → snapshot v(N+1)
5. Repeat 2–4 until GREEN (stop condition below)
6. Minimize: cut redundancy, re-test after EACH cut, revert any regression
0. Fixture + answer key
You cannot grade a test with no answer key. Before iterating, write down every
issue the fixture contains and the exact evidence that should surface it.
- Best fixture: a real artifact with known defects (e.g. a
CHANGELOG.md
on develop you already audited by hand). Real fixtures expose real ambiguity.
- Answer key: a list like "F1: entry X is misfiled → commit
abc merged after
pin def; F2: ### Fixed is a disallowed heading; F3: deprecation under the
wrong section." Grade every run against it.
- A skill with no fixture cannot be pressure-tested. If you can't build one, the
skill is probably too vague to be useful — fix that first.
- Prefer the LIVE state; historical replays carry time-anchored traps. If the
skill resolves any bound from "now" (current tags,
origin/develop, HEAD), a
checked-out past state gives meaningless results — the bound is anchored to the
present, not the fixture's era. In one run, auditing a pre-release commit bounded
a section by a pin that didn't exist yet, and the untagged-release fallback
(origin/develop) pointed at today's tip, so the "too new" check could never
fire and the audit ran clean while proving nothing. Use the live artifact as the
fixture, or freeze the time-relative inputs too — otherwise you test a mirage.
- Grade coverage against what the real task touches, not what the skill looks
at. If the fixture's defects span the whole file but the skill only inspects
the top section, a literal run reports "clean" and is structurally blind to most
of the answer key. A scope mismatch between skill and task is itself a finding.
1. Snapshot to a stable path
Copy the skill under test to a temp path (/tmp/<skill>-test/SKILL-vN.md) and
point the subagent at ONLY that path. Never point it at the file you're editing
or an installed copy — a stale .claude/skills/ copy will silently override your
work. Tell the agent explicitly: "ignore any installed copy; use only this path."
2. Dispatch a correctly-tooled, fresh subagent
- Tools must match what the skill's commands need. A skill full of
git/gh
shell commands tested by a no-terminal agent proves nothing — it will only catch
surface issues (headings, wording) and give false confidence on the real logic.
Use a terminal-capable general subagent for shell-based skills.
- Fresh context every iteration so prior runs don't inflate apparent clarity.
- Give it the fixture setup, the snapshot path, and the literal-follow rules.
3. Collect two distinct signals
Grade every run on both — they fail independently:
| Signal | Question | A gap here means |
|---|
| Coverage | Did it catch every answer-key issue, using only documented commands? | The skill is missing a check → add it |
| Determinism | Did it have to guess, interpret, or invent anything? | The skill is ambiguous → spell it out |
"Ran clean with no errors" is not success. A command can exit 0, leak a
swallowed traceback, and still produce a plausible-but-wrong bound. Ask for the
friction log: every command that failed, was ambiguous, leaked an error, or forced
a guess — quoted with its exact command and actual output. The friction log,
not the verdict, is what drives the next iteration.
Absence of output is not proof. A clean pass and a silently-broken run look
identical — both print nothing. A check that greps a section and finds no problems,
and a check that ran on zero input (wrong path, empty range, swallowed error),
are indistinguishable from the outside. Make the skill emit a positive count
("N items checked, 0 flagged"), and have the test agent confirm the check ran on
real input, not an empty set, before trusting a clean result.
4. Fix root causes, not symptoms
Each friction item points at a real defect. Fix the cause:
| Real example from a changelog-skill loop | Root-cause fix |
|---|
| Audit loop checked only the lower bound → false "all clear" | Check both bounds of the range |
<V>=7.14.0 built tag therock-7.14.0 (404) → silent origin/develop fallback | Document that tags drop the patch component |
2>/dev/null on gh didn't cover the python3 in the pipe → leaked traceback | Move error handling to cover the whole pipe |
| Agent doubted a correct verdict and nearly overrode it | Add the why so a skeptic trusts it (persuasion, not just rules) |
| A clean placement audit and one that ran on zero commits looked identical | Emit a positive count ("N checked, 0 flagged") so a real pass is distinguishable |
| Skill inspected only the top section; the task spanned the whole file | Match the skill's scope to the task, or make the scope an explicit choice |
| Every rule was prose; the agent had to hand-derive a regex for each check | Give an enforced rule a copy-paste command/regex, not just a description |
| A shortcut grep covered 5 of the 7 layers the doc listed, but read as complete | Make the shortcut cover every item the doc enumerates, or name what it skips |
| "When X, do Y" with X ("changes to the public API") undefined → agent over-applied it | Define the trigger precisely; give the boundary cases (function vs enum vs comment) |
Fixture body was truncated with ..., so whole body-rule classes couldn't be graded | Give the agent the COMPLETE artifact, never a paraphrase or excerpt |
Silent-failure traps (|| fallback, 2>/dev/null) are the most dangerous:
they turn a wrong answer into a confident one. Make failures loud or document them.
5. Stop condition (loop for REAL improvements, optimally)
Stop when a literal run catches every answer-key issue, with zero guessing, no
blocking friction, and no invented steps. Not before — "ran clean" is a trap.
Not after — once it's deterministic and complete, more iterations just gold-plate.
Each iteration must fix a concrete failure a subagent actually hit; if you can't
name the failure, stop.
6. Minimize last, and guard against regressions
Only after GREEN, cut for size — and re-test after every cut, because a cut or
a "cleaner" rewrite can regress:
- Cut redundant tables, checklists, and restated conventions.
- Self-verify cheap mechanical changes locally (run the new regex/command on the
fixture) before spending a subagent.
- A proven heuristic beats theoretical completeness. In one loop a "more
correct" regex added false positives on the real fixture; the terse original had
zero. Reverting was the fix. Validate every change against the fixture; revert
anything that regresses, even if it looks smarter.
Test-Agent Prompt Template
Reuse this skeleton for every iteration (fill the bracketed parts):
Follow this skill LITERALLY and run its commands verbatim. Do NOT use prior
knowledge of [domain]. Do NOT add checks the skill doesn't instruct.
Skill under test (ONLY source of truth): /tmp/<skill>-test/SKILL-vN.md
Ignore any copy at .claude/skills/... — use only the path above.
Setup: [worktree / fixture commands]
Task: [what to audit/produce using only the skill's documented procedure]
Report back:
1. Judgment calls — did you have to guess or interpret ANYTHING? (KEY QUESTION)
2. Every issue found: exact text, responsible commit/line, which skill step
flagged it, the fix.
3. Friction log — every command that failed, leaked an error, produced wrong
output, or was ambiguous. Quote exact command + actual output. Say so
explicitly if it ran clean with zero guessing. (MOST IMPORTANT)
4. Verbatim key outputs.
5. Exact commands run, trimmed. Then clean up: [worktree remove].
Read-only. Do NOT edit the fixture or the skill.
The "KEY QUESTION" and "MOST IMPORTANT" labels matter — without them agents
report a tidy verdict and bury the friction that you actually need.
Common Mistakes
| Mistake | Why it breaks the test |
|---|
| Testing a shell-heavy skill with a no-terminal agent | Only surface issues surface; core logic untested → false pass |
| No fixture / no answer key | Can't distinguish "caught everything" from "ran clean" |
| Pointing the agent at the file you're editing or an installed copy | Stale copy silently overrides; you test the wrong text |
| Accepting the verdict, skipping the friction log | You miss the ambiguities that make the next reader fail |
| Treating "exit 0 / no errors" as success | Swallowed failures produce confident wrong answers |
| Letting the agent invent its own checks and calling it a pass | The check isn't in the skill — the next agent won't have it |
| Minimizing before it's correct, or not re-testing each cut | You shrink a broken skill, or a cut regresses silently |
| Looping forever / gold-plating after GREEN | Diminishing returns; stop when deterministic and complete |
| Using a historical/checked-out-past fixture for a skill with "now"-anchored bounds | Time-relative inputs resolve to the present → clean-but-meaningless run |
| Trusting empty output as a pass | Clean pass and silently-broken run are indistinguishable without a positive count |
| Grading only what the skill inspects, not what the task touches | Scope mismatch hides most of the answer key behind a "clean" verdict |
| Feeding the agent a truncated or paraphrased fixture | Rules that need the full artifact (body wording, trailing lines) can't be graded |
| Assuming a stated rule is enforceable without a command | Prose-only rules force the agent to invent a check; two agents check differently |
| Trusting a shortcut check that lists fewer items than the doc | It reads as complete while silently skipping layers the doc enumerated |