pi-legion 3.1.0 → 4.0.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.
Files changed (62) hide show
  1. package/CHANGELOG.md +215 -2
  2. package/CONTRIBUTING.md +4 -17
  3. package/README.md +25 -21
  4. package/agents/worker.md +1 -1
  5. package/docs/contracts/display-liveness-v1.md +373 -0
  6. package/docs/contracts/drop-non-pi-kinds-v4.md +198 -0
  7. package/docs/contracts/esc-abort-v1.md +4 -4
  8. package/docs/contracts/esc-no-retire-v3.md +2 -2
  9. package/docs/contracts/launch-admission-queue-v1.md +839 -0
  10. package/docs/contracts/status-panel-v1.md +174 -0
  11. package/docs/inprocess-supervisor.md +37 -4
  12. package/docs/legion-v2-contract.md +18 -2
  13. package/docs/performance-2026-10-19.md +199 -0
  14. package/docs/vexillatio-contract.md +3 -1
  15. package/index.ts +557 -76
  16. package/package.json +4 -2
  17. package/skills/pi-legion/SKILL.md +2 -3
  18. package/src/agents/agents.ts +17 -10
  19. package/src/agents/overrides.ts +0 -1
  20. package/src/agents/presets.ts +14 -40
  21. package/src/agents/settings.ts +26 -77
  22. package/src/agents/step-model.ts +7 -22
  23. package/src/api.ts +1 -35
  24. package/src/extension/event-bus.ts +80 -8
  25. package/src/extension/legion-commands.ts +41 -17
  26. package/src/extension/legion-doctor.ts +1 -1
  27. package/src/extension/legion-stop.ts +39 -13
  28. package/src/extension/legion-tools.ts +21 -4
  29. package/src/extension/liveness.ts +200 -0
  30. package/src/extension/playbook.ts +2 -2
  31. package/src/extension/recycle.ts +4 -0
  32. package/src/extension/runtime.ts +379 -15
  33. package/src/extension/slash.ts +0 -21
  34. package/src/extension/summary.ts +1 -1
  35. package/src/legion/db.ts +165 -1
  36. package/src/legion/events.ts +81 -16
  37. package/src/legion/nodes.ts +13 -2
  38. package/src/legion/rebuild.ts +7 -1
  39. package/src/legion/usage.ts +58 -4
  40. package/src/runs/orchestrator.ts +1165 -62
  41. package/src/runs/worktree.ts +190 -21
  42. package/src/shared/ignored-kind.ts +57 -0
  43. package/src/shared/progress.ts +11 -0
  44. package/src/shared/session.ts +199 -19
  45. package/src/shared/types.ts +50 -66
  46. package/src/supervisor/admission-queue.ts +516 -0
  47. package/src/supervisor/inprocess-supervisor.ts +108 -33
  48. package/src/supervisor/proc-memory.ts +67 -0
  49. package/src/supervisor/routing-supervisor.ts +58 -1
  50. package/src/tui/session-messages-file.ts +100 -0
  51. package/src/tui/status.ts +91 -18
  52. package/src/tui/tree-view.ts +28 -3
  53. package/src/tui/viz/layout.ts +54 -3
  54. package/src/tui/viz/model.ts +67 -14
  55. package/src/tui/viz/palette.ts +11 -0
  56. package/src/tui/viz/panels.ts +222 -8
  57. package/src/tui/viz/view.ts +110 -23
  58. package/src/backends/legacy/client.ts +0 -638
  59. package/src/backends/legacy/cursor-chat.ts +0 -348
  60. package/src/backends/legacy/runner.ts +0 -101
  61. package/src/backends/legacy/types.ts +0 -138
  62. package/src/runs/kind.ts +0 -260
package/CHANGELOG.md CHANGED
@@ -11,6 +11,216 @@ summary so you can see **2.x vs 0.16** without leaving the tree.
11
11
 
12
12
  ## [Unreleased]
13
13
 
