peaks-cli 1.3.5 → 1.3.7

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.
Files changed (53) hide show
  1. package/dist/src/cli/commands/slice-commands.js +9 -5
  2. package/dist/src/cli/commands/workspace-commands.js +46 -2
  3. package/dist/src/cli/program.js +0 -2
  4. package/dist/src/services/dashboard/project-dashboard-service.d.ts +0 -7
  5. package/dist/src/services/dashboard/project-dashboard-service.js +1 -8
  6. package/dist/src/services/ide/adapters/claude-code-adapter.js +0 -1
  7. package/dist/src/services/ide/adapters/trae-adapter.js +0 -13
  8. package/dist/src/services/ide/ide-types.d.ts +0 -2
  9. package/dist/src/services/session/session-manager.d.ts +55 -0
  10. package/dist/src/services/session/session-manager.js +68 -0
  11. package/dist/src/services/skills/skill-presence-service.d.ts +10 -4
  12. package/dist/src/services/skills/skill-presence-service.js +16 -11
  13. package/dist/src/services/slice/slice-check-service.js +36 -18
  14. package/dist/src/services/slice/slice-check-types.d.ts +40 -6
  15. package/dist/src/services/slice/slice-check-types.js +11 -1
  16. package/dist/src/shared/version.d.ts +1 -1
  17. package/dist/src/shared/version.js +1 -1
  18. package/package.json +1 -1
  19. package/skills/peaks-prd/SKILL.md +16 -16
  20. package/skills/peaks-prd/references/workflow.md +4 -4
  21. package/skills/peaks-qa/SKILL.md +30 -34
  22. package/skills/peaks-qa/references/regression-gates.md +1 -1
  23. package/skills/peaks-rd/SKILL.md +17 -10
  24. package/skills/peaks-rd/references/{openspec-mcp-cli.md → openspec-cli.md} +11 -14
  25. package/skills/peaks-solo/SKILL.md +1 -1
  26. package/skills/peaks-solo/references/a2a-artifact-mapping.md +1 -1
  27. package/skills/peaks-solo/references/browser-workflow.md +49 -38
  28. package/skills/peaks-solo/references/external-skill-invocation.md +9 -7
  29. package/skills/peaks-solo/references/micro-cycle.md +4 -2
  30. package/skills/peaks-solo/references/{openspec-mcp-workflow.md → openspec-workflow.md} +5 -20
  31. package/skills/peaks-solo/references/sub-agent-dispatch.md +16 -35
  32. package/skills/peaks-ui/SKILL.md +22 -24
  33. package/skills/peaks-ui/references/workflow.md +2 -2
  34. package/dist/src/cli/commands/mcp-commands.d.ts +0 -3
  35. package/dist/src/cli/commands/mcp-commands.js +0 -144
  36. package/dist/src/services/mcp/mcp-apply-service.d.ts +0 -31
  37. package/dist/src/services/mcp/mcp-apply-service.js +0 -112
  38. package/dist/src/services/mcp/mcp-call-service.d.ts +0 -17
  39. package/dist/src/services/mcp/mcp-call-service.js +0 -34
  40. package/dist/src/services/mcp/mcp-client-service.d.ts +0 -14
  41. package/dist/src/services/mcp/mcp-client-service.js +0 -49
  42. package/dist/src/services/mcp/mcp-install-registry.d.ts +0 -11
  43. package/dist/src/services/mcp/mcp-install-registry.js +0 -38
  44. package/dist/src/services/mcp/mcp-plan-service.d.ts +0 -29
  45. package/dist/src/services/mcp/mcp-plan-service.js +0 -109
  46. package/dist/src/services/mcp/mcp-protocol.d.ts +0 -24
  47. package/dist/src/services/mcp/mcp-protocol.js +0 -41
  48. package/dist/src/services/mcp/mcp-scan-service.d.ts +0 -8
  49. package/dist/src/services/mcp/mcp-scan-service.js +0 -214
  50. package/dist/src/services/mcp/mcp-stdio-transport.d.ts +0 -10
  51. package/dist/src/services/mcp/mcp-stdio-transport.js +0 -50
  52. package/dist/src/services/mcp/mcp-types.d.ts +0 -31
  53. package/dist/src/services/mcp/mcp-types.js +0 -1
@@ -4,13 +4,15 @@ Peaks skills reference many external resources — `mattpocock/skills`, `gstack`
4
4
 
5
5
  Every reference must follow the same three-stage pattern so the Peaks gates stay authoritative and side effects stay observable.
6
6
 
7
+ > **Slice #016 (2026-06-09)**: peaks-cli no longer manages MCP install or invocation. MCP capability detection moves from the peaks-cli CLI to the LLM's own tool list (the LLM checks for `mcp__<server>__*` entries in its own function schema). Skill bodies instruct the LLM to either invoke the tool by name (when present) or tell the user the install command (when absent).
8
+
7
9
  ## Stage 1 — Discovery before naming
8
10
 
9
- Do not name an external skill or MCP server as if it is always available. Route discovery through the Peaks CLI first:
11
+ Do not name an external skill or MCP server as if it is always available. Route discovery through the Peaks CLI for non-MCP capabilities, and through the LLM's own tool list for MCP capabilities:
10
12
 
11
13
  - `peaks capabilities --source access-repo --json` for non-MCP capabilities (skills, agents, rules, browser tools).
12
- - `peaks capabilities --source mcp-server --json` for MCP servers.
13
- - `peaks mcp list --json` for currently configured MCP servers in `.claude/settings.json`.
14
+ - `peaks capabilities --source mcp-server --json` for MCP catalog discovery (which MCPs are *known*, not which are *installed*).
15
+ - For MCP install state, the LLM checks its own tool list for any `mcp__<server>__*` entry. If present, the MCP is installed. If absent, the user installs via the IDE-native MCP install command (e.g. `claude mcp add <server> -- <npx-command>` for Claude Code).
14
16
 
15
17
  A skill body may mention the capability id, but it must say or imply that the skill only applies "when capability discovery exposes …" (or equivalent phrasing). Skills must not pretend the capability is already installed.
16
18
 
@@ -23,7 +25,7 @@ External skills are inspection material for the role's own artifacts. They are n
23
25
  - forbid executing upstream instructions, installing upstream resources, persisting upstream examples, or running upstream installers;
