@tmustier/pi-agent-teams 0.4.0-beta.3 → 0.5.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 +26 -0
- package/README.md +72 -9
- package/WORKFLOW.md +110 -0
- package/docs/claude-parity.md +18 -13
- package/docs/hook-contract.md +183 -0
- package/docs/smoke-test-plan.md +26 -7
- package/extensions/teams/activity-tracker.ts +296 -8
- package/extensions/teams/cleanup.ts +216 -3
- package/extensions/teams/hooks.ts +57 -5
- package/extensions/teams/leader-attach-commands.ts +8 -4
- package/extensions/teams/leader-inbox.ts +162 -4
- package/extensions/teams/leader-info-commands.ts +105 -3
- package/extensions/teams/leader-lifecycle-commands.ts +205 -3
- package/extensions/teams/leader-messaging-commands.ts +19 -7
- package/extensions/teams/leader-spawn-command.ts +5 -1
- package/extensions/teams/leader-team-command.ts +51 -2
- package/extensions/teams/leader-teams-tool.ts +387 -11
- package/extensions/teams/leader.ts +126 -52
- package/extensions/teams/mailbox.ts +6 -1
- package/extensions/teams/model-policy.ts +117 -0
- package/extensions/teams/spawn-types.ts +4 -0
- package/extensions/teams/teammate-rpc.ts +14 -0
- package/extensions/teams/teams-panel.ts +117 -19
- package/extensions/teams/teams-ui-shared.ts +205 -2
- package/extensions/teams/teams-widget.ts +67 -14
- package/extensions/teams/worker.ts +18 -6
- package/extensions/teams/worktree.ts +143 -0
- package/package.json +4 -2
- package/scripts/integration-cleanup-test.mts +419 -0
- package/scripts/integration-hooks-remediation-test.mts +382 -0
- package/scripts/integration-spawn-overrides-test.mts +10 -0
- package/scripts/smoke-test.mts +701 -3
- package/skills/agent-teams/SKILL.md +28 -7
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
## 0.5.0
|
|
4
|
+
|
|
5
|
+
### Features
|
|
6
|
+
|
|
7
|
+
- **DM routing to leader LLM context** — Teammate DMs are now injected into the leader's conversation via `sendLeaderLlmMessage` instead of only showing in the TUI. The leader can now act on DM requests autonomously. (Thanks **@davidsu** — #6, #29)
|
|
8
|
+
- **Batch-complete auto-wake** — `DelegationTracker` tracks task ID batches from `delegate()` calls. When all tasks in a batch complete, the idle leader is automatically woken to review results and continue orchestrating. Quality-gate aware. (Thanks **@RensTillmann** — #7, #29)
|
|
9
|
+
- **Worker completion messages in leader context** — Per-task completion/failure notifications injected into the leader LLM conversation with task subject, result summary, and progress counters. All-done detection warns when quality gates are still running. (#13)
|
|
10
|
+
- **Ergonomic worker status** — Real-time time-in-state, stall detection (configurable via `PI_TEAMS_STALL_THRESHOLD_MS`), last message summary, and model-per-worker in panel detail view. `member_status` tool action for agent-driven orchestration. (#10)
|
|
11
|
+
- **Tool call content in transcript** — Worker transcript view shows tool arguments inline: file paths, commands, patterns. Errors marked with ✗. (#18, #21, #23)
|
|
12
|
+
- **`/team done` + auto-done detection** — `/team done` ends a run (stops teammates, hides widget, notifies with summary). Widget auto-detects when all tasks complete. (#16)
|
|
13
|
+
- **Hook/model policy in panel** — Compact policy summary (hooks status, failure action, reopens, model inheritance) shown in widget and panel. (#20)
|
|
14
|
+
- **Model, thinking, task in spawn/panel** — Visible in spawn output, panel detail, and transcript header. (#19)
|
|
15
|
+
- **Urgent message interrupts** — `--urgent` flag on `/team dm` and `/team broadcast` interrupts active worker turns via steering. (#15)
|
|
16
|
+
- **Hook contract versioning** — Formal versioning and compatibility policy for quality-gate hooks. (#24)
|
|
17
|
+
|
|
18
|
+
### Fixes
|
|
19
|
+
|
|
20
|
+
- **Worktree/branch auto-cleanup** — Stale team dirs, worktrees, and branches cleaned up on shutdown and session switch. (#14)
|
|
21
|
+
- **`/team status` in README** — Added missing command to docs table. (#27)
|
|
22
|
+
- **Activity tracker** — Added `extractStartSummary`/`extractEndSummary` for tool transcript display.
|
|
23
|
+
|
|
24
|
+
## 0.4.0
|
|
25
|
+
|
|
26
|
+
Initial public release.
|
package/README.md
CHANGED
|
@@ -10,15 +10,16 @@ Core agent-teams primitives, matching Claude's design:
|
|
|
10
10
|
|
|
11
11
|
- **Shared task list** — file-per-task on disk with three states (pending / in-progress / completed) and dependency tracking so blocked tasks stay blocked until their prerequisites finish.
|
|
12
12
|
- **Auto-claim** — idle teammates automatically pick up the next unassigned, unblocked task. No manual dispatching required (disable with `PI_TEAMS_DEFAULT_AUTO_CLAIM=0`).
|
|
13
|
-
- **Direct messages and broadcast** — send a message to one teammate or all of them at once, via file-based mailboxes.
|
|
13
|
+
- **Direct messages and broadcast** — send a message to one teammate or all of them at once, via file-based mailboxes. Urgent messages can interrupt active turns via steering.
|
|
14
14
|
- **Graceful lifecycle** — spawn, stop, shutdown (with handshake), or kill teammates. The leader tracks who's online, idle, or streaming.
|
|
15
15
|
- **LLM-callable teams tool** — the model can spawn teammates, delegate tasks, mutate task assignment/status/dependencies, message teammates, and run lifecycle actions in tool calls (no slash commands needed).
|
|
16
|
-
- **Team cleanup** —
|
|
16
|
+
- **Team done + cleanup** — `/team done` ends a run (stops teammates, hides the widget, notifies with a summary); the widget auto-detects when all tasks are complete and shows a hint. `/team cleanup` tears down artifacts afterward.
|
|
17
17
|
|
|
18
18
|
Additional Pi-specific capabilities:
|
|
19
19
|
|
|
20
20
|
- **Git worktrees** — optionally give each teammate its own worktree so they work on isolated branches without conflicting edits.
|
|
21
21
|
- **Session branching** — clone the leader's conversation context into a teammate so it starts with full awareness of the work so far, instead of from scratch.
|
|
22
|
+
- **Completion notifications** — when a teammate finishes or fails a task, the leader LLM receives a structured `[Team]` message with task ID, subject, result summary, and progress counters so it can orchestrate autonomously without human intervention. When quality-gate hooks are active, the message warns that task states may still change.
|
|
22
23
|
- **Hooks / quality gates** — optional leader-side hooks on idle / task completion to run scripts (opt-in).
|
|
23
24
|
|
|
24
25
|
## UI style (terminology + naming)
|
|
@@ -110,9 +111,13 @@ Or drive it manually:
|
|
|
110
111
|
|
|
111
112
|
/tw # open the interactive widget panel
|
|
112
113
|
|
|
114
|
+
/team done # end run: stop teammates + hide widget
|
|
115
|
+
/team done --force # end run even with in-progress tasks
|
|
116
|
+
|
|
113
117
|
/team shutdown alice # graceful shutdown (handshake)
|
|
114
118
|
/team shutdown # stop all teammates (leader session remains active)
|
|
115
|
-
/team cleanup # remove team artifacts
|
|
119
|
+
/team cleanup # remove team artifacts (worktrees, branches, team dir)
|
|
120
|
+
/team gc --dry-run # preview stale team dirs that would be removed
|
|
116
121
|
```
|
|
117
122
|
|
|
118
123
|
Or let the model drive it with the delegate tool:
|
|
@@ -143,17 +148,21 @@ Or let the model drive it with the delegate tool:
|
|
|
143
148
|
| `task_dep_add` | `taskId`, `depId` | Add dependency edge (`taskId` depends on `depId`). |
|
|
144
149
|
| `task_dep_rm` | `taskId`, `depId` | Remove dependency edge. |
|
|
145
150
|
| `task_dep_ls` | `taskId` | Inspect dependency/block graph for one task. |
|
|
146
|
-
| `message_dm` | `name`, `message` | Send mailbox DM to one teammate. |
|
|
147
|
-
| `message_broadcast` | `message` | Send mailbox message to all discovered workers. |
|
|
151
|
+
| `message_dm` | `name`, `message` | Send mailbox DM to one teammate. Set `urgent=true` to interrupt their active turn. |
|
|
152
|
+
| `message_broadcast` | `message` | Send mailbox message to all discovered workers. Set `urgent=true` to interrupt active turns. |
|
|
148
153
|
| `message_steer` | `name`, `message` | Send steer instruction to a running RPC teammate. |
|
|
149
154
|
| `member_spawn` | `name` | Spawn one teammate (supports context/workspace/model/thinking/plan options). |
|
|
155
|
+
| `member_status` | optional `name` | Real-time worker status: activity, time in state, stall detection, tool use, tokens, last message. Omit name for all-worker summary. |
|
|
150
156
|
| `member_shutdown` | `name` or `all=true` | Request graceful shutdown via mailbox handshake. |
|
|
151
157
|
| `member_kill` | `name` | Force-stop one RPC teammate and unassign active tasks. |
|
|
152
158
|
| `member_prune` | _(none)_ | Mark stale non-RPC workers offline (`all=true` to force). |
|
|
159
|
+
| `team_done` | _(none)_ | End team run: stop all teammates, mark workers offline, hide widget (`all=true` to force with in-progress tasks). |
|
|
153
160
|
| `plan_approve` | `name` | Approve pending plan for a plan-required teammate. |
|
|
154
161
|
| `plan_reject` | `name` | Reject pending plan (`feedback` optional). |
|
|
155
162
|
| `hooks_policy_get` | _(none)_ | Read team hooks policy (configured + effective with env fallback). |
|
|
156
163
|
| `hooks_policy_set` | one or more of: `hookFailureAction`, `hookMaxReopensPerTask`, `hookFollowupOwner` | Update team hooks policy at runtime (`hooksPolicyReset=true` clears team overrides first). |
|
|
164
|
+
| `model_policy_get` | _(none)_ | Inspect teammate model policy and default inheritance behavior for the current leader model. |
|
|
165
|
+
| `model_policy_check` | optional `model` | Validate a model override before spawning (`<provider>/<modelId>` or `<modelId>`). |
|
|
157
166
|
|
|
158
167
|
Example calls:
|
|
159
168
|
|
|
@@ -161,10 +170,14 @@ Example calls:
|
|
|
161
170
|
{ "action": "task_assign", "taskId": "12", "assignee": "alice" }
|
|
162
171
|
{ "action": "task_dep_add", "taskId": "12", "depId": "7" }
|
|
163
172
|
{ "action": "message_broadcast", "message": "Sync: finishing this milestone" }
|
|
173
|
+
{ "action": "message_dm", "name": "alice", "message": "Stop using lib X, use Y instead", "urgent": true }
|
|
164
174
|
{ "action": "member_kill", "name": "alice" }
|
|
165
175
|
{ "action": "plan_approve", "name": "alice" }
|
|
166
176
|
{ "action": "hooks_policy_get" }
|
|
167
177
|
{ "action": "hooks_policy_set", "hookFailureAction": "reopen_followup", "hookMaxReopensPerTask": 2, "hookFollowupOwner": "member" }
|
|
178
|
+
{ "action": "model_policy_get" }
|
|
179
|
+
{ "action": "team_done" }
|
|
180
|
+
{ "action": "model_policy_check", "model": "openai-codex/gpt-5.1-codex-mini" }
|
|
168
181
|
```
|
|
169
182
|
|
|
170
183
|
## Commands
|
|
@@ -185,6 +198,7 @@ All management commands live under `/team`.
|
|
|
185
198
|
| --- | --- |
|
|
186
199
|
| `/team spawn <name> [fresh\|branch] [shared\|worktree] [plan] [--model <provider>/<modelId>] [--thinking <level>]` | Start a teammate |
|
|
187
200
|
| `/team list` | List teammates and their status |
|
|
201
|
+
| `/team status [name]` | Real-time worker state: stall detection, time in state, activity (omit name for summary) |
|
|
188
202
|
| `/team panel` | Interactive widget panel (same as `/tw`) |
|
|
189
203
|
| `/team attach list` | Discover existing team workspaces under `<teamsRoot>` |
|
|
190
204
|
| `/team attach <teamId> [--claim]` | Attach this session to an existing team workspace (`--claim` force-takes over an active claim) |
|
|
@@ -195,14 +209,16 @@ All management commands live under `/team`.
|
|
|
195
209
|
| `/team style <name>` | Set style (built-in or custom) |
|
|
196
210
|
| `/team send <name> <msg>` | Send a prompt over RPC |
|
|
197
211
|
| `/team steer <name> <msg>` | Redirect an in-flight run |
|
|
198
|
-
| `/team dm <name> <msg>` | Send a mailbox message |
|
|
199
|
-
| `/team broadcast <msg>` | Message all teammates |
|
|
212
|
+
| `/team dm <name> [--urgent] <msg>` | Send a mailbox message (`--urgent` interrupts active turns) |
|
|
213
|
+
| `/team broadcast [--urgent] <msg>` | Message all teammates (`--urgent` interrupts active turns) |
|
|
200
214
|
| `/team stop <name> [reason]` | Abort current work (resets task to pending) |
|
|
201
215
|
| `/team shutdown <name> [reason]` | Graceful shutdown (handshake) |
|
|
202
216
|
| `/team shutdown` | Stop all teammates (RPC + best-effort manual) (leader session remains active) |
|
|
203
217
|
| `/team prune [--all]` | Mark stale manual teammates offline (hides them in widget) |
|
|
204
218
|
| `/team kill <name>` | Force-terminate |
|
|
205
|
-
| `/team
|
|
219
|
+
| `/team done [--force]` | End run: stop teammates + hide widget (auto-detects when all tasks complete) |
|
|
220
|
+
| `/team cleanup [--force]` | Delete team artifacts (worktrees, branches, team dir) |
|
|
221
|
+
| `/team gc [--dry-run] [--force] [--max-age-hours=N]` | Garbage-collect stale team dirs older than N hours (default: 24) |
|
|
206
222
|
| `/team id` | Print team/task-list IDs and paths |
|
|
207
223
|
| `/team env <name>` | Print env vars to start a manual teammate |
|
|
208
224
|
|
|
@@ -210,12 +226,36 @@ Model inheritance note:
|
|
|
210
226
|
|
|
211
227
|
- If the leader is running a deprecated model id (e.g. Sonnet 4 non-4.5 variants), teammates will **not** inherit that id by default.
|
|
212
228
|
- Explicit deprecated `--model` overrides are rejected.
|
|
229
|
+
- Agents can introspect/check this at runtime via `teams` actions: `{ "action": "model_policy_get" }` and `{ "action": "model_policy_check", "model": "..." }`.
|
|
230
|
+
|
|
231
|
+
### Policy visibility
|
|
232
|
+
|
|
233
|
+
Both the persistent widget and the interactive panel (`/tw`) show a compact policy
|
|
234
|
+
summary below the header:
|
|
235
|
+
|
|
236
|
+
- **Hooks**: on/off status, `failureAction`, `maxReopensPerTask`, `followupOwner` (effective values from team config + env fallback)
|
|
237
|
+
- **Model**: leader model with deprecation warning when applicable, teammate selection source (`inherit`/`override`/`default`)
|
|
238
|
+
|
|
239
|
+
These values reflect the same resolution as the `hooks_policy_get` and `model_policy_get`
|
|
240
|
+
tool actions, but are continuously visible — no extra tool calls needed.
|
|
241
|
+
|
|
242
|
+
### Ergonomic worker status
|
|
243
|
+
|
|
244
|
+
The widget and panel show real-time worker state at a glance:
|
|
245
|
+
|
|
246
|
+
- **Time in state**: how long a worker has been in its current status (e.g. `3m12s`)
|
|
247
|
+
- **Stall detection**: when a streaming worker hasn't emitted any agent event for > 5 minutes, status changes to `⚠ stalled` (configurable via `PI_TEAMS_STALL_THRESHOLD_MS`)
|
|
248
|
+
- **Last message summary**: most recent assistant text (first 80–100 chars) visible in the panel's selected-worker detail section
|
|
249
|
+
- **Model per worker**: shown in the panel detail view when available
|
|
250
|
+
- **Current activity**: tool verb (e.g. `running…`, `editing…`) displayed inline
|
|
251
|
+
|
|
252
|
+
The `member_status` tool action provides the same information programmatically for agent-driven orchestration — no need to parse JSONL files or check file modification times.
|
|
213
253
|
|
|
214
254
|
### Panel shortcuts (`/tw` / `/team panel`)
|
|
215
255
|
|
|
216
256
|
- `↑/↓` or `w/s`: select teammate / scroll transcript
|
|
217
257
|
- `1..9`: jump directly to teammate in overview
|
|
218
|
-
- `enter`: open selected teammate transcript
|
|
258
|
+
- `enter`: open selected teammate transcript (shows tool args inline: file paths, commands, patterns; errors marked with ✗)
|
|
219
259
|
- `t` or `shift+t`: open selected teammate task list (task-centric view with deps/blocks); in task view, toggle back (`esc`/`t`/`shift+t`)
|
|
220
260
|
- task view: `c` complete, `p` pending, `i` in-progress, `u` unassign, `r` reassign selected task
|
|
221
261
|
- `m` or `d`: compose message to selected teammate
|
|
@@ -252,6 +292,7 @@ Model inheritance note:
|
|
|
252
292
|
| `PI_TEAMS_HOOKS_MAX_REOPENS_PER_TASK` | Reopen cap per task when failure action includes `reopen` (`0` disables auto-reopen) | `3` |
|
|
253
293
|
| `PI_TEAMS_HOOKS_FOLLOWUP_OWNER` | Follow-up owner policy: `member`, `lead`, `none` | `member` |
|
|
254
294
|
| `PI_TEAMS_HOOKS_CREATE_TASK_ON_FAILURE` | Legacy shortcut for `PI_TEAMS_HOOKS_FAILURE_ACTION=followup` | `0` (off) |
|
|
295
|
+
| `PI_TEAMS_STALL_THRESHOLD_MS` | Threshold (ms) before a streaming worker with no events is flagged as "stalled" | `300000` (5 min) |
|
|
255
296
|
|
|
256
297
|
## Storage layout
|
|
257
298
|
|
|
@@ -300,6 +341,8 @@ Hooks run with working directory = the **leader session cwd** and receive contex
|
|
|
300
341
|
- `PI_TEAMS_MEMBER`
|
|
301
342
|
- `PI_TEAMS_TASK_ID`, `PI_TEAMS_TASK_SUBJECT`, `PI_TEAMS_TASK_OWNER`, `PI_TEAMS_TASK_STATUS`
|
|
302
343
|
|
|
344
|
+
See [`docs/hook-contract.md`](docs/hook-contract.md) for the full versioned contract, JSON schema, and compatibility policy.
|
|
345
|
+
|
|
303
346
|
Hook policy can be controlled by agents at runtime via `teams` tool actions:
|
|
304
347
|
|
|
305
348
|
- `{ "action": "hooks_policy_get" }`
|
|
@@ -368,6 +411,26 @@ node scripts/e2e-rpc-test.mjs
|
|
|
368
411
|
|
|
369
412
|
Starts a leader in RPC mode, spawns a teammate, runs a shutdown handshake, verifies cleanup. Sets `PI_TEAMS_ROOT_DIR` to a temp directory so nothing touches `~/.pi/agent/teams`.
|
|
370
413
|
|
|
414
|
+
### Integration: hooks remediation loop
|
|
415
|
+
|
|
416
|
+
```bash
|
|
417
|
+
npm run integration-hooks-remediation-test
|
|
418
|
+
```
|
|
419
|
+
|
|
420
|
+
Deterministic leader-side integration flow that verifies failed `on_task_completed` hook handling end-to-end:
|
|
421
|
+
|
|
422
|
+
- task is reopened when policy includes `reopen`
|
|
423
|
+
- follow-up task is created/assigned when policy includes `followup`
|
|
424
|
+
- remediation mailbox nudge is emitted for the responsible teammate
|
|
425
|
+
|
|
426
|
+
### Integration: cleanup and garbage collection
|
|
427
|
+
|
|
428
|
+
```bash
|
|
429
|
+
npm run integration-cleanup-test
|
|
430
|
+
```
|
|
431
|
+
|
|
432
|
+
Tests worktree/branch cleanup lifecycle, full team directory removal, GC age/activity filtering, and filesystem fallback when no git context is available.
|
|
433
|
+
|
|
371
434
|
### tmux dogfooding
|
|
372
435
|
|
|
373
436
|
```bash
|
package/WORKFLOW.md
ADDED
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
---
|
|
2
|
+
tracker:
|
|
3
|
+
kind: linear
|
|
4
|
+
api_key: "$LINEAR_API_KEY"
|
|
5
|
+
team_key: "SYM"
|
|
6
|
+
project_slug: "db8e51049f48"
|
|
7
|
+
active_states:
|
|
8
|
+
- Todo
|
|
9
|
+
- In Progress
|
|
10
|
+
- In Review
|
|
11
|
+
- Merging
|
|
12
|
+
- Rework
|
|
13
|
+
terminal_states:
|
|
14
|
+
- Done
|
|
15
|
+
- Closed
|
|
16
|
+
- Cancelled
|
|
17
|
+
- Canceled
|
|
18
|
+
- Duplicate
|
|
19
|
+
polling:
|
|
20
|
+
interval_ms: 30000
|
|
21
|
+
workspace:
|
|
22
|
+
root: "$PI_SYMPHONY_WORKSPACE_ROOT"
|
|
23
|
+
worker:
|
|
24
|
+
runtime: pi
|
|
25
|
+
agent:
|
|
26
|
+
max_concurrent_agents: 4
|
|
27
|
+
max_turns: 8
|
|
28
|
+
max_retry_backoff_ms: 300000
|
|
29
|
+
codex:
|
|
30
|
+
turn_timeout_ms: 3600000
|
|
31
|
+
read_timeout_ms: 5000
|
|
32
|
+
stall_timeout_ms: 300000
|
|
33
|
+
pi:
|
|
34
|
+
command: pi
|
|
35
|
+
response_timeout_ms: 60000
|
|
36
|
+
session_dir_name: .pi-rpc-sessions
|
|
37
|
+
model:
|
|
38
|
+
provider: anthropic
|
|
39
|
+
model_id: claude-opus-4-6
|
|
40
|
+
thinking_level: xhigh
|
|
41
|
+
extension_paths:
|
|
42
|
+
- ../extensions/workspace-guard/index.ts
|
|
43
|
+
- ../extensions/proof/index.ts
|
|
44
|
+
- ../extensions/linear-graphql/index.ts
|
|
45
|
+
disable_extensions: true
|
|
46
|
+
disable_themes: true
|
|
47
|
+
orchestration:
|
|
48
|
+
phase_store: workpad
|
|
49
|
+
default_phase: implementing
|
|
50
|
+
passive_phases:
|
|
51
|
+
- waiting_for_checks
|
|
52
|
+
- waiting_for_human
|
|
53
|
+
- blocked
|
|
54
|
+
max_rework_cycles: 3
|
|
55
|
+
ownership:
|
|
56
|
+
required_label: symphony
|
|
57
|
+
required_workpad_marker: "## Symphony Workpad"
|
|
58
|
+
rollout:
|
|
59
|
+
mode: mutate
|
|
60
|
+
preflight_required: true
|
|
61
|
+
kill_switch_label: no-symphony-automation
|
|
62
|
+
kill_switch_file: /tmp/pi-symphony.pause
|
|
63
|
+
pr:
|
|
64
|
+
auto_create: true
|
|
65
|
+
base_branch: main
|
|
66
|
+
repo_slug: tmustier/pi-agent-teams
|
|
67
|
+
reuse_branch_pr: true
|
|
68
|
+
closed_pr_policy: new_branch
|
|
69
|
+
attach_to_tracker: true
|
|
70
|
+
required_labels:
|
|
71
|
+
- symphony
|
|
72
|
+
review_comment_mode: upsert
|
|
73
|
+
review_comment_marker: "<!-- symphony-review -->"
|
|
74
|
+
review:
|
|
75
|
+
enabled: true
|
|
76
|
+
agent: pr-reviewer
|
|
77
|
+
output_format: structured_markdown_v1
|
|
78
|
+
max_passes: 2
|
|
79
|
+
fix_consideration_severities:
|
|
80
|
+
- P0
|
|
81
|
+
- P1
|
|
82
|
+
- P2
|
|
83
|
+
merge:
|
|
84
|
+
mode: disabled
|
|
85
|
+
executor: gh
|
|
86
|
+
method: squash
|
|
87
|
+
strategy: queue
|
|
88
|
+
max_rebase_attempts: 2
|
|
89
|
+
require_green_checks: true
|
|
90
|
+
require_head_match: true
|
|
91
|
+
require_human_approval: true
|
|
92
|
+
approval_states:
|
|
93
|
+
- Merging
|
|
94
|
+
hooks:
|
|
95
|
+
timeout_ms: 60000
|
|
96
|
+
observability:
|
|
97
|
+
dashboard_enabled: true
|
|
98
|
+
refresh_ms: 1000
|
|
99
|
+
render_interval_ms: 16
|
|
100
|
+
server:
|
|
101
|
+
port: 4041
|
|
102
|
+
host: 127.0.0.1
|
|
103
|
+
---
|
|
104
|
+
|
|
105
|
+
Before starting implementation, read and apply the agent-friendly-design skill at:
|
|
106
|
+
`/Users/thomasmustier/.pi/agent/skills/agent-friendly-design/SKILL.md`
|
|
107
|
+
|
|
108
|
+
This project builds interfaces that AI agents operate (CLIs, tools, extensions, UI surfaces).
|
|
109
|
+
Every change should follow agent-friendly design principles: structured output, progressive disclosure,
|
|
110
|
+
clear error classification, token-budget awareness, and discoverability.
|
package/docs/claude-parity.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Claude Agent Teams parity roadmap (pi-agent-teams)
|
|
2
2
|
|
|
3
|
-
Last updated: 2026-
|
|
3
|
+
Last updated: 2026-03-21
|
|
4
4
|
|
|
5
5
|
This document tracks **feature parity gaps** between:
|
|
6
6
|
|
|
@@ -8,12 +8,12 @@ This document tracks **feature parity gaps** between:
|
|
|
8
8
|
- https://code.claude.com/docs/en/agent-teams#control-your-agent-team
|
|
9
9
|
- https://code.claude.com/docs/en/interactive-mode#task-list
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
...and this repository's implementation:
|
|
12
12
|
|
|
13
13
|
- `pi-agent-teams` (Pi extension)
|
|
14
14
|
|
|
15
15
|
> Terminology note: this extension supports `PI_TEAMS_STYLE=<style>`.
|
|
16
|
-
> This doc often uses
|
|
16
|
+
> This doc often uses "comrade" as a generic stand-in for "worker/teammate", but **styles can customize terminology, naming, and lifecycle copy**.
|
|
17
17
|
> Built-ins: `normal`, `soviet`, `pirate`. Custom styles live under `~/.pi/agent/teams/_styles/`.
|
|
18
18
|
|
|
19
19
|
## Scope / philosophy
|
|
@@ -30,8 +30,8 @@ This document tracks **feature parity gaps** between:
|
|
|
30
30
|
|
|
31
31
|
These are intentional differences / additions:
|
|
32
32
|
|
|
33
|
-
- **Configurable styles** (`/team style
|
|
34
|
-
- **Git worktrees** for isolation (`/team spawn <name>
|
|
33
|
+
- **Configurable styles** (`/team style ...`) for terminology + naming + lifecycle copy.
|
|
34
|
+
- **Git worktrees** for isolation (`/team spawn <name> ... worktree`).
|
|
35
35
|
- **Session branching** (clone leader context into a teammate).
|
|
36
36
|
- A **status widget + interactive panel** (`/tw`, `/team panel`).
|
|
37
37
|
|
|
@@ -41,19 +41,20 @@ Legend: ✅ implemented • 🟡 partial • ❌ missing
|
|
|
41
41
|
|
|
42
42
|
| Area | Claude docs behavior | Pi Teams status | Notes / next step | Priority |
|
|
43
43
|
| --- | --- | --- | --- | --- |
|
|
44
|
-
| Enablement | `CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS=1` + settings | N/A | Pi extension is available when installed/loaded. |
|
|
44
|
+
| Enablement | `CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS=1` + settings | N/A | Pi extension is available when installed/loaded. | - |
|
|
45
45
|
| Team config | `~/.claude/teams/<team>/config.json` w/ members | ✅ | `extensions/teams/team-config.ts` (under `~/.pi/agent/teams/...` or `PI_TEAMS_ROOT_DIR`). | P0 |
|
|
46
46
|
| Task list (shared) | `~/.claude/tasks/<taskListId>/` + states + deps | ✅ | File-per-task + deps (`blockedBy`/`blocks`); `/team task dep add|rm|ls`; self-claim skips blocked tasks. | P0 |
|
|
47
47
|
| Self-claim | Comrades self-claim next unassigned, unblocked task; file locking | ✅ | `claimNextAvailableTask()` + locks; enabled by default (`PI_TEAMS_DEFAULT_AUTO_CLAIM=1`). | P0 |
|
|
48
48
|
| Explicit assign | Lead assigns task to comrade | ✅ | `/team task assign` sets owner + pings via mailbox. | P0 |
|
|
49
|
-
|
|
|
50
|
-
| Comrade↔comrade messaging | Comrades message each other directly | ✅ | Worker tool `team_message
|
|
49
|
+
| "Message" vs "broadcast" | Send to one comrade or all comrades | ✅ | `/team dm` + `/team broadcast` use mailbox; `/team send` uses RPC. Recipients = config workers + RPC map + active task owners. | P0 |
|
|
50
|
+
| Comrade↔comrade messaging | Comrades message each other directly | ✅ | Worker tool `team_message` (with `urgent` flag for mid-turn interrupts); messages via mailbox + CC leader via `peer_dm_sent`. | P1 |
|
|
51
51
|
| Display modes | In-process selection (Shift+Up/Down); split panes (tmux/iTerm) | ❌ | Pi has widget/panel + commands, but no terminal-level comrade navigation/panes. | P2 |
|
|
52
52
|
| Delegate mode | Lead restricted to coordination-only tools | ✅ | `/team delegate [on|off]`; `tool_call` blocks `bash/edit/write`; widget shows `[delegate]`. | P1 |
|
|
53
|
-
| Plan approval | Comrade can be
|
|
54
|
-
| Shutdown handshake | Lead requests shutdown; comrade can approve/reject | ✅ | Protocol: `shutdown_request` → `shutdown_approved` / `shutdown_rejected`. `/team shutdown <name>` (graceful), `/team kill <name>` (SIGTERM). Wording is style-controlled (e.g.
|
|
55
|
-
| Cleanup team |
|
|
53
|
+
| Plan approval | Comrade can be "plan required" and needs lead approval to implement | ✅ | `/team spawn <name> plan` → read-only tools; sends `plan_approval_request`; `/team plan approve|reject`. | P1 |
|
|
54
|
+
| Shutdown handshake | Lead requests shutdown; comrade can approve/reject | ✅ | Protocol: `shutdown_request` → `shutdown_approved` / `shutdown_rejected`. `/team shutdown <name>` (graceful), `/team kill <name>` (SIGTERM). Wording is style-controlled (e.g. "was asked to shut down", "walked the plank"). | P1 |
|
|
55
|
+
| Cleanup team | "Clean up the team" removes shared resources after comrades stopped | ✅ | `/team done [--force]` ends run (stops teammates, hides widget, auto-detects completion). `/team cleanup [--force]` deletes artifacts. | P1 |
|
|
56
56
|
| Hooks / quality gates | `ComradeIdle`, `TaskCompleted` hooks | 🟡 | Optional leader-side hook runner (idle/task-complete/task-fail) via `PI_TEAMS_HOOKS_ENABLED=1` + scripts under `_hooks/`; inline failure surfacing + failure-action policies (`warn`/`followup`/`reopen`/`reopen_followup`) implemented; stable hook context payload exposed via `PI_TEAMS_HOOK_CONTEXT_JSON` + auto-remediation flow (reopen cap / follow-up owner policy / teammate notification). Runtime policy changes are agent-invocable via `teams` actions (`hooks_policy_get` / `hooks_policy_set`). | P2 |
|
|
57
|
+
| Widget liveliness | Status updates in near real-time | ✅ | Event-driven widget refresh on teammate tool start/end and turn completion; auto-done detection with `/team done` hint. | P2 |
|
|
57
58
|
| Task list UX | Ctrl+T toggle; show all/clear tasks by asking | 🟡 | Widget + `/team task list` + `/team task show` + `/team task clear`; panel supports fast `t`/`shift+t` toggle into task-centric view (`Ctrl+T` is reserved by Pi for thinking blocks). | P0 |
|
|
58
59
|
| Shared task list across sessions | `CLAUDE_CODE_TASK_LIST_ID=...` | ✅ | Worker env: `PI_TEAMS_TASK_LIST_ID` (manual workers). Leader: `/team task use <taskListId>` (persisted). Newly spawned workers inherit; existing workers need restart. | P1 |
|
|
59
60
|
| Join/attach flow | Join existing team context from another running session | 🟡 | `/team attach list`, `/team attach <teamId> [--claim]`, `/team detach` plus claim heartbeat/takeover handshake added. Widget/panel now show attached-mode banner + detach hint. | P2 |
|
|
@@ -94,13 +95,14 @@ Legend: ✅ implemented • 🟡 partial • ❌ missing
|
|
|
94
95
|
- `/team cleanup [--force]` deletes only `<teamsRoot>/<teamId>` after safety checks.
|
|
95
96
|
|
|
96
97
|
8) **Peer-to-peer messaging** ✅
|
|
97
|
-
- Worker tool `team_message`
|
|
98
|
+
- Worker tool `team_message` with `urgent` flag for mid-turn interrupts
|
|
98
99
|
- Mailbox transport; leader CC notifications
|
|
100
|
+
- Urgent messages delivered via `sendUserMessage({ deliverAs: "steer" })` to interrupt active turns
|
|
99
101
|
|
|
100
102
|
9) **Shared task list across sessions** ✅
|
|
101
103
|
- `/team task use <taskListId>` + persisted `config.json`
|
|
102
104
|
|
|
103
|
-
### P2: UX +
|
|
105
|
+
### P2: UX + "product-level" parity
|
|
104
106
|
|
|
105
107
|
10) **Hooks / quality gates** 🟡 (partial)
|
|
106
108
|
- Implemented: optional leader-side hook runner (opt-in + timeout + logs).
|
|
@@ -109,6 +111,7 @@ Legend: ✅ implemented • 🟡 partial • ❌ missing
|
|
|
109
111
|
- Implemented: runtime team-level policy overrides (via `teams` tool: `hooks_policy_get` / `hooks_policy_set`) layered over env defaults.
|
|
110
112
|
- Implemented: standardized hook context contract (`PI_TEAMS_HOOK_CONTEXT_VERSION=1`, `PI_TEAMS_HOOK_CONTEXT_JSON`).
|
|
111
113
|
- Implemented: autonomous remediation helpers (auto-reopen cap, follow-up owner policy, teammate remediation notification).
|
|
114
|
+
- Implemented: deterministic integration coverage (`scripts/integration-hooks-remediation-test.mts`) for failed hook -> reopen/follow-up/nudge flow.
|
|
112
115
|
- Still missing: broader contract versioning story + richer policy visualization UX.
|
|
113
116
|
|
|
114
117
|
11) **Better comrade interaction UX (within Pi constraints)** 🟡 (partial)
|
|
@@ -121,6 +124,8 @@ Legend: ✅ implemented • 🟡 partial • ❌ missing
|
|
|
121
124
|
- Implemented: agent-invocable dependency/messaging actions via `teams` tool (`task_dep_add|rm|ls`, `message_dm|broadcast|steer`).
|
|
122
125
|
- Implemented: agent-invocable lifecycle actions via `teams` tool (`member_spawn|shutdown|kill|prune`).
|
|
123
126
|
- Implemented: agent-invocable governance actions via `teams` tool (`plan_approve|plan_reject`).
|
|
127
|
+
- Implemented: agent-invocable model policy introspection/check actions via `teams` tool (`model_policy_get|model_policy_check`) to validate spawn overrides before execution.
|
|
128
|
+
- Implemented: agent-invocable end-of-run via `teams` tool (`team_done`) with structured error classification (`status`/`reason`/`hint`).
|
|
124
129
|
- Next: optional tmux split-pane integration and deeper dependency/task editing flows in panel.
|
|
125
130
|
|
|
126
131
|
12) **Join/attach flow** 🟡 (partial)
|
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
# Hook Contract
|
|
2
|
+
|
|
3
|
+
Versioned specification for the interface between pi-agent-teams and hook scripts.
|
|
4
|
+
|
|
5
|
+
Hook scripts are external programs (`.js`, `.mjs`, `.sh`, or bare executables) that run
|
|
6
|
+
on lifecycle events. This document defines what hooks receive and what pi-agent-teams
|
|
7
|
+
guarantees across releases.
|
|
8
|
+
|
|
9
|
+
## Current version
|
|
10
|
+
|
|
11
|
+
**Contract version: 1**
|
|
12
|
+
|
|
13
|
+
Exported as `HOOK_CONTRACT_VERSION` from `extensions/teams/hooks.ts`.
|
|
14
|
+
|
|
15
|
+
## Contract surface
|
|
16
|
+
|
|
17
|
+
Hooks receive context through two channels:
|
|
18
|
+
|
|
19
|
+
| Channel | Format | Key / field |
|
|
20
|
+
|---|---|---|
|
|
21
|
+
| Environment variable | string | `PI_TEAMS_HOOK_CONTEXT_VERSION` — the contract version as a string |
|
|
22
|
+
| Environment variable | JSON string | `PI_TEAMS_HOOK_CONTEXT_JSON` — structured payload (schema below) |
|
|
23
|
+
| Environment variables | flat strings | `PI_TEAMS_HOOK_EVENT`, `PI_TEAMS_TEAM_ID`, etc. (convenience) |
|
|
24
|
+
| Exit code | integer | `0` = pass, non-zero = fail |
|
|
25
|
+
|
|
26
|
+
### Context JSON schema (v1)
|
|
27
|
+
|
|
28
|
+
```jsonc
|
|
29
|
+
{
|
|
30
|
+
"version": 1, // always matches PI_TEAMS_HOOK_CONTEXT_VERSION
|
|
31
|
+
"event": "task_completed", // "idle" | "task_completed" | "task_failed"
|
|
32
|
+
"team": {
|
|
33
|
+
"id": "<teamId>",
|
|
34
|
+
"dir": "<absolute path>",
|
|
35
|
+
"taskListId": "<taskListId>",
|
|
36
|
+
"style": "normal" // current UI style id
|
|
37
|
+
},
|
|
38
|
+
"member": "<name>" | null, // teammate that triggered the event
|
|
39
|
+
"timestamp": "<ISO 8601>" | null,
|
|
40
|
+
"task": { // null for "idle" events; may also be null
|
|
41
|
+
// for task_completed/task_failed if the task
|
|
42
|
+
// was cleared before the leader processed it
|
|
43
|
+
"id": "3",
|
|
44
|
+
"subject": "<text>", // truncated to 1,000 chars
|
|
45
|
+
"description": "<text>", // truncated to 8,000 chars
|
|
46
|
+
"owner": "<name>" | null,
|
|
47
|
+
"status": "completed", // "pending" | "in_progress" | "completed"
|
|
48
|
+
// NOTE: for task_failed events the status is
|
|
49
|
+
// typically "pending" (reset before hook runs)
|
|
50
|
+
"blockedBy": ["1", "2"], // max 200 entries
|
|
51
|
+
"blocks": ["5"], // max 200 entries
|
|
52
|
+
"metadata": {}, // freeform key-value
|
|
53
|
+
"createdAt": "<ISO 8601>",
|
|
54
|
+
"updatedAt": "<ISO 8601>"
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
### Flat environment variables (v1)
|
|
60
|
+
|
|
61
|
+
| Variable | Always set | Description |
|
|
62
|
+
|---|---|---|
|
|
63
|
+
| `PI_TEAMS_HOOK_EVENT` | ✓ | Event name |
|
|
64
|
+
| `PI_TEAMS_HOOK_CONTEXT_VERSION` | ✓ | Contract version (string) |
|
|
65
|
+
| `PI_TEAMS_HOOK_CONTEXT_JSON` | ✓ | Full JSON payload |
|
|
66
|
+
| `PI_TEAMS_TEAM_ID` | ✓ | Team identifier |
|
|
67
|
+
| `PI_TEAMS_TEAM_DIR` | ✓ | Absolute path to team directory |
|
|
68
|
+
| `PI_TEAMS_TASK_LIST_ID` | ✓ | Task list identifier |
|
|
69
|
+
| `PI_TEAMS_STYLE` | ✓ | UI style id |
|
|
70
|
+
| `PI_TEAMS_MEMBER` | when available | Teammate name |
|
|
71
|
+
| `PI_TEAMS_EVENT_TIMESTAMP` | when available | ISO 8601 event timestamp |
|
|
72
|
+
| `PI_TEAMS_TASK_ID` | when task exists | Task id |
|
|
73
|
+
| `PI_TEAMS_TASK_SUBJECT` | when task exists | Task subject (untruncated) |
|
|
74
|
+
| `PI_TEAMS_TASK_OWNER` | when task has owner | Task owner name |
|
|
75
|
+
| `PI_TEAMS_TASK_STATUS` | when task exists | Task status |
|
|
76
|
+
|
|
77
|
+
### Hook exit code semantics
|
|
78
|
+
|
|
79
|
+
| Exit code | Meaning | Leader behavior |
|
|
80
|
+
|---|---|---|
|
|
81
|
+
| `0` | Pass | Record success in task metadata |
|
|
82
|
+
| Non-zero | Fail | Apply failure policy (warn / followup / reopen / reopen_followup) |
|
|
83
|
+
| Timeout (SIGTERM) | Fail | Same as non-zero exit |
|
|
84
|
+
|
|
85
|
+
## Compatibility policy
|
|
86
|
+
|
|
87
|
+
### Additive changes (no version bump)
|
|
88
|
+
|
|
89
|
+
The following changes are **backward-compatible** and do NOT increment the contract version:
|
|
90
|
+
|
|
91
|
+
- Adding new **optional** fields to the context JSON (hooks must tolerate unknown keys)
|
|
92
|
+
- Adding new **environment variables** (hooks must tolerate new env vars)
|
|
93
|
+
- Adding new **event types** (hooks only receive events matching their filename)
|
|
94
|
+
- Extending `metadata` with new keys
|
|
95
|
+
- Increasing truncation limits
|
|
96
|
+
|
|
97
|
+
### Breaking changes (version bump required)
|
|
98
|
+
|
|
99
|
+
The following changes **require incrementing** the contract version:
|
|
100
|
+
|
|
101
|
+
- Removing or renaming existing JSON fields
|
|
102
|
+
- Changing the type of an existing field
|
|
103
|
+
- Changing the semantics of an existing field (e.g., status values)
|
|
104
|
+
- Reducing truncation limits below current values
|
|
105
|
+
- Changing exit code semantics
|
|
106
|
+
- Removing environment variables
|
|
107
|
+
|
|
108
|
+
### Version lifecycle
|
|
109
|
+
|
|
110
|
+
1. **New version**: old version continues to be supported for at least one minor release
|
|
111
|
+
2. **Deprecation**: the old version emits a warning in hook logs
|
|
112
|
+
3. **Removal**: the old version is dropped in the next major release
|
|
113
|
+
|
|
114
|
+
### Hook author guidelines
|
|
115
|
+
|
|
116
|
+
Write hooks that are resilient to additive changes and race conditions:
|
|
117
|
+
|
|
118
|
+
```js
|
|
119
|
+
// ✅ Good: parse only the fields you need, ignore the rest
|
|
120
|
+
const ctx = JSON.parse(process.env.PI_TEAMS_HOOK_CONTEXT_JSON);
|
|
121
|
+
const taskId = ctx.task?.id;
|
|
122
|
+
|
|
123
|
+
// ✅ Good: always guard task access — task can be null even for
|
|
124
|
+
// task_completed/task_failed events (race: task cleared before leader reads it)
|
|
125
|
+
if (!ctx.task) {
|
|
126
|
+
console.log("Task already cleared, skipping quality gate");
|
|
127
|
+
process.exit(0);
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
// ✅ Good: don't assume task.status matches the event name —
|
|
131
|
+
// for task_failed events the status is typically "pending" (reset before hook runs)
|
|
132
|
+
if (ctx.event === "task_failed") {
|
|
133
|
+
console.log(`Task #${ctx.task.id} failed (current status: ${ctx.task.status})`);
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
// ✅ Good: check the version for breaking changes
|
|
137
|
+
const version = parseInt(process.env.PI_TEAMS_HOOK_CONTEXT_VERSION, 10);
|
|
138
|
+
if (version > 1) {
|
|
139
|
+
console.error(`Unsupported hook contract version: ${version}`);
|
|
140
|
+
process.exit(1);
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
// ❌ Bad: assume exact shape, fail on new fields
|
|
144
|
+
const { version, event, team, member, timestamp, task } = ctx;
|
|
145
|
+
assert(Object.keys(ctx).length === 5); // breaks when fields are added
|
|
146
|
+
|
|
147
|
+
// ❌ Bad: unconditionally access task fields
|
|
148
|
+
const subject = ctx.task.subject; // crashes when task is null
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
## Hook log format
|
|
152
|
+
|
|
153
|
+
Each hook invocation produces a log file in `<teamDir>/hook-logs/` with the structure:
|
|
154
|
+
|
|
155
|
+
```jsonc
|
|
156
|
+
{
|
|
157
|
+
"invocation": {
|
|
158
|
+
"event": "task_completed",
|
|
159
|
+
"teamId": "...",
|
|
160
|
+
// ... full invocation context
|
|
161
|
+
},
|
|
162
|
+
"result": {
|
|
163
|
+
"ran": true,
|
|
164
|
+
"hookPath": "/path/to/on_task_completed.js",
|
|
165
|
+
"command": ["node", "/path/to/on_task_completed.js"],
|
|
166
|
+
"exitCode": 0,
|
|
167
|
+
"timedOut": false,
|
|
168
|
+
"durationMs": 142,
|
|
169
|
+
"stdout": "...",
|
|
170
|
+
"stderr": "...",
|
|
171
|
+
"contractVersion": 1 // traces which version was used
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
## Changelog
|
|
177
|
+
|
|
178
|
+
### v1 (initial)
|
|
179
|
+
|
|
180
|
+
- Context JSON with `version`, `event`, `team`, `member`, `timestamp`, `task`
|
|
181
|
+
- Flat env vars: `PI_TEAMS_HOOK_EVENT`, `PI_TEAMS_HOOK_CONTEXT_VERSION`, `PI_TEAMS_HOOK_CONTEXT_JSON`, team/task fields
|
|
182
|
+
- Exit code 0 = pass, non-zero = fail
|
|
183
|
+
- Truncation: subject 1,000 chars, description 8,000 chars, blockedBy/blocks max 200 entries
|
package/docs/smoke-test-plan.md
CHANGED
|
@@ -20,13 +20,22 @@ npx tsx scripts/smoke-test.mts
|
|
|
20
20
|
| Module | Coverage |
|
|
21
21
|
|------------------|-----------------------------------------------------------------|
|
|
22
22
|
| `names.ts` | `sanitizeName` character replacement, edge cases |
|
|
23
|
-
| `
|
|
24
|
-
| `
|
|
23
|
+
| `model-policy.ts`| Deprecated model detection, teammate model selection/override |
|
|
24
|
+
| `teams-ui-shared.ts` | `isTeamDone` (9 edge cases), display helpers |
|
|
25
|
+
| `fs-lock.ts` | `withLock` returns value, cleans up lock file, stale locks |
|
|
26
|
+
| `mailbox.ts` | `writeToMailbox`, `popUnreadMessages`, read-once, urgent flag |
|
|
25
27
|
| `task-store.ts` | CRUD, `startAssignedTask`, `completeTask`, `claimNextAvailable`,|
|
|
26
28
|
| | `unassignTasksForAgent`, dependencies, `clearTasks` |
|
|
27
|
-
| `team-config.ts` | `ensureTeamConfig` (idempotent), `upsertMember`, `setMemberStatus`, `loadTeamConfig
|
|
29
|
+
| `team-config.ts` | `ensureTeamConfig` (idempotent), `upsertMember`, `setMemberStatus`, `loadTeamConfig`, hooks policy |
|
|
28
30
|
| `protocol.ts` | Structured message parsers (valid + invalid JSON + wrong type) |
|
|
29
|
-
|
|
|
31
|
+
| `teams-style.ts` | Custom styles, naming rules, pool naming |
|
|
32
|
+
| `hooks.ts` | Hook execution, failure policies, follow-up/reopen actions |
|
|
33
|
+
| `team-attach-claim.ts` | Acquire/release/heartbeat claims, staleness detection |
|
|
34
|
+
| `team-discovery.ts` | Team listing, config parsing, online worker counts |
|
|
35
|
+
| `/team done` | End-of-run cleanup, force-done with in-progress tasks, idempotency |
|
|
36
|
+
| `isTeamDone` | All branches: empty, completed, pending, streaming, stopped |
|
|
37
|
+
| docs drift guard | README, SKILL.md, help text consistency checks |
|
|
38
|
+
| Pi CLI | `pi --version` executes (skipped in CI if `pi` not on PATH) |
|
|
30
39
|
|
|
31
40
|
**Expected result:** `PASSED: <n> FAILED: 0`
|
|
32
41
|
|
|
@@ -95,7 +104,17 @@ Ask the model:
|
|
|
95
104
|
|
|
96
105
|
**Expected:** the `teams` tool is invoked, task created and assigned.
|
|
97
106
|
|
|
98
|
-
### 3g.
|
|
107
|
+
### 3g. End of run
|
|
108
|
+
|
|
109
|
+
```
|
|
110
|
+
/team done
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
**Expected:** all teammates stopped, widget hidden, summary notification shows task counts. If tasks are still in progress, use `/team done --force`.
|
|
114
|
+
|
|
115
|
+
After `/team done`, spawning a new teammate should automatically restore the widget.
|
|
116
|
+
|
|
117
|
+
### 3h. Shutdown (alternative to done)
|
|
99
118
|
|
|
100
119
|
```
|
|
101
120
|
/team shutdown agent1
|
|
@@ -138,9 +157,9 @@ pi --no-extensions -e extensions/teams/index.ts --mode rpc
|
|
|
138
157
|
|
|
139
158
|
| # | Test | Method | Status |
|
|
140
159
|
|---|-------------------------------|------------|--------|
|
|
141
|
-
| 1 | Unit primitives (
|
|
160
|
+
| 1 | Unit primitives (200+ asserts)| Automated | ✅ |
|
|
142
161
|
| 2 | Extension loading | CLI | ✅ |
|
|
143
|
-
| 3 | Interactive spawn/task/dm
|
|
162
|
+
| 3 | Interactive spawn/task/dm/done| Manual | 📋 |
|
|
144
163
|
| 4 | Worker-side RPC | Manual | 📋 |
|
|
145
164
|
|
|
146
165
|
✅ = verified in this run, 📋 = documented for manual execution.
|