agent-horde 0.1.5 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -50,7 +50,9 @@ found there as its brief. Unrelated files cost members context and invite them t
50
50
  from earlier runs persist in `.horde/` and will steer members; start with a fresh one when the
51
51
  task changes.
52
52
 
53
- A horde is at most twelve members today. Hordes of hordes are on the roadmap.
53
+ A horde is at most twelve members. For more hands, run a swarm: `3/12` launches three hordes of
54
+ twelve on disjoint workstreams of one task, each with its own ledgers, and merges their
55
+ deliverables at the end.
54
56
 
55
57
  **Tips.**
56
58
 
@@ -88,7 +90,7 @@ pi install npm:agent-horde
88
90
  Or from the repository, pinned to a tag:
89
91
 
90
92
  ```
91
- pi install git:github.com/eliyastein/agent-horde@v0.1.5
93
+ pi install git:github.com/eliyastein/agent-horde@v0.2.0
92
94
  ```
93
95
 
94
96
  To hack on it, clone and install in place. pi loads the files from the clone, so edits take effect
@@ -122,17 +124,44 @@ When you already know how the work splits, use `plan` to fix the partition at la
122
124
  Each layer becomes a seeded idea owned by one member, recorded in the run's `PLAN.md`, and that
123
125
  member works only its layer. Layers are assigned round-robin, so more layers than members gives
124
126
  some members two. Members without a layer become verifiers, and an unpartitioned run of three or
125
- more members makes its last member the verifier. `plan` suits "analyse each X" tasks; split design
126
- work by output type, such as spec, prototype, and generator, rather than by theme.
127
+ more members makes its last member the verifier (`--no-verifier` turns that off). `plan` suits
128
+ "analyse each X" tasks; split design work by output type, such as spec, prototype, and generator,
129
+ rather than by theme.
130
+
131
+ A run normally winds down once a validated answer exists and every idea is closed. `--until-stop`
132
+ keeps the whole horde working until you stop it: a validated answer is banked as the current one
133
+ and the proposal slot reopens, and a member whose session finishes gets a fresh session told to
134
+ extend, stress-test, or deepen the work.
135
+
136
+ ```
137
+ /agent-horde --dashboard --until-stop 8 find every way an unauthenticated request reaches the database
138
+ ```
139
+
140
+ A count of `H/M` runs a swarm: H hordes of M members on one task, at most four hordes. A planner
141
+ helper first splits the task into H disjoint workstreams with acceptance criteria and each horde
142
+ works only its slice, with its own ledgers under `.horde/swarms/<id>/hN/`; if the planner cannot
143
+ produce H distinct workstreams the launch stops and says so. `plan 3/12 a; b; c; d; e; f` skips
144
+ the planner and deals the layers round-robin to the hordes. Members read the other hordes' facts,
145
+ rule-outs and resources through the `horde` tool but write only to their own horde. The hordes
146
+ start a few seconds apart, run the normal lifecycle independently, and when the last one has
147
+ finished a synthesis helper merges their deliverables into the swarm's `DELIVERABLE.md`, each
148
+ claim attributed to its horde. `--until-stop` applies to every horde.
149
+
150
+ ```
151
+ /agent-horde --dashboard=1234 3/12 audit the service for authorization bugs
152
+ ```
127
153
 
128
154
  | command | effect |
129
155
  |---|---|
130
- | `/agent-horde status` | the active run and each member |
131
- | `/agent-horde stop-clean [postmortem]` | members wrap up, then the run finalizes |
156
+ | `/agent-horde status` | the active run and each member; one block per horde in a swarm |
157
+ | `/agent-horde stop-clean [postmortem]` | members wrap up, then the run finalizes; this is how an `--until-stop` run ends |
132
158
  | `/agent-horde stop-hard` | terminate members now |
133
159
  | `/agent-horde pause`, `resume` | suspend and resume member processes |
134
160
  | `/agent-horde help` | every flag and target |
135
161
 
