本文へ移動
cccskills
無料GitHub で公開

swarming-failing-tests

Runs a long swarm of hundreds to thousands of cheap headless coding workers that drive a large failing-test backlog to green. Failures are clustered by signature, each worker fixes one cluster in its own git worktree, a serial no-regression merge gate lands the fixes, the loop resumes across restarts for hours, and it federates across sibling sessions over git branches when one container's CPU is not enough. Use for "fix these thousands of failing tests with a Haiku swarm", "drive the test suite to green with hundreds of agents", "build this compiler or interpreter against a conformance suite", "launch, relaunch or check in on the swarm loop", "the swarm is stuck, idle or rejecting everything", "parallel agents fixing tests keep hitting merge conflicts and regressions", "add sibling containers to the swarm", or "compare models on the tail the swarm could not fix". Ships the harness, a per-project TOML config, a fake-worker selftest, check-in signals and the 2026-10-12 haiku-cc failure catalogue.

インストール方法を見る

含まれるファイル(26)

  • SKILL.md20.0 KB
  • assets/haiku-cc.toml5.2 KB
  • assets/sibling-brief.md3.9 KB
  • assets/swarm.example.toml3.3 KB
  • assets/worker_prompt.template.md3.7 KB
  • CHANGELOG.md2.0 KB
  • references/config.md7.3 KB
  • references/project-setup.md5.0 KB
  • references/run-2026-10-12.md13.6 KB
  • references/scaling-out.md8.0 KB
  • scripts/sibling_setup.sh3.8 KB
  • scripts/swarm.py9.1 KB
  • scripts/swarmkit/__init__.py66 B
  • scripts/swarmkit/common.py9.4 KB
  • scripts/swarmkit/compare.py13.6 KB
  • scripts/swarmkit/config.py9.2 KB
  • scripts/swarmkit/doctor.py4.9 KB
  • scripts/swarmkit/fake_worker.py6.0 KB
  • scripts/swarmkit/federation.py18.8 KB
  • scripts/swarmkit/merge.py27.6 KB
  • scripts/swarmkit/run.py39.5 KB
  • scripts/swarmkit/selftest.py21.6 KB
  • scripts/swarmkit/stats.py6.4 KB
  • scripts/swarmkit/testrun.py9.0 KB
  • scripts/swarmkit/worker_result.schema.json385 B
  • scripts/swarmkit/workqueue.py6.7 KB

SKILL.md(原文)

インストールする前に、エージェントに与えられる指示の中身を確認できます。

Swarming failing tests

A loop that turns a test suite's failures into merged fixes, unattended, for hours:

known.json --cluster by signature--> work items --one headless worker each, own worktree-->
  result JSON --serial gate: apply on main, compat check, run smoke + targets + sample,
  zero regressions, >=1 target flips--> fast-forward main --> re-check the whole cluster --> repeat

Every mechanism in it fixed a failure that cost hours on 2026-10-12, when Haiku 5.5 workers built hcc (a C compiler in Python) against ~42K tests: 1,051 hub workers, 464 merges, $24.88 of worker spend by 18:30Z. The catalogue of those failures, each with its signal and where it is handled, is references/run-2026-10-12.md.

SK=/mnt/skills/user/swarming-failing-tests       # or <claude-skills clone>/swarming-failing-tests
SWARM="python3 $SK/scripts/swarm.py"             # every command below; --root defaults to the git toplevel

When to use it, and when not

Use it when all hold: a test command can report every test's status as JSON; there are hundreds or more failing tests; a fix can be checked by re-running tests; and the work will run for hours, longer than anyone watches.

