Run a swarm of parallel agents that each hunt for one OpenTofu-vs-pulumi-hcl runtime divergence and prove it with a failing tfcompat test. Use when the user asks to "spin up N agents", "run a swarm", or hunt for a tfcompat mismatch in parallel.
npx skills add https://github.com/pulumi/pulumi-hcl --skill swarm-tfcompat-bugs
Dispatch N agents that each independently hunt a different OpenTofu-vs-pulumi-hcl
runtime divergence and prove it with a single failing tfcompat test. The goal of a
swarm run is to surface one genuine failure and report it back to the user — not to
fix anything, not to open PRs. You (the lead) own de-confliction (every agent works a
disjoint area so no two chase the same divergence) and adjudication (deciding which
returned candidate is a real, in-direction failure worth reporting).
Each agent runs the find-tfcompat-bug skill — which is
itself entirely find-and-prove and stops at a failing test. Agents must not continue
into the fix-tfcompat-bug skill (fix, sweep, changelog,
branch, PR). Read find-tfcompat-bug first for the find-and-prove technique; this one adds
the swarm orchestration and de-confliction around it.
A swarm run is done when one agent has produced a **genuine, in-direction failing
tfcompat test** and you have confirmed it. Report back to the user:
tests/tfcompat/<l1|l2>_<name>_test.go +testdata/cases/<name>/ files the agent created, left in the working tree (uncommitted).
master,proving it fails for the right reason (real OpenTofu-vs-pulumi difference, not a harness
error).
Do not fix the divergence, write a changelog, branch, or open a PR. Stop at a proven,
reported failure. The user drives what happens next.
prevents collisions. Never spawn N agents with the same instructions. Good seams to
split along (mix and match to reach N):
funcs; cidr/IP funcs; date/time + numeric funcs; the to* type converters +
can/try/type; the sensitivity-marks seam (sensitive/nonsensitive/
issensitive); file-content/file-hash/path.* resolution.
count/for_each/dynamicmeta-arguments; lifecycle (prevent_destroy/ignore_changes/replace_triggered_by/
create_before_destroy); pre/postcondition + variable validation; preview/destroy
lifecycle; sensitivity propagation through state.
heredocs/trim markers, index/attr access, ==/!= coercion. (Note: this seam
delegates to upstream hclsyntax/cty and has historically been clean — assign it
only when you have spare agents.)
(a) every bug already fixed/shipped, and (b) seams already proven clean. Without this,
agents re-discover already-fixed bugs and report a "failure" that is actually already
handled. Re-derive it each run from git log, the open PRs (gh pr list), and the
existing tests/tfcompat/testdata/cases/ directory.
guard against overlap.
subagent_type: general-purpose andrun_in_background: true (so they run truly concurrently and notify you on
completion). Give each a unique name (e.g. hunter-<domain>). Worktree isolation is
not needed — agents only *add* new test files under tests/tfcompat/ and don't
edit shared source, so they can share the working tree. (If you do hand out worktrees,
remember the winning test files live in that worktree, not the main tree — collect them.)
confirm it is a real, in-direction failure before declaring victory (see "Vetting"
below). The first candidate that passes vetting is the deliverable — report it and wind
the swarm down.
in-direction divergence in my domain" has done its job — do not pressure it to invent
one. A fabricated or out-of-direction "failure" is worse than a clean negative.
hunt, not a steady-state swarm. You do not need to maintain headcount at N, spawn
replacements indefinitely, or monitor any PRs. Once one candidate is vetted and
reported, stop spawning and let remaining agents finish or wind them down. If all
agents return negatives, you may spawn a fresh wave over still-unclaimed domains (with
an updated exclusion list) — but if the search space is genuinely picked over, say so
rather than spawning into exhausted ground.
.claude/skills/find-tfcompat-bug/SKILL.md — find a candidatedivergence and prove it with a failing test. **Stop at the proven failure. Do NOT
continue into fix-tfcompat-bug: no fix, no changelog, no branch, no PR.**" Plus the
global CLAUDE.md rules
(research don't guess; faithfully verify against OpenTofu source/docs/probe; no hacks).
differs. pulumi-being-*more-lenient* is NOT the bug — discard it and keep hunting.
make build, then run the candidate test with the freshly builtbinaries on PATH and -count=1:
PATH="$PWD/bin:$PATH" go test ./tests/tfcompat/ -run 'Test(L1|L2)<Name>' -count=1 -v.
The test must FAIL on master, and the failure must show the genuine
OpenTofu-vs-pulumi difference (a real output diff or matching ExpectErr), not a
harness/setup error.
_test.go + testdata/cases/<name>/ files left uncommitted in the working tree,
plus the captured failure output. Honest negative if the domain is genuinely clean.
(2) the test name + paths of the files it created, (3) the captured failing-test output
proving it fails for the right reason — or an honest negative naming what it probed.
Before reporting a candidate as *the* failure, confirm:
master with freshly builtbinaries and -count=1. It must fail.
output diff or a matched ExpectErr — not a missing provider, a fixture typo, a
panic in the harness, or an unrelated build error.
errors or produces a different value. pulumi-hcl being *more lenient* than OpenTofu
is not the bug — reject it and keep looking.
re-surfaced.
A candidate that fails any check is sent back (or the agent stands down); keep adjudicating
incoming candidates until one passes all four.
general-purpose, background, unique names.before reporting it as the single deliverable.
Take pulumi/swarm-tfcompat-bugs from the repository into ~/.claude/skills for personal
use, or into .claude/skills inside a project.
The agent identifies a skill by the name field in its header. Two skills with the
same name cannot sit side by side — one of them will be ignored.