162
+ Every control takes a target: `member-3`, `h2` for one horde of a swarm, `h2:member-3` for one
163
+ member of one horde, or `all`; a bare `member-3` in a swarm names that member in every horde.
164
+
136
165
  When the run ends, the report is injected into your conversation. Everything else stays under
137
166
  `.horde/`; add it to your `.gitignore`.
138
167
 
@@ -172,11 +201,13 @@ die, runs the repair phase, freezes acceptance, and writes the report.
172
201
  - Ideas, findings, facts, and resources are deduplicated on identifiers first, then wording; a
173
202
  duplicate returns the existing id and records a corroborator.
174
203
  - Every finding names a concern slug; a look-alike of an existing slug is refused.
175
- - A review records the revision it checked, its scope, a verdict, and evidence. Runnable
176
- artifacts need a tested or reproduced review from a non-owner; documents need a sourced or
177
- derived one.
204
+ - A review records the revision it checked, its scope, a verdict, evidence, and any limits
205
+ outside the target's criteria. Runnable artifacts need a tested or reproduced review from a
206
+ non-owner; documents need a sourced or derived one. A reviewer can carry its review forward to
207
+ an unchanged revision instead of redoing it.
178
208
  - Solved is two-phase: one member proposes, a different member validates, and the run winds down
179
- only when every idea it created is closed.
209
+ only when every idea it created is closed. Under `--until-stop` the answer is banked instead
210
+ and the horde keeps going until `stop-clean` or `stop-hard`.
180
211
  - Peer messages, reviews, and evidence enter a member's context as data. They cannot authorize
181
212
  tools or override the task.
182
213
 
@@ -194,6 +225,7 @@ linked to the page that shows it, so a run reads left to right: who claimed what
194
225
  landed under which ideas, who reviewed whom, and where actions were rejected. It is server-rendered
195
226
  SVG/HTML with no scripts. The download icon on every page exports the whole dashboard as a zip of
196
227
  static pages that opens from disk, after a warning that it may carry sensitive data from the machine.
228
+ Every page's footer names the agent-horde version and, from a checkout, the commit it runs at.
197
229
 
198
230
  ## Benchmark: FinanceBench
199
231
 
package/docs/REFERENCE.md CHANGED
@@ -7,7 +7,7 @@ at one problem beat a single linear one: research, audits, design exploration, R
7
7
  ## Usage
8
8
 
9
9
  ```
10
- /agent-horde [--dashboard[=<port>]] [--no-verifier] <count> <prompt>
10
+ /agent-horde [--dashboard[=<port>]] [--no-verifier] [--until-stop] <count> <prompt>
11
11
  /agent-horde plan [--dashboard] <count> <layer; layer; ...>
12
12
  /agent-horde status [target]
13
13
  /agent-horde stop-hard [target] SIGTERM, SIGKILL after 5s (alias: stop)
@@ -16,8 +16,10 @@ at one problem beat a single linear one: research, audits, design exploration, R
16
16
  /agent-horde help
17
17
  ```
18
18
 
19
- `target` is `all` (default), `member-N`, `N`, or a comma or space separated list. Subcommands and
20
- member targets tab-complete.
19
+ `count` is `M` members (1 to 12) or `H/M`: H hordes of M members, H at most 4; a plain `M` is a
20
+ swarm of one. `target` is `all` (default), `member-N`, `N`, `hN` (one horde of a swarm),
21
+ `hN:member-M`, `hN:M`, or a comma or space separated list; a bare member names that member in
22
+ every horde. Subcommands and targets tab-complete.
21
23
 
22
24
  The command returns immediately. A widget above the editor shows each member's status, current
23
25
  tool, elapsed time, turns, and resets. Members inherit the parent session's model and thinking
@@ -72,11 +74,23 @@ own when the parent is gone, even after a SIGKILL or OOM kill.
72
74
  HEAD, never writes to `.horde/`, and stays up after the run until the session ends. A busy port
73
75
  refuses the run before any run directory is created. Live pages reload every three seconds
74
76
  (`?refresh=0` disables); expandable entries are URL-backed, so they stay open across refreshes.
