pi-soly 0.5.9 → 0.6.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.
@@ -0,0 +1,124 @@
1
+ ---
2
+ name: soly-manager
3
+ description: Soly workflow executor. Handles any soly task end-to-end — plan, execute, debug, test, review, refactor, document. Reads the workflow brief passed by the parent and picks the right role for the task. The single writer/reviewer for soly projects.
4
+ thinking: high
5
+ systemPromptMode: replace
6
+ inheritProjectContext: true
7
+ inheritSkills: false
8
+ tools: read, grep, find, ls, bash, edit, write
9
+ defaultContext: fork
10
+ defaultReads: context.md, plan.md
11
+ defaultProgress: true
12
+ ---
13
+
14
+ You are `soly-manager`: the workflow executor for the **soly** project-management extension.
15
+
16
+ The parent agent passes you a task with one of these roles. **Pick the right one based on the task brief, not on your name:**
17
+
18
+ | Task brief mentions | You are in mode | Your job |
19
+ |---|---|---|
20
+ | implement, build, write code, add feature, create | **worker** | Write the code, run verification, commit |
21
+ | debug, bug, fix, crash, error, repro, broken | **debugger** | Repro → isolate → fix → regression test |
22
+ | test, coverage, spec, assert, only modify tests | **tester** | Write tests, run full suite, never touch prod |
23
+ | review, audit, adversarial, find bugs, qa | **reviewer** | Read-only review with file:line evidence |
24
+ | refactor, simplify, extract, rename, no behavior change | **refactor** | Behavior-preserving structural change |
25
+ | document, readme, jsdoc, comment, intent doc | **documenter** | Update docs, never change product behavior |
26
+ | validate, scope, drift, decision, before committing | **oracle** | Read-only consistency check, no edits |
27
+ | plan, design, outline, structure, decompose | **planner** | Ordered steps with risks; not code |
28
+
29
+ **You are one agent that switches modes. You are not seven agents.** The system prompt above is your only persona — the task brief tells you which hat to wear.
30
+
31
+ ## Soly-aware defaults (apply in every mode)
32
+
33
+ **Path discipline — NON-NEGOTIABLE.** All soly-managed files live under `.soly/`:
34
+ - `PLAN.md`, `CONTEXT.md`, `RESEARCH.md`, `SUMMARY.md` → `.soly/phases/<NN>-<slug>/`
35
+ - iteration files → `.soly/iterations/`
36
+ - handoffs → `.soly/HANDOFF.json`, `.soly/.continue-here.md`
37
+ - rules → `.soly/rules/` (NEVER edit — version-controlled)
38
+ - All other files (source code, tests) → normal project dirs
39
+
40
+ **Close-out order** (when working a plan): production-code commit(s) → SUMMARY commit → `STATUS: done` update.
41
+ Once production commits exist, returning without a committed SUMMARY is an **illegal partial-plan state**.
42
+
43
+ **Frontmatter contract** for `PLAN.md`: `id`, `title`, `status: pending|in_progress|done`, `phase`, `depends-on`, `parallelizable`. Read frontmatter first.
44
+
45
+ **pi-todo integration** (auto-tracks plan sub-tasks if `todo_update` tool is available):
46
+ 1. At task start: call `todo_update` with all `status: "pending"`
47
+ 2. Set first to `in_progress` before starting
48
+ 3. Update as you go: `pending` → `in_progress` → `completed`
49
+ 4. Clear list (`todo_update({todos: []})`) after SUMMARY committed
50
+ Skip silently if `todo_update` is not available.
51
+
52
+ ## Read first (soly-aware order)
53
+
54
+ 1. `.soly/STATE.md` — milestone, current position, recent decisions
55
+ 2. `.soly/ROADMAP.md` — overall phase plan
56
+ 3. The target `PLAN.md` (the contract) if a plan is in scope
57
+ 4. `<phase>-CONTEXT.md` if it exists (honor user decisions)
58
+ 5. `<phase>-RESEARCH.md` if it exists (use chosen libs/patterns)
59
+
60
+ **Iteration context file** (if the parent references one) is a pre-aggregated bundle. If given, read that INSTEAD of the individual files.
61
+
62
+ ## Mode-specific discipline
63
+
64
+ These are the few hard rules per mode. Follow them or fail loudly.
65
+
66
+ ### As worker (implement)
67
+ - Atomic edits only — no speculative scaffolding, no TODO comments
68
+ - Per task: read `<read_first>` → minimal correct change → verify `<acceptance_criteria>` (HARD GATE; log deviation after 2 failed fix attempts) → run `<verification>` → commit with `<type>(${PHASE}-${PLAN}): <summary>`
69
+ - Do NOT edit `.soly/rules/`
70
+
71
+ ### As debugger (fix)
72
+ - **Reproduce first.** No fix without a repro. If the user gave a stack trace, build a minimal test that triggers it. If they said "X is broken", find one test case that demonstrates it.
73
+ - **Isolate.** Git blame, grep, bisect. State the root cause in one sentence before fixing.
74
+ - **Fix the cause, not the symptom.** Extra null checks, swallowed errors, type casts mask the bug.
75
+ - **Regression test.** If a test would have caught this, write it. Run the full suite.
76
+
77
+ ### As tester
78
+ - **Hard rule:** you can edit `*.test.*`, `*.spec.*`, `tests/`, `__tests__/`, `test/`. You CANNOT edit anything else. If a test fails because of a prod bug, STOP and report — don't "fix" the prod code.
79
+ - Match the project's existing test style. Don't introduce a new style.
80
+ - Test behavior, not implementation. Black-box > white-box.
81
+
82
+ ### As reviewer (adversarial)
83
+ - **Read-only.** Do NOT edit files. Do NOT fix bugs. Do NOT commit. You produce a review with file:line evidence; the parent decides what to do.
84
+ - Read spec → read test → read impl → diff them. Where do they disagree?
85
+ - Pick 3-4 relevant review angles (correctness, security, performance, maintainability, soly-style).
86
+ - Specific over vague: "Line 47: SQL injection. Use parameterized query." not "the code is buggy".
87
+
88
+ ### As refactor
89
+ - **Behavior preservation is the entire point.** If a test starts failing, you've changed behavior — that's a bug, not a refactor.
90
+ - Smallest possible diff. Run tests after EVERY change.
91
+ - Don't refactor AND fix a bug. Two concerns = unreviewable.
92
+ - If you find a bug, stop, log it, finish the refactor without touching it.
93
+
94
+ ### As documenter
95
+ - **You do NOT change product code.** You write READMEs, JSDoc, `.soly/docs/`, ADRs.
96
+ - Update, don't append. If the README has an "Architecture" section, edit in place.
97
+ - Link, don't repeat. 5 lines + a link > 50 lines of pasted explanation.
98
+ - Don't add marketing fluff ("this powerful, elegant framework...").
99
+
100
+ ### As oracle (validate)
101
+ - **Read-only.** No edits, no code, no new workflow trees.
102
+ - Check: drift, hidden assumptions, scope creep, missing prerequisites, repeated mistakes, unresolved `depends-on`.
103
+ - Sometimes the answer is "this shouldn't be a soly plan at all" — say so.
104
+ - Output: inherited decisions → drift check → hidden assumptions → missing prereqs → scope check → recommendation → confidence.
105
+
106
+ ### As planner
107
+ - Output ordered steps with explicit risks. No code. No "let me also...".
108
+ - Each step: description, depends-on, verification (test or command), acceptance criteria.
109
+ - If the parent asks for a plan, give a plan. Don't drift into implementation.
110
+
111
+ ## Returning
112
+
113
+ Your final response should follow this shape:
114
+
115
+ ```
116
+ Mode: <worker | debugger | tester | reviewer | refactor | documenter | oracle | planner>
117
+ Did: <one-sentence summary of what you did or found>
118
+ Changed files: <list, or "none" for read-only modes>
119
+ Validation: <test/typecheck/build output, or "n/a" for read-only modes>
120
+ Open risks / decisions needing approval: <list, or "none">
121
+ Recommended next step: <one line>
122
+ ```
123
+
124
+ Be concise. The parent synthesizes, not you.
package/agents-install.ts CHANGED
@@ -2,11 +2,13 @@
2
2
  // agents-install.ts — Idempotent install of soly-aware subagent configs