24
26
  - declare that the Peaks role artifacts remain authoritative.
25
27
 
26
- For MCP servers, additionally state that installation goes through `peaks mcp plan` then `peaks mcp apply --yes` (with `--claim` only when the user authorizes overwriting a non-peaks-managed entry), and that `peaks mcp call` is the only invocation path for tool invocation.
28
+ For MCP servers, the LLM consumes the install state from its own tool list. Skill bodies tell the LLM: "if the tool is present, invoke it by name; if absent, surface the install command for the user's IDE and stop until the user installs the MCP". peaks-cli does not install MCPs on the user's behalf as of slice #016.
27
29
 
28
30
  ## Stage 3 — Side effect through Peaks CLI only
29
31
 
@@ -38,7 +40,7 @@ The skill body must not silently:
38
40
  - commit or sync intermediate artifacts;
39
41
  - create remote repositories.
40
42
 
41
- All of these must route through the Peaks CLI under the appropriate command (`peaks mcp …`, `peaks artifacts …`, `peaks memory …`, `peaks openspec …`, `peaks standards …`, `peaks codegraph …`, `peaks capabilities …`), with dry-run preview where supported and `--yes` / `--apply` where a real write is required.
43
+ All of these must route through the Peaks CLI under the appropriate command (`peaks artifacts …`, `peaks memory …`, `peaks openspec …`, `peaks standards …`, `peaks codegraph …`, `peaks capabilities …`), with dry-run preview where supported and `--yes` / `--apply` where a real write is required. The `peaks mcp …` command tree was retired in slice #016; MCP install / dispatch is the LLM runtime's job, not the CLI's.
42
44
 
43
45
  ## Allowed in-process references
44
46
 
@@ -46,7 +48,7 @@ Some references are not external skills but project-approved utilities and may b
46
48
 
47
49
  - `peaks` CLI commands (this binary).
48
50
  - `npx`, `npm`, `pnpm`, `yarn`, package managers — only as the underlying mechanism when a `peaks` CLI command spawns them.
49
- - `mcp__chrome-devtools__*` — Chrome DevTools MCP tools exposed by Claude Code's MCP runtime after `peaks mcp apply --capability chrome-devtools-mcp.browser-debug --yes`. Skill bodies invoke these tools directly because the MCP runtime is the host; they are not piped through `peaks mcp call`. Login / CAPTCHA / SSO / MFA handoff rules and sanitization rules in `browser-workflow.md` still apply.
51
+ - `mcp__chrome_devtools__*` — Chrome DevTools MCP tools exposed by the LLM's MCP runtime when the user has installed Chrome DevTools MCP (Claude Code: `claude mcp add chrome-devtools -- npx chrome-devtools-mcp@latest`). Skill bodies tell the LLM to invoke these tools by name when they appear in the tool list. Login / CAPTCHA / SSO / MFA handoff rules and sanitization rules in `browser-workflow.md` still apply.
50
52
 
51
53
  These are not subject to capability discovery because they are part of the Peaks engineering surface, not external skills. The previous `gstack/browse/dist/browse` binary reference is no longer endorsed — see `browser-workflow.md` for the migration recipe.
52
54
 
@@ -66,5 +68,5 @@ When a skill body adds a new external reference, it must include the equivalent
66
68
  1. read the failing skill body section;
67
69
  2. identify the external skill or MCP that triggered the failure;
68
70
  3. add the capability discovery clause, the reference-only qualifier, the do-not-execute clause, and the Peaks-authoritative gate to that section;
69
- 4. for MCP servers, point the user at `peaks mcp plan/apply/call` instead of describing manual `.claude/settings.json` edits;
71
+ 4. for MCP servers, point the LLM at the tool-list self-check (its own `mcp__<server>__*` namespace) instead of describing manual `~/.claude/settings.json` edits;
70
72
  5. rerun the audit.
@@ -89,12 +89,14 @@ peaks slice check [--rid <rid>] [--project <path>] [--json]
89
89
 
90
90
  这个命令编排:
91
91
  1. `npx tsc --noEmit`(typecheck)