75
- Every page has a JSON twin under `/api/<same path>`.
77
+ Every page has a JSON twin under `/api/<same path>`. The footer of every page names the
78
+ agent-horde version from its package.json and, when it runs from a git checkout, the commit it is
79
+ at (`-dirty` when the tree has uncommitted changes), linked to the commit on GitHub.
80
+
81
+ Every page belongs to one scope, fixed by its URL: the **project** (`/` and the bare ledger paths,
82
+ the ledgers single runs share), one **run** (`/runs/<id>/...`), or one **swarm**
83
+ (`/swarms/<id>/...`). Under the `runs` link a scope line names the scope, and a page row offers that
84
+ scope's pages (overview, the six ledgers, collaboration, graph; the project has the ledgers only),
85
+ with the current page marked. Inside a swarm the scope line adds horde tabs, `all | h1 | h2 ...`,
86
+ that keep the page type: from h2's findings, h3 opens h3's findings and `all` the swarm's. A horde's
87
+ pages are its run's pages, `/runs/<swarm-id>-h2/...`. No link falls back to another run. While a swarm
88
+ is running or finishing, project pages show a pointer to the same page in the swarm, since its
89
+ hordes write their own ledgers and leave the project ones untouched.
76
90
 
77
91
  | page | shows |
78
92
  |------|-------|
79
- | `/` | every run: active marker, start, count, model, outcome, prompt, files present |
93
+ | `/` | every swarm and run: state (active, finalizing, pending, finished, not started), start, count, model, outcome, prompt, files present |
80
94
  | `/runs/<id>` | prompt, outcome, canary, clean-stop countdown, plan layers, members table, run files |
81
95
  | `/runs/<id>/members/<m>` | live activity, last and final text, log tail (`?tail=<n>`), transcript link |
82
96
  | `/runs/<id>/members/<m>/log` | the member log; `tail=0` is the whole file (1 MiB cap) |
@@ -86,16 +100,27 @@ Every page has a JSON twin under `/api/<same path>`.
86
100
  | `/runs/<id>/collaboration` | messages, review scope, artifact acceptance, resources, event audit |
87
101
  | `/runs/<id>/graph` | the run as a swimlane: one lane per member plus the parent, phase bands, every event a link to its ledger entry (`?w=<px>`, `?from=<s>&to=<s>`); the axis is real time until the last member exits, then the synthesis phases share a compressed tail |
88
102
  | `/runs/<id>/graph.mmd` | the same run as a Mermaid flowchart with absolute dashboard links (text/plain) |
89
- | `/ideas`, `/board`, `/findings`, `/claims`, `/facts`, `/resources` | the shared ledgers; `?run=<id>\|all`, `?view=clusters`, `?owner=<m>` filter them; `/resources` also lists who cited each resource in the active run, as REPORT.md counts reuse |
103
+ | `/runs/<id>/ideas`, `board`, `findings`, `claims`, `facts`, `resources` | the run's ledgers: a horde's own, or for a single run the project ledgers with board and findings narrowed to the run and facts split into this run and carried; `?view=clusters`, `?owner=<m>`, `?order=oldest` |
104
+ | `/ideas`, `/board`, `/findings`, `/claims`, `/facts`, `/resources` | the project ledgers across every single run; `/resources` also lists who cited each resource in a live single run, as REPORT.md counts reuse |
105
+ | `/swarms/<id>` | one row per horde (state, outcome, members, findings, accepted artifacts, cost, workstream), the partition, the merge state, swarm files |
106
+ | `/swarms/<id>/ideas`, `board`, `findings`, `claims`, `facts`, `resources`, `collaboration` | every horde's ledger, or its acceptance, requests and reviews, on one page under a per-horde heading; ids repeat per horde, and each horde's event audit stays on its run page |
107
+ | `/swarms/<id>/graph` | one lane per horde with its phase marks, and the merge step |
108
+ | `/swarms/<id>/files/<NAME>` | `SWARM`, `REPORT`, `DELIVERABLE`; 404 until written |
90
109
  | `/export` | confirms the export and starts the download of `/export.zip` (`?back=<path>` names the page to return to); no JSON twin |