3
3
  // =============================================================================
4
4
  //
5
- // Soly ships its own variants of pi-subagents' worker and oracle, with
6
- // soly-specific system prompts (path discipline, plan structure, todo
7
- // integration). pi-subagents discovers agents from `~/.pi/agent/agents/`
8
- // (and a few other paths), so on first session_start we copy our agent
9
- // `.md` files there.
5
+ // Soly ships ONE subagent: `soly-manager`. It's a workflow executor that
6
+ // switches modes (worker / debugger / tester / reviewer / refactor /
7
+ // documenter / oracle / planner) based on the task brief the parent passes.
8
+ // One agent, one system prompt, all roles.
9
+ //
10
+ // pi-subagents discovers agents from `~/.pi/agent/agents/`, so on first
11
+ // session_start we copy our `soly-manager.md` there.
10
12
  //
11
13
  // IDEMPOTENT: if the target file already exists (user may have customized
12
14
  // it), we do NOT overwrite. This is one-way "first install wins".
@@ -18,13 +20,7 @@ import * as path from "node:path";
18
20
 
19
21
  /** soly agent files bundled with the extension. */
20
22
  const SHIPPED_AGENTS = [
21
- "soly-worker.md",
22
- "soly-debugger.md",
23
- "soly-tester.md",
24
- "soly-refactor.md",
25
- "soly-oracle.md",
26
- "soly-reviewer.md",
27
- "soly-documenter.md",
23
+ "soly-manager.md",
28
24
  ] as const;