92
- 2. `npx vitest run`(全 suite
92
+ 2. `npx vitest run --changed`(默认;changed-only suite,只跑 git 改动相关的 test,~1-3s)。要全量请加 `--run-tests`;要彻底跳过请加 `--skip-tests`。
93
93
  3. 3-way fan-out(code-review + security-review + perf-baseline)
94
94
  4. `peaks workflow verify-pipeline --rid <rid> --project <path>`
95
95
 
96
96
  4 个 check 全绿 + verify-pipeline pass → 才进 `peaks request transition --state qa-handoff`,让 peaks-qa 接管。
97
97
 
98
+ > **新增 run 017(2026-06-09)**:边界默认走 changed-only suite,原来的全 suite 行为移到 `--run-tests` opt-in。`peaks-solo-test` skill 仍然是手动跑全量的入口。rationale: 全量 30s+ 严重拖慢 workflow;changed-only 命中 99% 真正回归。详见 PRD `.peaks/_runtime/2026-06-07-session-84feb7/prd/requests/002-017-2026-06-09-remove-auto-full-vitest-from-slice-check.md`。
99
+
98
100
  ## Micro-cycle → 边界 check → QA 的串联
99
101
 
100
102
  ```
@@ -139,7 +141,7 @@ verdict=return-to-rd → RD 修 (new slice 内部走 micro-cycle)
139
141
  ## 为什么这套比当前 peaks-solo 的设计合理
140
142
 
141
143
  - **快**:micro-cycle ~100ms(vs 30s 全 suite),改 10 个 bug 从 5 分钟降到 30 秒
142
- - **稳**:边界 check 不省,4 项检查(tsc + vitest + 3-way + verify-pipeline)一次全跑
144
+ - **稳**:边界 check 不省,4 项检查(tsc + vitest run --changed + 3-way + verify-pipeline)一次全跑;changed-only 模式 1-3s 内出结果,全量用 `--run-tests` opt-in
143
145
  - **清晰**:LLM 看到一个 explicit "禁止" 列表 + 强制 sequence,比"建议"更不容易越界
144
146
  - **可观测**:micro-cycle 走单测 → 边界跑 verify-pipeline,每步都有 JSON envelope 验证
145
147
 
@@ -1,6 +1,8 @@
1
- # OpenSpec and MCP Lifecycle for Peaks Solo
1
+ # OpenSpec Lifecycle for Peaks Solo
2
2
 
3
- Peaks Solo orchestrates RD, QA, and SC. When the target repository uses OpenSpec or external MCP servers, Solo must drive the full lifecycle through the Peaks CLI so each role works against the same stable surface.
3
+ Peaks Solo orchestrates RD, QA, and SC. When the target repository uses OpenSpec, Solo must drive the full lifecycle through the Peaks CLI so each role works against the same stable surface.
4
+
5
+ > **Slice #016 (2026-06-09)**: this document used to live at `openspec-mcp-workflow.md` and contained a section on the `peaks mcp *` lifecycle. The MCP subsystem was retired in slice #016; that section is gone. The OpenSpec lifecycle described below is unchanged.
4
6
 
5
7
  ## OpenSpec change lifecycle
6
8
 
@@ -20,23 +22,6 @@ Rules Solo applies:
20
22
  - `validate` is run twice per change in a refactor flow: once before slicing (RD entry gate) and once before archive (QA exit gate). Both must end with `data.valid === true`.
21
23
  - `archive --apply` is the lifecycle terminator; Solo only invokes it after QA acceptance and SC commit.
22
24
 
23
- ## MCP capability lifecycle
24
-
25
- ```text
26
- peaks mcp list / scan → Solo inventories what is configured today
27
- peaks mcp plan → Solo previews the install diff before any write
28
- peaks mcp apply --yes → Solo authorizes the install (real side effect)
29
- peaks mcp call → RD or QA invokes a tool on the installed server
30
- peaks mcp rollback → Solo restores from a peaks-managed backup
31
- ```
32
-
33
- Rules Solo applies:
34
-
35
- - `apply` is the first real side effect in the MCP track. It requires `--yes`, backs up `~/.claude/settings.json` first, and refuses to overwrite non-peaks-managed entries unless `--claim` is passed. Solo decides whether `--claim` is appropriate.
36
- - Required env vars must be set in the runtime environment before `apply` or `call`. Peaks refuses to spawn a server with missing env, surfacing each missing key in `envCheck.missing`.
37
- - `call` writes evidence into the RD or QA artifact. Solo never pastes secrets, full request/response bodies, or session tokens into the handoff capsule.
38
- - `rollback` is the recovery action when an install or update made things worse. The backup path is the one Peaks reported during `apply`.
39
-
40
25
  ## Refactor workflow wiring
41
26
 
42
27
  For `peaks-solo refactor` runs against a repository with `openspec/`:
@@ -46,7 +31,7 @@ For `peaks-solo refactor` runs against a repository with `openspec/`:
46
31
  3. QA exit gate — re-run `peaks openspec validate <id>` after implementation; record the result in the QA validation report.
47
32
  4. Archive — `peaks openspec archive <id> --apply` only after QA passes the exit gate and SC closes the final commit.
48
33
 
49
- If MCP servers are needed for docs lookup or research, Solo coordinates the one-time install before RD starts so RD does not block on capability resolution mid-slice.
34
+ If the consuming LLM needs an MCP server for docs lookup or research (e.g. Context7), it checks its own tool list for `mcp__<server>__*` and tells the user the install command if absent. peaks-cli is no longer in the install path; the LLM is the executor, the IDE is the dispatcher.
50
35
 
51
36
  ## Boundary
52
37
 
@@ -143,45 +143,26 @@ While running, call `peaks sub-agent heartbeat --record <dispatchRecordPath>
143
143
  to keep the user informed during the wait.
144
144
  ```
145
145
 
146
- **Slice #007-007-2026-06-07-mcp-decouple (G3 prompt template addition)**:
147
- when the sub-agent is dispatched into a non-Claude IDE (Trae, Cursor,
148
- Codex, Qoder, Tongyi, ...) or into a Claude Code environment where the
149
- LLM cannot directly invoke the `mcp__<server>__*` tool prefix, the
150
- sub-agent prompt must additionally include the MCP-decouple instruction
151
- below. Without it, the sub-agent would either fall back to direct
152
- `mcp__` invocations (which fail in non-Claude IDEs) or skip MCP
153
- operations entirely (which breaks RD/QA/UI flows that depend on the
154
- Playwright, Chrome DevTools, Figma, or Context7 servers).
146
+ **Slice #016 retirement (G3 prompt template — MCP subsystem removed)**:
147
+ The MCP-decouple paragraph from slice #007-007 no longer applies.
148
+ peaks-cli no longer manages MCP install or invocation. Sub-agents
149
+ check their own tool list for `mcp__<server>__*` entries and invoke
150
+ the tool by name directly. The only prompt-template addition that
151
+ remains is the tool-list self-check:
155
152
 
156
153
  ```
157
- When you need to use an MCP server (playwright, chrome-devtools, figma, or
158
- context7), do NOT invoke the `mcp__<server>__*` tool prefix directly. The
159
- canonical path is `peaks mcp call`:
160
-
161
- peaks mcp call --capability <capabilityId> --tool <toolName> --args-json '<argsObject>' --json
162
-
163
- where `<capabilityId>` is one of:
164
- - playwright-mcp.browser-validation (headed browser, primary E2E surface)
165
- - chrome-devtools-mcp.browser-debug (CDP to running Chrome on :9222, secondary)
166
- - figma-context-mcp.design-context (Figma design data, requires FIGMA_API_KEY)
167
- - context7.docs-lookup (library docs, requires CONTEXT7_API_KEY)
168
-
169
- For install / plan / detect, use:
170
- peaks mcp list --json
171
- peaks mcp plan --capability <capabilityId> --json
172
- peaks mcp apply --capability <capabilityId> --yes --json
173
-
174
- The `peaks mcp plan` envelope's `envCheck.missing` field is the source of
175
- truth for required env vars. Do not bake the `mcp__<server>__*` prefix
176
- into any artifact or message; the prefix is owned by the LLM runtime, not
177
- by the skill. On Trae, `capabilities.mcpInstall` is `false`; do not
178
- attempt `peaks mcp apply` on Trae — surface the manual install path
179
- instead.
154
+ This task may need an MCP server (playwright, chrome-devtools, figma,
155
+ or context7). Check your tool list for any `mcp__<server>__*` entry.
156
+ If present, invoke the tool by name directly. If absent, tell the user
157
+ the install command for their IDE (Claude Code:
158
+ `claude mcp add <server> -- <npx-command>`) and stop the sub-task until
159
+ the user installs the MCP. Do NOT hand-edit `.claude/settings.json` or
160
+ auto-install on the user's behalf.
180
161
  ```
181
162
 
182
- The MCP-decouple paragraph is required for any sub-agent dispatched
183
- into a non-Claude environment or any sub-agent that needs an MCP
184
- capability. The CLI auto-generates it for `role in (rd, qa, ui, txt)`
163
+ The tool-list self-check is required for any sub-agent that needs a
164
+ browser, design, or docs-lookup capability. The CLI auto-generates it
165
+ for `role in (rd, qa, ui, txt)`.
185
166
  when the active IDE is not `claude-code`; for `role = general-purpose`
186
167
  or unknown roles, the caller (the SKILL.md heart of the Dispatcher) must
187
168
  add it explicitly.
@@ -13,7 +13,7 @@ UI's headed-browser work (visual inspection, regression seed capture, Figma / li
13
13
 
14
14
  ### Contract 1 — Inspection screenshots must land under .peaks/<sid>/qa/screenshots/
15
15
 
16
- Every Playwright screenshot tool call (via `peaks mcp call --capability playwright-mcp.browser-validation --tool browser_take_screenshot --args-json '<args>' --json`) **MUST** pass `filename` (in the args object) inside `.peaks/<session-id>/qa/screenshots/`, named after the inspection target (e.g. `home-after-cta.png`, `empty-state-v2.png`). Do not let Playwright fall back to the project root. After every batch, run:
16
+ Every Playwright screenshot tool call (the LLM invokes `browser_take_screenshot` directly when the Playwright MCP is present in its tool list) **MUST** pass `filename` (in the args object) inside `.peaks/<session-id>/qa/screenshots/`, named after the inspection target (e.g. `home-after-cta.png`, `empty-state-v2.png`). Do not let Playwright fall back to the project root. After every batch, run:
17
17
 
18
18
  ```bash
19
19
  ls .peaks/<sid>/qa/screenshots/*.png 2>&1
@@ -61,7 +61,7 @@ What the sub-agent **MUST** still do:
61
61
  - Do NOT call `Skill(skill="...")`.
62
62
  - Do NOT call `peaks skill presence:set` — Solo owns the active-skill file.
63
63
  - Do NOT modify application code. UI is design-direction only; the actual frontend code is written in the RD implementation phase.
64
- - Do NOT install MCP servers. If `peaks mcp list` shows playwright-mcp missing and the headed browser is required, return `{"status":"blocked","blockedReason":"playwright-mcp-unavailable"}` and let Solo escalate to the user.
64
+ - Do NOT install MCP servers. If the LLM tool list does not include the Playwright MCP and the headed browser is required, return `{"status":"blocked","blockedReason":"playwright-mcp-unavailable"}` and let Solo escalate to the user. (peaks-cli no longer manages MCP install — the user runs `claude mcp add playwright -- npx @playwright/mcp@latest` themselves in Claude Code, or the IDE-specific install command otherwise.)
65
65
  - Do NOT commit, push, install hooks, or apply settings.json mutations.
66
66
  - Do NOT ask the user interactive questions. If you need clarification, return `{"status":"blocked","blockedReason":"<text>"}`.
67
67
 
@@ -129,14 +129,13 @@ peaks request init --role ui --id <request-id> --project <repo> --apply --json
129
129
  peaks request show <request-id> --role prd --project <repo> --json # read linked PRD scope
130
130
 
131
131
  # 2. ensure Playwright MCP is available for the visible browser check
132
- peaks mcp list --json
133
- # if playwright-mcp.browser-validation is NOT in the list:
134
- peaks mcp plan --capability playwright-mcp.browser-validation --json
135
- peaks mcp apply --capability playwright-mcp.browser-validation --yes --json
136
- # if apply fails or user denies installation:
137
- # mark browser gate as blocked with reason "playwright-mcp-unavailable"
138
- # NEVER silently downgrade to screenshots-only, manual steps, or other tools
139
- # → NEVER route through chrome-devtools-mcp as a browser-launch substitute (it cannot launch)
132
+ # Slice #016: peaks-cli no longer manages MCP install. The LLM checks
133
+ # its own tool list for any Playwright MCP entry in the LLM tool list. If absent, the
134
+ # LLM tells the user the install command (`claude mcp add playwright
135
+ # -- npx @playwright/mcp@latest` in Claude Code) and reports the gate
136
+ # as blocked. Do NOT silently downgrade to screenshots-only, manual
137
+ # steps, or other tools. Do NOT route through chrome-devtools-mcp as a
138
+ # browser-launch substitute (it cannot launch a browser of its own).
140
139
 
141
140
  # 3. read project-scan for component library and CSS framework context
142
141
  # check .peaks/<session-id>/rd/project-scan.md (blocking if missing for existing projects)
@@ -151,8 +150,8 @@ peaks mcp apply --capability playwright-mcp.browser-validation --yes --json
151
150
  # See "Prototype fidelity gate" section for the full decision tree.
152
151
 
153
152
  # 5. drive the running page or prototype through Claude Code MCP tools
154
- # (these are not Peaks-Cli CLI commands; they are invoked by the host MCP runtime)
155
- # peaks mcp call --capability playwright-mcp.browser-validation --tool browser_navigate --args-json '{"url":"<url>"}' --json
153
+ # (the LLM invokes these directly from its tool list no peaks-cli envelope)
154
+ # browser_navigate --args '{"url":"<url>"}'
156
155
  # → URL (after allow-list check), launches headed browser
157
156
  #
158
157
  # LOGIN GATE (MANDATORY checkpoint):
@@ -162,19 +161,18 @@ peaks mcp apply --capability playwright-mcp.browser-validation --yes --json
162
161
  # If user does not confirm within reasonable time → pause and ask.
163
162
  # Only after user confirmation, continue to:
164
163
  #
165
- # peaks mcp call --capability playwright-mcp.browser-validation --tool browser_take_screenshot --args-json '{"filename":"<abs-path>"}' --json
164
+ # browser_take_screenshot --args '{"filename":"<abs-path>"}'
166
165
  # → visible-browser confirmation
167
- # peaks mcp call --capability playwright-mcp.browser-validation --tool browser_snapshot --args-json '{}' --json
166
+ # browser_snapshot --args '{}'
168
167
  # → accessibility tree for regression seeds
169
- # peaks mcp call --capability playwright-mcp.browser-validation --tool browser_console_messages --args-json '{}' --json
168
+ # browser_console_messages --args '{}'
170
169
  # → console errors
171
- # peaks mcp call --capability playwright-mcp.browser-validation --tool browser_network_requests --args-json '{}' --json
170
+ # browser_network_requests --args '{}'
172
171
  # → failed network
173
- # peaks mcp call --capability playwright-mcp.browser-validation --tool browser_close --args-json '{}' --json
172
+ # browser_close --args '{}'
174
173
  # → end the session cleanly
175
- # The skill body NEVER bakes in the `mcp__playwright__` prefix; the LLM's runtime
176
- # resolves the tool name from the registered server. The capability id
177
- # `playwright-mcp.browser-validation` is the contract; the registry is the source of truth.
174
+ # The skill body NEVER bakes in the the Playwright MCP tools prefix; the LLM's runtime
175
+ # resolves the tool name from the registered server.
178
176
 
179
177
  # 5. write design-draft artifact to .peaks/<session-id>/ui/design-draft.md
180
178
 
@@ -238,7 +236,7 @@ Use gstack as a concrete design-review workflow reference for the `Plan → Revi
238
236
  - map browser walkthrough concepts to UI regression seeds when runtime validation is approved;
239
237
  - keep accessibility, performance, and product-specific visual direction as Peaks-Cli UI acceptance inputs.
240
238
 
241
- For frontend work, especially full-auto mode, use Playwright MCP to inspect the running page or prototype before accepting the UI direction. The skill body never bakes in the `mcp__playwright__` prefix; it uses `peaks mcp call --capability playwright-mcp.browser-validation --tool <name> --args-json '<args>' --json` for every browser operation (browser_navigate / browser_snapshot / browser_take_screenshot / browser_console_messages / browser_network_requests / browser_close). Playwright MCP launches a headed browser on demand; if `peaks mcp list --json` does not include `playwright`, install it through `peaks mcp plan --capability playwright-mcp.browser-validation --json` then `peaks mcp apply --capability playwright-mcp.browser-validation --yes --json` before attempting to inspect. (Chrome DevTools MCP is a secondary surface that connects to an already-running Chrome via `--remote-debugging-port=9222`; it does NOT launch a browser on its own.) If login, CAPTCHA, SSO, or MFA appears, the visible browser is already open; wait for the user to complete login and explicitly confirm completion before continuing. Capture only sanitized visible regressions, weak hierarchy, generic template patterns, console errors, and interaction problems as UI feedback that should return to design/RD before handing off to QA; do not retain login URLs, cookies, headers, tokens, storage state, browser traces, or screenshots/logs containing PII or SSO/MFA material. Canonical browser workflow: `peaks-solo/references/browser-workflow.md`.
239
+ For frontend work, especially full-auto mode, use the Playwright MCP to inspect the running page or prototype before accepting the UI direction. The LLM checks its own tool list for any Playwright MCP entry in the LLM tool list; if present, it invokes the tools by name directly (browser_navigate / browser_snapshot / browser_take_screenshot / browser_console_messages / browser_network_requests / browser_close) — there is no peaks-cli envelope. Playwright MCP launches a headed browser on demand; if the tool list is empty, the user installs via `claude mcp add playwright -- npx @playwright/mcp@latest` (Claude Code) or the IDE's own MCP install path. (Chrome DevTools MCP is a secondary surface that connects to an already-running Chrome via `--remote-debugging-port=9222`; it does NOT launch a browser on its own.) If login, CAPTCHA, SSO, or MFA appears, the visible browser is already open; wait for the user to complete login and explicitly confirm completion before continuing. Capture only sanitized visible regressions, weak hierarchy, generic template patterns, console errors, and interaction problems as UI feedback that should return to design/RD before handing off to QA; do not retain login URLs, cookies, headers, tokens, storage state, browser traces, or screenshots/logs containing PII or SSO/MFA material. Canonical browser workflow: `peaks-solo/references/browser-workflow.md`.
242
240
 
243
241
  ## Prototype fidelity gate (MANDATORY — check BEFORE any design work)
244
242
 
@@ -248,7 +246,7 @@ For frontend work, especially full-auto mode, use Playwright MCP to inspect the
248
246
 
249
247
  Check these sources in order:
250
248
 
251
- 1. **Figma design file** — If the PRD links to a Figma file, use `peaks mcp call --capability figma-context-mcp.design-context --tool get_figma_data --args-json '{"fileKey":"<key>"}' --json` to fetch the design (the skill body never bakes in the `mcp__Figma_AI_Bridge__` prefix; the prefix is owned by the LLM runtime, and `FIGMA_API_KEY` must be set in the env before `peaks mcp apply` — the plan envelope's `envCheck.missing` field is the source of truth). The Figma data IS the design. Replicate layout, spacing, colors, typography, and component choices exactly as specified.
249
+ 1. **Figma design file** — If the PRD links to a Figma file, the LLM checks its own tool list for any the Figma MCP entry. If present, it invokes `get_figma_data` (or similar) directly with `{"fileKey":"<key>"}`; `FIGMA_API_KEY` must be set in the user's env for the MCP to authenticate. The skill body never bakes in the Figma MCP prefix; the LLM's runtime owns the namespace. The Figma data IS the design. Replicate layout, spacing, colors, typography, and component choices exactly as specified.
252
250
  2. **PRD document screenshots** — If the PRD source (Feishu/Lark doc) contains screenshots or mockups, those ARE the visual target. Check `.peaks/<id>/prd/source/` for saved screenshots.
253
251
  3. **PRD visual descriptions** — If the PRD explicitly describes layout, component placement, or visual behavior, those descriptions are constraints, not suggestions.
254
252
  4. **Existing application pages** — If modifying an existing app, the existing visual language (component library, spacing patterns, color usage) is the fidelity baseline. New pages must match existing conventions.
@@ -355,8 +353,8 @@ Use `peaks capabilities --source access-repo --json` and `peaks capabilities --s
355
353
 
356
354
  - In full-auto frontend mode, prefer the `awesome-design-md` + `taste-skill`/`design-taste-frontend` combination before shadcn/ui or generic component-library output (capability discovery must confirm availability first).
357
355
  - shadcn/ui, React Bits, awesome-design-md, taste-skill, and ui-ux-pro-max-skill are UI references; do not treat unreviewed generated UI as finished design.
358
- - Chrome DevTools MCP and Agent Browser can support runtime UI inspection only after the user approves the app target. Install or update those MCP servers through `peaks mcp plan --capability <id> --json` then `peaks mcp apply --capability <id> --yes --json` rather than hand-editing settings; invoke their tools through `peaks mcp call --capability <id> --tool <name> --args-json '{...}' --json`.
359
- - Figma Context MCP and Penpot require user-authorized design access and must not persist tokens or private design data in project artifacts. Same `peaks mcp plan / apply / call` installation and invocation path applies.
356
+ - Chrome DevTools MCP and Agent Browser can support runtime UI inspection only after the user approves the app target. (Slice #016: peaks-cli no longer auto-installs these; the user runs the IDE-native MCP install command themselves, and the LLM invokes the tool by name from its tool list when present.)
357
+ - Figma Context MCP and Penpot require user-authorized design access and must not persist tokens or private design data in project artifacts. Same rule: the LLM's tool list is the source of truth; peaks-cli is not in the install path.
360
358
  - Check license, accessibility, and performance before translating external visual references into Peaks-Cli UI constraints.
361
359
 
362
360
  ## Boundaries
@@ -11,7 +11,7 @@ Use this path before generating or accepting frontend UI:
11
11
  3. Produce a concrete visual direction, not vague “clean modern” language.
12
12
  4. Reject generic AI UI tells: centered stock hero, uniform card grids, default shadcn/library styling, purple-blue gradients, three equal feature cards, generic placeholder copy, and static-only happy states.
13
13
  5. Require meaningful loading, empty, error, hover, focus, active, and responsive states.
14
- 6. Use Playwright MCP on the running page or prototype to inspect real browser output (install via `peaks mcp plan/apply --capability playwright-mcp.browser-validation --yes` if not yet present; open with `mcp__playwright__browser_navigate` / `navigate_page`, capture with `take_snapshot` and `take_screenshot`); visible browser confirmation is mandatory, and login/CAPTCHA/SSO/MFA requires waiting for explicit user confirmation before continuing.
14
+ 6. Use Playwright MCP on the running page or prototype to inspect real browser output (the LLM checks its tool list for `mcp__playwright__*`; if absent, the user installs via `claude mcp add playwright -- npx @playwright/mcp@latest` for Claude Code, or the IDE-native MCP install command otherwise — peaks-cli no longer auto-installs as of slice #016; open with `browser_navigate` / `navigate_page`, capture with `browser_snapshot` and `browser_take_screenshot`); visible browser confirmation is mandatory, and login/CAPTCHA/SSO/MFA requires waiting for explicit user confirmation before continuing.
15
15
  7. If the browser view looks generic, visually weak, broken, inaccessible, or has console/runtime errors, return to design/RD and iterate before handing off to QA.
16
16
 
17
17
  ## Outputs
@@ -21,7 +21,7 @@ Use this path before generating or accepting frontend UI:
21
21
  - visual direction with references;
22
22
  - design dials and rejected generic patterns;
23
23
  - interaction constraints;
24
- - Playwright MCP browser observations when frontend output exists (`mcp__playwright__browser_snapshot`, `take_screenshot`, `list_console_messages`, `list_network_requests`);
24
+ - Playwright MCP browser observations when frontend output exists (`browser_snapshot`, `browser_take_screenshot`, `browser_console_messages`, `browser_network_requests`);
25
25
  - UI regression seeds;
26
26
  - accessibility notes;
27
27
  - taste report.
@@ -1,3 +0,0 @@
1
- import { Command } from 'commander';
2
- import { type ProgramIO } from '../cli-helpers.js';
3
- export declare function registerMcpCommands(program: Command, io: ProgramIO): void;
@@ -1,144 +0,0 @@
1
- import { InvalidArgumentError } from 'commander';
2
- import { readFile } from 'node:fs/promises';
3
- import { scanMcpServers } from '../../services/mcp/mcp-scan-service.js';
4
- import { planMcpInstall } from '../../services/mcp/mcp-plan-service.js';
5
- import { applyMcpInstall, rollbackMcpInstall } from '../../services/mcp/mcp-apply-service.js';
6
- import { callMcpTool } from '../../services/mcp/mcp-call-service.js';
7
- import { createStdioTransportFromSpec } from '../../services/mcp/mcp-stdio-transport.js';
8
- import { fail, ok } from '../../shared/result.js';
9
- import { addJsonOption, failUnsupportedNonDryRun, getErrorMessage, printResult } from '../cli-helpers.js';
10
- function parsePositiveInteger(value) {
11
- if (!/^\d+$/.test(value)) {
12
- throw new InvalidArgumentError('must be a positive integer');
13
- }
14
- const parsed = Number(value);
15
- if (!Number.isSafeInteger(parsed) || parsed < 1) {
16
- throw new InvalidArgumentError('must be a positive integer');
17
- }
18
- return parsed;
19
- }
20
- async function resolveCallArgs(options) {
21
- if (options.argsJson !== undefined && options.args !== undefined) {
22
- throw new Error('Pass either --args-json or --args, not both');
23
- }
24
- const raw = options.argsJson !== undefined
25
- ? options.argsJson
26
- : options.args !== undefined ? await readFile(options.args, 'utf8') : '{}';
27
- const parsed = JSON.parse(raw);
28
- if (parsed === null || typeof parsed !== 'object' || Array.isArray(parsed)) {
29
- throw new Error('MCP tool arguments must be a JSON object');
30
- }
31
- return parsed;
32
- }
33
- export function registerMcpCommands(program, io) {
34
- const mcp = program.command('mcp').description('Manage Claude Code MCP servers');
35
- addJsonOption(mcp
36
- .command('list')
37
- .alias('scan')
38
- .description('Scan Claude Code settings for configured MCP servers')
39
- .option('--project <path>', 'project root to also scan project-level .claude/settings.json')).action(async (options) => {
40
- try {
41
- const report = await scanMcpServers(options.project !== undefined ? { projectRoot: options.project } : {});
42
- printResult(io, ok('mcp.list', report), options.json);
43
- }
44
- catch (error) {
45
- printResult(io, fail('mcp.list', 'MCP_LIST_FAILED', getErrorMessage(error), {}, ['Check Claude settings path and permissions before retrying']), options.json);
46
- process.exitCode = 1;
47
- }
48
- });
49
- addJsonOption(mcp
50
- .command('plan')
51
- .description('Plan an MCP server install diff for a capability (dry-run only)')
52
- .requiredOption('--capability <id>', 'capability id from the MCP install registry')
53
- .option('--project <path>', 'project root for scoped scan')
54
- .option('--dry-run', 'preview the install diff (always true)', true)
55
- .option('--no-dry-run', 'unsupported: peaks mcp plan never writes settings')).action(async (options) => {
56
- if (options.dryRun === false) {
57
- failUnsupportedNonDryRun(io, 'mcp.plan', options.json);
58
- return;
59
- }
60
- try {
61
- const planOptions = options.project !== undefined ? { projectRoot: options.project } : {};
62
- const plan = await planMcpInstall(options.capability, planOptions);
63
- if (plan.action === 'unknown-capability') {
64
- printResult(io, fail('mcp.plan', 'MCP_UNKNOWN_CAPABILITY', `No MCP install spec registered for capability ${options.capability}`, plan, plan.nextActions), options.json);
65
- process.exitCode = 1;
66
- return;
67
- }
68
- printResult(io, ok('mcp.plan', plan, [], plan.nextActions), options.json);
69
- }
70
- catch (error) {
71
- printResult(io, fail('mcp.plan', 'MCP_PLAN_FAILED', getErrorMessage(error), { capabilityId: options.capability }, ['Check Claude settings path and the capability id before retrying']), options.json);
72
- process.exitCode = 1;
73
- }
74
- });
75
- addJsonOption(mcp
76
- .command('apply')
77
- .description('Apply an MCP server install for a capability (writes .claude/settings.json with backup)')
78
- .requiredOption('--capability <id>', 'capability id from the MCP install registry')
79
- .option('--yes', 'confirm the write — required for any real side effect')
80
- .option('--claim', 'take ownership of an existing non-peaks-managed server entry')
81
- .option('--project <path>', 'project root for scoped scan')).action(async (options) => {
82
- if (options.yes !== true) {
83
- printResult(io, fail('mcp.apply', 'MCP_APPLY_REQUIRES_YES', 'Refusing to apply without --yes', { capabilityId: options.capability }, ['Re-run with --yes to confirm the write']), options.json);
84
- process.exitCode = 1;
85
- return;
86
- }
87
- try {
88
- const applyOptions = {};
89
- if (options.project !== undefined) {
90
- applyOptions.projectRoot = options.project;
91
- }
92
- if (options.claim === true) {
93
- applyOptions.claim = true;
94
- }
95
- const result = await applyMcpInstall(options.capability, applyOptions);
96
- printResult(io, ok('mcp.apply', result), options.json);
97
- }
98
- catch (error) {
99
- printResult(io, fail('mcp.apply', 'MCP_APPLY_FAILED', getErrorMessage(error), { capabilityId: options.capability }, ['Check the plan first with peaks mcp plan, then re-run apply']), options.json);
100
- process.exitCode = 1;
101
- }
102
- });
103
- addJsonOption(mcp
104
- .command('rollback')
105
- .description('Restore Claude Code settings.json from a peaks-managed MCP backup file')
106
- .requiredOption('--backup <path>', 'path to a previously created backup settings.json')).action(async (options) => {
107
- try {
108
- const result = await rollbackMcpInstall({ backupPath: options.backup });
109
- printResult(io, ok('mcp.rollback', result), options.json);
110
- }
111
- catch (error) {
112
- printResult(io, fail('mcp.rollback', 'MCP_ROLLBACK_FAILED', getErrorMessage(error), { backupPath: options.backup }, ['Verify the backup path and rerun']), options.json);
113
- process.exitCode = 1;
114
- }
115
- });
116
- addJsonOption(mcp
117
- .command('call')
118
- .description('Invoke a tool on an installed MCP server via stdio (spawns the server, calls tools/call, closes)')
119
- .requiredOption('--capability <id>', 'capability id from the MCP install registry')
120
- .requiredOption('--tool <name>', 'MCP tool name to invoke')
121
- .option('--args <path>', 'path to a JSON file describing the tool arguments object')
122
- .option('--args-json <jsonString>', 'inline JSON object describing the tool arguments')
123
- .option('--timeout <ms>', 'per-request timeout in milliseconds', parsePositiveInteger)).action(async (options) => {
124
- try {
125
- const args = await resolveCallArgs(options);
126
- const factory = createStdioTransportFromSpec;
127
- const callOptions = {
128
- capabilityId: options.capability,
129
- toolName: options.tool,
130
- args,
131
- transportFactory: factory
132
- };
133
- if (options.timeout !== undefined) {
134
- callOptions.timeoutMs = Number(options.timeout);
135
- }
136
- const result = await callMcpTool(callOptions);
137
- printResult(io, ok('mcp.call', result), options.json);
138
- }
139
- catch (error) {
140
- printResult(io, fail('mcp.call', 'MCP_CALL_FAILED', getErrorMessage(error), { capabilityId: options.capability, toolName: options.tool }, ['Check the capability id, tool name, args JSON, and required env vars before retrying']), options.json);
141
- process.exitCode = 1;
142
- }
143
- });
144
- }
@@ -1,31 +0,0 @@
1
- import { type PlanMcpInstallOptions, type McpInstallEnvCheck } from './mcp-plan-service.js';
2
- export type McpApplyAction = 'add' | 'update' | 'claimed' | 'noop';
3
- export type McpApplyBackupInfo = {
4
- path: string | null;
5
- skipped: boolean;
6
- };
7
- export type McpApplyResult = {
8
- capabilityId: string;
9
- action: McpApplyAction;
10
- backup: McpApplyBackupInfo;
11
- written: {
12
- settingsPath: string;
13
- managedMarkerPath: string;
14
- };
15
- envCheck: McpInstallEnvCheck;
16
- };
17
- export type McpApplyOptions = PlanMcpInstallOptions & {
18
- claim?: boolean;
19
- backupRoot?: string;
20
- clock?: () => string;
21
- };
22
- export type McpRollbackOptions = {
23
- backupPath: string;
24
- globalSettingsPath?: string;
25
- };
26
- export type McpRollbackResult = {
27
- restoredFrom: string;
28
- restoredTo: string;
29
- };
30
- export declare function applyMcpInstall(capabilityId: string, options?: McpApplyOptions): Promise<McpApplyResult>;
31
- export declare function rollbackMcpInstall(options: McpRollbackOptions): Promise<McpRollbackResult>;
@@ -1,112 +0,0 @@
1
- import { homedir } from 'node:os';
2
- import { dirname, join } from 'node:path';
3
- import { mkdir, writeFile } from 'node:fs/promises';
4
- import { pathExists, readText } from '../../shared/fs.js';
5
- import { planMcpInstall } from './mcp-plan-service.js';
6
- function defaultGlobalSettingsPath() {
7
- return join(homedir(), '.claude', 'settings.json');
8
- }
9
- function defaultManagedMarkerPath() {
10
- return join(homedir(), '.peaks', 'mcp-managed.json');
11
- }
12
- function defaultBackupRoot() {
13
- return join(homedir(), '.peaks-artifacts', 'mcp-backups');
14
- }
15
- function defaultClock() {
16
- return new Date().toISOString().replace(/[:.]/g, '-');
17
- }
18
- async function readJsonFile(path) {
19
- if (!(await pathExists(path))) {
20
- return {};
21
- }
22
- const raw = await readText(path);
23
- if (raw.length === 0) {
24
- return {};
25
- }
26
- const parsed = JSON.parse(raw);
27
- if (parsed === null || typeof parsed !== 'object' || Array.isArray(parsed)) {
28
- return {};
29
- }
30
- return parsed;
31
- }
32
- async function writeJsonFile(path, data) {
33
- await mkdir(dirname(path), { recursive: true });
34
- await writeFile(path, `${JSON.stringify(data, null, 2)}\n`, 'utf8');
35
- }
36
- function buildServerConfig(spec) {
37
- const env = {};
38
- for (const key of spec.envKeys) {
39
- env[key] = `\${${key}}`;
40
- }
41
- return { command: spec.command, args: [...spec.args], env };
42
- }
43
- async function createBackup(settingsPath, backupRoot, timestamp) {
44
- if (!(await pathExists(settingsPath))) {
45
- return null;
46
- }
47
- const backupPath = join(backupRoot, timestamp, 'settings.json');
48
- await mkdir(dirname(backupPath), { recursive: true });
49
- await writeFile(backupPath, await readText(settingsPath), 'utf8');
50
- return backupPath;
51
- }
52
- async function updateManagedMarker(markerPath, name) {
53
- const marker = await readJsonFile(markerPath);
54
- const existing = Array.isArray(marker.servers)
55
- ? marker.servers.filter((entry) => typeof entry === 'string')
56
- : [];
57
- if (!existing.includes(name)) {
58
- existing.push(name);
59
- }
60
- await writeJsonFile(markerPath, { ...marker, servers: existing });
61
- }
62
- export async function applyMcpInstall(capabilityId, options = {}) {
63
- const plan = await planMcpInstall(capabilityId, options);
64
- if (plan.action === 'unknown-capability' || plan.spec === null) {
65
- throw new Error(`No MCP install spec registered for capability ${capabilityId} (unknown-capability)`);
66
- }
67
- if (plan.envCheck.missing.length > 0) {
68
- throw new Error(`Refusing to apply: missing required env vars: ${plan.envCheck.missing.join(', ')}`);
69
- }
70
- if (plan.action === 'conflict' && options.claim !== true) {
71
- throw new Error(`Refusing to apply: server ${plan.spec.name} exists but is not peaks-managed (conflict). Re-run with --claim to take ownership.`);
72
- }
73
- const settingsPath = options.globalSettingsPath ?? defaultGlobalSettingsPath();
74
- const markerPath = options.managedMarkerPath ?? defaultManagedMarkerPath();
75
- const backupRoot = options.backupRoot ?? defaultBackupRoot();
76
- const clock = options.clock ?? defaultClock;
77
- if (plan.action === 'noop') {
78
- return {
79
- capabilityId,
80
- action: 'noop',
81
- backup: { path: null, skipped: true },
82
- written: { settingsPath, managedMarkerPath: markerPath },
83
- envCheck: plan.envCheck
84
- };
85
- }
86
- const backupPath = await createBackup(settingsPath, backupRoot, clock());
87
- const settings = await readJsonFile(settingsPath);
88
- const existingServers = settings.mcpServers !== null && typeof settings.mcpServers === 'object' && !Array.isArray(settings.mcpServers)
89
- ? settings.mcpServers
90
- : {};
91
- const nextServers = { ...existingServers, [plan.spec.name]: buildServerConfig(plan.spec) };
92
- await writeJsonFile(settingsPath, { ...settings, mcpServers: nextServers });
93
- await updateManagedMarker(markerPath, plan.spec.name);
94
- const action = plan.action === 'conflict' ? 'claimed' : plan.action;
95
- return {
96
- capabilityId,
97
- action,
98
- backup: { path: backupPath, skipped: false },
99
- written: { settingsPath, managedMarkerPath: markerPath },
100
- envCheck: plan.envCheck
101
- };
102
- }
103
- export async function rollbackMcpInstall(options) {
104
- if (!(await pathExists(options.backupPath))) {
105
- throw new Error(`Refusing to rollback: backup file not found at ${options.backupPath}`);
106
- }
107
- const target = options.globalSettingsPath ?? defaultGlobalSettingsPath();
108
- const content = await readText(options.backupPath);
109
- await mkdir(dirname(target), { recursive: true });
110
- await writeFile(target, content, 'utf8');
111
- return { restoredFrom: options.backupPath, restoredTo: target };
112
- }