@sztlink/pi-ensemble 0.1.0-alpha.12

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.
@@ -0,0 +1,149 @@
1
+ # pi-ensemble quickstart
2
+
3
+ `pi-ensemble` is a local coordination ledger for coding agents. It does not start agents or move work between machines. It only writes readable files under `.pi-ensemble/`.
4
+
5
+ ## 1. Initialize a workspace
6
+
7
+ ```bash
8
+ cd /path/to/project
9
+ ensemble init --agent pi
10
+ ensemble status
11
+ ```
12
+
13
+ If you often work from nested repositories, subdirectories, or a neutral runtime root, pin the canonical ledger root:
14
+
15
+ ```bash
16
+ export PI_ENSEMBLE_ROOT=/path/to/project
17
+ ensemble overview
18
+ # or per command:
19
+ ensemble --root /path/to/project overview
20
+
21
+ # Example: agent stays in /home/aya while ledger lives in /home/aya/implante
22
+ PI_ENSEMBLE_ROOT=/home/aya/implante ensemble inbox --agent claude --since-last-read
23
+ ```
24
+
25
+ This creates:
26
+
27
+ ```txt
28
+ .pi-ensemble/
29
+ config.yaml
30
+ blackboard.md
31
+ agents/pi/inbox.md
32
+ agents/pi/state.json
33
+ worktrees.json
34
+ audit.jsonl
35
+ ```
36
+
37
+ ## 2. Record a durable fact
38
+
39
+ ```bash
40
+ ensemble note "Decision: Pi is coordinating; Claude lead will run Agent Teams internally." --from pi
41
+ ensemble board
42
+ ```
43
+
44
+ Use the blackboard for facts that should outlive terminal scrollback.
45
+
46
+ ## 3. Send a handoff
47
+
48
+ ```bash
49
+ ensemble send claude-lead \
50
+ "Please run a three-teammate Agent Teams review. Mirror only final findings back here." \
51
+ --from pi \
52
+ --type handoff
53
+ ```
54
+
55
+ The receiver reads only new messages since its last read:
56
+
57
+ ```bash
58
+ ensemble inbox --agent claude-lead --since-last-read
59
+ ```
60
+
61
+ When the receiver is done:
62
+
63
+ ```bash
64
+ ensemble send pi "Result: findings saved at docs/review.md" --from claude-lead --type result
65
+ # Optional lifecycle trace:
66
+ ensemble ack msg_xxx --from claude-lead --body "received"
67
+ ensemble done msg_xxx --from pi --body "resolved"
68
+ ```
69
+
70
+ ## 4. Claim paths before concurrent work
71
+
72
+ ```bash
73
+ ensemble claim lib/core.mjs --agent claude-lead
74
+ ```
75
+
76
+ If another agent tries to claim the same path, `pi-ensemble` fails unless `--force` is used:
77
+
78
+ ```bash
79
+ ensemble claim lib/core.mjs --agent pi
80
+ # Path already claimed by claude-lead...
81
+ ```
82
+
83
+ Release when done:
84
+
85
+ ```bash
86
+ ensemble release lib/core.mjs --agent claude-lead
87
+ ```
88
+
89
+ ## 5. JSON mode for adapters
90
+
91
+ Adapters can use JSON output:
92
+
93
+ ```bash
94
+ ensemble inbox --agent pi --since-last-read --json
95
+ ensemble claim docs/ROADMAP.md --agent pi --json
96
+ ensemble claims --json
97
+ ensemble audit --limit 20 --json
98
+ ensemble timeline --limit 20
99
+ ensemble messages --open
100
+ ensemble overview
101
+ ensemble doctor
102
+ ```
103
+
104
+ ## Pi usage
105
+
106
+ After installing as a Pi package and reloading Pi:
107
+
108
+ ```txt
109
+ /ensemble status
110
+ /ensemble note durable fact
111
+ /ensemble send claude-lead handoff text --type handoff
112
+ /ensemble inbox
113
+ ```
114
+
115
+ Pi also gets an `ensemble` tool with the same core actions.
116
+
117
+ ## Claude Code / Agent Teams usage
118
+
119
+ Claude Code can participate through the CLI. See [`CLAUDE_AGENT_TEAMS.md`](CLAUDE_AGENT_TEAMS.md) for the full lead-session pattern.
120
+
121
+ Recommended lead-session commands:
122
+
123
+ ```bash
124
+ # from the project root, or prefix with PI_ENSEMBLE_ROOT=/canonical/root from a neutral runtime root
125
+ ensemble overview
126
+ ensemble inbox --agent claude-lead --since-last-read
127
+ ensemble claim <path> --agent claude-lead
128
+ ensemble note "Claude lead spawned Agent Teams internally; durable milestone only." --from claude-lead
129
+ ensemble send pi "Result pointer: <path/url>" --from claude-lead --type result
130
+ ```
131
+
132
+ Keep internal Agent Teams chatter inside Claude. Mirror only durable milestones, ownership, and outcomes into `pi-ensemble`.
133
+
134
+ ## tmux wake adapter
135
+
136
+ If `ensemble-tmux` is available, use it only to wake panes. If you already wrote the long inbox message with `ensemble send`, use `wake` rather than `send` to avoid duplicate inbox entries:
137
+
138
+ ```bash
139
+ ensemble-tmux wake claude-lead --message "New handoff in inbox"
140
+ # or write + wake in one step:
141
+ ensemble-tmux send claude-lead "New handoff in inbox" --from pi --type handoff
142
+ ```
143
+
144
+ Rule:
145
+
146
+ ```txt
147
+ long message -> .pi-ensemble inbox
148
+ short wake ping -> tmux
149
+ ```
@@ -0,0 +1,313 @@
1
+ # pi-ensemble roadmap
2
+
3
+ The discovery that Claude Code Agent Teams already covers much of the “many Claude workers” vision clarifies the project rather than weakening it:
4
+
5
+ > The stronger orchestrators become, the smaller `pi-ensemble` should remain.
6
+ >
7
+ > `pi-ensemble` is not the team manager. It is the local ledger/protocol that keeps cross-agent work legible, portable, and auditable.
8
+
9
+ Core invariant:
10
+
11
+ > If Pi, Claude Code, tmux, or any adapter disappears, the coordination history must still be readable from files.
12
+
13
+ ## Thesis — form should follow coordination behavior
14
+
15
+ The durable behavior in hybrid coding workspaces is not “spawn N workers”. It is:
16
+
17
+ - hand off intent;
18
+ - record durable facts;
19
+ - mark ownership;
20
+ - point to results;
21
+ - leave an audit trail;
22
+ - wake another runtime when needed.
23
+
24
+ That behavior suggests a smaller form:
25
+
26
+ ```txt
27
+ blackboard + inbox + claims + audit
28
+ ```
29
+
30
+ Not this:
31
+
32
+ ```txt
33
+ scheduler + team manager + lifecycle controller
34
+ ```
35
+
36
+ `pi-ensemble` should express the trace of collaboration, not control the collaboration itself.
37
+
38
+ ## Positioning
39
+
40
+ `pi-ensemble` sits between runtimes and orchestrators, not above them.
41
+
42
+ ```txt
43
+ Felipe
44
+
45
+ Pi maestro / Claude lead / Claude Agent Teams / Codex / other agents
46
+
47
+ pi-ensemble core ledger
48
+
49
+ tmux wake adapter / dashboards / launchers / watchers / bridges
50
+ ```
51
+
52
+ What stays inside other systems:
53
+
54
+ - Agent Teams task decomposition;
55
+ - worker topology and specialist roles;
56
+ - session lifecycle, resume, shutdown;
57
+ - provider/model-specific routing;
58
+ - launcher and pane management.
59
+
60
+ What belongs in `pi-ensemble`:
61
+
62
+ - durable handoffs across runtimes;
63
+ - shared facts worth keeping;
64
+ - path/worktree ownership;
65
+ - result pointers;
66
+ - audit trail;
67
+ - minimal coordination state a human can inspect.
68
+
69
+ ## Design principles
70
+
71
+ 1. **Core stays file-only** — no daemon, no spawn, no network, no tmux dependency.
72
+ 2. **Core is a ledger, not a runtime** — record coordination state; do not supervise sessions.
73
+ 3. **No team model in core** — no fixed maestro/worker abstraction, even if some users adopt that pattern.
74
+ 4. **Humans can inspect everything** — deleting the adapters must leave the work legible.
75
+ 5. **Claims before concurrency** — path/worktree ownership must be explicit when work overlaps.
76
+ 6. **Adapters translate, core does not command** — wakeups, dashboards, launchers, mirrors live outside core.
77
+ 7. **Protocol neutrality wins** — Pi, Claude Code, Codex, and future agents should all fit without special privilege.
78
+
79
+ ## Current state — v0.1 alpha
80
+
81
+ Implemented:
82
+
83
+ - CLI: `init`, `status`, `note`, `send`, `inbox`, `board`, `claim`, `release`.
84
+ - Core file layout under `.pi-ensemble/`.
85
+ - Markdown blackboard and inboxes.
86
+ - JSON audit log and worktree/path claims.
87
+ - Pi package extension with slash command and tool.
88
+ - Local `ensemble-tmux` adapter.
89
+ - Docs: `SPEC`, `SECURITY`, `AUDIT`, `ADAPTERS`, `LANDSCAPE`.
90
+
91
+ Known limitations:
92
+
93
+ - No formal adapter contract yet.
94
+ - No JSON-first output mode for easy machine bridging.
95
+ - Claim conflict policy is still minimal.
96
+ - Inbox read/ack semantics are intentionally simple.
97
+ - No versioned migration policy yet.
98
+ - Slash command parsing is intentionally minimal.
99
+
100
+ ## Cuts / reframes from the previous roadmap
101
+
102
+ These items should be removed from the core product direction or demoted to adapters/docs:
103
+
104
+ - **No evolution toward a built-in maestro/workers system.** That is a usage pattern, not the product.
105
+ - **No `dispatch` / `collect` core CLI.** If they exist later, they should be thin wrappers or external helpers.
106
+ - **No core task engine as scheduler.** At most, future task files should be receipts/mirrors, not runtime control.
107
+ - **No agent registry or session discovery in core.** Runtime presence belongs to adapters.
108
+ - **No pane/window orchestration in core.** tmux stays a wake transport only.
109
+ - **No Claude-only UX clone of Agent Teams.** Competing at that layer is a category error.
110
+
111
+ ## Priority reset
112
+
113
+ ### Phase 1 — Harden the ledger
114
+
115
+ Goal: make the current substrate boring, inspectable, and stable.
116
+
117
+ Deliverables:
118
+
119
+ - Add minimal tests for core operations using the Node test runner.
120
+ - Add validation for agent names, message types, and claim targets.
121
+ - Add `--json` output for `status`, `inbox`, `board`, and claim state where useful.
122
+ - Improve claim behavior:
123
+ - warn or fail on already-claimed paths;
124
+ - record previous owner in audit;
125
+ - document shared/read-only claim conventions.
126
+ - Add explicit protocol version metadata.
127
+ - Add `docs/QUICKSTART.md` with Pi, Claude Code, Agent Teams lead-session, and generic terminal examples.
128
+
129
+ Acceptance:
130
+
131
+ ```txt
132
+ A new user can install pi-ensemble, initialize a repo, run a cross-runtime handoff, inspect the files, and understand what happened without reading source code.
133
+ ```
134
+
135
+ ### Phase 2 — Define the adapter contract
136
+
137
+ Goal: make adapters first-class without polluting core.
138
+
139
+ Deliverables:
140
+
141
+ - Document a minimal adapter contract in `docs/ADAPTERS.md`:
142
+ - what adapters may write;
143
+ - what must remain durable;
144
+ - what belongs only in local adapter config;
145
+ - safe wake pattern: long body in inbox, short ping out-of-band.
146
+ - Clarify which fields are protocol and which are adapter metadata.
147
+ - Document how adapters should preserve auditability when mirroring external events.
148
+ - Keep `ensemble-tmux` explicitly separate from core package concerns.
149
+
150
+ Acceptance:
151
+
152
+ ```txt
153
+ A tmux bridge, a dashboard, and a Claude-side helper can all interoperate with the same .pi-ensemble folder without introducing hidden state into core.
154
+ ```
155
+
156
+ ### Phase 3 — Claude Agent Teams interop
157
+
158
+ Goal: make `pi-ensemble` useful beside Agent Teams instead of against it.
159
+
160
+ Status: first docs/examples landed in `docs/CLAUDE_AGENT_TEAMS.md` and `examples/claude-agent-teams-lead.md`.
161
+
162
+ Deliverables:
163
+
164
+ - Document the recommended pattern:
165
+ - Pi or a human talks to a Claude lead session;
166
+ - the lead may use Agent Teams internally;
167
+ - only durable cross-runtime milestones get mirrored into `pi-ensemble`.
168
+ - Provide examples for when to mirror:
169
+ - claim ownership before major edits;
170
+ - record durable facts to blackboard;
171
+ - send result/handoff back to Pi or another runtime;
172
+ - keep ephemeral intra-team chatter out of core.
173
+ - If tooling is added, keep it as an optional bridge that writes normal `pi-ensemble` files.
174
+
175
+ Acceptance:
176
+
177
+ ```txt
178
+ A Claude lead session can use Agent Teams internally while Pi still sees durable handoffs, ownership, and outcomes through pi-ensemble.
179
+ ```
180
+
181
+ ### Phase 4 — Neutral multi-runtime interop
182
+
183
+ Goal: make the protocol feel native to more than Pi and Claude.
184
+
185
+ Deliverables:
186
+
187
+ - Harden the Pi package surface.
188
+ - Add Codex/OpenCode/generic CLI recipes.
189
+ - Document claim conventions for worktrees vs paths.
190
+ - Consider tiny helper scripts/examples for other runtimes to append notes, results, and claims without needing a full plugin.
191
+
192
+ Acceptance:
193
+
194
+ ```txt
195
+ Pi, Claude Code, Codex, and a plain shell script can all participate in the same coordination ledger with no runtime having special authority.
196
+ ```
197
+
198
+ ### Phase 5 — Read-only observability
199
+
200
+ Goal: add visibility without turning the project into mission control.
201
+
202
+ Status: first CLI/tool inspection landed with `ensemble overview`, `ensemble timeline`, and `ensemble doctor`.
203
+
204
+ Possible deliverables:
205
+
206
+ - Read-only dashboard rendering `.pi-ensemble/`.
207
+ - Timeline/audit viewer.
208
+ - Claim inspector.
209
+ - Activity summarizer.
210
+
211
+ Rule:
212
+
213
+ ```txt
214
+ Observe from the files first. Do not move control back into the dashboard.
215
+ ```
216
+
217
+ ### Phase 6 — v1.0 stability
218
+
219
+ Goal: freeze the file protocol.
220
+
221
+ Required:
222
+
223
+ - Versioned spec for `.pi-ensemble/` layout.
224
+ - Migration policy.
225
+ - Compatibility tests for old state folders.
226
+ - Security review.
227
+ - Public examples.
228
+ - npm publication decision.
229
+
230
+ Non-goals for v1.0:
231
+
232
+ - no daemon;
233
+ - no remote sync;
234
+ - no auto-spawn;
235
+ - no background autonomous workers;
236
+ - no credential handling;
237
+ - no mandatory tmux;
238
+ - no built-in team manager.
239
+
240
+ ## Core vs adapter boundary
241
+
242
+ Visible in core ledger:
243
+
244
+ - blackboard notes that matter later;
245
+ - inbox handoffs, questions, results, acknowledgements;
246
+ - path/worktree claims;
247
+ - audit events;
248
+ - minimal agent names and timestamps;
249
+ - pointers to external artifacts when needed.
250
+
251
+ Keep outside core / adapter zone:
252
+
253
+ - pane IDs and tmux window mapping;
254
+ - spawn/stop/shutdown/resume semantics;
255
+ - Agent Teams topology and worker count;
256
+ - provider/model details;
257
+ - prompt assembly and ephemeral chatter;
258
+ - heartbeats, retries, polling loops;
259
+ - launcher state and session discovery.
260
+
261
+ Heuristic:
262
+
263
+ > If the information is needed to reconstruct ownership, decisions, or outcomes, it belongs in core.
264
+ >
265
+ > If the information is only needed to operate a specific runtime, keep it in the adapter.
266
+
267
+ ## Immediate dogfood test
268
+
269
+ Run the next test on the project itself with the new positioning:
270
+
271
+ ```txt
272
+ Pi:
273
+ frames the task, consolidates, and keeps the shared question alive.
274
+
275
+ Claude lead:
276
+ may use Agent Teams internally for execution/review if useful,
277
+ but mirrors only durable milestones into pi-ensemble.
278
+
279
+ Codex or another agent:
280
+ contributes a bounded audit/review through the same inbox/claim protocol.
281
+
282
+ Tmux:
283
+ only wakes sessions.
284
+ ```
285
+
286
+ Success criteria:
287
+
288
+ - Felipe can still talk to one lead surface at a time.
289
+ - `pi-ensemble` stores cross-runtime coordination, not every internal team interaction.
290
+ - Claims prevent overlapping edits across runtimes.
291
+ - Pi can reconstruct the story from `.pi-ensemble/` alone.
292
+ - Replacing Agent Teams with another orchestrator would not break the protocol.
293
+
294
+ ## Public framing
295
+
296
+ Use:
297
+
298
+ ```txt
299
+ shared workspace coordination ledger for coding agents
300
+ blackboard + mailbox + claims protocol for local coding agents
301
+ structured handoff layer for hybrid coding workflows
302
+ ```
303
+
304
+ Avoid:
305
+
306
+ ```txt
307
+ swarm
308
+ hivemind
309
+ control plane
310
+ agent command bus
311
+ autonomous workforce
312
+ Agent Teams replacement
313
+ ```
@@ -0,0 +1,111 @@
1
+ # Runtime recipes
2
+
3
+ These recipes show how different coding-agent runtimes can participate in the same `.pi-ensemble/` ledger without needing native plugins.
4
+
5
+ ## Common rules
6
+
7
+ All runtimes should:
8
+
9
+ 1. Start from the project root, or stay in a neutral runtime root and set `PI_ENSEMBLE_ROOT=/path/to/project`.
10
+ 2. Read `ensemble overview`.
11
+ 3. Read their new inbox items with `--since-last-read` before broad/clearing reads.
12
+ 4. Claim paths before edits.
13
+ 5. Record durable facts with `ensemble note`.
14
+ 6. Return exact result pointers with `ensemble send <target> ... --type result`.
15
+ 7. Release claims when done.
16
+
17
+ ## Pi
18
+
19
+ Pi has a native package extension and tool. Use Pi for field framing, synthesis, and cross-runtime decisions.
20
+
21
+ ```txt
22
+ /ensemble status
23
+ /ensemble inbox
24
+ /ensemble note <durable fact>
25
+ /ensemble send claude-lead <handoff> --type handoff
26
+ ```
27
+
28
+ Recommended Pi role:
29
+
30
+ - keep the question alive;
31
+ - decide what should be mirrored;
32
+ - avoid becoming a relay by hand;
33
+ - use Claude Agent Teams when Claude-only parallelism is enough.
34
+
35
+ ## Claude Code lead
36
+
37
+ Claude can use the CLI directly. If Claude starts in a neutral runtime root, prefix commands with `PI_ENSEMBLE_ROOT=/canonical/ledger/root`:
38
+
39
+ ```bash
40
+ PI_ENSEMBLE_ROOT=/home/aya/implante ensemble inbox --agent claude-lead --since-last-read
41
+ PI_ENSEMBLE_ROOT=/home/aya/implante ensemble ack msg_xxx --from claude-lead --body "received"
42
+ PI_ENSEMBLE_ROOT=/home/aya/implante ensemble claim src/foo.ts --agent claude-lead
43
+ PI_ENSEMBLE_ROOT=/home/aya/implante ensemble note "Started Agent Teams review for src/foo.ts" --from claude-lead
44
+ PI_ENSEMBLE_ROOT=/home/aya/implante ensemble send pi "Result: findings at docs/foo-review.md" --from claude-lead --type result
45
+ PI_ENSEMBLE_ROOT=/home/aya/implante ensemble release src/foo.ts --agent claude-lead
46
+ ```
47
+
48
+ If using native Agent Teams, mirror only durable milestones. See `CLAUDE_AGENT_TEAMS.md`.
49
+
50
+ ## Codex / generic terminal agent
51
+
52
+ Any terminal agent can use the CLI:
53
+
54
+ ```bash
55
+ cd /path/to/project
56
+ ensemble inbox --agent codex --since-last-read
57
+ ensemble claim tests/foo.test.ts --agent codex
58
+ # do work
59
+ ensemble send pi "Result: tests added at tests/foo.test.ts" --from codex --type result
60
+ ensemble release tests/foo.test.ts --agent codex
61
+ ```
62
+
63
+ If the runtime prefers JSON:
64
+
65
+ ```bash
66
+ ensemble status
67
+ ensemble inbox --agent codex --since-last-read --json
68
+ ensemble claim tests/foo.test.ts --agent codex --json
69
+ ```
70
+
71
+ ## Plain shell script
72
+
73
+ A script can mirror external events without being an agent runtime:
74
+
75
+ ```bash
76
+ #!/usr/bin/env bash
77
+ set -euo pipefail
78
+ cd /path/to/project
79
+ ensemble note "CI finished: $GITHUB_RUN_URL" --from ci-bot
80
+ ensemble send pi "CI result: $GITHUB_RUN_URL" --from ci-bot --type result
81
+ ```
82
+
83
+ Use stable agent names such as `ci-bot`, `watcher`, `bench-runner`, or `github-mirror`.
84
+
85
+ ## tmux wake adapter
86
+
87
+ Use tmux only to wake a pane after writing the real message. If the message already exists in the inbox, use `wake`; if not, `send` can write + wake in one step:
88
+
89
+ ```bash
90
+ ensemble-tmux wake claude-lead --message "Read your pi-ensemble inbox"
91
+ ensemble-tmux send claude-lead "Read your pi-ensemble inbox" --from pi --type handoff
92
+ ```
93
+
94
+ The wake prompt should be shell-safe and short. Long message bodies belong in inbox files.
95
+
96
+ ## Worktree convention
97
+
98
+ If each runtime works in a separate git worktree, claim the worktree root:
99
+
100
+ ```bash
101
+ ensemble claim ../worktrees/feature-a --agent claude-lead
102
+ ```
103
+
104
+ If multiple runtimes share a worktree, claim specific paths:
105
+
106
+ ```bash
107
+ ensemble claim src/auth --agent claude-lead
108
+ ensemble claim tests/auth.test.ts --agent codex
109
+ ```
110
+
111
+ Do not use `--force` unless a human/Pi intentionally resolves ownership.
package/docs/SPEC.md ADDED
@@ -0,0 +1,132 @@
1
+ # pi-ensemble v0.1-alpha spec
2
+
3
+ ## Purpose
4
+
5
+ A local, file-based coordination protocol for parallel coding agents operated by one developer.
6
+
7
+ ## Non-goals
8
+
9
+ - Agent spawning or supervision
10
+ - Network sync or remote execution
11
+ - Automatic LLM routing
12
+ - Git hooks or background daemons
13
+ - Secrets management
14
+ - Multi-user collaboration
15
+
16
+ ## Protocol version
17
+
18
+ `config.yaml` stores `version: 1`. v0.1 treats this as the file-protocol version.
19
+
20
+ ## Directory layout
21
+
22
+ ```txt
23
+ .pi-ensemble/
24
+ config.yaml
25
+ blackboard.md
26
+ agents/
27
+ <name>/
28
+ inbox.md
29
+ inbox.read.md # created lazily on first cleared inbox read
30
+ state.json
31
+ worktrees.json
32
+ audit.jsonl
33
+ ```
34
+
35
+ ## Agent names
36
+
37
+ Agent names must match:
38
+
39
+ ```txt
40
+ ^[A-Za-z0-9][A-Za-z0-9._-]{0,63}$
41
+ ```
42
+
43
+ Examples: `pi`, `claude`, `claude-lead`, `codex.1`.
44
+
45
+ ## Message types
46
+
47
+ - `note`: durable shared observation
48
+ - `handoff`: actionable transfer of responsibility
49
+ - `question`: explicit question needing answer
50
+ - `result`: completed output or artifact pointer
51
+ - `ack`: acknowledgement / receipt
52
+
53
+ ## Message ids and lifecycle
54
+
55
+ `ensemble send` creates a message id (`msg_...`) and writes it into the inbox heading as an anchor:
56
+
57
+ ```md
58
+ ## 2026-05-06T... — pi → claude [question] {#msg_abc123...}
59
+ ```
60
+
61
+ Message lifecycle is audit-only:
62
+
63
+ - `ack MESSAGE_ID`: recipient or observer records receipt/acceptance;
64
+ - `done MESSAGE_ID`: actor records that the handoff/question is resolved;
65
+ - `messages [--open]`: reconstructs lifecycle state from `audit.jsonl`.
66
+
67
+ No scheduler, router, retry loop, or process state is implied by these events.
68
+
69
+ ## Inbox read state
70
+
71
+ Each agent has `state.json`. `lastReadAt` is updated whenever that agent reads its inbox, including non-clearing reads. Status/overview expose:
72
+
73
+ - `pending`: total retained message blocks in `inbox.md`;
74
+ - `unread`: retained messages newer than `lastReadAt`;
75
+ - `stale`: retained messages already read but not cleared.
76
+
77
+ `ensemble inbox --since-last-read` returns only unread messages, marks them read, and does not clear retained history unless `--clear` is also passed.
78
+
79
+ ## Claims
80
+
81
+ `worktrees.json` maps resolved paths to current owner metadata:
82
+
83
+ ```json
84
+ {
85
+ "/repo/src/foo.ts": { "agent": "claude", "since": "..." }
86
+ }
87
+ ```
88
+
89
+ A path claimed by another agent cannot be overwritten or released unless the caller uses a force override. Overrides are audited and keep the previous owner in the audit record.
90
+
91
+ ## Root resolution
92
+
93
+ By default, commands search upward from the current directory until they find `.pi-ensemble/`.
94
+
95
+ For nested repositories or canonical shared ledgers, callers can override root resolution with:
96
+
97
+ ```bash
98
+ PI_ENSEMBLE_ROOT=/path/to/workspace ensemble overview
99
+ ensemble --root /path/to/workspace overview
100
+ ```
101
+
102
+ The Pi extension/tool accepts the same concept via `--root` in slash commands or a `root` parameter in the tool.
103
+
104
+ ## Machine-readable output
105
+
106
+ The CLI supports `--json` for operations that adapters commonly consume: `note`, `send`, `ack`, `done`, `messages`, `inbox`, `board`, `claims`, `audit`, `timeline`, `overview`, `doctor`, `claim`, and `release`. `status` is JSON by default.
107
+
108
+ ## Health checks
109
+
110
+ `ensemble doctor` is read-only observability for ledger hygiene. It checks required protocol files, config version, audit JSONL parse issues, agent names, unread/retained inbox summaries, claim path/owner sanity, and nested `.pi-ensemble` folders under the selected root.
111
+
112
+ ## Invariants
113
+
114
+ 1. All state is human-readable.
115
+ 2. All state-changing operations append an event to `audit.jsonl`.
116
+ 3. The package never starts processes or runs shell commands.
117
+ 4. The package never opens network connections.
118
+ 5. Deleting `.pi-ensemble/` fully resets the protocol.
119
+ 6. Adapters may wake or visualize runtimes, but the durable source of truth remains `.pi-ensemble/`.
120
+
121
+ ## Pi package surface
122
+
123
+ - Slash command: `/ensemble ...`
124
+ - Tool: `ensemble({ action, agent, to, type, body, path, clear, sinceLastRead })`
125
+ - CLI: `ensemble ...`
126
+
127
+ ## v0.1 done when
128
+
129
+ - `ensemble init/status/note/send/inbox/board/claim/release` work locally.
130
+ - Pi extension exposes the same operations.
131
+ - SECURITY.md clearly states no network/spawn/exec/credentials/persistence.
132
+ - README frames this as shared workspace coordination, not command/control.