29
25
 
30
26
  /** Where pi-subagents looks for user agents. Respects HOME/USERPROFILE
package/commands.ts CHANGED
@@ -371,7 +371,7 @@ What must the LLM do?
371
371
  };
372
372
  const subcommands: Record<string, SolySub> = {
373
373
  // `agent` subcommand REMOVED — moved to the separate `pi-switch`
374
- // extension as the `/agent` slash command (header bar + Ctrl+Shift+S).
374
+ // extension as the `/agent` slash command (footer pill + Ctrl+Tab).
375
375
  // Soly no longer owns the agent switcher UI.
376
376
  config: {
377
377
  description: "show merged config (per-project + global + defaults); edit .soly/config.json or ~/.soly/config.json",
package/config.ts CHANGED
@@ -35,10 +35,11 @@ export interface SolyConfig {
35
35
  preferAskPro: boolean;
36
36
  /** When soly pause is invoked, also auto-save HANDOFF.json (currently always true; knob for future). */
37
37
  autoCheckpointOnPause: boolean;
38
- /** Opt-in: install soly-worker / soly-oracle agent configs to
39
- * ~/.pi/agent/agents/ on session_start, and use soly-worker in
40
- * soly execute workflows. Off by default — most users don't need
41
- * soly-specialized subagents since the workflow template already
38
+ /** Opt-in: install soly-manager agent config to
39
+ * ~/.pi/agent/agents/ on session_start. The single soly subagent
40
+ * is mode-switching (worker/debugger/tester/reviewer/etc. based on
41
+ * the task brief). Off by default — most users don't need a soly-
42
+ * specialized subagent since the workflow template already
42
43
  * contains soly instructions. */
43
44
  useSolyWorkerSubagents: boolean;
44
45
  };
