Add agent-swarm skill

This commit is contained in:
Emil Shanaty
2026-10-27 18:50:15 +03:00
commit 54a5c849d4
14 changed files with 1285 additions and 0 deletions
+185
View File
@@ -0,0 +1,185 @@
# Workflow orchestration
The `workflow` tool runs one JavaScript body with top-level `await` and returns a JSON value. It is the only way to fan out dozens of agents without flooding the lead's context.
## Call shape
```json
{
"meta": {"name": "swarm-wave-1", "description": "Build wave", "phases": [{"title": "wave 1"}]},
"script": "<script body>",
"args": {
"wave": 1,
"tasks": [{"id": "T01", "write": ["src/a.ts"]}],
"schema": "<paste the contents of assets/report.schema.json>",
"concurrency": 6
},
"run_in_background": false
}
```
- `meta.phases` is optional; use one phase per wave and `phase()` inside the script.
- `args` is data, never evaluated. The script cannot read files; pass paths and small structured facts.
- Pass `args.schema` as the parsed schema object, not a path or a string.
- Pass `args.concurrency` explicitly. It must be ≤ the free active-child slots; do not rely on the engine to queue.
- The tool blocks until every child settles. Use `run_in_background` for long waves; poll with `job_output`, cancel with `job_kill`.
## agent()
`agent(prompt, opts)` starts one child and resolves with:
- its final text when no schema is passed;
- a validated object when `schema` is passed;
- `null` when the child fails, returns a non-completed stop reason, or produces no structured value.
Options: `label`, `phase`, `schema`, `provider`, `model`. Unknown or deferred options kill the script.
`agent()` can also **throw** when the runtime cannot start a child (for example `active child limit reached`). That throw is not a `null`; if it happens inside `parallel`, it can abort the whole run. Wrap each `agent()` call in `try/catch` inside the batched runner and record a scheduling failure for that task instead of losing the batch.
The child is disposed after the call; there is no follow-up message inside a workflow. Design tasks as one-shot packets.
## parallel vs pipeline
- `parallel([thunks])` — start every thunk together; await all. It is **not a queue**: it does not limit concurrency. Use it only for a chunk whose size fits the free slots.
- `pipeline(items, ...stages)` — per-item chain with no barrier. Use only when each item must pass through stages without waiting for the wave (for example, extract → summarize per source). It multiplies agent count by the number of stages.
- For more items than slots, run batches sequentially and use `parallel` inside each batch (`assets/wave.workflow.js`).
Do not use `parallel` for dependent tasks; use separate waves and let the lead inspect results.
## Schema subset
The engine validates a strict subset. Keep schemas boring:
- Object root (`"type": "object"`).
- `properties`, `required` (names must exist in `properties`), `additionalProperties` boolean.
- Arrays with `items`.
- Strings/numbers/integers/booleans/null, `enum` of scalars, `const`.
- `oneOf` only with exactly-one semantics and no sibling keywords.
- No `minItems`, `maxLength`, `pattern`, `format`, `$ref`, `anyOf`, `allOf`.
A schema miss returns `null`. Verifiers should use the **minimal** schema in `assets/verdict.schema.json`:
`{task_id, verdict, summary, review_file}`. Put the detailed findings in `.swarm/reviews/Vxx.md`; do not make a long findings array required in the workflow schema. If a schema miss happens, read the review file on disk before deciding that the verification failed, then retry with the smaller schema.
## Concurrency and caps
- **Do not hardcode a concurrency default.** The active-child cap is host/policy-specific. Some runtimes allow 14; this environment rejected 8 workers when other children were active. Treat the cap as runtime data.
- **Preflight:** read the runtime diagnostics or `list_agents`; record `slot_cap` and `active_at_dispatch` in `.swarm/state.json`. Recon, verifiers, integrators and any other active children all count.
- **Batch size:** `min(8, slot_cap - active_at_dispatch - 1)`, at least 2. If you do not know the cap, use 6. Leave at least one free slot for retries.
- Each child holds a slot for its whole life. A `parallel` call starts every thunk immediately; if the batch exceeds free slots, the spawns throw.
- Slots are FIFO; a slow task delays later ones. Keep tasks in a batch similar in size.
- `maxTotalAgents`: 1000 per run. `maxItemsPerCall`: 4096 per `parallel`/`pipeline`.
### Batched worker runner
Use `assets/wave.workflow.js`. It splits `args.tasks` into chunks of `args.concurrency`, runs one `parallel` chunk at a time, catches `agent()` throws per task, and returns a structured failure for scheduling errors instead of killing the run. If a chunk reports a limit error, rerun only the unstarted tasks with a smaller concurrency.
## Retry pattern
Full template: `assets/wave.workflow.js`. Retry only when the result is `null` or `status === "failed"`. Do not retry `blocked` — that needs a lead decision. Do not retry a spawn/limit error immediately; shrink the batch or let the lead dispatch the remainder.
```js
async function runOne(t) {
for (let attempt = 1; attempt <= 2; attempt++) {
try {
const r = await agent(promptFor(t, attempt), {
label: t.id,
phase: "wave 1",
schema: REPORT
});
if (r && r.status !== "failed") return r;
log(`${t.id}: attempt ${attempt} produced no usable report`);
} catch (error) {
const message = String(error && error.message ? error.message : error);
if (!/(limit|spawn|could not start|active child|capacity|start a child)/i.test(message)) {
throw error; // invalid options/schema must fail loudly
}
return failed(t, `scheduling error: ${message}`);
}
}
return failed(t);
}
```
On the second attempt, add one line: what failed and what to check. Do not repeat the whole brief. Catch **only** spawn/scheduling failures around `agent()`; invalid hook options or an unsupported schema should still fail loudly so you fix the script.
## Prompt assembly
Build the prompt from `args`, not from prose in the script:
```js
const promptFor = (t, attempt) => [
`You are agent ${t.id} in a coordinated swarm.`,
`Read .swarm/brief.md, .swarm/tasks/${t.id}.md, and .swarm/contracts.md first.`,
`Write only within: ${(t.write || []).join(", ") || "(read-only task)"}, plus your own report, review, and scratch under .swarm/reports/, .swarm/reviews/, and .swarm/tmp/${t.id}/.`,
`Do not edit other tasks' files or reports; do not run installs, repo-wide format/lint/codegen, migrations, dev servers, or git writes.`,
`Run the acceptance checks and record exact commands and results.`,
`Write .swarm/reports/${t.id}.json and return the same object.`,
`If a load-bearing unknown or a needed file outside scope blocks you, return status "blocked" with blocked_question; do not guess.`,
attempt > 1
? `A previous attempt produced no usable report. Re-read the task and fix the cause or report the exact blocker.`
: ""
].filter(Boolean).join("\n");
```
The task card carries the details; the prompt carries the role, scope, and protocol. Do not duplicate the card in the prompt.
## Verification runner
Use `assets/verify.workflow.js` for the verify wave (after freezing the tree). It embeds the minimal verdict schema and fetches reviews in batches:
```json
{
"script": "<contents of assets/verify.workflow.js>",
"args": {
"wave": 3,
"tasks": [{"id": "V01", "review": ".swarm/reviews/V01.md"}],
"concurrency": 4
},
"run_in_background": true
}
```
The verifier writes the review file first and returns only `{task_id, verdict, summary, review_file}`. If the workflow reports `null`/`no usable verdict`, check the review file; then re-run with the minimal schema. Code is frozen during this wave.
## Background runs
Use `run_in_background: true` when a wave may exceed ~10 minutes or you want live progress in the job list. The call returns a job id; `job_output` with `wait: true` blocks until settlement. If a wave hangs, `job_kill` cancels the run and disposes children. A background run's result arrives once, at settlement.
## Archetypes
### Code
- Units: module/feature/file cluster, each with its own tests.
- Ownership: source + test files per unit; shared types and barrels are integrator-only.
- Acceptance: targeted test command, typecheck, lint on changed files.
- Verify: a fresh agent runs the tests and reads the diff; no self-review.
### Research
- Units: one question or one source cluster per agent; output files under `research/`.
- Ownership: one file per agent; no shared notes file.
- Acceptance: source URLs resolve, claims are dated, every criterion covered.
- Verify: citation check and a consistency pass; a second agent samples claims.
### Content / documents
- Units: one section per agent, plus one editor-integrator.
- Ownership: sections are separate files; the editor owns the assembled document.
- Acceptance: section brief, word budget, terminology list, citations.
- Verify: one editor pass for voice and transitions; a fact-checker for claims.
## Verification runs
Use `assets/verify.workflow.js` with `assets/verdict.schema.json` after freezing the tree. Each verifier:
1. writes its full review to `.swarm/reviews/Vxx.md` first;
2. returns only `{task_id, verdict, summary, review_file}`;
3. reports `pass`, `pass_with_risks`, or `fail` plus evidence in the file.
If the workflow returns `null`/`no usable verdict`, check the review file before treating it as a product failure; then retry with the minimal schema or message the verifier for a concise verdict. After any fix, re-run the affected verifier and mark the old review stale.
## Failure handling
- `null` per item: ordinary child failure; retry or mark failed in the result. Do not fail the whole wave.
- Spawn/limit error inside `agent()`: catch per task, keep completed results, and rerun only unstarted tasks with a smaller batch. This is a scheduling failure, not a worker failure.
- A thrown hook error (bad option, unsupported schema, unknown hook) kills the run: fix the script. Do not hide it in a broad try/catch.
- Cancellation: stop the run, inspect partial reports on disk; do not trust the tool result.
## Cost
Each child carries the system prompt, tool schemas, packet, code reads, and its output: typically 10–40k tokens. A 12-agent wave is roughly 150–400k tokens, but a host capped at 8 cannot run 12 at once; batches reduce peak concurrency, not total cost. Budget before dispatch and count retries/re-verifications; stop at `max_agents`.
+147
View File
@@ -0,0 +1,147 @@
# Work packets
A packet is everything one agent needs and nothing else. The lead writes packets; workers read them. Packets live on disk so the workflow prompt stays short and every worker sees the same facts.
## The context ladder
1. `.swarm/brief.md` — shared by all tasks: goal, success criteria, stack, commands, conventions, hazards, forbidden actions.
2. `.swarm/tasks/Txx.md` — one task: objective, inputs, deliverables, write scope, contract, acceptance, stop conditions.
3. `.swarm/contracts.md` — frozen interfaces; read the relevant section only.
4. Pointers — `path:line` ranges, not pasted code.
5. Examples — one short example only where the format is ambiguous.
If a worker needs the lead's conversation, the packet is incomplete. If a packet exceeds one page, split the task.
## Brief
Copy `assets/brief.md.tmpl`. Rules:
- Goal is one paragraph; success criteria are checkable.
- List the exact build/test/lint commands. Workers should not guess.
- Map only the paths a worker may need; link the rest.
- Hazards: generated files, migrations, flaky tests, shared ports, secrets. Name what not to touch.
- Global forbidden actions are identical in every packet; keep them in the brief to save prompt space.
- No solution design, no task list, no worker-specific details.
## Task card
Copy `assets/task.md.tmpl`. Rules:
- Objective: what must exist when done, in 1–3 sentences.
- Inputs: brief, contract section, and exact code ranges.
- Deliverables: paths, including tests.
- Write scope: globs. Everything else is read-only.
- Contract: exact signature or output shape. If it is not written, it is not frozen.
- Acceptance: 1–3 commands a verifier can re-run. "Code is clean" is not a check.
- Stop conditions: time/attempt limit (25 min for S/M, 45–60 for L) plus "ask, do not guess" for load-bearing unknowns.
- Never include another task's internal details; workers do not need the whole plan.
## Verifier card
Copy `assets/verifier.md.tmpl`. Rules:
- State plainly: you did not write this; do not fix it.
- State that the tree is frozen: no source/test/docs/manifest edits during verification.
- Give criteria, changed paths, and commands; withhold the worker's rationale.
- Require a table: criterion, command, observed, pass/fail.
- Ask for scope, contract, and test-quality checks.
- Require the full review file **first**, then a minimal `{task_id, verdict, summary, review_file}` return (`assets/verdict.schema.json`). The review file is the source of truth; a schema miss must not erase the verification work.
## Report
Copy `assets/report.schema.json` to `.swarm/report.schema.json` and `assets/verdict.schema.json` to `.swarm/verdict.schema.json` during bootstrap; workers/verifiers read those copies. Field discipline:
- `status`: `done` (acceptance met), `partial` (some criteria met, listed), `blocked` (needs a lead decision), `failed` (attempted, cannot proceed).
- `verdict` (verifiers only): `pass`, `pass_with_risks`, or `fail`; the detailed findings belong in the review file, not a required workflow array.
- `files_changed`: exact deliverable/code paths, no globs. Coordination artifacts under `.swarm/` are implicit and may be omitted.
- `evidence`: commands and observed results, one line each.
- `acceptance`: per check, `pass|fail|not_run` plus evidence.
- `assumptions`: load-bearing assumptions the lead must confirm.
- `blocked_question`: one precise question, only when `status=blocked`.
Keep `summary` under ~300 characters. The lead reads summaries first and opens a report only for `blocked`/`failed`.
## Common mistakes
| Mistake | Fix |
|---|---|
| Pasting the whole conversation into every prompt | Write a brief; point to files |
| Vague acceptance ("works well") | A command and an expected result |
| No non-goals | List what not to touch |
| Two tasks own one file | Serialize or merge |
| Task needs 2+ hours | Split by deliverable, not by file count |
| Worker invents an interface | Freeze it in `contracts.md` |
| Report is an essay | Schema + one-line evidence |
| No stop condition | S/M 25 min, L 45–60 min / 3 attempts, then `blocked` |
| Verifier reads the worker's summary | Give the artifact and the criteria only |
| Verifier returns prose and loses its verdict | Write review file first; minimal verdict schema |
| Source edited during verification | Freeze, then re-run the affected verifier |
| Lead re-reads every report | Read summary + evidence; open only exceptions |
## Example: code task
```markdown
# T04 — Add retry to the HTTP client
Role: worker | Wave: 1 | Depends on: T02 | Effort: M
## Objective
`fetchJson` retries idempotent GET requests up to 2 times on 5xx and network errors, with a 100 ms base delay and no retry on 4xx.
## Inputs
- `.swarm/brief.md`
- `.swarm/contracts.md` §HTTP client
- `src/http/client.ts:40-120`
- `src/http/client.test.ts:1-60`
## Deliverables
- `src/http/client.ts` — retry loop
- `src/http/client.test.ts` — 3 cases: 5xx retry, 4xx no retry, network retry
## Write scope
- `src/http/client.ts`
- `src/http/client.test.ts`
## Read-only
- `src/http/types.ts`, `package.json`
## Contract
`fetchJson(url: string, init?: RequestInit): Promise<Json>` — unchanged signature; retries only when `init.method` is absent or `GET`.
## Constraints
- No new dependencies; use the existing `sleep` helper.
- Do not change error types or messages.
## Acceptance
1. `pnpm vitest run src/http/client.test.ts` → all pass.
2. `pnpm tsc --noEmit` → no new errors.
## Stop conditions
25 minutes for S/M (45–60 for L) or 3 failed attempts at the same step; a needed change outside the write scope → `blocked`.
```
## Example: research task
```markdown
# T07 — Compare three vendors on data residency
Role: worker | Wave: 1 | Depends on: — | Effort: S
## Objective
A 400–600 word comparison of Vendor A/B/C on data residency, with a source URL for every factual claim.
## Inputs
- `.swarm/brief.md`
- `.swarm/contracts.md` §Report format
- `research/questions.md` §2
## Deliverables
- `research/vendors/data-residency.md`
## Write scope
- `research/vendors/data-residency.md`
## Acceptance
1. Every factual claim has a source URL that resolves.
2. All three vendors covered on: storage region, subprocessors, deletion policy.
3. No claims older than 18 months without a date.
## Stop conditions
If a vendor publishes nothing on a criterion, write "not disclosed" with the source checked; do not infer.
```
+188
View File
@@ -0,0 +1,188 @@
# Swarm playbook
Detailed runbook for `agent-swarm`. Read this after the fit check passes. Keep `.swarm/state.json` current; it is the resume point if the session restarts.
## 0. Fit check and budget
Answer these before spawning:
- **Units.** Can you list 8+ deliverables that different agents can finish without waiting for each other?
- **Writes.** Can every unit get a disjoint write scope? Name the shared files now.
- **Checks.** Does every unit have a command or criterion a verifier can re-run?
- **Interfaces.** Can you freeze signatures, data shapes, and file names before dispatch?
- **Breadth.** Is the time dominated by many independent pieces, not one deep chain?
Budget:
- `agents ≈ units + ceil(units / 5) verifiers + 1–2 integrators + 2–4 recon`; add retries and re-verifications explicitly.
- Tokens ≈ `agents × 20k` (10–40k per agent depending on code reads).
- Waves ≈ `ceil(units / batch_size)` + verify + integrate, where `batch_size` comes from the **real** active-child cap, not from a documented default.
- Stop at `max_agents` or `max_waves`, whichever comes first. Record both, plus `slot_cap`, `active_at_dispatch`, `batch_size`, retries and re-verifications in `state.json`.
Go: a 40-file migration with per-module tests, a 30-source research report, a 20-section document with a style guide.
No-go: one failing test, one architectural decision, a refactor where every file imports the same core module.
## 1. Recon (2–4 agents)
Give each recon agent one question, not the whole task:
- Structure: entry points, modules, build/test commands.
- Conventions: naming, error handling, test style, formatting.
- Hazards: generated files, migrations, flaky tests, shared caches, secrets.
- Prior work: existing branches, TODOs, partial implementations.
Require findings as `path:line — fact`, no proposals. Merge into `.swarm/brief.md` and `.swarm/map.md`. Cap recon at ~10% of the budget and **10–15 minutes per recon agent**; on a small repo, do it yourself.
Recon lifecycle matters: each recon agent writes its report and stops. It must kill GUI/probe processes it started, must not run the full test suite, and must not keep a slot while the build wave starts. If a recon agent is still active after its report exists, interrupt it; otherwise it silently consumes one of the active-child slots.
## 2. Plan gate
Resolve `<skill>` to the base directory reported by the skill loader. If the workspace is a git repository, add `.swarm/` to `.gitignore` before the baseline so coordination files never reach the diff. Bootstrap once:
```sh
mkdir -p .swarm/tasks .swarm/reports .swarm/reviews .swarm/tmp
cp <skill>/assets/brief.md.tmpl .swarm/brief.md
cp <skill>/assets/report.schema.json .swarm/report.schema.json
cp <skill>/assets/verdict.schema.json .swarm/verdict.schema.json
node <skill>/scripts/audit-scope.mjs --init
```
Write the plan before any worker starts.
**Decomposition.** One task = one deliverable, one writer, one acceptance check, at most one page. Budget **5–25 minutes for S/M** and **40–60 minutes for L**; the old blanket 25-minute rule underestimates large UI/refactor files. If a task is expected to produce a single source file over ~1,500 lines, split it by module or accept that it will be a long, integration-heavy task. If it needs two writers, split it; if it needs the whole repo, it is not a task.
**Ownership.** Every path in exactly one `write` list. Add an explicit `LEAD` task whose `write` list contains lead/integrator-owned shared files, screenshots, licenses and the final report; without it, audit-scope reports the lead's own integration edits as unowned. Shared files are integrator-only: `package.json`, lockfiles, `tsconfig`, CI config, barrel/index files, schemas, migrations, i18n catalogs, snapshots, generated code. If two tasks must touch one file, serialize them with `depends_on` or merge them.
**Contracts.** Freeze what crosses a boundary: function signatures, types, file names, CLI flags, error behavior, output format. Put them in `.swarm/contracts.md`; workers may not change them without returning `blocked`.
**Coverage matrix.** Each success criterion → task(s) → check. A criterion with no task is a hole; a task with no criterion is scope creep.
**Visual acceptance.** For a GUI or visual product, define a deterministic screenshot/artifact command before dispatch (fixed window sizes, output path, clean pointer state) and put it in the acceptance matrix. Do not rely on desktop portal capture; it is unreliable on shared sessions and under Wayland.
**Waves.** Topologically sort by `depends_on`, then balance effort across batches. Do **not** plan 8–12 workers from a documented default: discover the runtime active-child cap first. Compute `batch_size = clamp(slot_cap - active_children - 1, 2, 8)`; recon and any other subagents count as active children. If the cap is unknown, use 6. Put foundational or risky tasks in batch 1; verify after the last build batch.
**Gate checklist:**
- [ ] 8+ tasks, each with objective, inputs, write scope, acceptance, stop condition.
- [ ] No path in two write scopes.
- [ ] Contracts frozen for every cross-task interface.
- [ ] Coverage matrix complete.
- [ ] `slot_cap`, `active_at_dispatch`, and `batch_size` are recorded and `batch_size` fits the available slots.
- [ ] Recon agents have stopped (or have been interrupted); no extra children hold slots.
- [ ] A `LEAD`/`INTEGRATOR` task owns shared files, screenshots, licenses and the final report.
- [ ] For a visual/GUI product, a deterministic screenshot command and sizes are in the acceptance matrix.
- [ ] `.swarm/brief.md`, `plan.json`, `plan.md`, `ownership.md`, `contracts.md`, `tasks/*.md` exist.
- [ ] `audit-scope.mjs --init` recorded the baseline.
If any box is empty, fix the plan; do not dispatch.
Minimal `plan.json` shape:
```json
{
"goal": "one line",
"tasks": [
{
"id": "LEAD",
"title": "lead-owned shared files, screenshots, licenses, final report",
"wave": 0,
"status": "in_progress",
"depends_on": [],
"write": ["package.json", "docs/**", "LICENSE*"],
"read": []
},
{
"id": "T01",
"title": "short title",
"wave": 1,
"status": "pending",
"depends_on": [],
"write": ["src/feature/**"],
"read": ["src/types.ts"],
"acceptance": ["pnpm vitest run src/feature"]
}
]
}
```
`audit-scope.mjs` reads only `id` and `write`. Keep those accurate. Use `path/**` for directories, including directories the task will create.
## 3. Build wave
Dispatch one `workflow` call per build wave (see `references/orchestration.md`). Use `assets/wave.workflow.js`, which splits tasks into batches, catches spawn errors instead of discarding the whole wave, and carries `args.concurrency`.
Before the call:
- [ ] Task cards are on disk and reference real paths.
- [ ] `args.tasks` carries `{id, write}` for each task.
- [ ] The report schema is passed as `args.schema`, and `args.concurrency` is at most the free slot count.
- [ ] Every task has a stop condition.
- [ ] Baseline exists and `state.json` records the cap.
After the call:
- [ ] Triage structured reports: done / partial / blocked / failed.
- [ ] Treat `spawn/runtime error` and `active child limit` results as scheduling failures, not worker failures: keep completed results and dispatch only the unstarted remainder in a smaller batch.
- [ ] Run `node <skill>/scripts/audit-scope.mjs` (the lead runs it; workers do not); revert or reassign out-of-scope changes.
- [ ] Run the build/test gate yourself; do not ask workers to fix shared breakage.
- [ ] Update `plan.json` and `state.json`.
- [ ] Decide: continue, answer blocked, re-scope, or stop.
Do not paste reports into the next prompt. Summarize decisions into the brief or contracts. Open a full report only for `blocked` and `failed`.
### Answering a blocked task
A `blocked` report is a request for a lead decision, not a failure. Fast path:
1. Read the exact `blocked_question` and the relevant contract section.
2. Make the smallest possible shared/contract change yourself (or via the integrator), and update `.swarm/contracts.md` and `state.json`.
3. `send_message` to the **same** worker with the decision and any exact signatures; ask it to continue under the same write scope.
4. Do not spawn a replacement until the original worker cannot continue, and do not retry a blocked task with the same unanswered prompt.
If the block reveals an underspecified interface shared by several tasks, update the contract once and message all affected workers. If two blocked tasks need conflicting contracts, stop and re-plan.
## 4. Verify wave
Choose verifiers by risk cluster, not one per task: 4–6 verifiers for 8–12 tasks. A verifier gets the task cards, the changed files (or diff), and the acceptance commands. It does not get the worker's rationale and does not fix anything.
**Freeze before verify.** Once you start this wave, do not edit source, tests or docs. If you already started and then fixed something, mark the in-flight review stale and re-run that verifier on the new build. A verifier's verdict is only valid for the exact tree it saw.
Use `assets/verify.workflow.js` and `assets/verdict.schema.json`, not the full worker report schema. The verifier's detailed review **must be written to `.swarm/reviews/Vxx.md` before it returns**; the workflow return is only `{task_id, verdict, summary, review_file}`. Do not treat a workflow `null`/`no usable verdict` as a product failure if the review file exists — read the file, then re-run with the minimal schema if needed.
Evidence standard: for every criterion, a command and its observed result. `pass` without evidence is `not_run`. Accept `pass_with_risks` only with named risks and a follow-up task. Verifiers should copy or hash-check generated files rather than rewriting the tree; if a required gate script rewrites generated artifacts, report the hash delta.
On failure, create a fix task with the verifier's repro; do not send the verifier back to fix its own finding. After fixes, re-run the affected verifier and mark the previous review stale; repeat until the remaining findings are minor/documented. Then run a final integrated verification pass.
## 5. Integrate
One integrator (two only for disjoint areas) owns:
- shared files and cross-cutting edits;
- merge conflicts and import/barrel fixes;
- one formatting/lint pass over changed files;
- the full acceptance suite.
No parallel workers during integration. The integrator may read all task cards and reviews; it writes `.swarm/integration.md` with what changed and why. Freeze the tree while the final verification runs; any post-verification edit invalidates the affected evidence.
## 6. Close
Final review is against the **original request**, not the plan: a fresh agent checks the success criteria, the diff, and the evidence. Then the lead writes `.swarm/final-report.md` with these sections:
- Shipped — what exists now, with paths.
- Not shipped / deferred — and why.
- Evidence — commands and observed results.
- Risks and open questions.
- Cost — agents, waves, wall-clock.
- Artifacts — `.swarm/...` paths.
## Failure recovery
| Signal | Likely cause | Action |
|---|---|---|
| Workers edit the same file | ownership map missed a shared file | stop, reassign, serialize, re-audit |
| Many `blocked` on the same interface | contract underspecified | answer once in `contracts.md`, retry those tasks only |
| Many schema `null`s | schema too strict or prompt unclear | loosen schema, add one example to the task card |
| Wave slower than serial | units too small or too coupled | merge units, reduce batch size |
| Workflow dies with `active child limit reached` | batch sized from wrong cap; recon still active | shrink batch, interrupt finished recon, dispatch only unstarted tasks |
| `no usable verdict` but review files exist | verifier schema miss / prose return | read review files; switch to `verdict.schema.json`; re-run if stale |
| Verifier reviewed an older build | source edited during verify | freeze, re-run affected verifier, mark old review stale |
| `blocked` task with a shared-file need | contract omits an integration point | lead applies the change, messages the same worker, no replacement |
| Verifiers find the same defect | brief missing a convention | fix the brief, add a check, re-run affected tasks |
| Lead context filling up | reading full reports | read summary + evidence; open only exceptions |
| A worker hangs | no per-agent timeout exists | kill the job, split the task, add a tighter stop condition |
## Time and cost
Parallel speedup is bounded by the sequential share and by the real slot cap, not by the number of tasks. Push sequential work down: recon once, contracts before dispatch, verification in parallel. A 36-unit task with 10-minute units and a 6-slot batch is ~6 batches × 10 min ≈ 60 min of agent work, plus plan, verify and integration; do not promise a 3× speedup when the host caps active children at 8 or fewer.