pi-soly 0.5.10 → 0.7.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/agents/soly-manager.md +124 -0
- package/agents-install.ts +113 -36
- package/commands.ts +1 -1
- package/config.ts +5 -4
- package/index.ts +15 -14
- package/package.json +2 -1
- package/skills/soly-framework/SKILL.md +320 -0
- package/switch/README.md +21 -24
- package/switch/core.ts +4 -11
- package/switch/index.ts +2 -2
- package/switch/prompt.ts +24 -27
- package/switch/tests/core.test.ts +1 -1
- package/switch/tests/index.test.ts +3 -2
- package/switch/tests/prompt.test.ts +26 -24
- package/agents/soly-debugger.md +0 -60
- package/agents/soly-documenter.md +0 -82
- package/agents/soly-oracle.md +0 -69
- package/agents/soly-refactor.md +0 -65
- package/agents/soly-reviewer.md +0 -107
- package/agents/soly-tester.md +0 -56
- package/agents/soly-worker.md +0 -84
|
@@ -0,0 +1,320 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: soly-framework
|
|
3
|
+
description: Use when the user asks how to do anything with the soly framework for pi — start a new project, plan or execute a phase, pause and resume sessions, add rules, add intent docs, write PLAN.md or SUMMARY.md, troubleshoot issues. Triggers on "how do I", "what's the command for", "soly help", "soly framework", and any practical question about using the soly extension. NOT loaded for generic code questions — only when the user is working with the soly workflow.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# soly framework
|
|
7
|
+
|
|
8
|
+
The **soly** extension adds project-management workflow to [pi-coding-agent](https://github.com/nicobailon/pi-coding-agent): intent docs, ROADMAP/STATE/PHASE state machine, and subagent-driven plan execution. This skill is your complete reference for using it.
|
|
9
|
+
|
|
10
|
+
## Quick start (read first if new)
|
|
11
|
+
|
|
12
|
+
**Mental model — three layers, always in system prompt, in this order:**
|
|
13
|
+
|
|
14
|
+
1. **Project intent** (`.soly/docs/`) — the 0-point. What the user wants the app to be. Written BEFORE plans, by humans.
|
|
15
|
+
2. **Project state** (`.soly/STATE.md`, `ROADMAP.md`) — where we are, current phase, recent decisions.
|
|
16
|
+
3. **Project rules** (`.soly/rules/`, `~/.soly/rules/`) — how to behave in this project.
|
|
17
|
+
|
|
18
|
+
**Workflow model — phases and plans:**
|
|
19
|
+
|
|
20
|
+
- A **phase** is a milestone (e.g. "01-foundation"). Has one or more `PLAN.md` files.
|
|
21
|
+
- A **plan** is one ordered execution unit. Has `<task>` blocks.
|
|
22
|
+
- A **task** is the smallest unit. Has type, description, verify, accept.
|
|
23
|
+
- **Close-out**: production code commits → `SUMMARY.md` → `STATE.md` updated → ROADMAP check.
|
|
24
|
+
|
|
25
|
+
## Slash commands (interactive mode)
|
|
26
|
+
|
|
27
|
+
| Command | What it does |
|
|
28
|
+
|---|---|
|
|
29
|
+
| `/plan [N]` | Generate or update `PLAN.md` for phase N (or current phase) |
|
|
30
|
+
| `/execute [N[.MM]]` | Dispatch plan(s) to `soly-manager` subagent. `N` = all plans in phase. `N.MM` = specific plan. |
|
|
31
|
+
| `/discuss N` | Discussion-driven scoping for phase N — capture decisions before planning |
|
|
32
|
+
| `/inspect` | One-screen summary: position, phases, recent decisions |
|
|
33
|
+
| `/pause` | Save handoff (`HANDOFF.json` + `.continue-here.md`) for later resume |
|
|
34
|
+
| `/resume` | Restore from a paused handoff |
|
|
35
|
+
| `/quick <task>` | One-shot task that doesn't need a full plan — direct dispatch |
|
|
36
|
+
| `/soly` | Project state inspection (alias for `/inspect`) |
|
|
37
|
+
| `/why` | Show what context the LLM's last turn was based on |
|
|
38
|
+
| `/agent [name]` | Switch the current cycle agent (or open picker) |
|
|
39
|
+
|
|
40
|
+
`/soly <verb>` plain-text aliases also work for some verbs (legacy compat).
|
|
41
|
+
|
|
42
|
+
## File structure
|
|
43
|
+
|
|
44
|
+
```
|
|
45
|
+
<project-root>/
|
|
46
|
+
├── .soly/
|
|
47
|
+
│ ├── ROADMAP.md # phase table
|
|
48
|
+
│ ├── STATE.md # current position + decisions log
|
|
49
|
+
│ ├── docs/ # 0-point intent docs (human-written, locked)
|
|
50
|
+
│ │ ├── vision.md
|
|
51
|
+
│ │ └── architecture.md
|
|
52
|
+
│ ├── rules/ # project rules (version-controlled)
|
|
53
|
+
│ │ ├── code-style.md
|
|
54
|
+
│ │ └── testing.md
|
|
55
|
+
│ ├── phases/
|
|
56
|
+
│ │ ├── 01-foundation/
|
|
57
|
+
│ │ │ ├── 01-CONTEXT.md # domain + decisions for phase 1
|
|
58
|
+
│ │ │ ├── 01-RESEARCH.md # what we looked up
|
|
59
|
+
│ │ │ ├── 01-PLAN-01.md # plan 1
|
|
60
|
+
│ │ │ ├── 01-PLAN-01-SUMMARY.md
|
|
61
|
+
│ │ │ ├── 01-PLAN-02.md
|
|
62
|
+
│ │ │ └── 01-PLAN-02-SUMMARY.md
|
|
63
|
+
│ │ └── 02-feature-x/
|
|
64
|
+
│ │ └── ...
|
|
65
|
+
│ ├── iterations/ # per-execution context bundles (auto)
|
|
66
|
+
│ ├── HANDOFF.json # pause snapshot
|
|
67
|
+
│ └── .continue-here.md # pause resume marker
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
## Frontmatter conventions
|
|
71
|
+
|
|
72
|
+
### PLAN.md frontmatter (required)
|
|
73
|
+
|
|
74
|
+
```markdown
|
|
75
|
+
---
|
|
76
|
+
id: 01-02 # phase-plan, zero-padded
|
|
77
|
+
title: Add OAuth flow
|
|
78
|
+
status: pending # pending | in_progress | done
|
|
79
|
+
phase: 1
|
|
80
|
+
depends-on: [] # other plan ids
|
|
81
|
+
parallelizable: true # can run alongside siblings
|
|
82
|
+
---
|
|
83
|
+
|
|
84
|
+
# Add OAuth flow
|
|
85
|
+
|
|
86
|
+
## read_first
|
|
87
|
+
- .soly/STATE.md
|
|
88
|
+
- .soly/ROADMAP.md
|
|
89
|
+
- .soly/rules/code-style.md
|
|
90
|
+
|
|
91
|
+
## tasks
|
|
92
|
+
- [ ] **type: implement**, description: Add token refresh logic
|
|
93
|
+
- files: src/auth/refresh.ts
|
|
94
|
+
- verify: bun test src/auth/refresh.test.ts
|
|
95
|
+
- accept: Refresh succeeds when token is expired; fails when refresh_token is also expired
|
|
96
|
+
|
|
97
|
+
- [ ] **type: tdd**, description: Write integration test for the auth flow
|
|
98
|
+
- verify: bun test src/auth/
|
|
99
|
+
|
|
100
|
+
- [ ] **type: checkpoint**, description: Pause for human review of UX
|
|
101
|
+
|
|
102
|
+
## verification
|
|
103
|
+
- bun test
|
|
104
|
+
- bun run typecheck
|
|
105
|
+
- bun run lint
|
|
106
|
+
|
|
107
|
+
## risks
|
|
108
|
+
- Token storage depends on the encryption scheme (see .soly/docs/architecture.md)
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
### SUMMARY.md frontmatter
|
|
112
|
+
|
|
113
|
+
```markdown
|
|
114
|
+
---
|
|
115
|
+
plan: 01-02
|
|
116
|
+
completed: 2026-06-15
|
|
117
|
+
duration: 47min
|
|
118
|
+
files-touched: 7
|
|
119
|
+
---
|
|
120
|
+
|
|
121
|
+
# Summary
|
|
122
|
+
|
|
123
|
+
## Tasks
|
|
124
|
+
- [x] Add token refresh logic
|
|
125
|
+
- [x] Write integration test
|
|
126
|
+
- [x] Pause for human review
|
|
127
|
+
|
|
128
|
+
## Deviations
|
|
129
|
+
- Refactored `auth/refresh.ts` to use singleton pattern (was factory). Documented in `architecture.md`.
|
|
130
|
+
|
|
131
|
+
## Verification
|
|
132
|
+
- `bun test`: 142 passing
|
|
133
|
+
- `bun run typecheck`: clean
|
|
134
|
+
- `bun run lint`: 0 warnings
|
|
135
|
+
|
|
136
|
+
## Next
|
|
137
|
+
- Phase 02 plan 01: User profile page
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
### Rules file frontmatter (optional)
|
|
141
|
+
|
|
142
|
+
```markdown
|
|
143
|
+
---
|
|
144
|
+
applyTo: "src/**/*.ts" # glob (optional, default: all)
|
|
145
|
+
priority: 50 # higher wins on conflict (default: 0)
|
|
146
|
+
---
|
|
147
|
+
|
|
148
|
+
# TypeScript style
|
|
149
|
+
|
|
150
|
+
- Strict mode required
|
|
151
|
+
- Never use `any` — use `unknown` and narrow
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
## Path discipline (NON-NEGOTIABLE)
|
|
155
|
+
|
|
156
|
+
**All soly-managed files live under `.soly/`.** Source code lives in the project's normal source tree.
|
|
157
|
+
|
|
158
|
+
| File kind | Goes to |
|
|
159
|
+
|---|---|
|
|
160
|
+
| `PLAN.md`, `SUMMARY.md`, `CONTEXT.md`, `RESEARCH.md` | `.soly/phases/<NN>-<slug>/` |
|
|
161
|
+
| Intent docs (0-point) | `.soly/docs/` |
|
|
162
|
+
| Rules | `.soly/rules/` (project) or `~/.soly/rules/` (user) |
|
|
163
|
+
| Handoff | `.soly/HANDOFF.json`, `.soly/.continue-here.md` |
|
|
164
|
+
| Iteration context | `.soly/iterations/` (auto-generated) |
|
|
165
|
+
| Production code, tests | project's normal `src/`, `tests/`, `app/`, etc. |
|
|
166
|
+
|
|
167
|
+
Use absolute paths (or paths starting with `$SOLY_DIR`) when calling tools. Never bare relative names that could land in cwd.
|
|
168
|
+
|
|
169
|
+
## Close-out order
|
|
170
|
+
|
|
171
|
+
The only legal sequence for finishing a plan:
|
|
172
|
+
|
|
173
|
+
1. Production code commits (1+)
|
|
174
|
+
2. `SUMMARY.md` committed
|
|
175
|
+
3. `STATE.md` "Current Position" block updated
|
|
176
|
+
4. `ROADMAP.md` phase checkbox updated
|
|
177
|
+
5. `PLAN.md` frontmatter `status: done`
|
|
178
|
+
|
|
179
|
+
Once production commits exist, returning without a committed `SUMMARY.md` is an **illegal partial-plan state** — the next `/execute` will detect it and refuse to start.
|
|
180
|
+
|
|
181
|
+
## Cycle agents (4 built-in)
|
|
182
|
+
|
|
183
|
+
| Agent | Writes | Use for |
|
|
184
|
+
|---|---|---|
|
|
185
|
+
| `worker` | ✅ | Generic implementation, full tools |
|
|
186
|
+
| `oracle` | ❌ | Decision-consistency, no file edits |
|
|
187
|
+
| `scout` | ❌ | Codebase recon, read-only |
|
|
188
|
+
| `reviewer` | ❌ | Adversarial code review |
|
|
189
|
+
|
|
190
|
+
Switch with `/agent <name>` or `Ctrl+Tab` (cycles through). Footer pill shows current: `· ⚡ worker` / `▶ 🐢 oracle`.
|
|
191
|
+
|
|
192
|
+
## Subagent: soly-manager (single, mode-switching)
|
|
193
|
+
|
|
194
|
+
Spawn via `subagent({ agent: "soly-manager", task: ... })`. The task brief tells it which mode to be in:
|
|
195
|
+
|
|
196
|
+
| Task brief mentions | Mode |
|
|
197
|
+
|---|---|
|
|
198
|
+
| implement, build, write code, add feature, create | **worker** |
|
|
199
|
+
| debug, bug, fix, crash, error, repro, broken | **debugger** |
|
|
200
|
+
| test, coverage, spec, assert, only modify tests | **tester** |
|
|
201
|
+
| review, audit, adversarial, find bugs, qa | **reviewer** |
|
|
202
|
+
| refactor, simplify, extract, rename, no behavior change | **refactor** |
|
|
203
|
+
| document, readme, jsdoc, comment, intent doc | **documenter** |
|
|
204
|
+
| validate, scope, drift, decision, before committing | **oracle** |
|
|
205
|
+
| plan, design, outline, structure, decompose | **planner** |
|
|
206
|
+
|
|
207
|
+
**soly-manager is ONE agent that switches modes. Don't spawn soly-worker / soly-debugger / etc. — those don't exist anymore.**
|
|
208
|
+
|
|
209
|
+
## Tools the LLM can call
|
|
210
|
+
|
|
211
|
+
| Tool | Purpose |
|
|
212
|
+
|---|---|
|
|
213
|
+
| `soly_read(artifact, phase, taskId)` | Read soly artifacts: STATE, plan, context, research, ROADMAP, requirements, project, milestone, task |
|
|
214
|
+
| `soly_log_decision(decision, rationale, phase)` | Append to STATE.md Decisions table |
|
|
215
|
+
| `soly_list_phases()` | List all phases with plan counts, C/R markers |
|
|
216
|
+
| `soly_list_tasks()` | List all tasks across features (kind, status, priority, deps) |
|
|
217
|
+
| `soly_todos(paths, limit)` | Scan working tree for TODO/FIXME/HACK/XXX/NOTE |
|
|
218
|
+
| `soly_env()` | Detect runtime (package manager, runtimes, services, scripts) |
|
|
219
|
+
| `soly_snippet(path, offset, limit)` | Read bounded line range with line numbers |
|
|
220
|
+
| `soly_doc_search(query, limit)` | Search .md/.html under cwd (prioritizes intent docs) |
|
|
221
|
+
| `soly_intent()` | List 0-point intent docs from `.soly/docs/` |
|
|
222
|
+
| `soly_scratchpad(limit)` | Recent conversation recap (one line per turn) |
|
|
223
|
+
| `ask_pro(questions)` | Multi-question picker (tabbed, single/multi-select, ⭐, Other…) |
|
|
224
|
+
| `todo_update(todos)` | Update task list rendered in footer |
|
|
225
|
+
|
|
226
|
+
## Add a new rule (most common task)
|
|
227
|
+
|
|
228
|
+
Three places, in priority order:
|
|
229
|
+
|
|
230
|
+
1. **Project rule** — `~/.pi/agent/agents/soly/rules/<name>.md` (version-controlled, shared with team)
|
|
231
|
+
2. **User rule** — `~/.soly/rules/<name>.md` (per-user, not committed)
|
|
232
|
+
3. **Phase rule** — `<phase-dir>/<plan>.md.rules/<name>.md` (active only for that plan)
|
|
233
|
+
|
|
234
|
+
Use `/rulewizard` slash command to scaffold a new rule with the right frontmatter.
|
|
235
|
+
|
|
236
|
+
A rule file looks like:
|
|
237
|
+
|
|
238
|
+
```markdown
|
|
239
|
+
---
|
|
240
|
+
applyTo: "src/**/*.ts"
|
|
241
|
+
priority: 50
|
|
242
|
+
---
|
|
243
|
+
|
|
244
|
+
# TypeScript style
|
|
245
|
+
|
|
246
|
+
- Strict mode required
|
|
247
|
+
- Never use `any`
|
|
248
|
+
- Prefer `type` over `interface`
|
|
249
|
+
```
|
|
250
|
+
|
|
251
|
+
## Add a new intent doc
|
|
252
|
+
|
|
253
|
+
Create a file in `.soly/docs/`:
|
|
254
|
+
|
|
255
|
+
```markdown
|
|
256
|
+
# Architecture
|
|
257
|
+
|
|
258
|
+
## Goal
|
|
259
|
+
|
|
260
|
+
Build a CLI tool that...
|
|
261
|
+
|
|
262
|
+
## Non-obvious constraints
|
|
263
|
+
|
|
264
|
+
- Must work offline (no network calls)
|
|
265
|
+
- Must be a single static binary
|
|
266
|
+
- Must integrate with the existing `~/.config/x` schema
|
|
267
|
+
```
|
|
268
|
+
|
|
269
|
+
Intent docs are 0-point — written BEFORE any plan, by humans. They define the "why", not the "how".
|
|
270
|
+
|
|
271
|
+
## Common workflows
|
|
272
|
+
|
|
273
|
+
### Start a new project
|
|
274
|
+
|
|
275
|
+
1. `soly init` (or manually create `.soly/`, `docs/`, `rules/`)
|
|
276
|
+
2. Write 1-3 intent docs in `.soly/docs/`
|
|
277
|
+
3. Create `ROADMAP.md` with phase table
|
|
278
|
+
4. `/plan 1` to start phase 1
|
|
279
|
+
|
|
280
|
+
### Add a feature to an existing phase
|
|
281
|
+
|
|
282
|
+
1. `/plan 1.05` (next plan number)
|
|
283
|
+
2. Edit the generated `PLAN.md`
|
|
284
|
+
3. `/execute 1.05`
|
|
285
|
+
|
|
286
|
+
### Pause a long session
|
|
287
|
+
|
|
288
|
+
1. `/pause` → writes `HANDOFF.json` + `.continue-here.md`
|
|
289
|
+
2. Later, in a new session: `/resume`
|
|
290
|
+
|
|
291
|
+
### Troubleshoot a partial plan
|
|
292
|
+
|
|
293
|
+
If `/execute` complains about illegal partial state:
|
|
294
|
+
|
|
295
|
+
1. `cat .soly/iterations/<latest>.md` — see what the last run did
|
|
296
|
+
2. Check if `SUMMARY.md` exists for the last plan
|
|
297
|
+
3. If yes, finish close-out: update `STATE.md` + `ROADMAP.md`
|
|
298
|
+
4. If no, either commit the SUMMARY or revert the production commits
|
|
299
|
+
|
|
300
|
+
## Where to look for answers
|
|
301
|
+
|
|
302
|
+
- **"What command does X"** → this skill, Slash commands section
|
|
303
|
+
- **"What does PLAN.md look like"** → this skill, Frontmatter section
|
|
304
|
+
- **"How to add a rule"** → this skill, Add a new rule section
|
|
305
|
+
- **"Why did the LLM do Y"** → `/why`
|
|
306
|
+
- **"What context is loaded"** → `soly_read(artifact: "state")` + `soly_doc_search(...)`
|
|
307
|
+
- **"What was the recent conversation"** → `soly_scratchpad()`
|
|
308
|
+
|
|
309
|
+
## Don'ts
|
|
310
|
+
|
|
311
|
+
- ❌ Edit `.soly/rules/` files you didn't write — those are project invariants
|
|
312
|
+
- ❌ Skip the SUMMARY — illegal partial state
|
|
313
|
+
- ❌ Spawn `soly-worker` or `soly-debugger` — use `soly-manager` (mode-switches)
|
|
314
|
+
- ❌ Write rules in code comments — use `.soly/rules/*.md` files
|
|
315
|
+
- ❌ Edit `.soly/phases/*/PLAN.md` after `status: in_progress` — create a new plan
|
|
316
|
+
- ❌ Put intent docs anywhere other than `.soly/docs/`
|
|
317
|
+
|
|
318
|
+
## When in doubt
|
|
319
|
+
|
|
320
|
+
Call `soly_read(artifact: "state")` and `soly_read(artifact: "roadmap")` first. The system prompt has the layers, but `soly_read` gives you full content. Then check `soly_doc_search` for any other relevant docs.
|
package/switch/README.md
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
# pi-switch — generic subagent switcher for pi
|
|
2
2
|
|
|
3
|
-
A tiny pi extension that gives you a **persistent indicator of the current subagent** (
|
|
3
|
+
A tiny pi extension that gives you a **persistent indicator of the current subagent** (footer pill) and lets you **cycle / set / create** agents. Generic — works with any agent in `~/.pi/agent/agents/`.
|
|
4
4
|
|
|
5
5
|
## Features
|
|
6
6
|
|
|
7
|
-
- **
|
|
8
|
-
- **Ctrl+
|
|
7
|
+
- **Footer pill** — always shows current agent with emoji + description
|
|
8
|
+
- **Ctrl+Tab** to cycle to next agent (Shift+Tab is taken by pi's thinking-level cycler)
|
|
9
|
+
- **F2** as fallback for terminals that don't pass Ctrl+Tab through
|
|
9
10
|
- **`/agent`** slash command to show current + available
|
|
10
11
|
- **`/agent <name>`** to set explicitly
|
|
11
12
|
- **`/agent create <name>`** to scaffold a new user agent
|
|
@@ -13,7 +14,8 @@ A tiny pi extension that gives you a **persistent indicator of the current subag
|
|
|
13
14
|
- **`/agent recommend <task>`** to suggest the right agent for a task
|
|
14
15
|
- **Task → agent heuristics** baked into the system prompt so the LLM picks the right agent for the task
|
|
15
16
|
- Persists to `.soly/agent` (if soly project) or `~/.pi-switch/agent` (standalone)
|
|
16
|
-
- Reads user agents from `~/.pi/agent/agents/*.md` on every cycle — drop a file and Ctrl+
|
|
17
|
+
- Reads user agents from `~/.pi/agent/agents/*.md` on every cycle — drop a file and Ctrl+Tab to see it
|
|
18
|
+
- Silent switch — only the pill updates, chat stays clean
|
|
17
19
|
|
|
18
20
|
## How agents work
|
|
19
21
|
|
|
@@ -21,9 +23,9 @@ Agents are markdown files with YAML frontmatter. pi-subagents (and pi-switch) di
|
|
|
21
23
|
|
|
22
24
|
| Path | Type | Editable |
|
|
23
25
|
|---|---|---|
|
|
24
|
-
| `~/.pi/agent/npm/node_modules/pi-subagents/agents/*.md` | built-in (worker, oracle, scout,
|
|
26
|
+
| `~/.pi/agent/npm/node_modules/pi-subagents/agents/*.md` | built-in (worker, oracle, scout, reviewer) | ❌ |
|
|
25
27
|
| `~/.pi/agent/agents/*.md` | user-defined | ✅ |
|
|
26
|
-
| `~/.pi/agent/extensions/soly/agents/*.md` (auto-installed if `useSolyWorkerSubagents: true` in `.soly/config.json`) | soly-
|
|
28
|
+
| `~/.pi/agent/extensions/pi-soly/agents/*.md` (auto-installed if `useSolyWorkerSubagents: true` in `.soly/config.json`) | soly-manager (mode-switching subagent) | ✅ source |
|
|
27
29
|
|
|
28
30
|
### Frontmatter schema
|
|
29
31
|
|
|
@@ -45,7 +47,7 @@ You are `my-reviewer`. The system prompt goes here.
|
|
|
45
47
|
## Create a new agent
|
|
46
48
|
|
|
47
49
|
### Option A: manually
|
|
48
|
-
Drop a markdown file in `~/.pi/agent/agents/<name>.md` (see schema above). Press `Ctrl+
|
|
50
|
+
Drop a markdown file in `~/.pi/agent/agents/<name>.md` (see schema above). Press `Ctrl+Tab` in pi — it joins the cycle.
|
|
49
51
|
|
|
50
52
|
### Option B: via slash command
|
|
51
53
|
```
|
|
@@ -58,8 +60,8 @@ You'll be prompted for a one-liner description. Then edit the file to specialize
|
|
|
58
60
|
| Action | How |
|
|
59
61
|
|---|---|
|
|
60
62
|
| See current + available | `/agent` |
|
|
61
|
-
| Cycle | `Ctrl+
|
|
62
|
-
| Set explicitly | `/agent soly-
|
|
63
|
+
| Cycle | `Ctrl+Tab` (or `F2`) |
|
|
64
|
+
| Set explicitly | `/agent soly-manager` |
|
|
63
65
|
| Diagnose | `/agent doctor` |
|
|
64
66
|
| Recommend for a task | `/agent recommend investigate React Server Components` |
|
|
65
67
|
|
|
@@ -71,37 +73,32 @@ The LLM's system prompt includes a table mapping task keywords to agents. When t
|
|
|
71
73
|
|
|
72
74
|
| Keywords | Agent | Why |
|
|
73
75
|
|---|---|---|
|
|
74
|
-
| research, investigate, look up, find out, explore, compare libraries | 📚 researcher | external docs, ecosystem behavior |
|
|
75
76
|
| scout, scan, map, where is, locate, skim | 🔍 scout | codebase recon |
|
|
76
|
-
| plan, design, architect, outline, structure | 📋 planner | decompose into steps |
|
|
77
77
|
| review, audit, check, adversarial, critique, qa | 👀 reviewer | adversarial review |
|
|
78
78
|
| oracle, decision, tradeoff, which approach, drift | 🔮 oracle | decision consistency |
|
|
79
|
-
|
|
|
80
|
-
|
|
|
81
|
-
| refactor, clean up, simplify, extract, rename | 🔄 soly-refactor | pure refactoring |
|
|
82
|
-
| document, docs, readme, jsdoc | 📝 soly-documenter | doc updates |
|
|
83
|
-
| implement, build, write code, add feature | ⚡ worker | implementation |
|
|
84
|
-
| orchestrate, coordinate, dispatch, chain | 🤝 delegate | multi-agent |
|
|
79
|
+
| implement, build, write code, add feature, debug, fix, test, refactor, document, plan, validate | ⚡ soly-manager | workflow executor, mode-switches from task brief |
|
|
80
|
+
| (anything else) | ⚡ worker | generic implementation |
|
|
85
81
|
|
|
86
82
|
Same keywords in Russian work (изучи, баг, тест, etc.).
|
|
87
83
|
|
|
88
84
|
## Integration with other extensions
|
|
89
85
|
|
|
90
|
-
- **soly** reads `globalThis.__PI_SWITCH_AGENT__` to know which
|
|
91
|
-
- **
|
|
86
|
+
- **pi-soly** reads `globalThis.__PI_SWITCH_AGENT__` to know which cycle agent is active. Falls back to `"worker"` if pi-switch isn't loaded.
|
|
87
|
+
- **pi-soly** also auto-installs `soly-manager.md` (single mode-switching subagent) to `~/.pi/agent/agents/` when `useSolyWorkerSubagents: true` in `.soly/config.json`.
|
|
92
88
|
|
|
93
89
|
## Files
|
|
94
90
|
|
|
95
91
|
- `core.ts` — agent metadata, discovery, cycling, persistence
|
|
96
92
|
- `prompt.ts` — system-prompt section + task→agent heuristics + `recommendAgent`
|
|
97
|
-
- `index.ts` —
|
|
98
|
-
- `tests/core.test.ts` —
|
|
99
|
-
- `tests/prompt.test.ts` —
|
|
93
|
+
- `index.ts` — footer pill, Ctrl+Tab / F2, `/agent` slash command, `/agent create`/`/agent doctor`/`/agent recommend`
|
|
94
|
+
- `tests/core.test.ts` — tests for core logic
|
|
95
|
+
- `tests/prompt.test.ts` — tests for prompt + recommendAgent
|
|
96
|
+
- `tests/index.test.ts` — tests for slash command parsing
|
|
100
97
|
|
|
101
98
|
## Development
|
|
102
99
|
|
|
103
100
|
```bash
|
|
104
|
-
cd
|
|
105
|
-
bun test #
|
|
101
|
+
cd packages/pi-soly/switch
|
|
102
|
+
bun test # switch tests
|
|
106
103
|
bun run typecheck # tsc --noEmit
|
|
107
104
|
```
|
package/switch/core.ts
CHANGED
|
@@ -7,8 +7,9 @@
|
|
|
7
7
|
// agent). Generic — works with pi-subagents' built-ins (worker, oracle,
|
|
8
8
|
// scout, ...) AND any user-defined agent in `~/.pi/agent/agents/`.
|
|
9
9
|
//
|
|
10
|
-
// Cycle order (Shift+Tab in pi is taken by thinking-level
|
|
11
|
-
//
|
|
10
|
+
// Cycle order (Shift+Tab in pi is taken by thinking-level; we use Ctrl+Tab
|
|
11
|
+
// as the primary shortcut, with F2 as fallback for terminals that don't
|
|
12
|
+
// pass Ctrl+Tab through).
|
|
12
13
|
//
|
|
13
14
|
// Communication with other extensions:
|
|
14
15
|
// - Writes `globalThis.__PI_SWITCH_AGENT__` (in-process)
|
|
@@ -29,11 +30,7 @@ export const BUILTIN_AGENTS: readonly string[] = [
|
|
|
29
30
|
"worker",
|
|
30
31
|
"oracle",
|
|
31
32
|
"scout",
|
|
32
|
-
"researcher",
|
|
33
|
-
"planner",
|
|
34
|
-
"context-builder",
|
|
35
33
|
"reviewer",
|
|
36
|
-
"delegate",
|
|
37
34
|
] as const;
|
|
38
35
|
|
|
39
36
|
/** Visual metadata for every known agent. Used by the rich status badge,
|
|
@@ -49,11 +46,7 @@ export const AGENT_META: Record<string, AgentMeta> = {
|
|
|
49
46
|
worker: { emoji: "\u26a1", shortLabel: "worker", description: "generic implementation, all tools", writesFiles: true },
|
|
50
47
|
oracle: { emoji: "\ud83d\udd2e", shortLabel: "oracle", description: "decision-consistency, no file edits", writesFiles: false },
|
|
51
48
|
scout: { emoji: "\ud83d\udd0d", shortLabel: "scout", description: "codebase recon, read-only", writesFiles: false },
|
|
52
|
-
researcher: { emoji: "\ud83d\udcda", shortLabel: "researcher", description: "external docs / libraries", writesFiles: false },
|
|
53
|
-
planner: { emoji: "\ud83d\udccb", shortLabel: "planner", description: "planning + ordering, no code", writesFiles: false },
|
|
54
|
-
"context-builder": { emoji: "\ud83c\udfd7", shortLabel: "ctx-builder", description: "context handoff for other agents", writesFiles: true },
|
|
55
49
|
reviewer: { emoji: "\ud83d\udc40", shortLabel: "reviewer", description: "adversarial code review", writesFiles: false },
|
|
56
|
-
delegate: { emoji: "\ud83e\udd1d", shortLabel: "delegate", description: "pure orchestration, dispatches others", writesFiles: false },
|
|
57
50
|
};
|
|
58
51
|
|
|
59
52
|
/** Get metadata for an agent. Falls back to a neutral entry for unknown. */
|
|
@@ -160,7 +153,7 @@ export function groupedAvailableAgents(userDir?: string): Array<{ header: string
|
|
|
160
153
|
export function formatHeaderLine(agent: string): string {
|
|
161
154
|
const meta = getAgentMeta(agent);
|
|
162
155
|
const writeTag = meta.writesFiles ? "" : " \u00b7 read-only";
|
|
163
|
-
return `${meta.emoji} ${agent} \u00b7 ${meta.description}${writeTag} [Ctrl+
|
|
156
|
+
return `${meta.emoji} ${agent} \u00b7 ${meta.description}${writeTag} [Ctrl+Tab to cycle]`;
|
|
164
157
|
}
|
|
165
158
|
|
|
166
159
|
// ---------------------------------------------------------------------------
|
package/switch/index.ts
CHANGED
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
// UI philosophy:
|
|
16
16
|
// - Header is for content, not for tool chrome. Move agents to footer.
|
|
17
17
|
// - Click to explore, hotkey to power-use, no DOM clutter in between.
|
|
18
|
-
// - Visual change is the pill text
|
|
18
|
+
// - Visual change is the pill text only. Chat stays clean.
|
|
19
19
|
// =============================================================================
|
|
20
20
|
|
|
21
21
|
import type { ExtensionAPI, ExtensionUIContext } from "@earendil-works/pi-coding-agent";
|
|
@@ -242,7 +242,7 @@ function createAgent(
|
|
|
242
242
|
const description = desc?.trim() || `custom agent (${name})`;
|
|
243
243
|
fs.writeFileSync(file, agentTemplate(name, description), "utf-8");
|
|
244
244
|
ui.notify(
|
|
245
|
-
`pi-switch: created ${file}\n → next Ctrl+
|
|
245
|
+
`pi-switch: created ${file}\n → next Ctrl+Tab to see it in the cycle\n → edit the system prompt to specialize`,
|
|
246
246
|
"info",
|
|
247
247
|
);
|
|
248
248
|
});
|
package/switch/prompt.ts
CHANGED
|
@@ -19,7 +19,7 @@ export const TASK_AGENT_HINTS: ReadonlyArray<{
|
|
|
19
19
|
agent: "scout", emoji: "\ud83d\udd0d",
|
|
20
20
|
why: "codebase recon, patterns, file locations" },
|
|
21
21
|
{ pattern: /\b(plan|design|architect|outline|structure|break\s*down|steps|order)\b/i,
|
|
22
|
-
agent: "
|
|
22
|
+
agent: "soly-manager", emoji: "\ud83d\udccb",
|
|
23
23
|
why: "decompose into ordered steps, identify risks" },
|
|
24
24
|
{ pattern: /\b(review|audit|check|adversarial|critique|find\s+bugs|qa)\b/i,
|
|
25
25
|
agent: "reviewer", emoji: "\ud83d\udc40",
|
|
@@ -28,22 +28,22 @@ export const TASK_AGENT_HINTS: ReadonlyArray<{
|
|
|
28
28
|
agent: "oracle", emoji: "\ud83d\udd2e",
|
|
29
29
|
why: "decision consistency, hidden assumptions, drift detection" },
|
|
30
30
|
{ pattern: /\b(debug|bug|fix|crash|error|stack\s*trace|repro|why\s+is\s+this\s+broken)\b/i,
|
|
31
|
-
agent: "soly-
|
|
31
|
+
agent: "soly-manager", emoji: "\ud83d\udc1e",
|
|
32
32
|
why: "isolated bug investigation with minimal repro" },
|
|
33
33
|
{ pattern: /\b(test|tests|coverage|spec|assert)\b/i,
|
|
34
|
-
agent: "soly-
|
|
34
|
+
agent: "soly-manager", emoji: "\ud83e\uddea",
|
|
35
35
|
why: "test-only work, never modifies prod code" },
|
|
36
36
|
{ pattern: /\b(refactor|clean\s*up|simplify|extract|rename|restructure|no\s+behavior\s+change)\b/i,
|
|
37
|
-
agent: "soly-
|
|
37
|
+
agent: "soly-manager", emoji: "\ud83d\udd04",
|
|
38
38
|
why: "pure refactoring, behavior-preserving" },
|
|
39
39
|
{ pattern: /\b(document|docs|readme|jsdoc|comment|annotate)\b/i,
|
|
40
|
-
agent: "soly-
|
|
40
|
+
agent: "soly-manager", emoji: "\ud83d\udcdd",
|
|
41
41
|
why: "doc updates, READMEs, inline annotations" },
|
|
42
42
|
{ pattern: /\b(implement|build|write\s+code|add\s+feature|create\s+the)\b/i,
|
|
43
43
|
agent: "worker", emoji: "\u26a1",
|
|
44
44
|
why: "generic implementation with all tools" },
|
|
45
45
|
{ pattern: /\b(orchestrate|coordinate|dispatch|chain|run\s+in\s+parallel|first\s+.+\s+then)\b/i,
|
|
46
|
-
agent: "
|
|
46
|
+
agent: "soly-manager", emoji: "\ud83e\udd1d",
|
|
47
47
|
why: "multi-agent orchestration" },
|
|
48
48
|
// Russian keywords (loose match — Russian words inflect heavily; we match
|
|
49
49
|
// word stems, accepting some false positives as the cost of broader coverage)
|
|
@@ -54,7 +54,7 @@ export const TASK_AGENT_HINTS: ReadonlyArray<{
|
|
|
54
54
|
agent: "scout", emoji: "\ud83d\udd0d",
|
|
55
55
|
why: "codebase recon, patterns, file locations" },
|
|
56
56
|
{ pattern: /(спланир|plan|design|architect)/i,
|
|
57
|
-
agent: "
|
|
57
|
+
agent: "soly-manager", emoji: "\ud83d\udccb",
|
|
58
58
|
why: "decompose into ordered steps, identify risks" },
|
|
59
59
|
{ pattern: /(проверь|ревью|аудит|review|audit)/i,
|
|
60
60
|
agent: "reviewer", emoji: "\ud83d\udc40",
|
|
@@ -63,22 +63,22 @@ export const TASK_AGENT_HINTS: ReadonlyArray<{
|
|
|
63
63
|
agent: "oracle", emoji: "\ud83d\udd2e",
|
|
64
64
|
why: "decision consistency, hidden assumptions, drift detection" },
|
|
65
65
|
{ pattern: /(баг|ошибк|почему\s+(?:падает|ломает)|debug|bug|crash|stack\s*trace|repro)/i,
|
|
66
|
-
agent: "soly-
|
|
66
|
+
agent: "soly-manager", emoji: "\ud83d\udc1e",
|
|
67
67
|
why: "isolated bug investigation with minimal repro" },
|
|
68
68
|
{ pattern: /(тест|покрыт|test|coverage|spec|assert)/i,
|
|
69
|
-
agent: "soly-
|
|
69
|
+
agent: "soly-manager", emoji: "\ud83e\uddea",
|
|
70
70
|
why: "test-only work, never modifies prod code" },
|
|
71
71
|
{ pattern: /(рефактор|упрост|refactor|simplify|extract|restructure)/i,
|
|
72
|
-
agent: "soly-
|
|
72
|
+
agent: "soly-manager", emoji: "\ud83d\udd04",
|
|
73
73
|
why: "pure refactoring, behavior-preserving" },
|
|
74
74
|
{ pattern: /(документ|описани|document|readme|jsdoc)/i,
|
|
75
|
-
agent: "soly-
|
|
75
|
+
agent: "soly-manager", emoji: "\ud83d\udcdd",
|
|
76
76
|
why: "doc updates, READMEs, inline annotations" },
|
|
77
77
|
{ pattern: /(реализуй|сделай|напиши|создай|implement|build|add\s+feature|create\s+the)/i,
|
|
78
78
|
agent: "worker", emoji: "\u26a1",
|
|
79
79
|
why: "generic implementation with all tools" },
|
|
80
80
|
{ pattern: /(оркестрируй|координируй|orchestrate|coordinate|dispatch|chain)/i,
|
|
81
|
-
agent: "
|
|
81
|
+
agent: "soly-manager", emoji: "\ud83e\udd1d",
|
|
82
82
|
why: "multi-agent orchestration" },
|
|
83
83
|
];
|
|
84
84
|
|
|
@@ -98,37 +98,34 @@ export function buildPiSwitchSection(): string {
|
|
|
98
98
|
|
|
99
99
|
## pi-switch — when to use \`/agent\`
|
|
100
100
|
|
|
101
|
-
The \`/agent\` slash command + \`Ctrl+
|
|
101
|
+
The \`/agent\` slash command + \`Ctrl+Tab\` shortcut cycle through 4 built-in cycle agents. Use the right one for the job:
|
|
102
102
|
|
|
103
|
-
- **Read-only / no edits** (oracle, scout,
|
|
104
|
-
- **Write tools** (worker
|
|
103
|
+
- **Read-only / no edits** (oracle, scout, reviewer): for analysis, planning, review. They won't modify files.
|
|
104
|
+
- **Write tools** (worker): for implementation.
|
|
105
105
|
- **User-defined** in \`~/.pi/agent/agents/\`: any agent the user has added — drop a markdown file with YAML frontmatter (name, description) and it joins the cycle automatically.
|
|
106
106
|
|
|
107
|
-
The current agent is shown in
|
|
107
|
+
The current agent is shown in the footer status line as \`[emoji name]\`.
|
|
108
108
|
|
|
109
|
-
When you need a specialist for a sub-task, use the right agent via the parent LLM's \`subagent(...)\` call
|
|
109
|
+
When you need a specialist for a sub-task, use the right agent via the parent LLM's \`subagent(...)\` call.
|
|
110
110
|
|
|
111
|
-
**
|
|
111
|
+
**Soly subagent:** there is exactly one — \`soly-manager\`. It's a workflow executor that switches modes (worker/debugger/tester/reviewer/refactor/documenter/oracle/planner) based on the task brief. For any soly plan execution, spawn \`soly-manager\` via \`subagent(...)\` with the task — it picks the right mode itself.
|
|
112
|
+
|
|
113
|
+
**Task → agent heuristics.** Before launching a generic \`subagent(...)\`, scan the request for these keywords:
|
|
112
114
|
|
|
113
115
|
| Keywords in request | Suggested agent | Why |
|
|
114
116
|
|---|---|---|
|
|
115
|
-
| research, investigate, look up, find out, explore, compare libraries, what is the best | 📚 researcher | external docs, ecosystem behavior |
|
|
116
117
|
| scout, scan, map, find all, where is, locate, explore codebase, skim | 🔍 scout | codebase recon, patterns, file locations |
|
|
117
|
-
| plan, design, architect, outline, structure, break down, steps, order | 📋 planner | decompose into ordered steps, identify risks |
|
|
118
118
|
| review, audit, check, adversarial, critique, find bugs, qa | 👀 reviewer | adversarial correctness, security, style review |
|
|
119
119
|
| oracle, decision, tradeoff, compare, which approach, is this wise, drift | 🔮 oracle | decision consistency, hidden assumptions |
|
|
120
|
-
|
|
|
121
|
-
|
|
|
122
|
-
| refactor, clean up, simplify, extract, rename, restructure, no behavior change | 🔄 soly-refactor | pure refactoring, behavior-preserving |
|
|
123
|
-
| document, docs, readme, jsdoc, comment, annotate | 📝 soly-documenter | doc updates, READMEs, inline annotations |
|
|
124
|
-
| implement, build, write code, add feature, create the | ⚡ worker | generic implementation with all tools |
|
|
125
|
-
| orchestrate, coordinate, dispatch, chain, run in parallel | 🤝 delegate | multi-agent orchestration |
|
|
120
|
+
| implement, build, write code, add feature, create the, debug, fix, test, refactor, document, plan, validate | ⚡ soly-manager | workflow executor, picks mode from task brief |
|
|
121
|
+
| (anything else) | ⚡ worker | generic implementation, all tools |
|
|
126
122
|
|
|
127
123
|
For multi-step tasks, the orchestrator (you) decides which agents run and in what order. You can chain agents via \`subagent({ chain: [...] })\` or run them in parallel via parallel tasks.
|
|
128
124
|
|
|
129
125
|
DON'T:
|
|
130
|
-
- Launch a worker for analysis (use oracle/scout)
|
|
126
|
+
- Launch a worker for analysis (use oracle/scout/reviewer)
|
|
131
127
|
- Launch an oracle for implementation (it has no write tools)
|
|
128
|
+
- Spawn soly-worker / soly-debugger / soly-tester — there is only \`soly-manager\`
|
|
132
129
|
- Manually edit \`.soly/agent\` or \`~/.pi-switch/agent\` — use the slash command
|
|
133
130
|
`;
|
|
134
131
|
}
|
|
@@ -105,7 +105,7 @@ describe("formatHeaderLine", () => {
|
|
|
105
105
|
test("always non-empty (even for default)", () => {
|
|
106
106
|
const h = formatHeaderLine("worker");
|
|
107
107
|
expect(h).toContain("worker");
|
|
108
|
-
expect(h).toContain("Ctrl+
|
|
108
|
+
expect(h).toContain("Ctrl+Tab");
|
|
109
109
|
});
|
|
110
110
|
test("includes read-only tag when applicable", () => {
|
|
111
111
|
const h = formatHeaderLine("oracle");
|
|
@@ -13,9 +13,10 @@ import { availableAgents } from "../core.js";
|
|
|
13
13
|
describe("/agent handler parse logic (regression for `/agent researcher` bug)", () => {
|
|
14
14
|
// The original bug: `/agent researcher` was interpreted as "show list"
|
|
15
15
|
// instead of "set agent to researcher" because the parser only checked
|
|
16
|
-
// the SECOND token, not the first.
|
|
16
|
+
// the SECOND token, not the first. (After cycle reduction, `researcher`
|
|
17
|
+
// is no longer a built-in, so we use `oracle` as the example agent.)
|
|
17
18
|
test("single-arg '/agent <name>' is a set, not a list", () => {
|
|
18
|
-
const input = "
|
|
19
|
+
const input = "oracle";
|
|
19
20
|
const parts = input.trim().split(/\s+/);
|
|
20
21
|
const subcommand = parts[0]?.toLowerCase();
|
|
21
22
|
const cycle = availableAgents();
|