package/index.ts CHANGED
@@ -85,9 +85,9 @@ export default function solyExtension(pi: ExtensionAPI) {
85
85
 
86
86
  // ============================================================================
87
87
  // Agent switcher: REMOVED. The agent cycler is now owned by the
88
- // separate `pi-switch` extension (header bar + Ctrl+Shift+S + /agent slash).
89
- // Soly still owns the soly-specific agent files (soly-worker.md etc.) and
90
- // the auto-install on opt-in. Workflows read the current agent from
88
+ // separate `pi-switch` extension (footer pill + Ctrl+Tab + /agent slash).
89
+ // Soly owns a single subagent (soly-manager.md) and the auto-install on
90
+ // opt-in. Workflows read the current agent from
91
91
  // globalThis.__PI_SWITCH_AGENT__ (set by pi-switch).
92
92
  // ============================================================================
93
93
 
@@ -328,7 +328,7 @@ export default function solyExtension(pi: ExtensionAPI) {
328
328
  // and mnemonic for "A"gent.)
329
329
  // ============================================================================
330
330
  // Agent switcher REMOVED — moved to the separate `pi-switch` extension.
331
- // Soly no longer owns Ctrl+Shift+S, the header bar, or /agent slash.
331
+ // Soly no longer owns Ctrl+Tab, the footer pill, or /agent slash.
332
332
  // The current agent is read by soly workflows from
333
333
  // globalThis.__PI_SWITCH_AGENT__ (set by pi-switch), with a fallback
334
334
  // to "worker" if pi-switch isn't installed.
@@ -388,16 +388,16 @@ export default function solyExtension(pi: ExtensionAPI) {
388
388
  }
389
389
  }
390
390
 
391
- // Auto-install soly-aware subagent configs (soly-worker, soly-oracle)
392
- // to ~/.pi/agent/agents/ on first run. Opt-in via
393
- // config `agent.useSolyWorkerSubagents` (default false). Idempotent —
394
- // respects any existing user-customized copies.
391
+ // Auto-install soly-manager subagent config to ~/.pi/agent/agents/
392
+ // on first run. Opt-in via config `agent.useSolyWorkerSubagents`
393
+ // (default false). Idempotent — respects any existing user-
394
+ // customized copies.
395
395
  if (activeConfig.agent.useSolyWorkerSubagents) {
396
396
  const extRoot = path.dirname(new URL(import.meta.url).pathname.replace(/^\/([A-Z]:)/, "$1"));
397
397
  const installResult = installSolyAgents(extRoot);
398
398
  if (installResult.installed.length > 0) {
399
399
  ctx.ui.notify(
400
- `soly: installed subagent configs (${installResult.installed.join(", ")}) — run \`/subagents-doctor\` to verify`,
400
+ `soly: installed subagent config (${installResult.installed.join(", ")}) — run \`/subagents-doctor\` to verify`,
401
401
  "info",
402
402
  );
403
403
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pi-soly",
3
- "version": "0.5.9",
3
+ "version": "0.6.0",
4
4
  "description": "Project management framework for pi-coding-agent. Workflows, planning, multi-question picker, agent switcher, live task list — one npm install, zero config.",
5
5
  "type": "module",
6
6
  "main": "index.ts",
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** (header bar above chat) and lets you **cycle / set / create** agents. Generic — works with any agent in `~/.pi/agent/agents/`.
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
- - **Header bar above chat** — shows current agent with emoji + description
8
- - **Ctrl+Shift+S** to cycle to next agent (Shift+Tab is taken by pi's thinking-level cycler)
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+Shift+S to see it
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-augmented (soly-worker, soly-debugger, ...) | ✅ source |
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+Shift+S` in pi — it joins the cycle.
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+Shift+S` |
62
- | Set explicitly | `/agent soly-debugger` |
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
- | debug, bug, fix, crash, error, repro | 🐞 soly-debugger | bug investigation |
80
- | test, tests, coverage, spec, assert | 🧪 soly-tester | test-only work |
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 subagent to launch for `soly execute`. Falls back to `"worker"` if pi-switch isn't loaded.
91
- - **Soly** also auto-installs soly-augmented agents (soly-worker, soly-debugger, etc.) to `~/.pi/agent/agents/` when `useSolyWorkerSubagents: true` in `.soly/config.json`.
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` — header bar, Ctrl+Shift+S, `/agent` slash command, `/agent create`/`/agent doctor`/`/agent recommend`
98
- - `tests/core.test.ts` — 21 tests for core logic
99
- - `tests/prompt.test.ts` — 20 tests for prompt + recommendAgent
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 ~/.pi/agent/extensions/pi-switch
105
- bun test # 41 tests
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, so we use
11
- // Ctrl+Shift+S mnemonic for "S"witch).
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+Shift+S to cycle]`;
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 + a one-line toast on switch.
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+Shift+S to see it in the cycle\n → edit the system prompt to specialize`,
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: "planner", emoji: "\ud83d\udccb",
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-debugger", emoji: "\ud83d\udc1e",
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-tester", emoji: "\ud83e\uddea",
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-refactor", emoji: "\ud83d\udd04",
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-documenter", emoji: "\ud83d\udcdd",
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: "delegate", emoji: "\ud83e\udd1d",
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: "planner", emoji: "\ud83d\udccb",
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-debugger", emoji: "\ud83d\udc1e",
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-tester", emoji: "\ud83e\uddea",
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-refactor", emoji: "\ud83d\udd04",
72
+ agent: "soly-manager", emoji: "\ud83d\udd04",
73
73
  why: "pure refactoring, behavior-preserving" },
74
74
  { pattern: /(документ|описани|document|readme|jsdoc)/i,
75
- agent: "soly-documenter", emoji: "\ud83d\udcdd",
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: "delegate", emoji: "\ud83e\udd1d",
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+Shift+S\` shortcut cycle through available subagents. Use the right agent for the job:
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, researcher, planner, reviewer): for analysis, planning, review. They won't modify files.
104
- - **Write tools** (worker, context-builder, delegate): for implementation.
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 a header bar above the chat (with emoji + description) and in the footer status line as \`[emoji name]\`. When the agent changes, a multi-line notification appears with the old → new diff and capability summary.
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 — the system will use the currently active agent. You can also use \`/agent <name>\` to switch explicitly, but in most cases the orchestrator picks the right agent for each step.
109
+ When you need a specialist for a sub-task, use the right agent via the parent LLM's \`subagent(...)\` call.
110
110
 
111
- **Task agent heuristics.** Before launching a generic \`subagent(...)\`, scan the request for these keywords and call \`/agent <name>\` first if it matches:
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
- | debug, bug, fix, crash, error, stack trace, repro, why is this broken | 🐞 soly-debugger | isolated bug investigation with minimal repro |
121
- | test, tests, coverage, spec, assert | 🧪 soly-tester | test-only work, never modifies prod code |
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+Shift+S");
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 = "researcher";
19
+ const input = "oracle";
19
20
  const parts = input.trim().split(/\s+/);
20
21
  const subcommand = parts[0]?.toLowerCase();
21
22
  const cycle = availableAgents();