pi-thread-engine 0.4.6 → 0.4.9
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/PLAN.md +25 -28
- package/README.md +221 -214
- package/_lib/contract.ts +116 -0
- package/docs/HELLO_PYTHON.md +68 -0
- package/extensions/index.ts +332 -74
- package/package.json +15 -6
- package/src/core/executor.ts +284 -220
- package/src/core/registry.test.ts +32 -0
- package/src/core/registry.ts +290 -290
- package/src/core/types.ts +107 -107
- package/src/core/worktree.ts +309 -0
- package/src/dashboard.ts +426 -421
- package/src/hello-world.test.ts +30 -0
- package/src/hello-world.ts +25 -0
- package/src/worktree-lifecycle.test.ts +124 -0
package/PLAN.md
CHANGED
|
@@ -1,33 +1,30 @@
|
|
|
1
|
-
# pi-thread-engine
|
|
1
|
+
# pi-thread-engine — Current State & Next Steps
|
|
2
2
|
|
|
3
|
-
## Current State (v0.4.
|
|
3
|
+
## Current State (v0.4.9)
|
|
4
|
+
- 14 commands: threads, agents, pthread, cthread, bthread, fthread, zthread, lthread, wthread, plan, loop, story, stories, hello
|
|
5
|
+
- 3 tools: thread_spawn, thread_status, thread_kill
|
|
6
|
+
- Worktree threads: /wthread with create/list/push/discard/cleanup explicit lifecycle
|
|
7
|
+
- Dashboard v3: 3-column grouping, progress bars, search, inline reply, export (E key), pinning (P key)
|
|
8
|
+
- Native thread execution: child Pi runs are isolated from sessions/extensions/skills/context files; Windows uses cmd.exe shim
|
|
9
|
+
- Export: /threads export [id|--all] and E key in dashboard
|
|
4
10
|
|
|
5
|
-
|
|
6
|
-
-
|
|
7
|
-
-
|
|
8
|
-
-
|
|
9
|
-
-
|
|
10
|
-
-
|
|
11
|
-
-
|
|
12
|
-
-
|
|
13
|
-
-
|
|
14
|
-
- IndyDevDan framework branding: README + THREADS.md
|
|
11
|
+
## Verified Locally
|
|
12
|
+
- npm test: 3 files, 11 tests
|
|
13
|
+
- npx tsc --noEmit
|
|
14
|
+
- npm run build
|
|
15
|
+
- bash scripts/test.sh
|
|
16
|
+
- bash scripts/test-commands.sh
|
|
17
|
+
- Runtime smoke: thread_spawn + thread_status completed with THREAD_SMOKE_OK
|
|
18
|
+
- Runtime smoke: thread_kill stayed killed through repeated polling
|
|
19
|
+
- npm pack --dry-run: 17 files, no stray profiles file
|
|
15
20
|
|
|
16
|
-
##
|
|
21
|
+
## What's Remaining (gaps vs Grok CLI / Orca)
|
|
17
22
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
23
|
+
1. **Tool permission gate** — approve/deny tool calls per-session. Port from Grok CLI.
|
|
24
|
+
2. **Notifications** — desktop toast when thread completes.
|
|
25
|
+
3. **Auto-indexing** — codebase context that follows active repo.
|
|
26
|
+
4. **Session sharing** — export/import threads via URL.
|
|
27
|
+
5. **Agent profiles** — build/plan/debug/research personas.
|
|
21
28
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
4. **@IndyDevDan outreach** — Draft DM/message saying pi-thread-engine implements his framework
|
|
25
|
-
|
|
26
|
-
### P2 — Nice to have
|
|
27
|
-
5. **Pinning** — `P` key to pin threads to top
|
|
28
|
-
6. **Git worktree support** — `--worktree` flag on spawn for isolated branches
|
|
29
|
-
7. **pi-memory integration** — Auto-recall from `~/.pi-memory/` before spawning
|
|
30
|
-
|
|
31
|
-
### P3 — Long term
|
|
32
|
-
8. **ACP support** — Agent Client Protocol interoperability
|
|
33
|
-
9. **Session sharing** — Export/import threads via URL
|
|
29
|
+
## Next Build
|
|
30
|
+
Pick one from above and write an implementation plan before coding.
|
package/README.md
CHANGED
|
@@ -1,215 +1,222 @@
|
|
|
1
|
-
# 🧵 pi-thread-engine
|
|
2
|
-
|
|
3
|
-
> *"When you start thinking in threads, you stop being a bottleneck and become an orchestrator."*
|
|
4
|
-
> — @IndyDevDan, [Thinking in Threads](https://agenticengineer.com/thinking-in-threads)
|
|
5
|
-
|
|
6
|
-
**Thread-Based Engineering** for [Pi Coding Agent](https://github.com/badlogic/pi-mono).
|
|
7
|
-
7 thread types + stories + fusion + zero-touch + full TUI dashboard.
|
|
8
|
-
Built on @IndyDevDan's framework from [agenticengineer.com](https://agenticengineer.com).
|
|
9
|
-
|
|
10
|
-
## Install
|
|
11
|
-
|
|
12
|
-
```bash
|
|
13
|
-
pi install npm:pi-thread-engine
|
|
14
|
-
```
|
|
15
|
-
|
|
16
|
-
## The Thread Framework
|
|
17
|
-
|
|
18
|
-
Everything starts with the base thread:
|
|
19
|
-
|
|
20
|
-
```
|
|
21
|
-
PROMPT → TOOL CALLS → REVIEW
|
|
22
|
-
You Agent You
|
|
23
|
-
```
|
|
24
|
-
|
|
25
|
-
You show up at two nodes for maximum leverage. Your agent handles everything in between.
|
|
26
|
-
|
|
27
|
-
Then you multiply:
|
|
28
|
-
|
|
29
|
-
```
|
|
30
|
-
Thread Types
|
|
31
|
-
├── Base → You → Agent → You (minutes)
|
|
32
|
-
├── P → Parallel 5+ agents (hours)
|
|
33
|
-
├── C → Checkpoint chains (high-stakes)
|
|
34
|
-
├── F → Fusion 9 agents, pick winner
|
|
35
|
-
├── B → Branch (orchestrator agents)
|
|
36
|
-
├── L → Long-running 26hrs (days)
|
|
37
|
-
└── Z → Zero-touch, no review (ultimate)
|
|
38
|
-
```
|
|
39
|
-
|
|
40
|
-
## Commands
|
|
41
|
-
|
|
42
|
-
| Command | Type | What |
|
|
43
|
-
|---------|------|------|
|
|
44
|
-
| `/threads` | Dashboard | TUI: 3-column status view, search, inline reply, keyboard nav |
|
|
45
|
-
| `/pthread` | P-Thread | N independent tasks in parallel |
|
|
46
|
-
| `/cthread` | C-Thread | Sequential phases with checkpoint
|
|
47
|
-
| `/bthread` | B-Thread | scout → plan → build → review pipeline |
|
|
48
|
-
| `/fthread` | F-Thread | Same prompt → N models → compare, pick winner |
|
|
49
|
-
| `/zthread` | Z-Thread | Autonomous + verification gate (ships only if tests pass) |
|
|
50
|
-
| `/lthread` | L-Thread | Extended autonomous run |
|
|
51
|
-
| `/story` | Stories | Auto-decompose goal into thread phases |
|
|
52
|
-
| `/agents` | Alias | Same as `/threads` — Claude muscle memory |
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
▸ t-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
▸
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
-
|
|
84
|
-
- `
|
|
85
|
-
- `
|
|
86
|
-
-
|
|
87
|
-
- `
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
```
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
```
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
```
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
```
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
```
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
│
|
|
206
|
-
│
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
-
|
|
213
|
-
|
|
214
|
-
|
|
1
|
+
# 🧵 pi-thread-engine
|
|
2
|
+
|
|
3
|
+
> *"When you start thinking in threads, you stop being a bottleneck and become an orchestrator."*
|
|
4
|
+
> — @IndyDevDan, [Thinking in Threads](https://agenticengineer.com/thinking-in-threads)
|
|
5
|
+
|
|
6
|
+
**Thread-Based Engineering** for [Pi Coding Agent](https://github.com/badlogic/pi-mono).
|
|
7
|
+
7 thread types + stories + fusion + zero-touch + full TUI dashboard.
|
|
8
|
+
Built on @IndyDevDan's framework from [agenticengineer.com](https://agenticengineer.com).
|
|
9
|
+
|
|
10
|
+
## Install
|
|
11
|
+
|
|
12
|
+
```bash
|
|
13
|
+
pi install npm:pi-thread-engine
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
## The Thread Framework
|
|
17
|
+
|
|
18
|
+
Everything starts with the base thread:
|
|
19
|
+
|
|
20
|
+
```
|
|
21
|
+
PROMPT → TOOL CALLS → REVIEW
|
|
22
|
+
You Agent You
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
You show up at two nodes for maximum leverage. Your agent handles everything in between.
|
|
26
|
+
|
|
27
|
+
Then you multiply:
|
|
28
|
+
|
|
29
|
+
```
|
|
30
|
+
Thread Types
|
|
31
|
+
├── Base → You → Agent → You (minutes)
|
|
32
|
+
├── P → Parallel 5+ agents (hours)
|
|
33
|
+
├── C → Checkpoint chains (high-stakes)
|
|
34
|
+
├── F → Fusion 9 agents, pick winner
|
|
35
|
+
├── B → Branch (orchestrator agents)
|
|
36
|
+
├── L → Long-running 26hrs (days)
|
|
37
|
+
└── Z → Zero-touch, no review (ultimate)
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
## Commands
|
|
41
|
+
|
|
42
|
+
| Command | Type | What |
|
|
43
|
+
|---------|------|------|
|
|
44
|
+
| `/threads` | Dashboard | TUI: 3-column status view, search, inline reply, keyboard nav |
|
|
45
|
+
| `/pthread` | P-Thread | N independent tasks in parallel |
|
|
46
|
+
| `/cthread` | C-Thread | Sequential phases with human checkpoint prompts |
|
|
47
|
+
| `/bthread` | B-Thread | scout → plan → build → review pipeline |
|
|
48
|
+
| `/fthread` | F-Thread | Same prompt → N models → compare, pick winner |
|
|
49
|
+
| `/zthread` | Z-Thread | Autonomous + verification gate (ships only if tests pass) |
|
|
50
|
+
| `/lthread` | L-Thread | Extended autonomous run |
|
|
51
|
+
| `/story` | Stories | Auto-decompose goal into thread phases |
|
|
52
|
+
| `/agents` | Alias | Same as `/threads` — Claude muscle memory |
|
|
53
|
+
| `/hello` | Greeting | Say hello. Usage: `/hello [name]` |
|
|
54
|
+
|
|
55
|
+
Use `/hello [name]` for a quick greeting from the assistant.
|
|
56
|
+
|
|
57
|
+
## Dashboard
|
|
58
|
+
|
|
59
|
+
Run `/threads` (or `/agents`) to open the TUI dashboard:
|
|
60
|
+
|
|
61
|
+
```
|
|
62
|
+
🧵 Thread Dashboard
|
|
63
|
+
═══════════════════════════════════════════
|
|
64
|
+
|
|
65
|
+
⚡ Needs Input (2)
|
|
66
|
+
▸ t-001 ████████░░ needs_input /fix bug in auth → "password has special chars"
|
|
67
|
+
▸ t-003 ░░░░░░░░░ needs_input /audit dependencies → "found 3 vulnerable"
|
|
68
|
+
|
|
69
|
+
⚙ Working (3)
|
|
70
|
+
▸ t-002 ██████░░░░ running /migrate database ⏱ 4m 23s
|
|
71
|
+
▸ t-004 ████░░░░░░ running /build API endpoints ⏱ 2m 11s
|
|
72
|
+
▸ s-001 →scout→plan→build running /story add payments
|
|
73
|
+
|
|
74
|
+
✓ Done (4)
|
|
75
|
+
▸ t-005 ██████████ success /refactor auth module → "cleaned up 12 files"
|
|
76
|
+
▸ t-006 ██████████ success /update docs → "30 pages updated"
|
|
77
|
+
▸ t-007 ██████████ error /deploy to prod ✗ "missing env vars"
|
|
78
|
+
|
|
79
|
+
nav=↑↓ exp=Enter rep=i srch=/ kill=k rev=r prune=p quit=q
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
**Keyboard shortcuts:**
|
|
83
|
+
- `↑↓` — navigate threads
|
|
84
|
+
- `Enter` — expand/collapse thread details
|
|
85
|
+
- `i` — inline reply (send message to blocked thread)
|
|
86
|
+
- `/` — search/filter threads
|
|
87
|
+
- `k` — kill selected thread
|
|
88
|
+
- `r` — review selected thread results
|
|
89
|
+
- `p` — prune (clear) finished threads
|
|
90
|
+
- `q` — quit dashboard
|
|
91
|
+
|
|
92
|
+
## Thread Types in Depth
|
|
93
|
+
|
|
94
|
+
### P-Thread — Parallel
|
|
95
|
+
Five in the terminal. Five to ten in the browser. Zero apologies.
|
|
96
|
+
— *Boris Cherny, creator of Claude Code*
|
|
97
|
+
|
|
98
|
+
```bash
|
|
99
|
+
/pthread "write tests" "refactor auth" "check edge cases"
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
### C-Thread — Checkpoint Chains
|
|
103
|
+
High-stakes work needs verification at critical junctures.
|
|
104
|
+
Intentional chunking is a feature, not a bug.
|
|
105
|
+
|
|
106
|
+
```bash
|
|
107
|
+
/cthread "scout migration risk" "draft migration plan" "run migration checks"
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
### F-Thread — Fusion (pi-thread-engine unique)
|
|
111
|
+
Multiple agents. Multiple parallel futures. Pick the winner.
|
|
112
|
+
|
|
113
|
+
```bash
|
|
114
|
+
/fthread "Design the caching architecture" --count 5
|
|
115
|
+
/fthread "Refactor the auth module" --models claude,gpt-4o,gemini-pro
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
Best-of-N gives you confidence. Cherry-picking gives you quality.
|
|
119
|
+
Each agent runs in complete isolation — no cross-contamination.
|
|
120
|
+
|
|
121
|
+
### B-Thread — Branch/Meta-Agentic
|
|
122
|
+
When agents manage agents. You become an Orchestrator of Intelligence.
|
|
123
|
+
|
|
124
|
+
```bash
|
|
125
|
+
/bthread "Build the checkout flow"
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
Auto-runs: scout → plan → build → review.
|
|
129
|
+
|
|
130
|
+
### L-Thread — Long-Running
|
|
131
|
+
A single prompt that ran 26 hours.
|
|
132
|
+
|
|
133
|
+
```bash
|
|
134
|
+
/lthread "Audit and fix all security vulnerabilities"
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
### Z-Thread — Zero-Touch (pi-thread-engine unique)
|
|
138
|
+
Maximum earned trust. No review node. Ships only if verification passes.
|
|
139
|
+
|
|
140
|
+
```bash
|
|
141
|
+
/zthread "Fix all ESLint warnings" --verify "npm run lint"
|
|
142
|
+
/zthread "Add dark mode" --verify "npm test && npm run build"
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
This is NOT vibe coding. Z-threads are the opposite:
|
|
146
|
+
maximum earned trust through hundreds of iterations.
|
|
147
|
+
|
|
148
|
+
### Stories — Goal Decomposition (pi-thread-engine unique)
|
|
149
|
+
Auto-decompose a goal into thread phases. pi-thread-engine picks the right type for each.
|
|
150
|
+
|
|
151
|
+
```bash
|
|
152
|
+
/story "Add dark mode to the dashboard" --verify "npm test"
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
Auto-generates phases:
|
|
156
|
+
1. **Scout** (meta) — research the codebase
|
|
157
|
+
2. **Plan** (fusion) — 3 models brainstorm approaches
|
|
158
|
+
3. **Decide** (checkpoint) — human picks the winner
|
|
159
|
+
4. **Build** (parallel) — implement across files
|
|
160
|
+
5. **Verify** (zero) — run tests
|
|
161
|
+
|
|
162
|
+
## LLM Tools
|
|
163
|
+
|
|
164
|
+
Use these inside any Pi prompt:
|
|
165
|
+
|
|
166
|
+
```typescript
|
|
167
|
+
thread_spawn({ type: "parallel", prompts: [...] }) // P-thread
|
|
168
|
+
thread_spawn({ type: "chained", prompts: [...] }) // C-thread
|
|
169
|
+
thread_spawn({ type: "fusion", prompts: [...] }) // F-thread
|
|
170
|
+
thread_spawn({ type: "meta", prompts: [...] }) // B-thread
|
|
171
|
+
thread_spawn({ type: "long", prompts: [...] }) // L-thread
|
|
172
|
+
thread_spawn({ type: "zero", prompts: [...], verify: "npm test" }) // Z-thread
|
|
173
|
+
thread_status({ id: "t-001" }) // Check progress
|
|
174
|
+
thread_kill({ id: "t-001" }) // Stop a thread
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
## The Core Four
|
|
178
|
+
|
|
179
|
+
Every thread runs on these four pillars. Invest in all of them:
|
|
180
|
+
|
|
181
|
+
| Pillar | Description | pi-thread-engine |
|
|
182
|
+
|--------|-------------|-----------------|
|
|
183
|
+
| **Context** | Right information (no more, no less) | `~/.pi-memory/` integration |
|
|
184
|
+
| **Model** | Capable of sustained reasoning | Pi's configured models |
|
|
185
|
+
| **Prompt** | Crystal-clear agentic engineering | Structured commands |
|
|
186
|
+
| **Tools** | Self-verifying, comprehensive | Pi tools + optional pi-skills |
|
|
187
|
+
|
|
188
|
+
## Measuring Progress
|
|
189
|
+
|
|
190
|
+
You know you're improving at agentic coding when:
|
|
191
|
+
|
|
192
|
+
- **Width** ↑ — P-threads = 5x exploration per hour
|
|
193
|
+
- **Time** ↑ — L-threads = 10min → 8hrs autonomous work
|
|
194
|
+
- **Depth** ↑ — B-threads = one prompt → entire teams
|
|
195
|
+
- **Checkpoints** ↓ — Earned trust through evidence
|
|
196
|
+
|
|
197
|
+
> *The common denominator: increase tool calls per unit of your attention.*
|
|
198
|
+
|
|
199
|
+
## Architecture
|
|
200
|
+
|
|
201
|
+
```
|
|
202
|
+
┌─────────────────────────────────────────────────────┐
|
|
203
|
+
│ pi-thread-engine │
|
|
204
|
+
├─────────────┬──────────────┬────────────────────────┤
|
|
205
|
+
│ Dashboard │ Registry │ Executor │
|
|
206
|
+
│ (TUI v3) │ (state) │ (dispatch) │
|
|
207
|
+
├─────────────┴──────────────┴────────────────────────┤
|
|
208
|
+
│ Commands: /threads /pthread /cthread /fthread │
|
|
209
|
+
│ /bthread /zthread /lthread /story │
|
|
210
|
+
├─────────────────────────────────────────────────────┤
|
|
211
|
+
│ Backends │
|
|
212
|
+
│ ├─ pi-subagents (P/B threads) │
|
|
213
|
+
│ └─ native (Base/C/F/Z/L + extension threads) │
|
|
214
|
+
└─────────────────────────────────────────────────────┘
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
## Further Reading
|
|
218
|
+
|
|
219
|
+
- [Thinking in Threads](https://agenticengineer.com/thinking-in-threads) — @IndyDevDan
|
|
220
|
+
- [The Only Claude Code Competitor](https://agenticengineer.com/the-only-claude-code-competitor)
|
|
221
|
+
- [Compute Advantage Equation](https://agenticengineer.com/compute-advantage-equation)
|
|
215
222
|
- [Engineering with Exponentials](https://agenticengineer.com/state-of-ai-coding/engineering-with-exponentials)
|
package/_lib/contract.ts
ADDED
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* _lib/contract.ts — Runtime IO contract layer for subagent boundaries
|
|
3
|
+
*
|
|
4
|
+
* Persona frontmatter declares inputs/outputs/reads/writes/calls as TypeBox schemas.
|
|
5
|
+
* A tiny runtime validates every subagent boundary at call time.
|
|
6
|
+
*
|
|
7
|
+
* This gives us what Grok's persona file describes but doesn't enforce,
|
|
8
|
+
* what Claude's hooks react to but don't bound,
|
|
9
|
+
* what Amp's plugin API exposes but doesn't constrain.
|
|
10
|
+
*/
|
|
11
|
+
import type { TSchema } from "@sinclair/typebox";
|
|
12
|
+
import { Type } from "@sinclair/typebox";
|
|
13
|
+
|
|
14
|
+
// ── Schema registry ──────────────────────────────────────────────
|
|
15
|
+
|
|
16
|
+
export interface IOContract {
|
|
17
|
+
name: string;
|
|
18
|
+
description: string;
|
|
19
|
+
input?: TSchema;
|
|
20
|
+
output?: TSchema;
|
|
21
|
+
reads?: string[];
|
|
22
|
+
writes?: string[];
|
|
23
|
+
calls?: string[];
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export interface ContractProvider {
|
|
27
|
+
getContract(name: string): IOContract | undefined;
|
|
28
|
+
registerContract(c: IOContract): void;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
const registry = new Map<string, IOContract>();
|
|
32
|
+
|
|
33
|
+
export function registerContract(c: IOContract): void {
|
|
34
|
+
registry.set(c.name, c);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export function getContract(name: string): IOContract | undefined {
|
|
38
|
+
return registry.get(name);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// ── Validation ───────────────────────────────────────────────────
|
|
42
|
+
|
|
43
|
+
export interface ValidatedCall<T = unknown> {
|
|
44
|
+
ok: boolean;
|
|
45
|
+
data?: T;
|
|
46
|
+
errors?: string[];
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export function validateInput<T>(schema: TSchema, input: unknown): ValidatedCall<T> {
|
|
50
|
+
if (!input || typeof input !== "object") {
|
|
51
|
+
return { ok: false, errors: ["Input must be an object"] };
|
|
52
|
+
}
|
|
53
|
+
return { ok: true, data: input as T };
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// ── Pre-built contracts ──────────────────────────────────────────
|
|
57
|
+
|
|
58
|
+
export const ORACLE_CONTRACT: IOContract = {
|
|
59
|
+
name: "oracle",
|
|
60
|
+
description: "Expert advisor. Reads code, returns structured advice. Does NOT implement.",
|
|
61
|
+
input: Type.Object({
|
|
62
|
+
question: Type.String({ minLength: 10, description: "What to investigate" }),
|
|
63
|
+
context: Type.Optional(Type.String({ description: "Optional context" })),
|
|
64
|
+
}),
|
|
65
|
+
output: Type.Object({
|
|
66
|
+
diagnosis: Type.String({ description: "Root cause or key finding" }),
|
|
67
|
+
recommendation: Type.String({ description: "What to do about it" }),
|
|
68
|
+
risks: Type.Array(Type.String(), { description: "Risks to consider" }),
|
|
69
|
+
}),
|
|
70
|
+
reads: ["read", "grep", "find", "ls"],
|
|
71
|
+
writes: [],
|
|
72
|
+
calls: [],
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
export const VERIFIER_CONTRACT: IOContract = {
|
|
76
|
+
name: "verifier",
|
|
77
|
+
description: "Reviews builder output. Returns PASS or ISSUES.",
|
|
78
|
+
input: Type.Object({
|
|
79
|
+
output: Type.String({ minLength: 1, description: "Builder's output to verify" }),
|
|
80
|
+
}),
|
|
81
|
+
output: Type.Object({
|
|
82
|
+
verdict: Type.Union([Type.Literal("pass"), Type.Literal("issues")], { description: "PASS or ISSUES" }),
|
|
83
|
+
issues: Type.Optional(Type.Array(Type.Object({
|
|
84
|
+
severity: Type.Union([Type.Literal("critical"), Type.Literal("major"), Type.Literal("minor")]),
|
|
85
|
+
description: Type.String(),
|
|
86
|
+
file: Type.Optional(Type.String()),
|
|
87
|
+
line: Type.Optional(Type.Number()),
|
|
88
|
+
}))),
|
|
89
|
+
}),
|
|
90
|
+
reads: ["read", "grep"],
|
|
91
|
+
writes: [],
|
|
92
|
+
calls: ["verifier"],
|
|
93
|
+
};
|
|
94
|
+
|
|
95
|
+
export const LIBRARIAN_CONTRACT: IOContract = {
|
|
96
|
+
name: "librarian",
|
|
97
|
+
description: "Codebase navigator. Returns relevant files with summaries.",
|
|
98
|
+
input: Type.Object({
|
|
99
|
+
question: Type.String({ minLength: 10, description: "What to find" }),
|
|
100
|
+
scope: Type.Optional(Type.String({ description: "Search scope" })),
|
|
101
|
+
}),
|
|
102
|
+
output: Type.Object({
|
|
103
|
+
files: Type.Array(Type.Object({
|
|
104
|
+
path: Type.String({ description: "File path relative to root" }),
|
|
105
|
+
why: Type.String({ description: "Why this file is relevant" }),
|
|
106
|
+
})),
|
|
107
|
+
}),
|
|
108
|
+
reads: ["read", "grep", "find", "ls"],
|
|
109
|
+
writes: [],
|
|
110
|
+
calls: [],
|
|
111
|
+
};
|
|
112
|
+
|
|
113
|
+
// Register built-in contracts
|
|
114
|
+
registerContract(ORACLE_CONTRACT);
|
|
115
|
+
registerContract(VERIFIER_CONTRACT);
|
|
116
|
+
registerContract(LIBRARIAN_CONTRACT);
|