14
+ ## [4.0.0] — 2026-10-24
15
+
16
+ A major line — but not only the pi-only collapse. Relative to 3.1.0 this release
17
+ removes every non-`pi` agent kind and the archived Herdr backend behind it, along
18
+ with the settings and error codes that only its transport read. It also carries
19
+ everything else that landed on `master` while that removal was held back: a
20
+ launch admission queue that queues instead of refusing, one liveness verdict
21
+ shared by every display surface, a status panel built on pid / rss /
22
+ context-token data, and ten measured performance fixes.
23
+
24
+ ### Breaking
25
+
26
+ - **Kinds collapse to `pi`.** `AGENT_KINDS` is now `["pi"]`; the
27
+ `cursor` / `claude` / `codex` / `gemini` and other third-party CLI kinds are
28
+ gone, and with them the `cursorModel` / `nativeModelFor` / `planKindStart`
29
+ model translation and the "model dropped, runs on its own default" notice
30
+ (a `pi` child expresses every model, so the case no longer exists). `kind` is
31
+ still a legal frontmatter key, but `pi` is the only accepted value: a non-`pi`
32
+ value is ignored — one note on stderr per role (deduplicated, because the
33
+ catalog is re-read on several UI paths) naming the role and the original
34
+ value — and the role launches as `kind: pi`. The same applies to
35
+ `subagents.presets.<role>.kind` and `subagents.agentOverrides.<role>.kind`,
36
+ the three places a role's `kind` can come from. No legacy prefix aliases.
37
+ - **Herdr backend removed.** `src/backends/legacy/` and `test/legacy/` are
38
+ deleted, together with the deprecated `pi-legion/api` re-exports that only
39
+ served them (`createHerdrClient`, `parseHerdrResponse`, `mapHerdrErrorCode`,
40
+ `readPaneDiagnostic`, `createCommandRunner`, `resolveHerdrBin`, `HerdrClient`
41
+ and their types). `pi-legion@0.16.x` stays the pin for the Herdr-era
42
+ execution model; the `spawnMode: rpc` / `inprocess` backends are unaffected —
43
+ those are two ways of running **Pi**, not third-party transports.
44
+ - **Dead `herdr.*` settings removed.** `subagents.herdr.*` is no longer parsed
45
+ (a leftover block is silently ignored, as it has been ignored since 2.0.0),
46
+ the seven `herdr` constants are gone from `DEFAULTS`, and
47
+ `ErrorCodes.HERDR_UNAVAILABLE` / `ErrorCodes.PANE_BUSY` are removed.
48
+ `RunRecord.herdr` and `StatusEntry.herdrStatus` stay: they carry live
49
+ `{supervisor, node_id}` state, not backend selection.
50
+
51
+ ### Added
52
+
53
+ - **Launch admission queue (#266).** A launch that exceeds a *concurrency* gate
54
+ (`maxChildrenPerNode`, `maxActive`, ledger `max_children_per_node` /
55
+ `max_active_nodes`) no longer fails with `BUDGET_EXCEEDED`. It is enqueued,
56
+ the caller gets `▶ scout-7 (scout) supervisor=inprocess queued(3)` and treats
57
+ the work as dispatched, and the child starts automatically when a slot frees.
58
+ Previously a 12-step fan-out against `maxChildrenPerNode: 8` ran 8 children and
59
+ reported 4 errors — and nothing ever retried them, because the parent was
60
+ already inside `wait` and the freed slot had no subscriber.
61
+ - New settings: `subagents.inprocess.maxQueuedLaunches` (default **32**) and
62
+ `subagents.inprocess.launchQueueTimeoutMs` (default **900000**). Both are
63
+ shared by the in-process and RPC paths — one scheduler, not two.
64
+ - Depth, spawn-per-session, memory, name-collision and config errors are still
65
+ refused synchronously, byte-identically to before: only gates that a slot
66
+ release can satisfy are queueable. `maxChildrenPerNode: 0` is a hard refusal
67
+ (0 means "no children", so waiting can never satisfy it).
68
+ - A queued launch reserves nothing: no ledger row, no child run directory, no
69
+ worktree, no session file. `timeout`/`overflow`/`stop` are reported by name;
70
+ `stop` dequeues without ever spawning, and a parent-turn abort flushes the
71
+ queue and says how many launches it dropped.
72
+ - `subagent({action:"status"})` shows `state=queued`, `collect`/`wait` block
73
+ until admission instead of reading the placeholder session path, and
74
+ `async: false` reports `↳ <name> waited Ns in the launch queue`.
75
+ - Two new process-only events (`launch_queued`, `launch_admitted`) and a
76
+ `legion-queue: N queued` status pill.
77
+
78
+
79
+ - **One liveness verdict for every display surface (#liveness).** The list, the
80
+ text view and the railway chart each decided "is this agent still working?"
81
+ their own way, and the railway one compared two clocks that no single writer
82
+ owned: `eventOverrides` vetoed an event against `node.updatedAt`, but the
83
+ event row is stamped by this process's event bus while `updatedAt` is stamped
84
+ by the child's heartbeat — and only `isAlive` children are heartbeaten, so a
85
+ dead child's `updatedAt` freezes. The comparison ranked two clocks and the
86
+ losing side was the truthful one: a finished node was repainted `running`,
87
+ forever, because the frozen row never moved again. `src/extension/liveness.ts`
88
+ replaces all three with one `liveness(facts)` in TOTAL ORDER — `live` /
89
+ `dead` / `unknown` — with no clock, no fs and no timer of its own. Unknown or
90
+ unrecognized states now render `unknown` instead of being guessed into
91
+ `retired`, and `queued` is a first-class display state.
92
+ - Contract: `docs/contracts/display-liveness-v1.md` (frozen first, then
93
+ implemented; D1-a and D5-a record two amendments found during the work).
94
+
95
+ - **A status panel on the `/legion` board (#241, #245).** A fifth pane carries
96
+ the `/legion status` table onto the full-screen viewer — name · role · state ·
97
+ supervisor · ctx · rss · turns — graded down by absolute column count
98
+ (72/52/36/20) so a narrow board keeps name · state instead of a column of
99
+ stubs. A portrait layout gets a zero-area rect and Tab skips it rather than
100
+ painting a fifth pane that cannot fit. Only an `rpc` child owns a process, so
101
+ only it shows rss; an `inprocess` child shows `—` rather than a share of the
102
+ host figure it does not own, because a fabricated number would get used.
103
+ - `pid`, `spawnMode`, `contextTokens` and `rss` are optional on `VizNode` and
104
+ projected conditionally: a missing mode renders `unknown`, never a guessed
105
+ `rpc`. No new `legion.db` column and no schema-version bump — pid is
106
+ host-scoped and never persisted, so a rebuild from a `ChildRecord` invents
107
+ none.
108
+ - Context tokens are absolute only. Session JSONL carries no context window,
109
+ so no percentage is computed and none is displayed.
110
+ - `/legion status` also stopped dropping `spawnMode` and now supplies `owner`.
111
+
112
+ - **`/legion stop --force` (#179).** The TUI slash command can now hard-retire a
113
+ child, equivalent to the tool's `force: true`; `--force` / `-f` is listed in
114
+ the doctor help and the README. This closes the "optional follow-up" that the
115
+ docs had been carrying.
116
+
117
+ - **`vexillatio` accepts `tasks[]` on its own.** `task` was required, so a
118
+ `{tasks: [...]}` call was rejected by the host's typebox pre-validation before
119
+ Legion ever saw it, and callers had to send a dummy `task` and retry. It is
120
+ optional now; a `tasks[]`-only launch is legal.
121
+
122
+ ### Changed
123
+
124
+ - **WAL is now an enforced startup precondition (#236).** `openLegionDb` used to
125
+ discard the value returned by `PRAGMA journal_mode = WAL`. That PRAGMA is a
126
+ *query*: the returned mode is the ground truth, and SQLite is entitled to
127
+ answer with the mode it settled on rather than to fail — which is how a
128
+ connection ends up on a rollback journal while every reader of the code
129
+ believes WAL is live. The ledger's durability reasoning (single-writer
130
+ serialisation, readers that never block the writer, the shutdown checkpoint)
131
+ rests entirely on WAL, so the observed mode is now captured and verified: a
132
+ file database that does not report `wal` throws at startup, with the observed
133
+ mode in the message, instead of surfacing later as data loss. `:memory:` is
134
+ exempt deliberately, keyed on `PRAGMA database_list` reporting an empty
135
+ `file` — not on a database name, and not by accident.
136
+ - The M2-(g) concurrency acceptance now runs as `npm run test:wal-stress`:
137
+ 60 supervisor processes against one ledger, 9004 attempts, 9004 commits, 0
138
+ busy, p50 1.03 ms / p95 1.99 ms / p99 4.92 ms.
139
+
140
+ - **The worker role's turn budget is 45 minutes, not 30.** The worker does the
141
+ heaviest per-dispatch work — several files, its own verification run, and a
142
+ report — yet it shared centurion's budget while scout gets 10 minutes and
143
+ reviewer 15. Two dispatches in this repository were cut off mid-work, one
144
+ with nothing on disk and one that ran out while verifying. 45 rather than 60
145
+ keeps a genuinely stuck child from holding a concurrency slot for an hour.
146
+ Only `timeoutMs` changed.
147
+
148
+ ### Fixed
149
+
150
+ - **A poison event row no longer freezes the cross-process event poller
151
+ (#233).** `node_abandoned` was missing from the event-type closed set, so a
152
+ snapshot row of that type could not be decoded; the 250 ms poller then threw
153
+ on the same row forever, its cursor never advanced, and no later event was
154
+ ever delivered. The closed set now contains `node_abandoned` (15 types), and
155
+ the poller advances past a single poison row instead of freezing: the row is
156
+ reported once through `onError`, the cursor steps over it, and the remaining
157
+ events in that batch are still delivered.
158
+
159
+ - **A finished supervisor's pid is no longer read as its successor's (#250).**
160
+ `rss` probes re-read `/proc/<pid>` after the child had exited, and Linux
161
+ reuses pids; the panel could attribute a stranger's memory to a retired node.
162
+ The probe now closes the race it was silently losing.
163
+
164
+ - **The log view stays inside its rect on narrow panes (#251).** `drawLog` wrote
165
+ past its own `maxX` when the pane was squeezed, which corrupted the frame
166
+ beside it.
167
+
168
+ - **The live overlay no longer scans the whole tree per token (#261).** A
169
+ per-token `getTreeNodes()` call made a long child turn quadratic in the number
170
+ of nodes; the scan is gone and re-opening the node that is already open is
171
+ guarded.
172
+
173
+ - **Repository subdirectories are no longer mistaken for child worktrees
174
+ (#237 P10).** The probe treated any git-visible path below the repo root as an
175
+ existing worktree, so a dispatch from `src/` could reuse the wrong directory.
176
+ All git probes are now bounded: `GIT_PROBE_TIMEOUT_MS = 5_000` and
177
+ `GIT_WORKTREE_TIMEOUT_MS = 120_000`, so a hung `git` can no longer wedge a
178
+ launch forever.
179
+
180
+ - **`SubagentError` is exported explicitly again.** It had reached
181
+ `pi-legion/api` only as a side effect of the legacy client re-exporting it, so
182
+ removing the Herdr backend silently dropped it from the public surface. It is
183
+ a deliberate export now, pinned by a test.
184
+
185
+ ### Performance
186
+
187
+ Ten fixes measured against the baseline in `docs/performance-2026-10-19.md`,
188
+ plus the harness that measured them (#239). Numbers below are the before/after
189
+ from each fix's own commit.
190
+
191
+ - **`collect()` no longer waits out a fixed settle-quiet window (#232).** An
192
+ already-settled turn cost a flat ~2.5 s of dead time; that wait is dropped when
193
+ the turn is settled (2509 ms → 503 ms).
194
+ - **The settle polls back off instead of re-parsing every 500 ms (#232).** The
195
+ transient-connection wait re-parsed the whole session file on every tick. It
196
+ now keeps the last parse, re-parses only when the artifact size moved, and
197
+ backs off 500 ms → 4 s. On an unchanged file in a 900 s window: 1800
198
+ iterations / 1804 parses → 228 iterations / 5 parses. The blip tolerance is
199
+ unchanged — sleeps are clamped to the remaining budget and the loop still ends
200
+ exactly on the deadline.
201
+ - **The `/legion` log view reads the session incrementally (#234).** It seeks
202
+ past the cached byte offset and projects only the new JSONL lines, instead of
203
+ re-parsing from the top on every refresh.
204
+ - **`attachUsageTotals` is one batched query (#235/#248).** It accounted for
205
+ ~72% of the cost of a UI snapshot; it is now a chunked `IN` query instead of a
206
+ per-node round trip.
207
+ - **Heartbeats are one transaction (#236 P1).** N children meant N commits;
208
+ eight children now cost one (3.83 ms → 0.99 ms, 3.9×).
209
+ - **Prepared statements are cached per connection (#236 P2).** `getNode` ×400
210
+ drops 15.7 ms → 4.8 ms.
211
+ - **Session parsing projects its result instead of `structuredClone` (#237 P7).**
212
+ - **The DB event source seeds its cursor at attach instead of replaying the log
213
+ (#238).** Attaching used to block ~1027 ms on replay.
214
+ - **Widget events are coalesced into one snapshot and one paint per tick
215
+ (#238).** `legion-tools` emits N `mail_sent` events in one synchronous loop, so
216
+ every burst cost 2N scans; a burst now costs a constant 2 snapshots — 2575 ms
217
+ → 4.4 ms for 1000 events over a 120-node ledger. `applyTreeEvent` itself still
218
+ runs synchronously, per event, in arrival order: it is an incremental state
219
+ machine, not a render, so deferring or reordering it would change the state it
220
+ computes.
221
+ - **The messages rate-limit `COUNT` is covered by an index (#237 P9).** 50k rows
222
+ go from a `SCAN` to ~6.6 µs.
223
+
14
224
  ## [3.1.0] — 2026-10-19
15
225
 
16
226
  ### Added
@@ -436,12 +646,15 @@ First **Pi Legion** line on headless Pi RPC. Relative to the final Herdr-era
436
646
 
437
647
  Last line that runs children in Herdr panes. Not developed further on this
438
648
  branch — pin `pi-legion@0.16.x` if you still need that model. See
439
- [Herdr transition](README.md#herdr-transition-and-role-migration) in the README.
649
+ [Herdr transition](README.md#supported-kinds) in the README.
440
650
 
441
651
  Earlier 0.11–0.15 history (including the `pi-herdr-swarm` /
442
652
  `@zzjcool/pi-herdr-subagents` renames) lives in git tags and older Releases.
443
653
 
444
- [Unreleased]: https://github.com/zzjcool/pi-legion/compare/v3.0.2...HEAD
654
+ [Unreleased]: https://github.com/zzjcool/pi-legion/compare/v4.0.0...HEAD
655
+ [4.0.0]: https://github.com/zzjcool/pi-legion/compare/v3.1.0...v4.0.0
656
+ [3.1.0]: https://github.com/zzjcool/pi-legion/compare/v3.0.3...v3.1.0
657
+ [3.0.3]: https://github.com/zzjcool/pi-legion/compare/v3.0.2...v3.0.3
445
658
  [3.0.2]: https://github.com/zzjcool/pi-legion/compare/v3.0.1...v3.0.2
446
659
  [3.0.1]: https://github.com/zzjcool/pi-legion/compare/v3.0.0...v3.0.1
447
660
  [3.0.0]: https://github.com/zzjcool/pi-legion/compare/v2.0.4...v3.0.0
package/CONTRIBUTING.md CHANGED
@@ -107,10 +107,10 @@ the top of that file). Do not fail CI on it.
107
107
  Prefer **TDD** for behaviour changes: a failing test in `test/unit` or
108
108
  `test/integration` first, then the production code. Integration tests should
109
109
  drive the orchestrator through `FakeSupervisor` (`test/helpers/fake-supervisor.ts`)
110
- so nesting / launch / collect stay covered without a live `pi`. The herdr-era
111
- helpers `createHerdrClient` / `createFakeRunner` remain as **deprecated legacy**
112
- exports (see `src/api.ts` and `test/legacy/`); use them only when touching the
113
- archived Herdr backend.
110
+ so nesting / launch / collect stay covered without a live `pi`. The old
111
+ herdr-era `createHerdrClient` / `createFakeRunner` helpers are **gone** as of
112
+ v4.0.0, together with `src/backends/legacy/` and `test/legacy/`; everything
113
+ runs as `kind: pi`, in-process or over `pi --mode rpc`.
114
114
 
115
115
  ## Mock LLM
116
116
 
@@ -161,19 +161,6 @@ Or all at once (RPC mainline **1–11** only):
161
161
  npm run test:docker
162
162
  ```
163
163
 
164
- **Legacy Herdr / Space / kind checks** live under `test/legacy/docker/` (need
165
- pi-legion **0.16.x** Herdr-era setup). They are **not** part of
166
- `npm run test:docker`:
167
-
168
- ```bash
169
- bash test/legacy/docker/verify-12-workspace.sh # Herdr Space pin (legacy)
170
- bash test/legacy/docker/verify-13-kinds.sh # kind/model matrix; live CodeBuddy when mounted
171
- ```
172
-
173
- `verify-13-kinds.sh` also bind-mounts host `codebuddy` / `cursor-agent` and
174
- (unless `LIVE_KIND_PROBES=0`) calls live CodeBuddy. The numbered 1–11 scripts
175
- under `test/docker/` stay offline/mock.
176
-
177
164
  Override paths with `HOST_PI_AGENT`, `DOCKER_PI_HOME`, `PI_DOCKER_IMAGE`.
178
165
 
179
166
  Each `inside-N-*.sh` is what actually runs **in** the container. Keep those
package/README.md CHANGED
@@ -30,7 +30,7 @@ shared SQLite ledger records the whole tree.
30
30
  - [Team 配置](#team-配置)
31
31
  - [Parent/child context conventions](#parentchild-context-conventions)
32
32
  - [Delivery and resume](#delivery-and-resume)
33
- - [Herdr transition and role migration](#herdr-transition-and-role-migration)
33
+ - [Supported kinds](#supported-kinds)
34
34
  - [Changelog](CHANGELOG.md)
35
35
  - [Development](#development)
36
36
 
@@ -84,9 +84,8 @@ trades process isolation for spawn latency.
84
84
  **Automatic fallback to `rpc`:** when `spawnMode` is omitted *and* the resolved
85
85
  spawn cannot be in-process, Legion launches it over `pi --mode rpc` instead.
86
86
  That happens when the role needs an OS worktree (`worktree: true` — only the
87
- `centurion` role may hold this; see Isolation below). A `kind !== "pi"` role is
88
- rejected earlier with `INVALID_PARAMS` (only `kind: pi` children are supported
89
- at all), so it never reaches this fallback.
87
+ `centurion` role may hold this; see
88
+ [Delivery and resume](#delivery-and-resume)).
90
89
 
91
90
  **Explicit is strict:** `spawnMode: "inprocess"` with `worktree: true` is
92
91
  refused with `INVALID_PARAMS` (message prefers `set worktree: false`) rather
@@ -167,16 +166,17 @@ controls run graceful `stop` (a stopped parent retires its own subtree on
167
166
  shutdown); process exit / session shutdown also retires:
168
167
 
169
168
  - **`/legion stop`** stops every live subagent; **`/legion stop <name>`** stops
170
- one (`all` is an alias for no name). Names complete from the live children;
169
+ one (`all` is an alias for no name). Add **`--force`** / **`-f`** for hard
170
+ retire (same as tool `force: true`). Names complete from the live children;
171
171
  nested agents complete as `parent/name` and are reported as owned by their
172
172
  parent (stop the parent to retire them).
173
173
  - **`x`** on the selected live agent in the `/legion` view or its live
174
- overlay asks `y` to confirm in place, then stops it.
174
+ overlay asks `y` to confirm in place, then stops it (graceful; use
175
+ `/legion stop --force <name>` for hard retire).
175
176
  - **Tool**: `subagent({ action: "stop", name })` is graceful; pass
176
177
  `force: true` for hard retire (SIGTERM → SIGKILL + descendant sweep per
177
178
  `docs/retire-hardening-contract.md`). Example:
178
179
  `subagent({ action: "stop", name: "worker-0", force: true })`.
179
- TUI `/legion stop --force` is an optional follow-up (same `force: true`).
180
180
 
181
181
  **`wait` ≠ stop.** A `wait` timeout (or still-running result) does **not**
182
182
  retire children. The tool result includes live child names, elapsed ms, and
@@ -184,8 +184,8 @@ suggested decisions (`extend` / `steer_again` / `stop` / `force_stop`); the
184
184
  parent chooses the next tool call. See `docs/contracts/wait-not-stop.md`.
185
185
 
186
186
  While subagents are live, the railway header can show a dim
187
- `/legion stop [name|all]` hint (shortened on narrow terminals; idle gating /
188
- tree-strip coverage is a TUI follow-up).
187
+ `/legion stop [--force] [name|all]` hint (shortened on narrow terminals; idle
188
+ gating / tree-strip coverage is a TUI follow-up).
189
189
 
190
190
  ### Status (`/legion status`)
191
191
 
@@ -505,17 +505,13 @@ process ends, its child processes do not become detached workers; resuming the
505
505
  parent restores the squad, while already-settled children are not restarted.
506
506
  Keep the run records and session files while the tree may need to resume.
507
507
 
508
- ## Herdr transition and role migration
508
+ ## Supported kinds
509
509
 
510
- Version **0.16.x is the final Herdr-era line**. Pi Legion 2.x is RPC-only:
511
- child execution uses headless `pi --mode rpc` processes, and the legacy backend
512
- is archived under `src/backends/legacy/`, not offered as a v2 runtime option.
513
- Pin to `pi-legion` 0.16.x if a workflow must stay on the former Herdr-based
514
- execution model. A short breaking-change summary lives in
515
- [CHANGELOG.md](CHANGELOG.md#200---2026-10-14).
516
-
517
- Pi Legion 2.x supports `kind: pi` only. Migrate a custom role that uses another
518
- CLI kind by changing its frontmatter, for example:
510
+ Pi Legion runs `kind: pi` roles only. `kind` is still a legal frontmatter key,
511
+ but `pi` is the only accepted value: a non-`pi` value is ignored (one note on
512
+ stderr) and the role launches as `kind: pi`. The same holds for
513
+ `subagents.presets.<role>.kind` and `subagents.agentOverrides.<role>.kind` —
514
+ those three spots are the only places a role's `kind` can come from.
519
515
 
520
516
  ```yaml
521
517
  ---
@@ -524,8 +520,16 @@ kind: pi
524
520
  ---
525
521
  ```
526
522
 
527
- A non-Pi kind is rejected by v2. If that role must continue to run through
528
- another CLI, keep it on the 0.16.x line or replace it with a Pi role.
523
+ Child execution is Pi either way: in-process by default, with an automatic
524
+ `rpc` fallback when the resolved spawn needs an OS worktree (see
525
+ [Spawn mode](#spawn-mode)).
526
+
527
+ Version **0.16.x was the final Herdr-era line** — it launched children in Herdr
528
+ panes instead of Pi processes. That backend was archived under
529
+ `src/backends/legacy/` for 2.x and 3.x, and is gone in v4. Pin to
530
+ `pi-legion@0.16.x` if a workflow must stay on that former execution model; a
531
+ short breaking-change summary lives in
532
+ [CHANGELOG.md](CHANGELOG.md#200---2026-10-14).
529
533
 
530
534
  ## Development
531
535
 
package/agents/worker.md CHANGED
@@ -6,7 +6,7 @@ systemPromptMode: replace
6
6
  inheritProjectContext: true
7
7
  inheritSkills: false
8
8
  async: true
9
- timeoutMs: 1800000
9
+ timeoutMs: 2700000
10
10
  allowNestedSubagents: true
11
11
  acceptance:
12
12
  level: verified