@tmustier/pi-agent-teams 0.1.2 → 0.3.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/README.md +50 -9
- package/docs/claude-parity.md +22 -18
- package/docs/field-notes-teams-setup.md +6 -4
- package/docs/smoke-test-plan.md +139 -0
- package/eslint.config.js +74 -0
- package/extensions/teams/activity-tracker.ts +234 -0
- package/extensions/teams/fs-lock.ts +21 -5
- package/extensions/teams/leader-inbox.ts +175 -0
- package/extensions/teams/leader-info-commands.ts +139 -0
- package/extensions/teams/leader-lifecycle-commands.ts +343 -0
- package/extensions/teams/leader-messaging-commands.ts +148 -0
- package/extensions/teams/leader-plan-commands.ts +96 -0
- package/extensions/teams/leader-spawn-command.ts +57 -0
- package/extensions/teams/leader-task-commands.ts +421 -0
- package/extensions/teams/leader-team-command.ts +312 -0
- package/extensions/teams/leader-teams-tool.ts +227 -0
- package/extensions/teams/leader.ts +260 -1562
- package/extensions/teams/mailbox.ts +54 -29
- package/extensions/teams/names.ts +87 -0
- package/extensions/teams/protocol.ts +241 -0
- package/extensions/teams/spawn-types.ts +21 -0
- package/extensions/teams/task-store.ts +36 -21
- package/extensions/teams/team-config.ts +71 -25
- package/extensions/teams/teammate-rpc.ts +81 -23
- package/extensions/teams/teams-panel.ts +644 -0
- package/extensions/teams/teams-style.ts +62 -0
- package/extensions/teams/teams-ui-shared.ts +89 -0
- package/extensions/teams/teams-widget.ts +182 -0
- package/extensions/teams/worker.ts +100 -138
- package/extensions/teams/worktree.ts +4 -7
- package/package.json +32 -5
- package/scripts/integration-claim-test.mts +157 -0
- package/scripts/integration-todo-test.mts +532 -0
- package/scripts/lib/pi-workers.ts +105 -0
- package/scripts/smoke-test.mts +424 -0
- package/skills/agent-teams/SKILL.md +139 -0
- package/tsconfig.strict.json +22 -0
- package/extensions/teams/tasks.ts +0 -95
- package/scripts/smoke-test.mjs +0 -199
package/README.md
CHANGED
|
@@ -20,6 +20,17 @@ Additional Pi-specific capabilities:
|
|
|
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
22
|
|
|
23
|
+
## UI style
|
|
24
|
+
|
|
25
|
+
The extension supports two UI styles:
|
|
26
|
+
|
|
27
|
+
- **normal** (default): "Team leader" + "Teammate <name>"
|
|
28
|
+
- **soviet**: "Chairman" + "Comrade <name>" (in soviet mode, the system decides names for you)
|
|
29
|
+
|
|
30
|
+
Configure via:
|
|
31
|
+
- env: `PI_TEAMS_STYLE=normal|soviet`
|
|
32
|
+
- command: `/team style normal` or `/team style soviet`
|
|
33
|
+
|
|
23
34
|
## Install
|
|
24
35
|
|
|
25
36
|
**Option A — install from npm:**
|
|
@@ -46,9 +57,16 @@ Verify with `/team id` — it should print the current team info.
|
|
|
46
57
|
|
|
47
58
|
## Quick start
|
|
48
59
|
|
|
60
|
+
The fastest way to get going is `/swarm`:
|
|
61
|
+
|
|
49
62
|
```
|
|
50
|
-
#
|
|
63
|
+
/swarm build the auth module # agent spawns a team and coordinates the work
|
|
64
|
+
/swarm # agent asks you what to do, then swarms on it
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
Or drive it manually:
|
|
51
68
|
|
|
69
|
+
```
|
|
52
70
|
/team spawn alice # spawn a teammate (fresh session, shared workspace)
|
|
53
71
|
/team spawn bob branch worktree # spawn with leader context + isolated worktree
|
|
54
72
|
|
|
@@ -58,7 +76,10 @@ Verify with `/team id` — it should print the current team info.
|
|
|
58
76
|
/team dm alice Check the edge cases too # direct message
|
|
59
77
|
/team broadcast Wrapping up soon # message everyone
|
|
60
78
|
|
|
79
|
+
/tw # open the interactive widget panel
|
|
80
|
+
|
|
61
81
|
/team shutdown alice # graceful shutdown (handshake)
|
|
82
|
+
/team shutdown # stop all teammates (leader session remains active)
|
|
62
83
|
/team cleanup # remove team artifacts when done
|
|
63
84
|
```
|
|
64
85
|
|
|
@@ -79,25 +100,35 @@ Or let the model drive it with the delegate tool:
|
|
|
79
100
|
|
|
80
101
|
## Commands
|
|
81
102
|
|
|
82
|
-
|
|
103
|
+
### Shortcuts
|
|
83
104
|
|
|
84
|
-
|
|
105
|
+
| Command | Description |
|
|
106
|
+
| --- | --- |
|
|
107
|
+
| `/swarm [task]` | Tell the agent to spawn a team and work on a task |
|
|
108
|
+
| `/tw` | Open the interactive widget panel |
|
|
109
|
+
| `/team-widget` | Open the interactive widget panel (alias for `/tw`) |
|
|
110
|
+
|
|
111
|
+
### Team management
|
|
112
|
+
|
|
113
|
+
All management commands live under `/team`.
|
|
85
114
|
|
|
86
115
|
| Command | Description |
|
|
87
116
|
| --- | --- |
|
|
88
117
|
| `/team spawn <name> [fresh\|branch] [shared\|worktree]` | Start a teammate |
|
|
89
118
|
| `/team list` | List teammates and their status |
|
|
119
|
+
| `/team panel` | Interactive widget panel (same as `/tw`) |
|
|
120
|
+
| `/team style <normal\|soviet>` | Set UI style (normal/soviet) |
|
|
90
121
|
| `/team send <name> <msg>` | Send a prompt over RPC |
|
|
91
122
|
| `/team steer <name> <msg>` | Redirect an in-flight run |
|
|
92
123
|
| `/team dm <name> <msg>` | Send a mailbox message |
|
|
93
124
|
| `/team broadcast <msg>` | Message all teammates |
|
|
94
125
|
| `/team stop <name> [reason]` | Abort current work (resets task to pending) |
|
|
95
126
|
| `/team shutdown <name> [reason]` | Graceful shutdown (handshake) |
|
|
96
|
-
| `/team shutdown` |
|
|
127
|
+
| `/team shutdown` | Stop all teammates (leader session remains active) |
|
|
97
128
|
| `/team kill <name>` | Force-terminate |
|
|
98
129
|
| `/team cleanup [--force]` | Delete team artifacts |
|
|
99
130
|
| `/team id` | Print team/task-list IDs and paths |
|
|
100
|
-
| `/team env <name>` | Print env vars to start a manual
|
|
131
|
+
| `/team env <name>` | Print env vars to start a manual teammate |
|
|
101
132
|
|
|
102
133
|
### Tasks
|
|
103
134
|
|
|
@@ -119,6 +150,7 @@ All commands live under `/team`.
|
|
|
119
150
|
| --- | --- | --- |
|
|
120
151
|
| `PI_TEAMS_ROOT_DIR` | Storage root (absolute or relative to `~/.pi/agent`) | `~/.pi/agent/teams` |
|
|
121
152
|
| `PI_TEAMS_DEFAULT_AUTO_CLAIM` | Whether spawned teammates auto-claim tasks | `1` (on) |
|
|
153
|
+
| `PI_TEAMS_STYLE` | UI style (`normal` or `soviet`) | `normal` |
|
|
122
154
|
|
|
123
155
|
## Storage layout
|
|
124
156
|
|
|
@@ -136,13 +168,22 @@ All commands live under `/team`.
|
|
|
136
168
|
|
|
137
169
|
## Development
|
|
138
170
|
|
|
171
|
+
### Quality gate
|
|
172
|
+
|
|
173
|
+
```bash
|
|
174
|
+
npm run check
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
Runs strict TypeScript typechecking (`npm run typecheck`) and ESLint (`npm run lint`).
|
|
178
|
+
|
|
139
179
|
### Smoke test (no API keys)
|
|
140
180
|
|
|
141
181
|
```bash
|
|
142
|
-
|
|
182
|
+
npm run smoke-test
|
|
183
|
+
# or: npx tsx scripts/smoke-test.mts
|
|
143
184
|
```
|
|
144
185
|
|
|
145
|
-
Filesystem-level test of the task store, mailbox, and
|
|
186
|
+
Filesystem-level smoke test of the task store, mailbox, team config, and protocol parsers.
|
|
146
187
|
|
|
147
188
|
### E2E RPC test (spawns pi + one teammate)
|
|
148
189
|
|
|
@@ -150,7 +191,7 @@ Filesystem-level test of the task store, mailbox, and team config.
|
|
|
150
191
|
node scripts/e2e-rpc-test.mjs
|
|
151
192
|
```
|
|
152
193
|
|
|
153
|
-
Starts a leader in RPC mode, spawns a
|
|
194
|
+
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`.
|
|
154
195
|
|
|
155
196
|
### tmux dogfooding
|
|
156
197
|
|
|
@@ -159,7 +200,7 @@ Starts a leader in RPC mode, spawns a worker, runs a shutdown handshake, verifie
|
|
|
159
200
|
tmux attach -t pi-teams
|
|
160
201
|
```
|
|
161
202
|
|
|
162
|
-
Starts a leader + one tmux window per
|
|
203
|
+
Starts a leader + one tmux window per teammate for interactive testing.
|
|
163
204
|
|
|
164
205
|
## License
|
|
165
206
|
|
package/docs/claude-parity.md
CHANGED
|
@@ -12,12 +12,14 @@ This document tracks **feature parity gaps** between:
|
|
|
12
12
|
|
|
13
13
|
- `pi-agent-teams` (Pi extension)
|
|
14
14
|
|
|
15
|
+
> Terminology note: the extension supports `PI_TEAMS_STYLE=normal|soviet`. These docs often say "comrade" for parity with Claude Teams, but in **normal** style you’ll see "teammate" and "team leader" in the UI.
|
|
16
|
+
|
|
15
17
|
## Scope / philosophy
|
|
16
18
|
|
|
17
19
|
- Target the **same coordination primitives** as Claude Teams:
|
|
18
20
|
- shared task list
|
|
19
21
|
- mailbox messaging
|
|
20
|
-
- long-lived
|
|
22
|
+
- long-lived comrades
|
|
21
23
|
- Prefer **inspectable, local-first artifacts** (files + lock files).
|
|
22
24
|
- Avoid guidance that bypasses Claude feature gating; we only document behavior.
|
|
23
25
|
- Accept that some Claude UX (terminal keybindings + split-pane integration) may not be achievable in Pi without deeper TUI/terminal integration.
|
|
@@ -31,18 +33,18 @@ Legend: ✅ implemented • 🟡 partial • ❌ missing
|
|
|
31
33
|
| Enablement | `CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS=1` + settings | N/A | Pi extension is always available when installed/loaded. | — |
|
|
32
34
|
| Team config | `~/.claude/teams/<team>/config.json` w/ members | ✅ | Implemented via `extensions/teams/team-config.ts` (stored under `~/.pi/agent/teams/...` or `PI_TEAMS_ROOT_DIR`). | P0 |
|
|
33
35
|
| 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 |
|
|
34
|
-
| Self-claim |
|
|
35
|
-
| Explicit assign | Lead assigns task to
|
|
36
|
-
| “Message” vs “broadcast” | Send to one
|
|
37
|
-
|
|
|
38
|
-
| Display modes | In-process selection (Shift+Up/Down); split panes (tmux/iTerm) | ❌ | Pi has a widget + commands, but no terminal-level
|
|
36
|
+
| Self-claim | Comrades can self-claim next unassigned, unblocked task; file locking | ✅ | Implemented: `claimNextAvailableTask()` + locks; enabled by default (`PI_TEAMS_DEFAULT_AUTO_CLAIM=1`). | P0 |
|
|
37
|
+
| Explicit assign | Lead assigns task to comrade | ✅ | `/team task assign` sets owner + pings via mailbox. | P0 |
|
|
38
|
+
| “Message” vs “broadcast” | Send to one comrade or all comrades | ✅ | `/team dm` + `/team broadcast` use mailbox; `/team send` uses RPC. Broadcast recipients = team config workers + RPC-spawned map + active task owners; manual tmux workers self-register into `config.json` on startup. | P0 |
|
|
39
|
+
| Comrade↔comrade messaging | Comrades can message each other directly | ✅ | Workers register `team_message` LLM-callable tool; sends via mailbox + CC's leader with `peer_dm_sent` notification. | P1 |
|
|
40
|
+
| Display modes | In-process selection (Shift+Up/Down); split panes (tmux/iTerm) | ❌ | Pi has a widget + commands, but no terminal-level comrade navigation/panes. | P2 |
|
|
39
41
|
| Delegate mode | Lead restricted to coordination-only tools | ✅ | `/team delegate [on|off]` toggles; `pi.on("tool_call")` blocks `bash/edit/write`; `PI_TEAMS_DELEGATE_MODE=1` env. Widget shows `[delegate]`. | P1 |
|
|
40
|
-
| Plan approval |
|
|
41
|
-
| Shutdown handshake | Lead requests shutdown;
|
|
42
|
-
| Cleanup team | “Clean up the team” removes shared resources after
|
|
43
|
-
| Hooks / quality gates | `
|
|
42
|
+
| Plan approval | Comrade can be "plan required" and needs lead approval to implement | ✅ | `/team spawn <name> plan` sets `PI_TEAMS_PLAN_REQUIRED=1`; worker restricted to read-only tools; submits plan via `plan_approval_request`; `/team plan approve|reject <name>`. | P1 |
|
|
43
|
+
| Shutdown handshake | Lead requests shutdown; comrade can approve/reject | ✅ | Full protocol: `shutdown_request` → `shutdown_approved` or `shutdown_rejected` (when worker is busy). `/team shutdown <name>` (graceful) + `/team kill <name>` (force). | P1 |
|
|
44
|
+
| Cleanup team | “Clean up the team” removes shared resources after comrades stopped | ✅ | `/team cleanup [--force]` deletes only `<teamsRoot>/<teamId>` after safety checks. | P1 |
|
|
45
|
+
| Hooks / quality gates | `ComradeIdle`, `TaskCompleted` hooks | ❌ | Add optional hook runner in leader on idle/task-complete events (script execution + exit-code gating). | P2 |
|
|
44
46
|
| Task list UX | Ctrl+T toggle; show all/clear tasks by asking | 🟡 | Widget + `/team task list` show blocked/deps; `/team task show <id>`; `/team task clear [completed|all]`. No Ctrl+T toggle yet. | P0 |
|
|
45
|
-
| Shared task list across sessions | `CLAUDE_CODE_TASK_LIST_ID=...` | ✅ | `PI_TEAMS_TASK_LIST_ID` env
|
|
47
|
+
| Shared task list across sessions | `CLAUDE_CODE_TASK_LIST_ID=...` | ✅ | `PI_TEAMS_TASK_LIST_ID` env is **worker-side** (for manually started workers). The leader switches task lists via `/team task use <taskListId>` (persisted in `config.json`). Newly spawned workers inherit the new task list ID; existing workers need a restart to pick up changes. | P1 |
|
|
46
48
|
|
|
47
49
|
## Prioritized roadmap
|
|
48
50
|
|
|
@@ -64,7 +66,7 @@ Legend: ✅ implemented • 🟡 partial • ❌ missing
|
|
|
64
66
|
4) **Shutdown handshake** ✅
|
|
65
67
|
- Full protocol: `shutdown_request` → `shutdown_approved` / `shutdown_rejected`
|
|
66
68
|
- Worker rejects when busy (streaming + active task), auto-approves when idle
|
|
67
|
-
- Leader command: `/team shutdown <name> [reason...]` (graceful), `/team kill
|
|
69
|
+
- Leader command: `/team shutdown <name> [reason...]` (graceful), `/team kill <name>` as force
|
|
68
70
|
|
|
69
71
|
5) **Plan approval** ✅
|
|
70
72
|
- `/team spawn <name> [fresh|branch] [shared|worktree] plan` sets `PI_TEAMS_PLAN_REQUIRED=1`
|
|
@@ -80,7 +82,7 @@ Legend: ✅ implemented • 🟡 partial • ❌ missing
|
|
|
80
82
|
|
|
81
83
|
7) **Cleanup** ✅
|
|
82
84
|
- `/team cleanup [--force]` deletes only `<teamsRoot>/<teamId>` after safety checks.
|
|
83
|
-
- Refuses if RPC
|
|
85
|
+
- Refuses if RPC comrades are running or there are `in_progress` tasks unless `--force`.
|
|
84
86
|
|
|
85
87
|
8) **Peer-to-peer messaging** ✅
|
|
86
88
|
- Workers register `team_message` LLM-callable tool (recipient + message params)
|
|
@@ -93,10 +95,10 @@ Legend: ✅ implemented • 🟡 partial • ❌ missing
|
|
|
93
95
|
|
|
94
96
|
### P2: UX + “product-level” parity
|
|
95
97
|
|
|
96
|
-
10) **Better
|
|
98
|
+
10) **Better comrade interaction UX**
|
|
97
99
|
- Explore whether Pi’s TUI API can support:
|
|
98
|
-
- selecting a
|
|
99
|
-
- “entering” a
|
|
100
|
+
- selecting a comrade from the widget
|
|
101
|
+
- “entering” a comrade transcript view
|
|
100
102
|
- (Optional) tmux integration for split panes.
|
|
101
103
|
|
|
102
104
|
11) **Hooks / quality gates**
|
|
@@ -107,7 +109,9 @@ Legend: ✅ implemented • 🟡 partial • ❌ missing
|
|
|
107
109
|
|
|
108
110
|
## Where changes would land (code map)
|
|
109
111
|
|
|
110
|
-
- Leader orchestration
|
|
112
|
+
- Leader orchestration: `extensions/teams/leader.ts`
|
|
113
|
+
- Leader `/team` command dispatch: `extensions/teams/leader-team-command.ts`
|
|
114
|
+
- Leader LLM tool (`teams`): `extensions/teams/leader-teams-tool.ts`
|
|
111
115
|
- Worker mailbox polling + self-claim + protocols: `extensions/teams/worker.ts`
|
|
112
116
|
- Task store + locking: `extensions/teams/task-store.ts`, `extensions/teams/fs-lock.ts`
|
|
113
117
|
- Mailbox store + locking: `extensions/teams/mailbox.ts`
|
|
@@ -118,5 +122,5 @@ Legend: ✅ implemented • 🟡 partial • ❌ missing
|
|
|
118
122
|
|
|
119
123
|
- Keep tests hermetic by setting `PI_TEAMS_ROOT_DIR` to a temp directory.
|
|
120
124
|
- Extend:
|
|
121
|
-
- `scripts/smoke-test.
|
|
125
|
+
- `scripts/smoke-test.mts` (run via `npm run smoke-test`) for filesystem-only behaviors (deps, claiming, locking)
|
|
122
126
|
- `scripts/e2e-rpc-test.mjs` for protocol flows (shutdown handshake, plan approval)
|
|
@@ -4,12 +4,14 @@ Date: 2026-02-07
|
|
|
4
4
|
|
|
5
5
|
Goal: dogfood the Teams extension to implement its own roadmap (Claude parity), and capture anything that surprised/confused us while setting it up.
|
|
6
6
|
|
|
7
|
+
> Terminology note: the extension supports `PI_TEAMS_STYLE=normal|soviet`. In normal style the UI says "teammate" and "team leader"; in soviet style it says "comrade" and "chairman".
|
|
8
|
+
|
|
7
9
|
## Test run: test1
|
|
8
10
|
|
|
9
11
|
Decisions: tmux session `pi-teams-test1`; `PI_TEAMS_ROOT_DIR=~/projects/pi-agent-teams/test1`; `teamId=0baaa0e6-8020-4d9a-bf33-c1a65f99a2f7`; workers started manually in tmux (not `/team spawn`).
|
|
10
12
|
|
|
11
13
|
First impressions:
|
|
12
|
-
- Manual tmux workers are usable. Initially the leader showed “(no
|
|
14
|
+
- Manual tmux workers are usable. Initially the leader showed “(no comrades)” because it only tracked RPC-spawned workers; now manual workers **upsert themselves into `config.json` on startup**, and the leader widget renders online workers from team config.
|
|
13
15
|
- Pinning `PI_TEAMS_ROOT_DIR` made reruns/id discovery predictable (no “find the new folder” step).
|
|
14
16
|
- tmux workflow feels close to Claude-style split panes; bootstrap ergonomics still need smoothing.
|
|
15
17
|
- Surprise: `/team spawn <name> branch` failed once with `Entry <id> not found` (branch-from leaf missing on disk); `/team spawn <name> fresh` worked.
|
|
@@ -73,9 +75,9 @@ First impressions:
|
|
|
73
75
|
|
|
74
76
|
- **tmux vs `/team spawn`**: `/team spawn` uses `pi --mode rpc` subprocesses.
|
|
75
77
|
- Pros: simple, managed lifecycle.
|
|
76
|
-
- Cons: you don’t see a full interactive
|
|
78
|
+
- Cons: you don’t see a full interactive comrade UI like Claude’s split-pane mode.
|
|
77
79
|
- We manually started workers in separate tmux windows (setting `PI_TEAMS_WORKER=1`, `PI_TEAMS_TEAM_ID=...`, etc). This now shows up in the leader widget because workers upsert themselves into `config.json`, and the leader renders online workers from team config.
|
|
78
|
-
- Update: leader now renders
|
|
80
|
+
- Update: leader now renders comrades from `team config` and also auto-adds unknown senders on idle notifications (so manual tmux workers feel first-class).
|
|
79
81
|
- Improvement idea: optional spawn mode that starts a worker in a new tmux pane/window.
|
|
80
82
|
|
|
81
83
|
- **Two messaging paths** (`/team send` vs `/team dm`):
|
|
@@ -84,7 +86,7 @@ First impressions:
|
|
|
84
86
|
- Improvement idea: clearer naming and/or a single “message” command with a mode flag.
|
|
85
87
|
|
|
86
88
|
- **Runaway tasks / timeboxing**: a vague task prompt can turn into a long “research spiral”.
|
|
87
|
-
- In manual-tmux mode, there isn’t a great way (yet) for the leader to *steer* an in-flight run (unlike `/team steer` for RPC-spawned
|
|
89
|
+
- In manual-tmux mode, there isn’t a great way (yet) for the leader to *steer* an in-flight run (unlike `/team steer` for RPC-spawned comrades).
|
|
88
90
|
- Improvement idea: add a mailbox-level “steer” protocol message that workers can treat as an in-flight follow-up if they’re currently running.
|
|
89
91
|
|
|
90
92
|
- **Failure semantics are underspecified**: tool failures show up in the worker UI, but our task store currently only supports `pending|in_progress|completed`.
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
# pi-agent-teams — Runtime Smoke Test Plan
|
|
2
|
+
|
|
3
|
+
## Prerequisites
|
|
4
|
+
|
|
5
|
+
- `pi` CLI installed (`pi --version` → `0.52.x+`)
|
|
6
|
+
- `node_modules/` present (run `npm install` or symlink from main repo)
|
|
7
|
+
- `npx tsx` available for running `.mts` test scripts
|
|
8
|
+
|
|
9
|
+
## 1. Automated Unit Smoke Test (no interactive session)
|
|
10
|
+
|
|
11
|
+
Exercises all core primitives directly via `tsx`:
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
npx tsx scripts/smoke-test.mts
|
|
15
|
+
# or: npm run smoke-test
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
**What it tests** (overview):
|
|
19
|
+
|
|
20
|
+
| Module | Coverage |
|
|
21
|
+
|------------------|-----------------------------------------------------------------|
|
|
22
|
+
| `names.ts` | `sanitizeName` character replacement, edge cases |
|
|
23
|
+
| `fs-lock.ts` | `withLock` returns value, cleans up lock file |
|
|
24
|
+
| `mailbox.ts` | `writeToMailbox`, `popUnreadMessages`, read-once semantics |
|
|
25
|
+
| `task-store.ts` | CRUD, `startAssignedTask`, `completeTask`, `claimNextAvailable`,|
|
|
26
|
+
| | `unassignTasksForAgent`, dependencies, `clearTasks` |
|
|
27
|
+
| `team-config.ts` | `ensureTeamConfig` (idempotent), `upsertMember`, `setMemberStatus`, `loadTeamConfig` |
|
|
28
|
+
| `protocol.ts` | Structured message parsers (valid + invalid JSON + wrong type) |
|
|
29
|
+
| Pi CLI | `pi --version` executes (skipped in CI if `pi` not on PATH) |
|
|
30
|
+
|
|
31
|
+
**Expected result:** `PASSED: <n> FAILED: 0`
|
|
32
|
+
|
|
33
|
+
## 2. Extension Loading Test
|
|
34
|
+
|
|
35
|
+
Verify Pi can load the extension entry point without crashing:
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
pi --no-extensions -e extensions/teams/index.ts --help
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
**Expected:** exits 0, shows Pi help output (no TypeScript/import errors).
|
|
42
|
+
|
|
43
|
+
## 3. Interactive Smoke Test (manual)
|
|
44
|
+
|
|
45
|
+
### 3a. Launch Pi with the extension
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
# From the repo root:
|
|
49
|
+
pi --no-extensions -e extensions/teams/index.ts
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
Or, if the extension is symlinked into `~/.pi/agent/extensions/pi-agent-teams`:
|
|
53
|
+
|
|
54
|
+
```bash
|
|
55
|
+
pi # auto-loads from extensions dir
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
### 3b. Check extension is active
|
|
59
|
+
|
|
60
|
+
```
|
|
61
|
+
/team help
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
**Expected:** shows usage lines for `/team spawn`, `/team task`, etc.
|
|
65
|
+
|
|
66
|
+
### 3c. Spawn a teammate ("comrade" in soviet style)
|
|
67
|
+
|
|
68
|
+
```
|
|
69
|
+
/team spawn agent1 fresh shared
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
**Expected:** notification "Spawned agent1" or similar, widget shows `Teammate agent1: idle` (or `Comrade agent1: idle` in soviet style).
|
|
73
|
+
|
|
74
|
+
### 3d. Create and assign a task
|
|
75
|
+
|
|
76
|
+
```
|
|
77
|
+
/team task add agent1: Say hello
|
|
78
|
+
/team task list
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
**Expected:** task #1 created, assigned to agent1, status `pending` → `in_progress`.
|
|
82
|
+
|
|
83
|
+
### 3e. Verify mailbox delivery
|
|
84
|
+
|
|
85
|
+
```
|
|
86
|
+
/team dm agent1 ping from lead
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
**Expected:** "DM queued for agent1" notification.
|
|
90
|
+
|
|
91
|
+
### 3f. Delegate via tool
|
|
92
|
+
|
|
93
|
+
Ask the model:
|
|
94
|
+
> "Delegate a task to agent1: write a haiku about coding"
|
|
95
|
+
|
|
96
|
+
**Expected:** the `teams` tool is invoked, task created and assigned.
|
|
97
|
+
|
|
98
|
+
### 3g. Shutdown
|
|
99
|
+
|
|
100
|
+
```
|
|
101
|
+
/team shutdown agent1
|
|
102
|
+
/team kill agent1
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
**Expected:** agent1 goes offline, widget updates.
|
|
106
|
+
|
|
107
|
+
Optional: stop all teammates without ending the leader session:
|
|
108
|
+
|
|
109
|
+
```
|
|
110
|
+
/team shutdown
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
**Expected:** all teammates stop; leader remains active until you exit it (e.g. ctrl+d).
|
|
114
|
+
|
|
115
|
+
## 4. Worker-side Smoke (verifying child process)
|
|
116
|
+
|
|
117
|
+
To test the worker role directly:
|
|
118
|
+
|
|
119
|
+
```bash
|
|
120
|
+
PI_TEAMS_WORKER=1 \
|
|
121
|
+
PI_TEAMS_TEAM_ID=test-team \
|
|
122
|
+
PI_TEAMS_AGENT_NAME=agent1 \
|
|
123
|
+
PI_TEAMS_LEAD_NAME=team-lead \
|
|
124
|
+
PI_TEAMS_STYLE=normal \
|
|
125
|
+
pi --no-extensions -e extensions/teams/index.ts --mode rpc
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
**Expected:** process starts in RPC mode, registers `team_message` tool, polls mailbox.
|
|
129
|
+
|
|
130
|
+
## 5. Checklist Summary
|
|
131
|
+
|
|
132
|
+
| # | Test | Method | Status |
|
|
133
|
+
|---|-------------------------------|------------|--------|
|
|
134
|
+
| 1 | Unit primitives (60 asserts) | Automated | ✅ |
|
|
135
|
+
| 2 | Extension loading | CLI | ✅ |
|
|
136
|
+
| 3 | Interactive spawn/task/dm | Manual | 📋 |
|
|
137
|
+
| 4 | Worker-side RPC | Manual | 📋 |
|
|
138
|
+
|
|
139
|
+
✅ = verified in this run, 📋 = documented for manual execution.
|
package/eslint.config.js
ADDED
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
// @ts-check
|
|
2
|
+
import eslint from "@eslint/js";
|
|
3
|
+
import tseslint from "typescript-eslint";
|
|
4
|
+
|
|
5
|
+
export default tseslint.config(
|
|
6
|
+
{
|
|
7
|
+
ignores: [
|
|
8
|
+
"node_modules/**",
|
|
9
|
+
"dist/**",
|
|
10
|
+
"build/**",
|
|
11
|
+
"coverage/**",
|
|
12
|
+
".artifacts/**",
|
|
13
|
+
".research/**",
|
|
14
|
+
".resume-sessions/**",
|
|
15
|
+
],
|
|
16
|
+
},
|
|
17
|
+
|
|
18
|
+
eslint.configs.recommended,
|
|
19
|
+
...tseslint.configs.recommended,
|
|
20
|
+
|
|
21
|
+
{
|
|
22
|
+
files: ["extensions/**/*.ts", "scripts/**/*.ts", "scripts/**/*.mts"],
|
|
23
|
+
rules: {
|
|
24
|
+
// ━━ Project invariants (AGENTS.md) ━━
|
|
25
|
+
"@typescript-eslint/no-explicit-any": "error",
|
|
26
|
+
"@typescript-eslint/no-non-null-assertion": "error",
|
|
27
|
+
"@typescript-eslint/ban-ts-comment": [
|
|
28
|
+
"error",
|
|
29
|
+
{
|
|
30
|
+
"ts-ignore": true,
|
|
31
|
+
"ts-expect-error": true,
|
|
32
|
+
"ts-nocheck": true,
|
|
33
|
+
"ts-check": false,
|
|
34
|
+
},
|
|
35
|
+
],
|
|
36
|
+
|
|
37
|
+
// Imports/types
|
|
38
|
+
"@typescript-eslint/consistent-type-imports": [
|
|
39
|
+
"error",
|
|
40
|
+
{ prefer: "type-imports", disallowTypeAnnotations: false },
|
|
41
|
+
],
|
|
42
|
+
|
|
43
|
+
// General correctness
|
|
44
|
+
eqeqeq: ["error", "always"],
|
|
45
|
+
|
|
46
|
+
// Prefer TS-aware unused-vars
|
|
47
|
+
"no-unused-vars": "off",
|
|
48
|
+
"@typescript-eslint/no-unused-vars": [
|
|
49
|
+
"warn",
|
|
50
|
+
{
|
|
51
|
+
argsIgnorePattern: "^_",
|
|
52
|
+
varsIgnorePattern: "^_",
|
|
53
|
+
caughtErrorsIgnorePattern: "^_",
|
|
54
|
+
},
|
|
55
|
+
],
|
|
56
|
+
},
|
|
57
|
+
},
|
|
58
|
+
|
|
59
|
+
// Scripts/tests: console is expected
|
|
60
|
+
{
|
|
61
|
+
files: ["scripts/**/*.ts", "scripts/**/*.mts"],
|
|
62
|
+
rules: {
|
|
63
|
+
"no-console": "off",
|
|
64
|
+
},
|
|
65
|
+
},
|
|
66
|
+
|
|
67
|
+
// Extension source: discourage stray console.log
|
|
68
|
+
{
|
|
69
|
+
files: ["extensions/**/*.ts"],
|
|
70
|
+
rules: {
|
|
71
|
+
"no-console": "warn",
|
|
72
|
+
},
|
|
73
|
+
},
|
|
74
|
+
);
|