Repository navigation
v4.10.0 — cap heavy test suites across autopilot batches
Autopilot batches running side by side on one machine can now cap how many heavy test suites run at once across all of them, with no session acting as a dispatcher and no project named in the plugin. A new ## Autopilot field, Suite limit:, names N and the commands; each listed command then takes a slot in a lock the whole machine shares before it runs, and the rails hook denies a listed command run without the wrapper — in a worker's own calls and its subagents' alike.
Compatibility. No new agent, command, CONTEXT key, or guard script, and every skill keeps version: 3.0.0. The changes that matter to a user:
- A new
## Autopilotfield,Suite limit:—repomode only. Without it nothing changes: there is no lock, the preamble omits the line, and the settings line and reviewer report readsuite limit none/Suite slots: none. Inpluginmode the field is a settings stop. - A new script copied per batch,
_prompts/<batch>-suite-slots.sh, and a new log,_logs/<batch>-suite-slots.log. - The drivers export four more variables to every worker (
KENSPC_AUTOPILOT_SUITE_LIMIT,_COMMANDS,_WRAPPER,_LOG). A stubclaudeof your own that is meant to pass the driver's--self-testnow echoes six variables, not two. - A new stop condition, 12: a suite-slot holder aged 60 minutes or more.
- Guard counts are unchanged:
guards run: 13,self-tests run: 12.check-autopilot-scripts.sh --self-testnow takes about two minutes, up from about five seconds.
What changed
The Suite limit: field
- A positive integer N with one sub-bullet per command prefix, each one code span (
- `dotnet test`). Every run of a listed command takes a slot, whatever its arguments, and a caller enters only while fewer than its own N slots are held, so batches with different limits share one pool. Why: more than about two runs of one integration suite at once exhausted a machine's local ports, and the tests then failed on connection errors that read as findings; a batch'sRun facts:bound that batch alone.
The suite-slot wrapper, skills/autopilot/scripts/suite-slots.sh
suite-slots.sh run [--limit <n>] [--wait <seconds>] -- <command> [<arg>…]. Under amkdirmutex it counts the live holder files in/tmp/kenspc-suite-slots, reclaims holders whose wrapper and command pids are both gone (or reused, judged by their start time), and reclaims a dead or ownerless mutex.- Exits with the command's status; 75 with a
suite-slots: busy …line naming each holder when no slot frees within--wait(90 s by default, under the Bash tool's default timeout); 2 on a usage or lock-directory error, or whenpsgives no start time. A call nested inside a wrapped command runs at once. - Bash 3.2, no
flock. The holder-file layout is shared by every plugin version on the machine, so a change to it is a breaking change. Two accepted gaps are named in its header: grandchildren that ignore the forwarded SIGTERM, and a rare double reclaim of a dead mutex that can let N + 1 holders run.
The drivers (run.sh, run.ps1)
- Three new inputs,
AUTOPILOT_SUITE_LIMIT,AUTOPILOT_SUITE_COMMANDS,AUTOPILOT_SUITE_WRAPPER(refused unless absolute), exported on a fresh launch and on a resume, each overwriting the caller's value as the marker does.
The rails hook, check (f)
- With
KENSPC_AUTOPILOT_SUITE_COMMANDSset, a marked worker's Bash command that runs a listed command at a command position is denied, with the routebash <wrapper> run -- <the command>. The prefix's first word is compared by base name, so./scripts/test.shand/usr/local/share/dotnet/dotnet testare caught. Known misses: a listed command reached through a script,bash -c,make,eval, a variable, an alias, ortimeout/nice.
The autopilot skill
- Every launch sets the three inputs. Preamble § 3 names the lock directory as a write location; § 6 gains the
Suite limit:line (run through the wrapper, retry on exit 75, never run the command bare, size the Bash timeout for the wait, carry the line into every dispatch, ask the main session after 30 minutes of busy returns). - The repo-mode acceptance and the main session's corrected-case evidence runs go through the wrapper. The main session answers a long-wait question
wait onwhile every holder is younger than 60 minutes; a holder aged 60 minutes or more is stop condition 12. - The reviewer report gains a
Suite slots:line.
Guards
check-autopilot-scripts.shcovers the wrapper with thirteen fixtures under/bin/bashand four more mutants (eleven in all).check-autopilot-rails-hook.shgains adeny-suiteexpectation, its fixtures, and a ninth hook mutant.
Upgrading
claude plugin marketplace update kenspc-claude-plugin
claude plugin update kenspc@kenspc-claude-pluginThen start a new session. A running batch keeps the plugin text it started with.
Verification
The pre-flight passed on the release tree: the effort-override diff, two claude plugin validate --strict runs, guards run: 13, and self-tests run: 12. The implementation went through /kenspc-task-implement and its review on the installed 4.9.0 agents; the review's 21 findings (one HIGH) left 16 fixed and 3 deferred to the roadmap, and the one stale sentence its verifier found was corrected before the release. The smoke covered what changed, the autopilot alone: both drivers' --self-test passed and each turned red as the release checklist's row 11 expects; a live headless session (Claude Code 2.1.301, plugin loaded from this release) showed the rails hook's new check denying a listed command, and three concurrent wrappers at limit 2 showed the third waiting its turn (docs/dry-runs/suite-slots-live.md). No whole autopilot batch (row 11's headless run) was made for this release. Not checked: native Windows, and Linux machines whose clock is stepped (roadmap).