@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.
- package/CHANGELOG.md +103 -0
- package/LICENSE +21 -0
- package/README.md +142 -0
- package/SECURITY.md +27 -0
- package/bin/ensemble.mjs +217 -0
- package/docs/ADAPTERS.md +159 -0
- package/docs/AUDIT.md +20 -0
- package/docs/CLAUDE_AGENT_TEAMS.md +149 -0
- package/docs/LANDSCAPE.md +452 -0
- package/docs/QUICKSTART.md +149 -0
- package/docs/ROADMAP.md +313 -0
- package/docs/RUNTIME_RECIPES.md +111 -0
- package/docs/SPEC.md +132 -0
- package/examples/claude-agent-teams-lead.md +38 -0
- package/examples/ensemble-tmux +136 -0
- package/extensions/pi-ensemble.ts +212 -0
- package/lib/core.mjs +517 -0
- package/package.json +54 -0
|
@@ -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
|
+
```
|
package/docs/ROADMAP.md
ADDED
|
@@ -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.
|