diff --git a/README.md b/README.md
index 75182f1..0cc0b03 100644
--- a/README.md
+++ b/README.md
@@ -4,7 +4,7 @@ Canonical, reviewable documentation for the StructuPath Herdr Suite, published a
The product surface is organized by workflow readiness:
-- **Explore / Swarm** is the ready first workflow: bounded parallel candidates, reviewable worktrees, operator-selected harvest, and optional GitHub draft PR handoff. A separate strict candidate handoff requires passing validation and Browser QA plus an exact-SHA operator review before publication; it is an unreleased development path, not an automatic merge.
+- **Explore / Swarm** is the ready first workflow: bounded parallel candidates, reviewable worktrees, operator-selected harvest, and optional GitHub draft PR handoff. Release 0.5.0 adds per-slot checks, finish detection, a ranked compare view with merge-the-winner at the exact compared commit, broadcast to running agents, and a conflict resolver whose result is reviewed read-only before it lands. A separate strict candidate handoff requires passing validation and Browser QA plus an exact-SHA operator review before publication; it is not an automatic merge.
- **Deliver / Conductor** is an attended Stage 3 lifecycle: task-bound roles, exact-SHA gates, operator approval receipts, single-local-ref apply, and archival stand-down on exactly Herdr 0.7.5.
- **Browser** provides Chromium launch, external attach, shared sessions, agent-browser recording, and repeatable desktop/mobile QA. **Guard** provides text policy and an optional fail-open harness reporter.
diff --git a/data/plugins.json b/data/plugins.json
index 513af25..8d5d93a 100644
--- a/data/plugins.json
+++ b/data/plugins.json
@@ -47,14 +47,14 @@
"name": "Swarm",
"id": "structupath.swarm",
"repository": "https://github.com/StructuPath/herdr-swarm",
- "commit": "09dd1f22c95ca9c9e4cdb0e3510f886360d5f0fb",
- "version": "0.4.0",
+ "commit": "f750bc7d61f99d857e2276c5493fbe91254c9e7f",
+ "version": "0.5.0",
"min_herdr_version": "0.7.4",
"tested_herdr_versions": [
"0.7.4",
"0.7.5"
],
- "manifest_sha256": "eac43912706faf3458b2aeadc27c001e7c5c13b9b92279e9758d4412799fb848",
+ "manifest_sha256": "0608773dc11e55252e7d060392be3c76beca65ce65c49a5085dc39d1dd9144c4",
"actions": [
"fanout",
"status",
diff --git a/docs-src/Home.md b/docs-src/Home.md
index c744716..50079e6 100644
--- a/docs-src/Home.md
+++ b/docs-src/Home.md
@@ -43,7 +43,7 @@ compatibility with later versions.
| --- | --- | --- | --- | --- | --- |
| [Browser](Browser) | `structupath.browser` | `0.8.0` | `0.7.0` | `0.7.4` | Chromium launch, CDP attach, shared sessions, recording, and repeatable QA |
| [Guard](Guard) | `structupath.guard` | `0.2.0` | `0.7.5` | `0.7.5` | Text policy plus optional fail-open harness reporter |
-| [Swarm](Swarm) | `structupath.swarm` | `0.4.0` | `0.7.4` | `0.7.4`, `0.7.5` | Parallel candidates, review-first harvest, and PR publication |
+| [Swarm](Swarm) | `structupath.swarm` | `0.5.0` | `0.7.4` | `0.7.4`, `0.7.5` | Parallel candidates, per-slot checks, compare and merge the winner, conflict resolver, and PR publication |
| [Conductor](Conductor) | `structupath.conductor` | `0.4.0` | `0.7.5` | `0.7.5` | Attended Stage 3: exact-SHA gates, preview, approval receipts, and single-ref apply |
Versions are plugin-specific source evidence pinned in [`data/plugins.json`](https://github.com/StructuPath/herdr-suite-site/blob/main/data/plugins.json), not a claim that every plugin was tested on one suite-wide Herdr version. Recorded Herdr versions include retained historical compatibility evidence; they do not certify every new feature. Guard's accepted interrupt requests and harness verdicts do not prove command prevention.
diff --git a/docs-src/Swarm.md b/docs-src/Swarm.md
index 3452fc9..75f2e2c 100644
--- a/docs-src/Swarm.md
+++ b/docs-src/Swarm.md
@@ -8,14 +8,25 @@ Repo: [StructuPath/herdr-swarm](https://github.com/StructuPath/herdr-swarm) · D
| Field | Value |
| --- | --- |
-| Plugin release | `0.4.0` |
+| Plugin release | `0.5.0` |
| Minimum Herdr | `0.7.4` |
| Explicitly tested Herdr | `0.7.4`, `0.7.5` |
-| Evidence commit | `09dd1f22c95ca9c9e4cdb0e3510f886360d5f0fb` |
+| Evidence commit | `f750bc7d61f99d857e2276c5493fbe91254c9e7f` |
-The pinned source also records a [bounded Herdr 0.8.2 live smoke](https://github.com/StructuPath/herdr-swarm/blob/09dd1f22c95ca9c9e4cdb0e3510f886360d5f0fb/docs/readiness.md): fan-out, committed work, merge, automatic archive, abort, and prune dry-run. It found and fixed archive-state reconciliation and the newer runtime's `done` agent state. Version 0.4.0 retains these fixes and adds the explicit GitHub draft-PR handoff below; broad Herdr compatibility evidence remains 0.7.4/0.7.5.
+Version 0.5.0 adds the workflow described under **Pick the winner** below. The pinned [readiness record](https://github.com/StructuPath/herdr-swarm/blob/f750bc7d61f99d857e2276c5493fbe91254c9e7f/docs/readiness.md) documents a 2026-10-04 live end-to-end run of that flow on Herdr 0.8.2:
-An isolated Herdr 0.9.3/protocol 22 smoke registered all five actions and
+- fan-out with per-slot tasks, slot variables, and cloned dependencies;
+- finish detection, validate, compare, and broadcast;
+- a merge at the compared commit;
+- a conflict handed to a resolver, reviewed read-only, and landed;
+- the review flagging a file slipped into the merge;
+- archive with exact cleanup approvals, and prune dry-run.
+
+That run used scripted stand-in agents, not real model agents. It did not cover the status pane, which opens through the plugin action, or Herdr 0.7.4. The broad tested-version record remains 0.7.4/0.7.5.
+
+An earlier bounded 0.8.2 smoke (0.4.0) exercised fan-out, committed work, merge, automatic archive, abort, and prune dry-run. It found and fixed archive-state reconciliation and the newer runtime's `done` agent state.
+
+An isolated Herdr 0.9.3/protocol 22 smoke (0.4.0-era) registered all five actions and
used a disposable, no-remote repository with an inert local shell preset.
Scripted fan-out created one worktree and started one pane; the attended abort
closed that pane, removed the clean worktree, archived the run, and kept its
@@ -92,9 +103,9 @@ Setup logs preserve command output verbatim. Keep credentials out of setup outpu
### 4. Inspect every credible candidate
-Open Status and use `1`–`9` to visit each slot. Compare committed and uncommitted counts against the recorded fork SHA. A 0.7.5+ slot can remain labeled `working` after it finishes until Harvest previews it; state is informative, not a completion gate.
+Open Status and use `1`–`9` to visit each slot. Compare committed and uncommitted counts against the recorded fork SHA. While Status is open, finish detection marks a slot `finished` when its agent writes the `.swarm-done` marker or exits, and shows elapsed time per slot. State is informative, not a completion gate.
-Open Harvest, preview each candidate's diff, run its tests, and compare it against the criterion declared before fan-out. Dirty slots offer WIP commit, skip, or discard; review the backup behavior before discarding.
+Open Harvest. Press `w` for the ranked compare view, `v` to run your `validate.sh` on a slot, or preview each candidate's diff, run its tests, and compare it against the criterion declared before fan-out. Dirty slots offer WIP commit, skip, or discard; review the backup behavior before discarding.
### 5. Treat clean-slot selection as approval
@@ -106,6 +117,23 @@ Use `q` to leave Status or Harvest without selecting a candidate. Invoke Abort t
A first Explore run is successful when one chosen branch is merged without conflict, its tests pass on the base, the resulting diff meets the stated comparison criterion, and skipped work remains recoverable on branches until deliberate pruning.
+## Pick the winner
+
+Version 0.5.0 covers the whole path from fan-out to a landed winner. Each step is opt-in or read-only unless stated, and nothing merges without the operator's selection or confirmation. The [pinned README](https://github.com/StructuPath/herdr-swarm/blob/f750bc7d61f99d857e2276c5493fbe91254c9e7f/README.md#the-workflow-050) is the detailed reference.
+
+| Step | What it does |
+| --- | --- |
+| **Prepare slots** | Fan-out clones the repository's ignored `node_modules` (or a configured `clone-paths` list) into each worktree with copy-on-write. On Linux it's skipped where copy-on-write is unavailable; on macOS `cp -c` falls back to a full copy. Each slot gets `HERDR_SWARM_RUN_ID`, `HERDR_SWARM_SLOT`, and its own port range (10 per slot from 4100). `setup.sh` always receives them, and the agent receives them on Herdr 0.7.5+. |
+| **Different tasks per slot** | `` lines split `HERDR_SWARM_TASK_FILE` into per-slot sections after a shared preamble. Before anything is created, fan-out warns when slots given *different* tasks name the same tracked file. |
+| **Know when done** | Status records a slot `finished` when its agent writes `.swarm-done` or exits, and sends one Herdr notification when all slots are done. |
+| **Check** | `v` (or `harvest-step.sh validate The pinned source also records a bounded Herdr 0.8.2 live smoke: fan-out, committed work, merge, automatic archive, abort, and prune dry-run. It found and fixed archive-state reconciliation and the newer runtime's An isolated Herdr 0.9.3/protocol 22 smoke registered all five actions and
+ Version 0.5.0 adds the workflow described under Pick the winner below. The pinned readiness record documents a 2026-10-04 live end-to-end run of that flow on Herdr 0.8.2: That run used scripted stand-in agents, not real model agents. It did not cover the status pane, which opens through the plugin action, or Herdr 0.7.4. The broad tested-version record remains 0.7.4/0.7.5. An earlier bounded 0.8.2 smoke (0.4.0) exercised fan-out, committed work, merge, automatic archive, abort, and prune dry-run. It found and fixed archive-state reconciliation and the newer runtime's An isolated Herdr 0.9.3/protocol 22 smoke (0.4.0-era) registered all five actions and
used a disposable, no-remote repository with an inert local shell preset.
Scripted fan-out created one worktree and started one pane; the attended abort
closed that pane, removed the clean worktree, archived the run, and kept its
@@ -152,8 +162,8 @@ Fresh worktrees omit ignored dependencies, Setup logs preserve command output verbatim. Keep credentials out of setup output and review logs before sharing them. Open Status and use Open Harvest, preview each candidate's diff, run its tests, and compare it against the criterion declared before fan-out. Dirty slots offer WIP commit, skip, or discard; review the backup behavior before discarding. Open Status and use Open Harvest. Press Merge warning: selecting a clean slot in Harvest performs a review-first Use A first Explore run is successful when one chosen branch is merged without conflict, its tests pass on the base, the resulting diff meets the stated comparison criterion, and skipped work remains recoverable on branches until deliberate pruning. Version 0.5.0 covers the whole path from fan-out to a landed winner. Each step is opt-in or read-only unless stated, and nothing merges without the operator's selection or confirmation. The pinned README is the detailed reference. Elapsed time is shown; token usage and cost aren't, because Herdr carries no usage data and agents do not report it. In Harvest, press Imported Browser QA summaries must agree with per-run outcomes and counts. Unresolved requests or incomplete telemetry cannot produce a passing handoff check. A failed push creates no PR. A GitHub failure after a successful push leaves the published branch and local receipt intact. Inspect the error and retry the same command; a lost creation response triggers exact-PR rediscovery. A mismatched GitHub head refuses success and requires inspection, never a force-push correction. Press See the pinned GitHub handoff contract for the exact evidence and output schemas. Console can display an explicitly saved PR-status observation alongside project and QA evidence. The unreleased checkout adds See the pinned GitHub handoff contract for the exact evidence and output schemas. Console can display an explicitly saved PR-status observation alongside project and QA evidence. Version 0.5.0 includes Pinned compatibility evidence
Swarm
-structupath.swarm
+0.4.00.5.00.7.4
-0.7.4, 0.7.5Parallel candidates, review-first harvest, and PR publication
+Parallel candidates, per-slot checks, compare and merge the winner, conflict resolver, and PR publication
Conductor
diff --git a/docs/swarm/index.html b/docs/swarm/index.html
index 0913564..dfc6c17 100644
--- a/docs/swarm/index.html
+++ b/docs/swarm/index.html
@@ -60,7 +60,7 @@ Pinned evidence
Plugin release
-
+0.4.00.5.0
Minimum Herdr
@@ -72,12 +72,22 @@ Pinned evidence
-Evidence commit
-
+09dd1f22c95ca9c9e4cdb0e3510f886360d5f0fbf750bc7d61f99d857e2276c5493fbe91254c9e7fdone agent state. Version 0.4.0 retains these fixes and adds the explicit GitHub draft-PR handoff below; broad Herdr compatibility evidence remains 0.7.4/0.7.5.
+
+done agent state.3. Enter one bounded task and comparison criterion
.env files, and caches. If every agent fails immediately, add a reviewed plugin-config setup.sh or tell agents to install required dependencies, then start a new run.4. Inspect every credible candidate
-1–9 to visit each slot. Compare committed and uncommitted counts against the recorded fork SHA. A 0.7.5+ slot can remain labeled working after it finishes until Harvest previews it; state is informative, not a completion gate.1–9 to visit each slot. Compare committed and uncommitted counts against the recorded fork SHA. While Status is open, finish detection marks a slot finished when its agent writes the .swarm-done marker or exits, and shows elapsed time per slot. State is informative, not a completion gate.w for the ranked compare view, v to run your validate.sh on a slot, or preview each candidate's diff, run its tests, and compare it against the criterion declared before fan-out. Dirty slots offer WIP commit, skip, or discard; review the backup behavior before discarding.5. Treat clean-slot selection as approval
--no-ff merge. If the base branch is checked out, Swarm asks for explicit confirmation. If the base is not checked out anywhere, a plugin-owned detached worktree can advance the base ref after the preview without another confirmation screen. Treat slot selection as the approval action.5. Treat clean-slot selection as approval
q to leave Status or Harvest without selecting a candidate. Invoke Abort to stop an active run: it closes Swarm-owned panes and removes clean plugin-owned worktrees, while keeping branches and anything questionable.Success definition
Pick the winner
+
+
+
+
+
+
+Step
+What it does
+
+
+Prepare slots
+Fan-out clones the repository's ignored
+node_modules (or a configured clone-paths list) into each worktree with copy-on-write. On Linux it's skipped where copy-on-write is unavailable; on macOS cp -c falls back to a full copy. Each slot gets HERDR_SWARM_RUN_ID, HERDR_SWARM_SLOT, and its own port range (10 per slot from 4100). setup.sh always receives them, and the agent receives them on Herdr 0.7.5+.
+
+Different tasks per slot
+
+<!-- swarm-slot: N --> lines split HERDR_SWARM_TASK_FILE into per-slot sections after a shared preamble. Before anything is created, fan-out warns when slots given different tasks name the same tracked file.
+
+Know when done
+Status records a slot
+finished when its agent writes .swarm-done or exits, and sends one Herdr notification when all slots are done.
+
+Check
+
+v (or harvest-step.sh validate <slot>) runs your plugin-config validate.sh against the slot's clean commit and records the result bound to that SHA. It can run automatically on finish if you opt in. The strict candidate handoff uses this result by default.
+
+Compare
+
+w ranks slots by checks on their current commit, then commits, then finished. It never ranks by diff size. It shows files, +/-, dirty count, the files each pair both changed, and elapsed time. d shows the diff between two slots.
+
+Merge the winner
+
+m merges the chosen slot at the exact commit compared, and refuses if it moved. Only if that merge lands are the finished losers skipped and archived. Branches are always kept.
+
+Steer
+
+harvest-step.sh broadcast types one single-line message into every running slot's agent. It only does so where the slot's own agent program leads the pane, never into a shell, an editor, or an agent Herdr reports as blocked.
+
+
+Resolve conflicts
+For a conflict in Swarm's own detached merge tree,
+g starts a resolver agent beside the slot (Herdr 0.7.5+). c reviews its commit read-only: it lists every path changed beyond git's own automatic merge and the full diffstat. Only y records exactly the reviewed commit and lands it through the compare-and-swap. A merge you resolve by hand concludes the same way.Publish for PR review
p, then select a slot to publish its branch. The script equivalent is scripts/harvest-step.sh publish <slot> from the installed plugin root. Publication uses an ordinary push to origin, or the explicit HERDR_SWARM_PUBLISH_REMOTE override; it never force-pushes and does not create a GitHub PR itself.Explicit GitHub draft handoff
@@ -179,12 +234,12 @@ Explicit GitHub draft handoff
c, then a slot, for the pane's CI view. pr-status emits a ci_status tab-separated JSON record with passed, failed, pending, not_run, unknown, or no_pr status. Compare head_sha and local_head_sha: a passing remote check is not current candidate evidence when matches_local_head is false. Passing checks do not establish branch-protection completeness or authorize a merge. The command uses GitHub reads and the local run lock; it does not fetch, push, merge, or edit a PR.Strict candidate handoff in the local development checkout
-candidate-status <slot> and
-publish-candidate-pr <slot>; the pinned 0.4.0 commit above does not include
-these verbs. In the active run, select a clean committed slot, record typed
-passing validation checks, a separately passing Browser QA result
+Strict candidate handoff
+candidate-status <slot> and
+publish-candidate-pr <slot>. In the active run, select a clean committed
+slot, record typed passing validation checks (the result validate <slot>
+records is used when no file is named), a separately passing Browser QA result
for the same SHA, and an explicit operator review bound to the run ID, slot,
and SHA. Set HERDR_SWARM_CANDIDATE_VALIDATION_FILE,
HERDR_SWARM_CANDIDATE_BROWSER_QA_FILE, and
@@ -203,14 +258,15 @@ Strict candidate handoff in the local development checkout
It does not establish real GitHub authentication, CI, or remote PR creation.
Caller-supplied evidence and the operator JSON are not attestations; an
existing PR is reused without replacing its body, so reported evidence may
-not be attached to that PR. The source checkout's
-docs/github-handoff.md defines the development contract; the pinned URL
-above defines only the released contract.
docs/github-handoff.md linked above
+defines the contract.
After a remote PR is merged, preview again. Harvest recognizes merge ancestry and squash merges whose tree changes are contained in the base. Prune uses ancestry, so squash-merged branches may remain for deliberate review.
Swarm isolates working trees and provides reviewable branches; it does not sandbox agents. Write agents are trusted same-user principals and can access anything their operating-system user can access. Agents are instructed to commit locally and never push, while the operator remains the merge gate.
Harvest uses review-first, --no-ff merges and checks base drift. Dirty discards first create backup refs. Abort keeps branches, and prune is dry-run/env-gated. Active runs resolve by physical repository identity; conflicting generations are refused rather than guessed.
Ignored files remain outside Git's safety net. Removal requires the exact one-use cleanup_approval JSON returned by the inventory preview, bound to the resource, path, run, generation, and inventory digest. A generic yes is insufficient, and changed inventory invalidates approval. This also applies to ignored files in detached merge worktrees.
Ignored files remain outside Git's safety net. Removal requires the exact one-use cleanup_approval JSON returned by the inventory preview, bound to the resource, path, run, generation, and inventory digest. A generic yes is insufficient, and changed inventory invalidates approval. This also applies to ignored files in detached merge worktrees, and to node_modules cloned into a slot. Large sets are summarized by top-level directory in the prompt, while the approval still covers every exact file.
Broadcast types text into agents, so it refuses multi-line text, control characters, and a leading -. It only types into a pane whose foreground program is the slot's own agent. On Herdr 0.7.5+, Swarm reports agent state itself, so an open approval prompt does not read as blocked: do not broadcast while an agent may be asking for approval.
The conflict resolver never handles a conflict in your own checked-out branch. Its merge tree is kept until Swarm can prove the resolver is gone; an uncertain state blocks abort and conclude. A resolution's second parent must be the exact slot commit the merge started with. Hunk-level changes inside conflicted files are not flagged separately, so review the conflicted files' content.
Interactive fan-out uses the action. A zero-TTY run must invoke the pane script directly because action-spawned panes do not inherit caller environment in the pinned runtime:
HERDR_SWARM_SLOTS=3 \
@@ -220,7 +276,7 @@ Scripted fan-out
HERDR_WORKSPACE_ID='replace-with-repo-workspace-id' \
bash "$(herdr plugin list --json | jq -r '.plugins[] | select(.id=="structupath.swarm").root')/scripts/fanout-pane.sh"
-Per-slot overrides remain interactive-only. If a zero-TTY input is missing, the script exits with a named-variable error instead of waiting on an unreadable prompt.
+For a different task per slot, split the task file with <!-- swarm-slot: N --> lines (see Pick the winner above). Without HERDR_SWARM_SLOTS, the highest section number sets the slot count. Sections that don't fit the run, or a near-miss marker, refuse before anything is created. If a zero-TTY input is missing, the script exits with a named-variable error instead of waiting on an unreadable prompt.
q closes Status or Harvest without selecting work.
- Status reports committed and uncommitted counts. Harvest
- previews the selected candidate's diff.
+ Status reports committed and uncommitted counts and marks
+ each slot finished. Your validate.sh checks each
+ slot's exact commit, and Harvest's compare view ranks the
+ candidates and diffs any two.
- Merge one reviewed slot, skip the rest, or Abort while keeping - branches for recovery. For GitHub review, explicitly request - the draft PR handoff with the candidate's validation evidence. + Merge the winner at the exact commit you compared and skip the + rest, or Abort while keeping branches for recovery. A conflict + can go to a resolver agent, whose result you review before it + lands. For GitHub review, explicitly request the draft PR + handoff with the candidate's validation evidence.