91
110
  | `/export.zip` | the whole dashboard as static HTML (`application/zip`, streamed, no JSON twin); see below |
92
111
 
112
+ A page auto-refreshes while what it shows can change: a run's pages while the run is live or
113
+ finalizing, a swarm's while the swarm is in memory, the project ledgers while a single run is
114
+ live, and the index always. A swarm and its hordes show as `pending` from the moment their directories
115
+ are allocated until the hordes have a TASK.md, which covers the minutes the planner takes, and as
116
+ `not started` when the planner could not partition the task.
117
+
93
118
  The download icon in the top-right corner of every page opens a warning that the export may
94
119
  leak sensitive data from this machine. Its download link goes to `/export`, which closes the
95
120
  warning, explains the wait, and starts the download of `/export.zip`. The zip holds one
96
121
  folder, `horde-dashboard-<timestamp>/`, whose `index.html` opens the dashboard from disk: every
97
122
  run, member, transcript page and entry, log, run document, collaboration page, graph (each width,
98
- plus the Mermaid file), and the ledgers under each run filter, with links rewritten relative to
123
+ plus the Mermaid file), and the ledgers of every scope, with links rewritten relative to
99
124
  each other. Exported pages do not refresh, expandable entries use the browser's own disclosure,
100
125
  finding bodies are shown inline, transcripts are paged fifty entries at a time, and the export
101
126
  control itself is absent. Pages that fail to load are exported as their error page, so no link
@@ -132,11 +157,17 @@ the session files, so they show end cause, turns, and usage but no activity.
132
157
  SUMMARY.md REPORT.md per-member status and usage; the reconciled run report
133
158
  ANSWER.md DELIVERABLE.md POSTMORTEM.md solved answer; synthesis output; reviewer critique
134
159
  GRAPH.md Mermaid graph of the run, written last at finalize
160
+ swarms/<swarm-id>/
161
+ SWARM.md SWARM.json prompt, partition, horde list; the swarm's timeline for the dashboard
162
+ planner-sessions/ deliverable-sessions/ planner and merge helper sessions
163
+ REPORT.md DELIVERABLE.md per-horde totals and file list; the merged deliverable
164
+ h1/ h2/ ... one complete horde directory per horde: its own ledgers,
165
+ .lock and runs/<swarm-id>-hN/ with everything a run has
135
166
  ```
136
167
 
137
168
  Each run appends a `## Run <id>` heading to BOARD.md and FINDINGS.md that cites `TASK.md` by
138
- sha256. `runs/` is gitignored inside `.horde/`; add `.horde/` to the project `.gitignore` to keep
139
- the ledgers out of git too.
169
+ sha256. `runs/` and `swarms/` are gitignored inside `.horde/`; add `.horde/` to the project
170
+ `.gitignore` to keep the ledgers out of git too.
140
171
 
141
172
  ## The `horde` tool
142
173
 
@@ -154,17 +185,19 @@ from the same actor as an idempotent retry. The parent appends its own lifecycle
154
185
  | `list`, `findings`, `facts`, `claims`, `resources`, `concerns` | print a ledger |
155
186
  | `post` | append a message to BOARD.md |
156
187
  | `idea` | add an open checklist item; a near-duplicate returns the existing id |
157
- | `claim`, `done`, `drop`, `rule-out` | take, finish, release, or close idea #id |
188
+ | `claim`, `done`, `drop`, `rule-out` | take, finish, release, or close idea #id; `done` with a confirmed-negative result line is refused in favour of `rule-out` |
158
189
  | `finding` | file under a claimed `idea` with a `concern` and `support`; `importance` and `confidence` are optional; `deltaOf: F#` adds distinct evidence, `supersedes: F#` corrects |
159
190
  | `verify` | record your own reproduction of F#id with the support level you reached |
