batch_run ended with a bare wait, which blocks on every background job the calling shell has, not the ones it started. Harmless for all three current callers, but a future caller that backgrounds anything of its own would have batch_run block on it or consume its status. It now records each $! and reaps exactly those PIDs. The `wait "$pid" || true` there is load-bearing: unlike a bare wait, wait <pid> returns the job's status, so without it a single failing job would abort the set -e caller at the call site -- before run-tests.sh or sync-plugin-content.sh could read their .status files and print a summary. Status semantics stay in those files, exactly as before. check-vale-style-sync.sh's glob probe discarded vale's exit code and output and decided purely on a grep, so a failed exec, an OOM-killed vale or a full TMPDIR was indistinguishable from a real glob defect -- both printed "its glob sections do not cover a path" with no evidence. A flake seen once in this probe could not be diagnosed afterwards for that reason. The probe now attaches vale's rc and output: a genuine glob defect reads "vale exited 0 ... in 0 files", a killed vale reads "vale exited 137; output: <empty>". That flake was investigated and not reproduced -- 1680 probes across three contention setups including an offline namespace, all clean -- so nothing is changed speculatively. The misattribution is worth recording: it was reported against tests/test-vale-wrap.sh, which never invokes this script; the assertion belongs to check-vale-style-sync.sh and reaches a log through a different suite. Also drops the last stale field roster from agent-author's scaffolder. Its next-steps hint enumerated "(name, description, model, body only)" -- omitting disallowedTools, and never accurate anyway, since the template marks only description and the body FILL IN. Its --help carried the inverted form, already missing six forbidden fields. Both now state the shape rule and point at field-inventory.md, and a bats case enforces all-or-nothing: name every allowlisted field or name none, since a partial roster is the shape that goes stale silently. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01X7GvKuJfy2WrdBmUttV4DT
3.0 KiB
source_keys
| source_keys |
|---|
Scripts Reference
Conventions for scripts/new-agent.sh and any future scripts in this skill.
Contract
All scripts in this skill must follow these rules:
- No interactive prompts — agents run non-interactive; blocking on TTY input hangs indefinitely. Accept all input via positional arguments, flags, or environment variables.
- Structured output — file paths and status messages to stderr; nothing to stdout unless a downstream tool needs to consume it.
- Idempotent — "create if not exists" per file. The scaffold script skips any file that already exists; agents may safely re-run it.
- Meaningful exit codes —
0success,1invalid arguments or precondition failure. Document in--help. - Self-contained — no external package installs at runtime. The script uses only bash builtins and POSIX tools (
sed,mkdir,cat). - No restated field rosters — no script output, in
--helpor in next-steps guidance, enumerates permitted, forbidden, or required frontmatter fields. Point at theapm-agent-allowlistsection ofagent-audit'sreferences/field-inventory.md, whichagent-audit'svalidate.shreads from there as data. A roster copied into script output goes stale one step further out than the list itself: the next-steps hint(name, description, model, body only)kept printing after ADR-0016's 2026-08-14 amendment addeddisallowedToolsto the permitted set.tests/new-agent.batsenforces this for the plugin/APM branch — naming some allowlisted fields but not all is a failure.
Template variables
The scaffold script uses sed "s/AGENT_NAME/$AGENT_NAME/g" to substitute the agent name into templates. Template files must use AGENT_NAME (all caps, no delimiters) as the substitution token.
Do not add additional substitution tokens unless you update both the template files and the script in the same edit pass.
File placement
The script creates files at paths determined by scope detection (plugin/APM / project / user). Scope is resolved by walking up from the root directory: a type:-bearing apm.yml at or above the root marks the package root (plugin/APM scope, single file); an apm.yml without a type: field is a marketplace-only manifest and is skipped, the walk continues upward. If no such apm.yml is found, the root resolving to exactly $HOME is user scope; anything else is project scope. If scope detection logic changes, update the new-agent.sh usage comment and SKILL.md Step 1 scope detection description in the same pass.
Error messages
On failure, state: what went wrong, what was expected, what to try. Example:
Error: agent-name must use lowercase letters, numbers, and hyphens only.
No leading, trailing, or consecutive hyphens.
Received: 'My_Agent'
Vague errors leave agents unable to self-correct.
--help output
Keep --help concise — it may enter the agent's context window. Include: usage line, argument descriptions with scope detection table, exit codes. Omit prose explanations.