Fan out parallel fresh-context workers, drain them, and return one PASS/ISSUES/BLOCKED report. Use when work splits into independent slices, when racing several attempts at one brief, or when another skill asks for a fan-out.
Install
npx skillscat add noahdgrant/nightshift/ns-swarm Install via the SkillsCat registry.
Swarm
Fan out N workers. They cover separate slices or race the same brief. The parent waits, aggregates, and returns one report.
A worker is a fresh-context agent. It sees only its brief and the repo, never the parent's chat.
1. Frame
- State the done predicate and the report the swarm must return.
- Choose the shape:
- Partition: each worker gets one slice (a reviewer axis, a feature, a file group). Coverage is complete only when every slice has a result.
- Race: N workers get identical briefs. Declare the selection rule before spawning:
first pass(take the first PASS),rank all(order every result by evidence), orbest-of(pick one, say why). - A mix of both is fine. Name which workers are slices and which are race arms.
- Set N from the caller or derive it from the shape. N is total workers, not a concurrency limit.
- Name each worker's role for
ns ask(the caller supplies it, e.g.review.security,verify). Roles map to a harness and model in the user's config. This skill never names a model. - Give every worker that writes its own worktree (see "Writers" below). Read-only workers share the parent's worktree.
- When workers verify or measure commits, the brief names the exact SHAs. A measurement brief also names the method: sample count, what one sample is, order.
Done when the shape, N, roles, selection rule (for a race) and any SHAs are written down.
2. Write the briefs
Every brief stands alone. A reader with no chat history can act on it. Each one holds:
- the goal and the done predicate
- the exact slice or race arm, and what is out of scope
- the input files to read, by path
- how to verify
- the report format below
Write each brief to a file: <artifacts>/swarm/<run>/<worker>.brief.md, where <artifacts> is the caller's .ns/<unit-id>/ or a temp dir when there is no unit. Files keep the brief out of shell quoting, and the parent can audit what each worker saw.
Worker report format
VERDICT: PASS | ISSUES | BLOCKED
SCOPE: <slice or arm>
SHAS: <commits checked, when the brief named any>
METHOD: <how it was checked>
- <file:line> <one-line issue> | evidence: <command + output, or quoted code>PASS: the slice meets the done predicate, with the evidence that shows it.ISSUES: lists every issue the worker can prove, not only the first, each with evidence.BLOCKED: names what the worker could not get (hardware, credentials, a missing file).
3. Fan out
Pick the first launch mode the harness supports, and record which one ran:
- Subagents. Spawn all N in one message, in the background. Pass each its brief file.
ns ask. Run one headless process per worker, all at once. Read-only workers use the default mode. Workers that edit files or run commands (verify, build) add--write --cwd <their worktree>:
In# workers.tsv: one "<worker> <role>" pair per line while read -r w role; do { ns ask --role "$role" --prompt-file "$RUN/$w.brief.md" \ > "$RUN/$w.result.md" 2> "$RUN/$w.err"; echo $? > "$RUN/$w.exit"; } & done < "$RUN/workers.tsv" wait<worker>.exit, 3 means the role is not configured, 4 means its harness is missing. 5 means the harness has no write mode configured. Retry that worker under the caller's fallback role if it named one, otherwise run it inline.- Inline. No subagents and no
ns: run each brief yourself, one at a time, clearing your working notes between briefs. Write "ran inline, sequentially, not in fresh contexts" at the top of the report.
If a worker drops out, carry on with the rest and record the dropout.
Writers
A worker that edits files gets its own worktree and branch, so writers never share a working tree:
ns worktree new <unit-id>--<worker> --base ns/<unit-id>
# without ns:
git worktree add -b ns/<unit-id>--<worker> ../<repo>.worktrees/<unit-id>--<worker> ns/<unit-id>The brief names that path. The parent merges or cherry-picks the winning or accepted branches afterwards, then removes the worktrees with ns worktree remove or git worktree remove.
4. Aggregate
Read every result file or subagent reply.
- A result with no
VERDICTline, or one missing the SHAs and method its brief named, is malformed. Respawn that worker once. After a second miss, record a gap. - A missing result is a gap. A gap never counts as a pass.
- Partition: the swarm passes only when every slice reports
PASS. - Race: apply the selection rule declared in step 1, unchanged.
- Merge duplicate issues across workers and note which workers raised each one.
Done when every worker has a result, a dropout note, or a gap entry.
5. Report
Return one report. Summarise worker output in one-line issues and keep raw dumps in the result files, linked by path.
Launch mode: subagents | ns ask | inline (sequential)
Shape: partition | race (rule: first pass | rank all | best-of) | mixed
| Worker | Role | Scope | Verdict | Issues |
|---|---|---|---|---|
Issues
- <file:line> <one line> (workers: a, c) | evidence: <short>
Gaps and dropouts
- <worker>: <why>
Overall: PASS | ISSUES | BLOCKEDOverall is PASS only when every required slice passed and there are no gaps. Any gap or BLOCKED slice makes it BLOCKED; any proven issue makes it ISSUES.