160
- | `fact` | record a checkable fact; `deltaOf: T#` extends one |
191
+ | `amend` | rewrite the body prose of your own F#id (`text`) with a `note` saying why; the revision changes, reviews stay pinned to what they checked, earlier verification notes are kept as history of the previous revision, and the legacy `verified=` label and corroborators are dropped |
192
+ | `fact` | record a checkable fact; `deltaOf: T#` extends one; a fact about what an open idea or contested claim is still auditing is recorded as provisional on it |
161
193
  | `assert`, `confirm`, `contest`, `retract`, `supersede` | create or move claim C#id |
162
194
  | `resource` | claim a shared dataset, harness, corpus, or sandbox by name, with an optional `cleanup` command |
163
195
  | `solved`, `confirm-solved`, `contest-solved` | propose, validate, or refute the goal answer |
164
196
  | `message`, `inbox`, `ack`, `respond`, `resolve`, `defer` | targeted threads: question, blocker, review-request, challenge, handoff, decision |
165
197
  | `attach` | add supporting, contradicting, or extending evidence to a target |
166
- | `review` | record a revision-pinned check with explicit `checked` and `unchecked` scope, a verdict, and evidence refs; `evidenceText` attaches and reviews in one call |
167
- | `artifact` | publish a file under `artifacts/` with `artifactKind`, `criteria`, and revision-pinned `dependsOn` |
198
+ | `review` | record a revision-pinned check with explicit `checked` and `unchecked` (in-criteria gaps) scope, `limits` outside the criteria, a verdict, and evidence refs; `evidenceText` attaches and reviews in one call |
199
+ | `reattest` | carry your earlier review of F#/A# forward to its current revision, with evidence that what you checked is unchanged; refused across a changed artifact criteria or kind, a changed finding claim line, or a revision no `amend` started from |
200
+ | `artifact` | publish a file under `artifacts/` with `artifactKind`, `criteria`, and revision-pinned `dependsOn`; republishing a revision other artifacts pin needs `text` naming the change |
168
201
  | `resource-state` | publish building, ready, broken, or retired state with a lease, ports, and health evidence |
169
202
  | `inspect`, `collaboration` | one record in full (`F#`, `I#`, `R#`, `A#`, `E#`, `V#`, `Q#`, `answer`), or a paged index |
170
203
 
@@ -191,18 +224,40 @@ from the same actor as an idempotent retry. The parent appends its own lifecycle
191
224
  validated and every idea this run created or its members hold is done or ruled out. With no
192
225
  other member running, or no validation within `PI_HORDE_SOLVED_CONFIRM_MS`, an uncontested
193
226
  proposal commits as `solved-unvalidated`. Findings no other member reproduced hold wind-down
194
- while other members run, unless `PI_HORDE_ALLOW_UNVERIFIED=1`.
227
+ while other members run, unless `PI_HORDE_ALLOW_UNVERIFIED=1`. A proposal pins the revision of
228
+ every finding it cites. An answer that cites a superseded F# or quotes a provisional T# is
229
+ refused at `solved` and at `confirm-solved`; a pending proposal whose cited finding is
230
+ superseded or amended later is withdrawn (`solved-withdrawn`) for re-proposal. A contest that names idea ids reopens the proposal under a new revision
231
+ (`solved-reopened`) once every named idea is done or ruled out, with the citations it pinned;
232
+ if a cited finding changed or a quoted fact is still provisional by then, it is withdrawn instead. Repair serves a request about
233
+ the pending answer (`target=answer`) with the blockers.
195
234
  - **Reviews are revision-pinned.** A runnable artifact needs a full-scope `tested` or
196
235
  `reproduced` review from a non-owner. A `document` artifact (.md, .txt, .rst, .adoc, .pdf)
