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.
- package/CHANGELOG.md +215 -2
- package/CONTRIBUTING.md +4 -17
- package/README.md +25 -21
- package/agents/worker.md +1 -1
- package/docs/contracts/display-liveness-v1.md +373 -0
- package/docs/contracts/drop-non-pi-kinds-v4.md +198 -0
- package/docs/contracts/esc-abort-v1.md +4 -4
- package/docs/contracts/esc-no-retire-v3.md +2 -2
- package/docs/contracts/launch-admission-queue-v1.md +839 -0
- package/docs/contracts/status-panel-v1.md +174 -0
- package/docs/inprocess-supervisor.md +37 -4
- package/docs/legion-v2-contract.md +18 -2
- package/docs/performance-2026-10-19.md +199 -0
- package/docs/vexillatio-contract.md +3 -1
- package/index.ts +557 -76
- package/package.json +4 -2
- package/skills/pi-legion/SKILL.md +2 -3
- package/src/agents/agents.ts +17 -10
- package/src/agents/overrides.ts +0 -1
- package/src/agents/presets.ts +14 -40
- package/src/agents/settings.ts +26 -77
- package/src/agents/step-model.ts +7 -22
- package/src/api.ts +1 -35
- package/src/extension/event-bus.ts +80 -8
- package/src/extension/legion-commands.ts +41 -17
- package/src/extension/legion-doctor.ts +1 -1
- package/src/extension/legion-stop.ts +39 -13
- package/src/extension/legion-tools.ts +21 -4
- package/src/extension/liveness.ts +200 -0
- package/src/extension/playbook.ts +2 -2
- package/src/extension/recycle.ts +4 -0
- package/src/extension/runtime.ts +379 -15
- package/src/extension/slash.ts +0 -21
- package/src/extension/summary.ts +1 -1
- package/src/legion/db.ts +165 -1
- package/src/legion/events.ts +81 -16
- package/src/legion/nodes.ts +13 -2
- package/src/legion/rebuild.ts +7 -1
- package/src/legion/usage.ts +58 -4
- package/src/runs/orchestrator.ts +1165 -62
- package/src/runs/worktree.ts +190 -21
- package/src/shared/ignored-kind.ts +57 -0
- package/src/shared/progress.ts +11 -0
- package/src/shared/session.ts +199 -19
- package/src/shared/types.ts +50 -66
- package/src/supervisor/admission-queue.ts +516 -0
- package/src/supervisor/inprocess-supervisor.ts +108 -33
- package/src/supervisor/proc-memory.ts +67 -0
- package/src/supervisor/routing-supervisor.ts +58 -1
- package/src/tui/session-messages-file.ts +100 -0
- package/src/tui/status.ts +91 -18
- package/src/tui/tree-view.ts +28 -3
- package/src/tui/viz/layout.ts +54 -3
- package/src/tui/viz/model.ts +67 -14
- package/src/tui/viz/palette.ts +11 -0
- package/src/tui/viz/panels.ts +222 -8
- package/src/tui/viz/view.ts +110 -23
- package/src/backends/legacy/client.ts +0 -638
- package/src/backends/legacy/cursor-chat.ts +0 -348
- package/src/backends/legacy/runner.ts +0 -101
- package/src/backends/legacy/types.ts +0 -138
- 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#
|
|
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/
|
|
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
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
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
|
-
- [
|
|
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
|
|
88
|
-
|
|
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).
|
|
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
|
|
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
|
-
##
|
|
508
|
+
## Supported kinds
|
|
509
509
|
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
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
|
-
|
|
528
|
-
|
|
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
|
|