pi-maestro-teammate 0.2.0 → 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 CHANGED
@@ -1,52 +1,8 @@
1
1
  # pi-teammate
2
2
 
3
- > Teammate dispatch tool for [Pi](https://github.com/earendil-works/pi) — three-axis agent orchestration with P0 decoupling
3
+ > Teammate dispatch tool for [Pi](https://github.com/earendil-works/pi) — unified TaskSpec with DAG variable referencing
4
4
 
5
- Pi extension implementing teammate dispatch with **P0 three-axis decoupling** (name × reply_to × lifecycle). Spawn isolated pi subprocesses as teammates with protocol-versioned routing, parallel/chain execution, and structured output.
6
-
7
- ## Features
8
-
9
- ### Three-Axis Control
10
-
11
- | Axis | Field | Values | Purpose |
12
- |------|-------|--------|---------|
13
- | Addressability | `name` | string \| omit | Cross-agent routing via name |
14
- | Result Routing | `reply_to` | `"caller"` \| `"main"` | Where results go |
15
- | Lifecycle | `lifecycle` | `"ephemeral"` \| `"resident"` | One-shot or persistent |
16
-
17
- **Protocol version gate** — v2 (default) routes results to `caller`; v1 compat routes named agents to `main`. Explicit `reply_to` always wins.
18
-
19
- ### Execution Modes
20
-
21
- - **Single** — dispatch one agent with a task
22
- - **Parallel** — `tasks[]` runs multiple agents concurrently with configurable `concurrency`
23
- - **Chain** — `chain[]` sequential pipeline where each step receives `{previous}` result
24
-
25
- ### Reliability
26
-
27
- - **Model fallback chain** — primary model → `fallbackModels[]` from agent config → automatic retry on model failures
28
- - **Nesting depth guard** — `PI_TEAMMATE_DEPTH` env tracking with configurable max (default: 3) prevents fork bombs
29
- - **Windows-safe pi resolution** — `getPiSpawnCommand()` resolves the pi binary via env override, Windows script detection, or PATH
30
- - **Abort signal** — SIGTERM → 5s grace → SIGKILL
31
-
32
- ### Output & Tracking
33
-
34
- - **Structured output** — `outputSchema` validates child output against JSON Schema, returns parsed `structuredOutput`
35
- - **Rich progress** — `AgentProgress` with `recentTools[]`, `toolCount`, `tokens`, `durationMs`, `lastActivityAt`
36
- - **Session management** — derives child session directory from parent session, supports `context: "fork"`
37
- - **Correlation ID** — auto-generated per dispatch for result routing
38
-
39
- ### Agent Definitions
40
-
41
- Agents are markdown files with YAML frontmatter — discovered from project (`.pi/agents/`), user (`~/.pi/agent/extensions/teammate/agents/`), or builtin locations. Project overrides user overrides builtin.
42
-
43
- ## Install
44
-
45
- ```bash
46
- pi install npm:@pi-maestro/teammate
47
- # or from local path
48
- pi install ./pi-teammate
49
- ```
5
+ Pi extension implementing teammate dispatch with **unified TaskSpec model**. Single agent, parallel fan-out, sequential chains, and arbitrary DAGs all use the same schema — execution order is determined by `{name}` variable references between tasks.
50
6
 
51
7
  ## Quick Start
52
8
 
@@ -56,7 +12,7 @@ pi install ./pi-teammate
56
12
  { agent: "delegate", task: "Implement the auth middleware" }
57
13
  ```
58
14
 
59
- ### Parallel Execution
15
+ ### Parallel (no references = concurrent)
60
16
 
61
17
  ```
62
18
  { tasks: [
@@ -68,22 +24,34 @@ pi install ./pi-teammate
68
24
  }
69
25
  ```
70
26
 
71
- ### Chain Pipeline
27
+ ### Chain (linear references = sequential)
72
28
 
73
29
  ```
74
- { chain: [
75
- { agent: "scout", task: "Find the auth module structure" },
76
- { agent: "delegate", task: "Based on this context: {previous}\n\nRefactor the auth module" }
30
+ { tasks: [
31
+ { agent: "scout", name: "recon", task: "Find the auth module structure" },
32
+ { agent: "delegate", task: "Based on this context: {recon}\n\nRefactor the auth module" }
77
33
  ]
78
34
  }
79
35
  ```
80
36
 
81
- ### Three-Axis Routing
37
+ ### DAG (mixed references = auto-scheduling)
82
38
 
83
39
  ```
84
- { agent: "delegate", task: "...", name: "worker-1", reply_to: "caller", lifecycle: "ephemeral" }
40
+ { tasks: [
41
+ { agent: "scout", name: "api", task: "List all API routes",
42
+ outputSchema: {
43
+ type: "object",
44
+ properties: { routes: { type: "array", items: { type: "string" } } },
45
+ required: ["routes"]
46
+ } },
47
+ { agent: "scout", name: "db", task: "Map the database schema" },
48
+ { agent: "reviewer", task: "Routes: {api.routes}\nDB: {db}\n\nCheck consistency" }
49
+ ]
50
+ }
85
51
  ```
86
52
 
53
+ `api` and `db` run in parallel. `reviewer` waits for both, with `{api.routes}` resolved from structured output and `{db}` from text output.
54
+
87
55
  ### Structured Output
88
56
 
89
57
  ```
@@ -96,6 +64,147 @@ pi install ./pi-teammate
96
64
  }
97
65
  ```
98
66
 
67
+ In multi-task mode, structured outputs are aggregated by task `name` in the result's `structuredOutput` field.
68
+
69
+ ## Core Concepts
70
+
71
+ ### Two Rules
72
+
73
+ 1. **Reference = dependency**: `{name}` in a task's description means "wait for the task named `name` to complete, then inject its output here"
74
+ 2. **No reference = parallel**: tasks with no dependencies run concurrently (bounded by `concurrency`)
75
+
76
+ No `mode` field needed — the execution engine infers parallel, chain, or graph from the reference topology.
77
+
78
+ ### Variable References
79
+
80
+ | Syntax | Resolves to |
81
+ |--------|-------------|
82
+ | `{name}` | Full text output; or JSON string if the task has `outputSchema` |
83
+ | `{name.field}` | Field from structured output |
84
+ | `{name.arr[0].path}` | Nested field with array indexing |
85
+
86
+ Only tasks with a `name` field can be referenced. Non-task `{braces}` (JSON, format strings) are left untouched.
87
+
88
+ ### Default Inheritance
89
+
90
+ Top-level fields serve as defaults for all tasks:
91
+
92
+ | Field | Scope | Override |
93
+ |-------|-------|----------|
94
+ | `model` | Default model for all tasks | Per-task `model` wins |
95
+ | `cwd` | Default working directory | Per-task `cwd` wins |
96
+ | `outputSchema` | Default schema for all tasks | Per-task `outputSchema` wins |
97
+ | `timeoutMs` | Default timeout | Per-task `timeoutMs` wins |
98
+
99
+ ### Three-Axis Control
100
+
101
+ | Axis | Field | Values | Purpose |
102
+ |------|-------|--------|---------|
103
+ | Addressability | `name` | string \| omit | Variable referencing + teammate-send routing |
104
+ | Result Routing | `reply_to` | `"caller"` \| `"main"` | Where results go |
105
+ | Lifecycle | `lifecycle` | `"ephemeral"` \| `"resident"` | One-shot or persistent |
106
+
107
+ **Protocol version gate** — v2 (default) routes results to `caller`; v1 compat routes named agents to `main`. Explicit `reply_to` always wins.
108
+
109
+ ## TaskSpec Schema
110
+
111
+ ```typescript
112
+ interface TaskSpec {
113
+ agent: string; // Agent name (matches agents/*.md filename)
114
+ task?: string; // Task description with {name} variable support
115
+ name?: string; // Identifier for referencing and teammate-send
116
+ model?: string; // Model override
117
+ cwd?: string; // Working directory
118
+ outputSchema?: object; // JSON Schema for structured output
119
+ timeoutMs?: number; // Timeout in milliseconds
120
+ }
121
+ ```
122
+
123
+ ## Full Parameters
124
+
125
+ ```typescript
126
+ interface TeammateParams extends TaskSpec {
127
+ // Multi-task
128
+ tasks?: TaskSpec[]; // Multiple tasks with {name} references
129
+ concurrency?: number; // Max concurrent tasks (default: 4)
130
+
131
+ // Execution control (applies to ALL modes)
132
+ background?: boolean; // Run in background (default: true)
133
+ context?: "fresh" | "fork";
134
+
135
+ // P0 three-axis
136
+ reply_to?: "caller" | "main";
137
+ protocol_version?: number;
138
+
139
+ // Deprecated
140
+ chain?: Array<{ agent, task?, model? }>; // Use tasks with {name} references
141
+ }
142
+ ```
143
+
144
+ ## Validation & Error Handling
145
+
146
+ - **Duplicate names**: detected before execution, all tasks fail with error
147
+ - **Circular dependencies**: detected before execution via cycle detection
148
+ - **Missing reference**: `{unknown}` left as literal text (not a task name)
149
+ - **Field access without schema**: error when `{name.field}` used but task has no `outputSchema`
150
+ - **Upstream failure**: dependent tasks are skipped with "upstream dependency failed"
151
+
152
+ ## Deprecated: chain[]
153
+
154
+ The `chain` field is preserved for backward compatibility. It normalizes internally to `tasks` with sequential `{_stepN}` references:
155
+
156
+ ```
157
+ // This chain:
158
+ { chain: [
159
+ { agent: "scout", task: "Find auth code" },
160
+ { agent: "delegate", task: "Fix: {previous}" }
161
+ ]
162
+ }
163
+
164
+ // Is equivalent to:
165
+ { tasks: [
166
+ { agent: "scout", name: "_step0", task: "Find auth code" },
167
+ { agent: "delegate", name: "_step1", task: "Fix: {_step0}" }
168
+ ]
169
+ }
170
+ ```
171
+
172
+ ## Flat Agent Model
173
+
174
+ All agents are managed by the root process in a single flat `activeRuns` pool, regardless of who requested the spawn. Child agents that call the teammate tool send a proxy request to the root, which spawns the new agent as a peer — not a nested subprocess.
175
+
176
+ ### How It Works
177
+
178
+ ```
179
+ coordinator calls teammate({ agent: "scout", name: "recon" })
180
+ │ stdout: teammate_proxy_request
181
+ ▼
182
+ Root spawns scout → registers in root's activeRuns/namedAgents
183
+ │ IPC: teammate_proxy_result
184
+ ▼
185
+ coordinator receives result
186
+ ```
187
+
188
+ All agents are flat peers:
189
+ - `teammate-send({ to: "name" })` = one lookup in `namedAgents` → stdin. Direct delivery.
190
+ - `teammate-list` = iterate `activeRuns`. Flat, simple.
191
+ - `teammate-watch` = read agent's `outputLog`. Direct.
192
+
193
+ ### Child Proxy Tools
194
+
195
+ Child processes register proxy versions of all teammate tools. Each proxy:
196
+ 1. Writes a `teammate_proxy_request` JSON line to stdout
197
+ 2. Awaits the result via Node.js IPC (`process.on("message")`)
198
+
199
+ The root's event parser intercepts these requests and executes them locally. The IPC channel is established via `stdio: ["pipe","pipe","pipe","ipc"]` at spawn time.
200
+
201
+ ## Reliability
202
+
203
+ - **Model fallback chain** — primary model → `fallbackModels[]` from agent config → automatic retry
204
+ - **Flat agent pool** — all agents managed by root process; child proxy tools forward spawn requests to root; depth guard (`PI_TEAMMATE_DEPTH`) prevents runaway recursion
205
+ - **Windows-safe pi resolution** — `getPiSpawnCommand()` resolves the pi binary via env override, Windows script detection, or PATH
206
+ - **Abort signal** — SIGTERM → 5s grace → SIGKILL
207
+
99
208
  ## Agent Definition Format
100
209
 
101
210
  Create `agents/my-agent.md`:
@@ -114,8 +223,6 @@ defaultContext: fresh
114
223
  ---
115
224
 
116
225
  You are a specialized agent. Your system prompt goes here.
117
-
118
- Use the provided tools to accomplish the task.
119
226
  ```
120
227
 
121
228
  ### Frontmatter Fields
@@ -133,37 +240,12 @@ Use the provided tools to accomplish the task.
133
240
  | `inheritSkills` | bool | false | Inherit parent skills |
134
241
  | `defaultContext` | fresh\|fork | fresh | Default context mode |
135
242
 
136
- ## Architecture
137
-
138
- ```
139
- ┌─────────────────────────────────────────────────┐
140
- │ Parent Pi Session │
141
- │ │
142
- │ teammate tool call │
143
- │ │ │
144
- │ ├── resolve agent (project > user > built) │
145
- │ ├── resolve reply_to (protocol gate) │
146
- │ ├── check depth guard │
147
- │ ├── build model candidates │
148
- │ │ │
149
- │ ▼ │
150
- │ ┌─────────────────────────────────────┐ │
151
- │ │ spawn("pi", ["--mode","json","-p"])│ │
152
- │ │ env: PI_TEAMMATE_CHILD=1 │ │
153
- │ │ PI_TEAMMATE_DEPTH=N │ │
154
- │ │ PI_TEAMMATE_CORRELATION_ID=… │ │
155
- │ │ PI_TEAMMATE_REPLY_TO=caller │ │
156
- │ │ │ │
157
- │ │ stdout: JSON lines ──────────────► │ parse │
158
- │ │ (message_end, tool_result_end, │ events │
159
- │ │ usage, error) │ │
160
- │ └─────────────────────────────────────┘ │
161
- │ │ │
162
- │ ├── accumulate usage │
163
- │ ├── track progress (AgentProgress) │
164
- │ ├── model fallback on failure │
165
- │ └── return SingleResult │
166
- └─────────────────────────────────────────────────┘
243
+ ## Install
244
+
245
+ ```bash
246
+ pi install npm:@pi-maestro/teammate
247
+ # or from local path
248
+ pi install ./pi-teammate
167
249
  ```
168
250
 
169
251
  ## Environment Variables
@@ -1,19 +1,24 @@
1
1
  ---
2
2
  name: coordinator
3
- description: Orchestration-aware teammate agent for multi-step coordination tasks
3
+ description: Orchestration-aware teammate agent for multi-step task coordination with DAG variable referencing
4
4
  systemPromptMode: replace
5
5
  inheritProjectContext: true
6
6
  thinking: high
7
- tools: read, grep, find, ls, bash, edit, write
7
+ tools: read, grep, find, ls, bash, edit, write, teammate, teammate-send, teammate-list, teammate-watch
8
8
  inheritSkills: false
9
9
  ---
10
10
 
11
- You are a coordinator agent responsible for orchestrating multi-step tasks. You plan the execution strategy, coordinate between subtasks, and synthesize results.
11
+ You are a coordinator agent responsible for orchestrating multi-step tasks.
12
+
13
+ When dispatching subtasks via the teammate tool, use the unified TaskSpec model:
14
+ - Give each task a `name` so downstream tasks can reference its output via `{name}`
15
+ - Use `outputSchema` when a task's output needs to be consumed as structured data by dependents via `{name.field}`
16
+ - Tasks with no `{name}` references run in parallel; tasks that reference others wait automatically
12
17
 
13
18
  Your approach:
14
- 1. Analyze the task requirements and break them into steps
15
- 2. Execute steps in the correct order, respecting dependencies
16
- 3. Verify each step's output before proceeding
17
- 4. Synthesize a coherent result from all steps
19
+ 1. Analyze the task requirements and decompose into named subtasks
20
+ 2. Define data flow between subtasks using `{name}` variable references
21
+ 3. Let the execution engine resolve the dependency graph — no need to manually order
22
+ 4. Verify results and synthesize a coherent output
18
23
 
19
24
  Be methodical and thorough. Document your reasoning for key decisions. If a step fails, attempt recovery before reporting failure.
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "pi-maestro-teammate",
3
- "version": "0.2.0",
4
- "description": "Pi extension for teammate dispatch with P0 three-axis decoupling (name, reply_to, lifecycle)",
3
+ "version": "0.3.0",
4
+ "description": "Pi extension for teammate dispatch with P0 three-axis decoupling (name, reply_to)",
5
5
  "type": "module",
6
6
  "keywords": [
7
7
  "pi-package",