197
- accepts a full-scope `sourced` or `derived` review against its criteria. Changing criteria or
198
- dependencies needs changed bytes and a fresh review. Open blockers and challenges block
199
- acceptance; `defer` keeps the debt visible, the recipient can still `respond` to a deferred
200
- request, and the requester then resolves it. A challenger can withdraw its own blocking
201
- challenge on an F# or A# before any response by recording a supporting review of the current
202
- revision and resolving with evidence on it; limits that review discloses remain acceptance debt.
203
- The blocking challenge a `partially-supports` review raises is cleared when a different
204
- non-owner member records a full-scope `supports` review of the same revision; the resolution
205
- names both reviews. Acceptance names an open blocker as `blocked by Q#`.
236
+ accepts a full-scope `sourced` or `derived` review against its criteria. `unchecked` names gaps
237
+ inside the target's stated claim or criteria and keeps acceptance open; `limits` names
238
+ disclosures outside the criteria and is recorded on the acceptance (`Accepted with limits` in
239
+ ACCEPTANCE.md and COLLABORATION.md), never as a blocker. A `partially-supports` verdict refutes
240
+ nothing and opens no challenge: the acceptance names the review and what it left unchecked, and
241
+ another member's full-scope review settles it. Only `refutes` opens a challenge. Changing
242
+ criteria or dependencies needs changed bytes and a fresh review; republishing a revision that
243
+ other artifacts pin needs `text` naming the change, and the owner of each dependent is handed a
244
+ repin request when a pinned dependency is superseded or re-hashed. `reattest` carries a
245
+ reviewer's earlier review forward to the current revision with evidence that the checked
246
+ behaviour is unchanged; the parent prefers prior reviewers when assigning a re-review. Open
247
+ blockers and challenges block acceptance; `defer` keeps the debt visible, the recipient can
248
+ still `respond` to a deferred request, and the requester then resolves it. A challenger can
249
+ withdraw its own blocking challenge on an F# or A# before any response by recording a
250
+ supporting review of the current revision and resolving with evidence on it; limits that
251
+ review discloses remain acceptance debt. Acceptance names an open blocker as `blocked by Q#`.
252
+ - **Verifier.** The verifier's idea claims are refused while other members' findings await its
253
+ review at their current revision; the pending F# list follows every review, reattest and board
254
+ post. A verifier whose session closes with critical or high-importance findings unreviewed is
255
+ reset once more into a fresh session that owes them, within `PI_HORDE_RESET_CAP`. SUMMARY.md
256
+ derives its coverage sentence from the review records and names the unreviewed F#.
257
+ - **Reproductions.** A finding with an independent corroborator or a full-scope review is
258
+ settled: a claim whose text overlaps it is told to bring a new vector as `deltaOf`, and a
259
+ third duplicate report is dropped. A finding that cites a runnable under `artifacts/` no R# or
260
+ A# covers is told to register it.
206
261
  - **Inbox.** Targeted messages are inserted at turn boundaries, for at most
207
262
  `PI_HORDE_INBOX_TURNS` extra turns per session. A recipient answers with `respond`; `ack` is an
208
263
  optional first step that signals intent. Delivery is a context insertion, not
@@ -226,6 +281,57 @@ highest-importance unchecked assertions first with `horde review`, contest or su
226
281
  not reproduce, and claim ideas only when nothing is left to review. `--no-verifier` turns this
227
282
  off.
228
283
 