situationuse instead
fewer than ten tasks, e.g. setup, a suite builder, a refactorthe Agent tool directly (on 2026-10-12, 3 setup agents were run through claude -p for no gain)
a one-off fan-out of independent tasks (judges, extractors, per-file reviews) with no mergingdispatching-subagents
which model or effort a worker gets, and how to escalateagent-routing (this skill's measured answer for test-fix work is in "Which model" below)
a fixed multi-step pipeline with no model in the loopflowing
parallel Claude calls from claude.ai chatorchestrating-chat-agents (orchestrating-agents is its deprecated name)
a handful of failing testsfix them yourself, or one Agent-tool worker per cluster
no machine-readable test output yetwrite the runner first ("Project setup"), then come back

Abandon the run when the signals say the harness, not the workers, is the problem: SAME FAILURE, DENIALS or GATE REJECTS ALL twice in a row after a fix. Stop the loop ($SWARM stop), fix the cause, unpark if the fix invalidates earlier attempts, relaunch. Spending through a harness bug is how the abandoned tail was made.

Preflight checklist

Do every item before the first real launch. Each one cost hours when missed.

  1. Failing-test supply first. Haiku drained haiku-cc's conformance suites in 70 minutes and the queue sat empty. Have thousands of failing tests, a tier of real programs (one build failure blocks hundreds of tests), and a suite builder that works in its own worktree and commits to main. The loop baselines new suites within two minutes. Details: references/project-setup.md.
  2. Plan containers now if workers do real compute. When each worker compiles and runs tests, CPU caps the swarm whatever the launch mechanism: 4 vCPU held haiku-cc at load 10-22 for eight hours before siblings were added. Decide the partition and the number of sibling sessions at preflight: references/scaling-out.md.
  3. Disk. df -h /tmp <root>/.. needs 10 GB or more free. Worker scratch reached 14 GB and stale worktrees 5.6 GB on 2026-10-12. The loop deletes scratch on reap, sweeps stale worktrees at start, and stops launching below run.min_free_gb.
  4. The 2-hour background cap. A background Bash job dies at 2 hours, and at 30 minutes if you omit timeout. Launch with timeout: 7200000 and --max-minutes 110; the loop exits cleanly, workers keep running, and the next launch adopts them.
  5. Coordinator models. Every session you create inherits your model unless you pass model. Idle Opus siblings cost about $1.40 per check-in. Give siblings and experiment sessions a Sonnet or Haiku model.
  6. Push namespace. Federation pushes <prefix>main/state/cand/*. A push-policy guard (claude-workspace scripts/guards.py _ALLOWED_PREFIXES) must allow the prefix.
  7. Gitignore build artefacts and pin the language version the fast interpreter supports; set gate.compat_command to enforce the pin.

Setup

  1. Config. Copy assets/swarm.example.toml to <root>/swarm.toml and fill tests.command, paths.code/allowed/forbidden, queue.ladder, gate.always_suites/cheap_suites, gate.compat_command, worker.system_prompt, worker.repro_command, and worker.deny for whatever the workers must never run (network fetches when the answer is on the internet). Every key: references/config.md. A complete working config for haiku-cc is assets/haiku-cc.toml.
  2. Worker prompt. Start from assets/worker_prompt.template.md. Keep the result-JSON contract, "no git commits", "scratch outside the repo", "add a file, don't edit a shared list", and "revert and report failed with notes".
  3. Check the runner's output: $SWARM doctor --run-suite <a suite>. It exits 1 on a contract violation and prints WARN lines for a stage label on over 90% of failures, truncated located reasons, or signatures that do not cluster. Fix the runner before launch: on 2026-10-12 a broken stage regex labelled every failure parse. A stage that holds nearly every failure by design (decompilation: all missing at the start, nearly all match later) goes in tests.one_stage_ok.
  4. Selftest the harness (no model calls, about 3 minutes):
    $SWARM selftest; echo "selftest exit=$?"
    
    Exit 0 means every check passed. Read the exit code, never a tail of the output.
  5. Dry look at the queue: $SWARM refresh (first baseline), then $SWARM queue --top 20. The top items should be the clusters you would hand out first. If they are not, fix queue.ladder now.

Launch

One Bash call, run_in_background: true, timeout: 7200000. Run the loop itself, not a waiter, not nohup, and not inside a subagent (a subagent's background job dies with the subagent):

cd <root> && $SWARM run --concurrency 24 --max-usd 50 --max-minutes 110 \
    --batch 6 --sample 80 >> runs/swarm.log 2>&1

In the same turn: ps aux | grep '[s]warm.py run' shows it, and tail -5 runs/swarm.log shows LAUNCH lines or a first full refresh. Preflight failures print preflight: lines and exit 2; fix them rather than passing --force. Then end the turn and arm the first check-in: send_later(delay_minutes=50, initiation="own_followup", message="swarm check-in: ...").

Useful flags: --only 'suiteA/*,suiteB/*' (dispatch only these), --suites (what this node's gate runs), --model, --effort, --max-workers N, --no-launch.

Check-in protocol

Every ~50 minutes, by a self-re-arming send_later. Never loop on sleep.

tail -40 runs/swarm.log; $SWARM status; df -h /tmp <root>/..

Read the SIGNALS: block at the end of status and act:

signalmeaningact
none, loop alivehealthyre-arm the check-in
loop not running / DEAD (stale pid file)--max-minutes exit, the 2-hour cap, or a crashread the log tail for a traceback; relaunch the same command
REFRESHINGa refresh owns the gate tree; merging is pausedwait; a full refresh past an hour means raise gate.full_every, a quick one past ~10 min means trim gate.quick_suites
QUICK REGRESSIONSthe last quick refresh found regressions it could not revertread the log's bisect/revert lines; revert the culprit by hand now, while it is at most gate.quick_every merges back
GATE BACKLOGfinished workers outrun the gateraise --batch, lower --sample, or lower --concurrency so the gate gets CPU (haiku-cc: ~15 to ~41 merges/h)
CPU-BOUND (log: THROTTLE)load above the throttle with work waitingscale out: references/scaling-out.md
SUPPLY LOWunder 10 dispatchable itemsstart or speed up a suite builder now
PARTITION EXHAUSTED (log: IDLE)nothing dispatchable on this nodeadd supply, re-partition, unpark after a harness fix, or stand the node down
SAME FAILUREmost recent workers fail with one reasona prompt, auth or permission bug: stop, fix, relaunch
DENIALSworkers hit permission denialscheck worker.allow against what the prompt tells them to do
GATE REJECTS ALLnothing merged in the last 15 gatedread .swarm/rejected/; one test named in all = stale known state or a cross-partition regression: refresh --only-suites <suite>
DISK LOW (log: DISK)free space under 2x min_free_gbfind the hog (du -sh /tmp/* <wt_root>/*); the loop already stopped launching
UNBASELINED SUITESsuite dirs the baseline never rannormally clears within 2 minutes; else refresh --only-suites
ONE STAGEone stage label on over 90% of failuresthe runner's stage detection is broken: doctor, fix the runner

Also read the plain lines: quick refresh: (cadence, merges since the last, and its last result: regressions found, reverted, left), conflict hot spots (a shared file workers keep colliding on: make it self-registering, see project-setup), top rejection/failure reasons, last merge ... ago, and known now pass counts.

Scaling out

When one container's CPU is the cap, add sibling sessions, each owning a partition of the suites, joined through branches of one git repo with a hub that owns main and re-gates every candidate. The full procedure (when, partitioning, transport and its guard prerequisites, the sibling brief, create_session parameters, the cross-partition gate rule, stand-down and ledger collection, isolated experiment sessions) is references/scaling-out.md. Brief template: assets/sibling-brief.md. Bootstrap script: scripts/sibling_setup.sh.

Which model

Default: Haiku plus the harness's retry ladder. Treat Sonnet as an optional rung for a cluster that has failed the whole Haiku ladder, and never escalate a tail the harness created.

Measured 2026-10-12 on haiku-cc over three escalation runs (40, 4 and 10 clusters after base checks; same prompt, budget and base; each patch graded in isolation):

armsolve rate$ per solve
Haiku 5.5, default effort76/80, 8/8, 19/20 runs$0.011-0.012
Haiku 5.5, high effort8/8, 20/20 (runs 2-3)$0.018-0.023
Sonnet 5.5, medium80/80, 8/8, 20/20$0.075-0.087 (about 7x Haiku)

Over 54 clusters, cold Sonnet solved 2 that cold Haiku did not (run 1, c06 and c16). Haiku feature-mode workers in the live swarm fixed both later for $0.054 and $0.022: the retry path (notes from failed attempts, feature budget, effort ladder) closed both gaps. Run 3 was the tail the swarm had abandoned; Haiku solved it cold once the harness bugs that had parked it were fixed. The harness made that tail, not a Haiku capability limit. Scope: one compiler workload, small n. Re-measure on a new workload with $SWARM compare select|run|report, in its own container (compare selects from the abandoned tail at HEAD and base-checks the selection, because random failing clusters saturate and known state goes stale).

The ladder the harness runs per signature: attempt 1 at the configured effort; after a real failure (a lost merge race is not one) at high; after feature_after failures a single feature-mode worker with a bigger budget; a conflicted fix comes back as a rebase task. Rates and prices change: check agent-routing before reusing these numbers.

Partial credit

When a test can get measurably closer without passing (a byte-match fraction, a count of matching outputs) and failures depend on each other, a strict flip gate throws work away. On 2026-10-13 (swarm-decomp, matching decompilation) 125 partial workers, 39% of spend, were discarded; 103 of their notes named a callee another cluster had not written yet. Have the runner emit the measure per test (frac), set gate.partial_credit = "frac", and refresh. The gate then merges a candidate that raises the summed measure of its targets by gate.partial_min_gain with zero regressions, and the next worker starts from that code. Leave it off for pass/fail-only suites: there it only merges noise.

Earned exceptions

rulebanned whenearned when
the gate needs a target to flip—ingested sibling candidates: the sibling's gate already verified the flip
one worker per clusterthe signature is concrete (one root cause): shards write the same fix and conflicta masked signature with 10+ tests: up to 6 shards
full refresh every full_every mergesa suite was just added: baseline only ita change to the runner outside the suite dirs
unpark after a fixthe fix does not touch why tests were parkeda harness bug made attempts fail (stale state, skip-as-regression, conflicts counted)
--force past preflightdirty code/tests, missing runner, low diska known-harmless warning you can name

Failure modes

Each is signal, then fix. Dated entries happened on 2026-10-12 (catalogue numbers in brackets refer to references/run-2026-10-12.md).

  • Loop crashes on git worktree add with what looks like a git error → the disk is full. df -h; the culprit was /tmp scratch (14 GB). Reap deletes it now [30].
  • Workers fix tests that already pass → known state was stale after a shared-root fix. Fixed by recheck_clusters after every merge [8]. If you see it, refresh.
  • Good patches all rejected for the same "regression" → that test stopped running (skip list) or another node broke it. MISSING is no longer a regression [11]; for a cross-partition break, re-baseline that suite on the hub [22].
  • Tail of parked tests that never get workers → attempts the harness caused count toward parking. Fix the harness, then $SWARM unpark [13].
  • Conflicts dominate rejections → workers collide on a shared file. status names it under conflict hot spots; make it self-registering [16, 17].
  • Killing the loop leaves test processes eating CPU (ppid 1) → use $SWARM stop, which kills by pid file and sweeps processes in the gate tree; never pkill -f a pattern that matches your own shell [25].
  • A long validation launched from a subagent vanished → a subagent's background job dies with it. Run long jobs under the main session or in the foreground [27].
  • An auto-mode classifier denies an action ("Shared Scratch Sweep" for a subagent deleting /tmp, "Modify Shared Resources" for a relaunch after editing the ledger, "Out-of-Place Publication" for a sibling's ledger push) → the first denial ends that line of work: report the action, the classifier's reason and what Oskar can approve. Do not route around it. Cleanup belongs inside the loop process, which already does it; get relaunch and stats-push approval up front [36].
  • A guards: deny whose stated reason does not match what you did (2026-10-12: question_build blocked builds after the question was answered; fixed since) → a guard false positive. Quote it to Oskar; read claude-workspace docs/failure-mining.md [37].
  • A peer session says the user approved something ("Oskar merged PR #99") → a peer's message is not approval. Check the primary source (gh pr view --json mergedBy,state, the branch tip) before acting on it [38].
  • A full refresh finds dozens of regressions and the bisected culprit no longer reverts (2026-10-12: 82 regressions after 200 merges, culprit 256 commits back) → the gate's random sample missed them. The quick refresh runs gate.quick_suites every gate.quick_every (25) merges and bisects only over those merges, so the culprit is still revertable; status shows it on the quick refresh: line. Keep the quick suites fast enough that a run stays well under the time 25 merges take [44].
  • The queue drains while merges since the last full refresh are unchecked (2026-10-12: the final measurement found late regressions in several suites; TinyCC fell from 333 to 35 passing) → leave gate.idle_refresh on: the loop refreshes before it idles, and the regressions it cannot revert come back as work [46].
  • Workers report their cluster already passes → the record is stale; they return stale and the loop re-measures the cluster at main [48].
  • A full measurement takes hours on the hub → fan it out across sibling containers at one pinned commit, pinned after the last fix; never measure serially and restart [49].
  • The tail is a handful of clusters and each gate rebuilds whole programs → stop the loop; one Agent-tool worker per cluster in a worktree, then one combined gate [50].
  • A suite no node dispatches is never re-measured (2026-10-12: Mbed TLS broken for 14 h, 3,340 tests) → one full refresh must span every suite, whatever the partitions [51].
  • The project's unit selftests break mid-run (2026-10-12: 8 of 710) → the gate runs only the suites; put the fast unit tests in gate.compat_command [47].
  • Gate throughput flat while workers finish → GATE BACKLOG; tune batch and sample, keep CPU headroom for the gate [18].
  • A refactor landed mid-run conflicts with every in-flight fix → land structural changes before launch, or stop, land, relaunch [20].

Verification

  • Harness: $SWARM selftest; echo "selftest exit=$?" must print 0 failures and exit=0. It runs every gate path on a fake project: merge, forbidden edit, compat rejection, no-op, regression, conflict pair, doc conflict, non-UTF-8 diff, concrete signature not sharded, cluster recheck, skipped-not-regressed, effort ladder and feature mode, park and unpark, new-suite baseline, stale-worktree sweep, stop, the federation round trip (publish, seed, ingest, rebase, conflict-as-rebase, ledger export), and a quick refresh that reverts a regression the gate sample missed. On 2026-10-12, selftest | tail && git commit committed with 3 failures because the pipe hid the exit code. Gate commits on the real exit code.
  • A run: $SWARM status pass counts in known now rise between check-ins, and git log --format=%s -5 on main shows swarm commits with Swarm-Task: trailers.
  • A bad success: merges climbing while known now stays flat (fixes that flip only their own targets via special-casing), or no target test flipped dominating rejections (stale state). Sample three merged diffs before reporting progress.
  • Reports: state an outcome only from a check run after the last edit or relaunch: the status output, the selftest exit code, the merge count from the ledger. Not from memory of an earlier check.
  • Stats for a write-up: $SWARM stats --out runs/stats (metrics.json, report.md, and charts when matplotlib is importable). Annotate harness changes as they happen with $SWARM event "conflicts become rebase tasks"; the merge-rate curve cannot be read without them.

レビュー

まだレビューはありません。使ってみた感想をお寄せください。

同じリポジトリのスキル

概要と使いどころ

GitHub repository access in containerized environments using REST API and credential detection. Use when git clone fails, or when accessing private repos/writing files via API.

日本語の概要は準備中です。原文の説明を表示しています。

oaustegard/claude-skills1512026年10月13日 更新

Decide which model, effort level, and cascade shape each subagent gets, and how to keep improvement loops safe (evaluator-as-selector, stop on regression). Routes on measured cost-per-completed-task rather than per-token price, because a tier's token count varies more by task shape than price varies across tiers. Covers per-model effort semantics, the concision lever, cascade preconditions, context handoff, and watching a subagent fan-out live. Use when choosing a subagent's model or effort, when choosing how to escalate a failed attempt, or when asked which model or effort a task should get. Grounded in a 2026-07 calibration, a 2026-08 coding-cost study, a 2026-09 seeded-bug repair battery, a 2026-10 Haiku 5.5 ladder priced per spawn, and a 2026-10 retry-versus-escalation ladder on 295 SWE-bench Verified tasks; Managed Agents API specifics are operational, not calibrated.

日本語の概要は準備中です。原文の説明を表示しています。

oaustegard/claude-skills1512026年10月13日 更新

Securely manages API credentials for multiple providers (Anthropic Claude, Google Gemini, GitHub). Use when skills need to access stored API keys for external service invocations.

日本語の概要は準備中です。原文の説明を表示しています。

oaustegard/claude-skills1512026年10月13日 更新

Guidance for asking clarifying questions when user requests are ambiguous, have multiple valid approaches, or require critical decisions. Use when implementation choices exist that could significantly affect outcomes.

日本語の概要は準備中です。原文の説明を表示しています。

oaustegard/claude-skills1512026年10月13日 更新

Pre-change blast-radius report for a symbol or file. Walks tree-sitting references, augments with a plain-text scan over non-parsed files (configs, plain docs), and clusters affected sites by feature (`_FEATURES.md`) or top-level package. Use when about to refactor, rename, or delete something in a repo you don't own — "what breaks if I change `validateUser`", "who calls this", "is this safe to remove", "where is this used", "blast radius", "impact analysis". This is the CONVERGENT pre-change risk skill — for "what is this repo?" use exploring-codebases; for "where is X?" use searching-codebases.

日本語の概要は準備中です。原文の説明を表示しています。

oaustegard/claude-skills1512026年10月13日 更新

Read Bluesky/ATProto without depending on Bluesky's AppView — interactions on a user's posts, thread replies, any repo's records, network-wide backlinks across every lexicon, an account's handle and PDS history, which collections are active network-wide, and layer-by-layer outage diagnosis. Use when bsky.app or the AppView is down or slow, when a Bluesky read returns timeouts or 5xx, when asked who liked/replied/quoted/reposted something, when pulling live Bluesky context cheaply, when reading records straight from a PDS, when asked who references a record or account anywhere on the network, whether an account has changed handle or migrated servers, or which lexicons and non-Bluesky apps are active on atproto. Complements browsing-bluesky, which routes everything through the AppView and fails when it does.

日本語の概要は準備中です。原文の説明を表示しています。

oaustegard/claude-skills1512026年10月13日 更新

oaustegard のスキルをすべて見る

このスキルの問題を報告する