284
+ `--until-stop` keeps the whole horde working until you stop it. A validated solve does not wind
285
+ the run down: the answer is banked in ANSWER.md (and under `answers/`) as round N and the proposal
286
+ slot reopens, so a materially better answer can be proposed later. A member whose session finishes
287
+ is given a fresh session that reads the board, findings, and answer and adds ideas that extend,
288
+ stress-test, or deepen the work; these continuations count against no reset cap and are not
289
+ resets in the report. A session that finished within `PI_HORDE_CONTINUE_COOLDOWN_MS` (default
290
+ 60000) of starting waits out the remainder first, so a member that finds nothing to do cannot spin.
291
+ Crash and stall resets apply as usual. `stop-clean` and `stop-hard` end the run as usual and
292
+ `stop-clean` produces the report, deliverable, and postmortem; the last banked answer stands unless
293
+ a later proposal was validated too.
294
+
295
+ ## Horde of hordes
296
+
297
+ `H/M` launches a swarm: H concurrent hordes of M members on one task, H at most 4. A plain `M` is
298
+ a swarm of one and keeps the layout above; a larger swarm gets `.horde/swarms/<swarm-id>/` with one
299
+ complete horde directory per horde (`h1/`, `h2/`, ...), each with its own ledgers, lock and
300
+ `runs/<swarm-id>-hN/`. Hordes therefore never share a lock, a dedup pass or a coverage watermark,
301
+ and run ids stay unique across the swarm.
302
+
303
+ **Partition.** A plain prompt is split before launch by a read-only planner helper (`pi -p`, the
304
+ parent's model, `PI_HORDE_PLANNER_MS` timeout) into exactly H disjoint workstreams with one
305
+ acceptance criterion each, recorded in `SWARM.md` and in each horde's `TASK.md`; every member of a
306
+ horde is told its workstream and to work only on it. If the planner cannot produce H distinct
307
+ workstreams the launch stops with that message, the swarm directory keeps the planner session and
308
+ a `SWARM.md` saying why, and the slot stays free. `plan H/M a; b; c; ...` skips the planner: the
309
+ layers are dealt round-robin to the hordes (layer 1 to h1, layer 2 to h2, ...) and each horde runs
310
+ its share as its own plan, so there must be at least H layers.
311
+
312
+ **Sharing.** Shared read, local write. Each member's system prompt lists the sibling horde
313
+ directories; `horde facts` and `horde resources` append every sibling's entries tagged `[hN]`, and
314
+ `horde list` appends their done and ruled-out ideas, so a fact, a rule-out or a lab another horde
315
+ recorded is not re-derived. Open sibling ideas are not shown and nothing is written to a sibling:
316
+ the lock, dedup and coverage rules keep their per-horde scope. Members reuse a sibling's resource
317
+ by its path, not its R#.
318
+
319
+ **Lifecycle.** The hordes start `PI_HORDE_SWARM_STAGGER_MS` (default 5000) apart so H canaries do
320
+ not hit the provider at once; each then runs the lifecycle above unchanged, with its own canary,
321
+ resets, repair, acceptance, deliverable and post-mortem. `--until-stop` applies to every horde.
322
+ Controls take horde targets: `stop-clean h2` winds one horde down, `pause h2:member-3` one member,
323
+ `stop-hard` every horde, and `status` prints one block per horde. The swarm slot frees once every
324
+ horde has written its REPORT.md; after the last horde's finalize a synthesis helper reads the
325
+ hordes' DELIVERABLE.md, REPORT.md and ACCEPTANCE.md and writes the swarm `DELIVERABLE.md`, keeping
326
+ each claim attributed to its horde and to that horde's acceptance label, and the swarm `REPORT.md`
327
+ with per-horde members, turns, tokens, cost, findings and outcome. One swarm report is injected into
328
+ the parent conversation instead of one per horde. No horde reviews another's work; a verification
329
+ pass over the merged deliverable is not built.
330
+
331
+ **Dashboard and widget.** Each swarm has its own scope in the dashboard, with horde tabs and
332
+ swarm-wide ledger, collaboration and graph pages; see [Dashboard](#dashboard). The widget shows one
333
+ line per horde.
334
+
229
335
  ## Finding metadata
230
336
 
231
337
  `importance` (critical, high, medium, low, info), `confidence` (high, medium, low), and
@@ -253,10 +359,13 @@ carries a one-line diagnosis and, when generated, the post-mortem text.
253
359
  | variable | default | effect |
254
360
  |----------|---------|--------|
255
361
  | `PI_HORDE_DASHBOARD_PORT` | 7433 | dashboard port when `--dashboard` names none |
362
+ | `PI_HORDE_CONTINUE_COOLDOWN_MS` | 60000 | `--until-stop`: a finished session younger than this waits out the remainder before its fresh session starts |
256
363
  | `PI_HORDE_MAX_MINUTES` | off | clean stop at a wall-clock deadline |
257
364
  | `PI_HORDE_CANARY_MS` | 60000 | time for member-1 to produce output before a retry |
258
365
  | `PI_HORDE_STALL_MS` | 1800000 | reset a member with no ledger write for this long; `0` disables |
259
366
  | `PI_HORDE_RESET_CAP` | 2 | resets per member |
367
+ | `PI_HORDE_SWARM_STAGGER_MS` | 5000 | pause between one horde's launch and the next in a swarm |
368
+ | `PI_HORDE_PLANNER_MS` | 300000 | planner helper timeout when a swarm partitions a plain prompt |
260
369
  | `PI_HORDE_ACTIVE_GRACE_MS` | 15000 | one clean-stop extension for a member still producing output |
261
370
  | `PI_HORDE_SOLVED_CONFIRM_MS` | 120000 | wait for a second member to validate a solve |
262
371
  | `PI_HORDE_SOLVED_STOP_MS` | 30000 | extra wind-down window for a solve landing at the deadline |
@@ -295,9 +404,11 @@ watchdog.ts child exits when its parent pid is gone
295
404
  widget.ts TUI widget above the editor
296
405
  citations.ts R#/F#/T# and file-path citation checks for findings and generated artifacts
297
406
  dashboard.ts localhost HTTP server; dashboard-data.ts loads pages, dashboard-html.ts renders
407
+ build-info.ts the running package's version and checkout commit, for the dashboard footer
298
408
  collaboration-report.ts acceptance checks, frozen snapshots, collaboration metrics
299
409
  run-graph.ts events.jsonl projected into lanes, phases, nodes, and edges with dashboard links
300
410
  run-graph-svg.ts the swimlane SVG and its legend; run-graph-mermaid.ts the Mermaid export and GRAPH.md
411
+ swarm-graph.ts a swarm's hordes as lanes of lifecycle marks, plus the merge step
301
412
 
302
413
  ledger/ one module per .horde/ document, all writes under the .horde lock
303
414
  files.ts paths, init, atomic writes, shared entry formatting
@@ -322,10 +433,13 @@ tool/ the member-side `horde` tool
322
433
  resource-contract.ts resource generations, readiness, leases, and port coordination
323
434
 
324
435
  run/ the parent-side run lifecycle, sharing one HordeState
325
- types.ts HordeRun, HordeState, ReportDetails
326
- command.ts /agent-horde dispatch and session shutdown
436
+ types.ts HordeRun, Swarm, HordeState, ReportDetails
437
+ command.ts /agent-horde dispatch, horde-prefixed targets, session shutdown
327
438
  setup.ts run directory, TASK.md, roles, plan seeding
328
- launch.ts dashboard, deadline, canary preflight, fan-out
439
+ swarm.ts swarm directories and ids, dealing plan layers, planner output parsing
440
+ swarm-finalize.ts the swarm slot, the merge step, SWARM.json
441
+ swarm-report.ts per-horde totals: the swarm REPORT.md and the injected message
442
+ launch.ts dashboard, deadline, partition, staggered canary preflights, fan-out
329
443
  supervise.ts member spawn, reset on exit, stall detection
330
444
  schedule.ts artifact review assignment and superseded-dependency handoffs
331
445
  repair.ts bounded post-discovery reviews, owner repair, and recheck attempts
@@ -333,7 +447,7 @@ run/ the parent-side run lifecycle, sharing one HordeState
333
447
  controls.ts stop-hard, pause and resume, clean stop and its deadline
334
448
  finalize.ts reconcile, cleanups, SUMMARY.md and REPORT.md, report message, GRAPH.md
335
449
  lifecycle.ts parent lifecycle events in events.jsonl
336
- synthesis.ts deliverable and post-mortem helper agents
450
+ synthesis.ts deliverable, post-mortem, swarm merge and planner helper agents
337
451
  diagnosis.ts one-line run diagnosis
338
452
  ui.ts widget mount, status line, report renderer, notifications
339
453
  completions.ts command argument completions
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agent-horde",
3
- "version": "0.1.5",
3
+ "version": "0.2.0",
4
4
  "description": "Run a horde of pi agents on one task: shared ledgers, peer review, an auditable event log, and a live dashboard",
5
5
  "license": "MIT",
6
6
  "type": "module",