peaks-cli 1.3.2 → 1.3.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +6 -2
- package/dist/src/cli/commands/core-artifact-commands.js +6 -3
- package/dist/src/cli/commands/gate-commands.js +28 -19
- package/dist/src/cli/commands/hook-handle.d.ts +17 -0
- package/dist/src/cli/commands/hook-handle.js +111 -0
- package/dist/src/cli/commands/hooks-commands.js +72 -21
- package/dist/src/cli/commands/progress-commands.js +9 -2
- package/dist/src/cli/commands/progress-start-spawn.js +30 -4
- package/dist/src/cli/commands/project-commands.js +8 -4
- package/dist/src/cli/commands/statusline-commands.js +75 -17
- package/dist/src/cli/commands/sub-agent-commands.d.ts +5 -0
- package/dist/src/cli/commands/sub-agent-commands.js +488 -0
- package/dist/src/cli/commands/sub-agent-dispatch-guard.d.ts +55 -0
- package/dist/src/cli/commands/sub-agent-dispatch-guard.js +57 -0
- package/dist/src/cli/commands/workflow-commands.js +2 -1
- package/dist/src/cli/commands/workspace-commands.js +3 -0
- package/dist/src/cli/program.js +9 -0
- package/dist/src/hooks/pre-tool-use-sub-agent.d.ts +28 -0
- package/dist/src/hooks/pre-tool-use-sub-agent.js +105 -0
- package/dist/src/services/config/config-types.d.ts +1 -1
- package/dist/src/services/context/artifact-meta.d.ts +72 -0
- package/dist/src/services/context/artifact-meta.js +105 -0
- package/dist/src/services/context/context-guard.d.ts +49 -0
- package/dist/src/services/context/context-guard.js +91 -0
- package/dist/src/services/context/dispatch-context-guard.d.ts +27 -0
- package/dist/src/services/context/dispatch-context-guard.js +192 -0
- package/dist/src/services/context/headroom-client.d.ts +34 -0
- package/dist/src/services/context/headroom-client.js +117 -0
- package/dist/src/services/context/shared-channel.d.ts +92 -0
- package/dist/src/services/context/shared-channel.js +285 -0
- package/dist/src/services/context/threshold.d.ts +35 -0
- package/dist/src/services/context/threshold.js +76 -0
- package/dist/src/services/dashboard/project-dashboard-service.d.ts +23 -0
- package/dist/src/services/dashboard/project-dashboard-service.js +21 -0
- package/dist/src/services/dispatch/batch-counter.d.ts +27 -0
- package/dist/src/services/dispatch/batch-counter.js +85 -0
- package/dist/src/services/dispatch/dispatch-record-writer.d.ts +93 -0
- package/dist/src/services/dispatch/dispatch-record-writer.js +261 -0
- package/dist/src/services/dispatch/heartbeat-truncator.d.ts +26 -0
- package/dist/src/services/dispatch/heartbeat-truncator.js +13 -0
- package/dist/src/services/dispatch/leak-detector.d.ts +11 -0
- package/dist/src/services/dispatch/leak-detector.js +72 -0
- package/dist/src/services/dispatch/sub-agent-dispatcher.d.ts +127 -0
- package/dist/src/services/dispatch/sub-agent-dispatcher.js +98 -0
- package/dist/src/services/ide/adapters/claude-code-adapter.d.ts +18 -0
- package/dist/src/services/ide/adapters/claude-code-adapter.js +80 -0
- package/dist/src/services/ide/adapters/trae-adapter.d.ts +42 -0
- package/dist/src/services/ide/adapters/trae-adapter.js +98 -0
- package/dist/src/services/ide/hook-protocol.d.ts +47 -0
- package/dist/src/services/ide/hook-protocol.js +74 -0
- package/dist/src/services/ide/hook-translator.d.ts +72 -0
- package/dist/src/services/ide/hook-translator.js +128 -0
- package/dist/src/services/ide/ide-detector.d.ts +10 -0
- package/dist/src/services/ide/ide-detector.js +19 -0
- package/dist/src/services/ide/ide-registry.d.ts +14 -0
- package/dist/src/services/ide/ide-registry.js +45 -0
- package/dist/src/services/ide/ide-types.d.ts +180 -0
- package/dist/src/services/ide/ide-types.js +2 -0
- package/dist/src/services/ide/resource-profile.d.ts +52 -0
- package/dist/src/services/ide/resource-profile.js +33 -0
- package/dist/src/services/ide/shared/atomic-json.d.ts +15 -0
- package/dist/src/services/ide/shared/atomic-json.js +58 -0
- package/dist/src/services/ide/shared/safe-path.d.ts +11 -0
- package/dist/src/services/ide/shared/safe-path.js +29 -0
- package/dist/src/services/memory/project-context-service.js +2 -1
- package/dist/src/services/memory/project-memory-service.js +4 -3
- package/dist/src/services/perf/perf-baseline-service.js +2 -1
- package/dist/src/services/progress/progress-service.d.ts +1 -1
- package/dist/src/services/progress/progress-service.js +18 -14
- package/dist/src/services/security/safe-settings-path.d.ts +12 -0
- package/dist/src/services/security/safe-settings-path.js +104 -0
- package/dist/src/services/session/getSessionDir.d.ts +1 -0
- package/dist/src/services/session/getSessionDir.js +27 -0
- package/dist/src/services/session/index.d.ts +1 -0
- package/dist/src/services/session/index.js +1 -0
- package/dist/src/services/signal/cancel-handler.d.ts +14 -0
- package/dist/src/services/signal/cancel-handler.js +76 -0
- package/dist/src/services/skill/resume-detector.d.ts +54 -0
- package/dist/src/services/skill/resume-detector.js +334 -0
- package/dist/src/services/skill/skill-scheduler.d.ts +40 -0
- package/dist/src/services/skill/skill-scheduler.js +53 -0
- package/dist/src/services/skills/hooks-settings-service.d.ts +47 -29
- package/dist/src/services/skills/hooks-settings-service.js +190 -144
- package/dist/src/services/skills/statusline-settings-service.d.ts +33 -6
- package/dist/src/services/skills/statusline-settings-service.js +31 -34
- package/dist/src/services/slice/slice-archive-service.d.ts +20 -0
- package/dist/src/services/slice/slice-archive-service.js +111 -0
- package/dist/src/services/solo/batch-heartbeat-poller.d.ts +51 -0
- package/dist/src/services/solo/batch-heartbeat-poller.js +88 -0
- package/dist/src/services/solo/status-line-renderer.d.ts +34 -0
- package/dist/src/services/solo/status-line-renderer.js +55 -0
- package/dist/src/services/standards/ide-aware-standards-service.d.ts +94 -0
- package/dist/src/services/standards/ide-aware-standards-service.js +89 -0
- package/dist/src/services/standards/project-standards-service.d.ts +1 -2
- package/dist/src/services/workspace/reconcile-service.d.ts +36 -0
- package/dist/src/services/workspace/reconcile-service.js +107 -6
- package/dist/src/services/workspace/reconcile-types.d.ts +12 -0
- package/dist/src/shared/version.d.ts +1 -1
- package/dist/src/shared/version.js +1 -1
- package/package.json +2 -1
- package/scripts/install-skills.mjs +112 -2
- package/skills/peaks-ide/SKILL.md +159 -0
- package/skills/peaks-ide/references/audit-log-helper.md +52 -0
- package/skills/peaks-qa/SKILL.md +153 -55
- package/skills/peaks-qa/references/qa-fanout-contract.md +150 -0
- package/skills/peaks-rd/SKILL.md +134 -62
- package/skills/peaks-solo/SKILL.md +124 -37
- package/skills/peaks-solo/references/browser-workflow.md +22 -20
- package/skills/peaks-solo/references/context-governance.md +144 -0
- package/skills/peaks-solo/references/headroom-integration.md +107 -0
- package/skills/peaks-solo/references/runbook.md +3 -3
- package/skills/peaks-solo/references/sub-agent-dispatch.md +261 -0
- package/skills/peaks-solo/references/swarm-dispatch-contract.md +3 -37
- package/skills/peaks-txt/SKILL.md +17 -0
- package/skills/peaks-ui/SKILL.md +45 -10
package/skills/peaks-qa/SKILL.md
CHANGED
|
@@ -3,6 +3,36 @@ name: peaks-qa
|
|
|
3
3
|
description: QA and verification skill for Peaks. Use when a workflow needs unit-test coverage evidence, regression matrices, baseline reports, validation reports, acceptance checks, or refactor verification gates.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
|
+
## Two-axis naming convention
|
|
7
|
+
|
|
8
|
+
> **Read once at the top of this file; the rest of the skill is written against it.**
|
|
9
|
+
|
|
10
|
+
The `.peaks/` workspace is partitioned by **two orthogonal axes**. Every path in this SKILL.md uses one of them; mixing them is the original `.peaks/<sid>/` / `.peaks/_runtime/<sid>/` bug class this slice corrects.
|
|
11
|
+
|
|
12
|
+
| Axis | Path root | Holds | When to use |
|
|
13
|
+
|---|---|---|---|
|
|
14
|
+
| **change-id axis** (reviewable artifacts) | `.peaks/<changeId>/...` | PRD, RD plan, code-review, security-review, test-cases, handoff capsules, gate targets | The artifact should be reviewable on its own and survives across sessions for the same change. Change-id is the unit of work. |
|
|
15
|
+
| **session-id axis** (ephemeral state) | `.peaks/_runtime/<sessionId>/...` | Session bindings (`.peaks/_runtime/session.json`), live in-flight state, the per-session project-scan and tech-doc scaffold while the session is open | The artifact is session-scoped and only meaningful while the parent session is live. |
|
|
16
|
+
| **sub-agent axis** | `.peaks/_sub_agents/<sessionId>/...` | Sub-agent dispatch records, sub-agent heartbeats, per-sub-agent shared channel entries, sub-agent artifact outputs | A sub-agent ran in a parent session. The axis nests under the parent session-id; sub-agent outputs are flushed into the change-id root on commit. |
|
|
17
|
+
|
|
18
|
+
**Which CLI commands operate on which axis:**
|
|
19
|
+
|
|
20
|
+
- **change-id axis** (reviewable artifacts): `peaks request init`, `peaks request transition`, `peaks request show`, `peaks request lint`, `peaks request repair-status`, `peaks scan diff-vs-scope`, `peaks scan acceptance-coverage`. Inputs reference `.peaks/<changeId>/...`.
|
|
21
|
+
- **session-id axis** (ephemeral state): `peaks session info`, `peaks session start`, `peaks session finish`, `peaks session list`. Reads/writes `.peaks/_runtime/<sessionId>/session.json`.
|
|
22
|
+
- **sub-agent axis** (under parent session-id): `peaks sub-agent dispatch`, `peaks sub-agent heartbeat`, `peaks sub-agent share`, `peaks sub-agent shared-read`. All output paths are under `.peaks/_sub_agents/<sessionId>/...`.
|
|
23
|
+
|
|
24
|
+
**Placeholder convention used in this file:**
|
|
25
|
+
|
|
26
|
+
- `<changeId>` / `<change-id>` — the change-id axis. Use when describing a path that lives at `.peaks/<changeId>/...` (root-level, NOT inside `_runtime/`).
|
|
27
|
+
- `<sessionId>` / `<session-id>` — the session-id axis. Use when describing a path that lives at `.peaks/_runtime/<sessionId>/...` or `.peaks/_sub_agents/<sessionId>/...`. The long form `<session-id>` is used inside bash / shell examples where `<sessionId>` would break parsing.
|
|
28
|
+
- The bare `<sid>` placeholder is **forbidden** in new content — it is ambiguous between the two axes. Legacy occurrences are replaced by this convention; new content must use the right axis label.
|
|
29
|
+
|
|
30
|
+
**Cross-references:**
|
|
31
|
+
|
|
32
|
+
- Slice `2026-06-05-change-id-as-unit-of-work` (commits `48958fc` + `928eb53`) — established the change-id axis as the canonical root for reviewable artifacts (`src/shared/change-id.ts:131,335`, `src/services/scan/acceptance-coverage-service.ts:155`).
|
|
33
|
+
- Slice `005-session-runtime-dir-regression` (commit `178a47e`) — added the `getSessionDir()` resolver at `src/services/session/getSessionDir.ts` and routed 4 stragglers that were constructing `.peaks/${sessionId}` (no `_runtime/`) through the canonical resolver. Defense-in-depth scan: `tests/unit/services/session/session-dir-canonical.test.ts`.
|
|
34
|
+
- Slice `006-5th-writer-changeid-path` (this slice) — disambiguates the SKILL.md placeholders and adds the regression test `tests/unit/skills/skills-skill-md-naming.test.ts` that mechanically enforces (a) zero bare `<sid>`, (b) every `.peaks/<X>/` reference has an axis label, (c) the "Two-axis naming convention" callout is present in `peaks-solo`, `peaks-rd`, `peaks-qa`.
|
|
35
|
+
|
|
6
36
|
# Peaks-Cli QA
|
|
7
37
|
|
|
8
38
|
Peaks-Cli QA proves that planned changes are protected and accepted.
|
|
@@ -11,29 +41,31 @@ Peaks-Cli QA proves that planned changes are protected and accepted.
|
|
|
11
41
|
|
|
12
42
|
These two contracts are non-negotiable. The previous prose-only phrasing let the LLM skip the browser gate entirely when an auth wall appeared, and let screenshots land in the project root because the LLM forgot to pass `filename`. Both fail modes are blocking violations; the rules below are what a reviewer should hold the skill to.
|
|
13
43
|
|
|
14
|
-
### Contract 1 — Screenshot path is mandatory and must land under .peaks/<
|
|
44
|
+
### Contract 1 — Screenshot path is mandatory and must land under .peaks/_runtime/<sessionId>/qa/screenshots/
|
|
15
45
|
|
|
16
|
-
Every `
|
|
46
|
+
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) whose absolute path is **inside** `.peaks/_runtime/<sessionId>/qa/screenshots/`. Concrete form:
|
|
17
47
|
|
|
18
48
|
```bash
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
49
|
+
peaks mcp call \
|
|
50
|
+
--capability playwright-mcp.browser-validation \
|
|
51
|
+
--tool browser_take_screenshot \
|
|
52
|
+
--args-json '{"filename":".peaks/_runtime/<session-id>/qa/screenshots/<state-or-step>.png","fullPage":true}' \
|
|
53
|
+
--json
|
|
22
54
|
```
|
|
23
55
|
|
|
24
|
-
The default behaviour of Playwright MCP when `filename` is omitted or points outside that directory is to write a screenshot to the current working directory, which leaves `.png` files scattered at the project root. **This is a workflow violation.** If a screenshot does land outside `.peaks/<
|
|
56
|
+
The default behaviour of Playwright MCP when `filename` is omitted or points outside that directory is to write a screenshot to the current working directory, which leaves `.png` files scattered at the project root. **This is a workflow violation.** If a screenshot does land outside `.peaks/_runtime/<session-id>/qa/screenshots/` for any reason (e.g. an upstream tool wrote there), QA MUST move it into that directory before declaring the test report complete; do not commit project-root `.png` files. Sanitise before retention: no login URLs, cookies, headers, tokens, storage state, browser traces, or screenshots/logs containing PII or SSO/MFA material.
|
|
25
57
|
|
|
26
58
|
This rule is enforced by a Peaks-Cli preflight check inside this skill:
|
|
27
59
|
|
|
28
60
|
```bash
|
|
29
61
|
# After every browser_take_screenshot batch and before declaring the test report complete:
|
|
30
|
-
ls .peaks/<
|
|
62
|
+
ls .peaks/_runtime/<session-id>/qa/screenshots/*.png 2>&1
|
|
31
63
|
# Expected: at least one .png file under the screenshots directory.
|
|
32
64
|
# "No such file" → BLOCKED. Either the screenshot was never taken, or
|
|
33
65
|
# it landed in the project root (move it before continuing).
|
|
34
66
|
find . -maxdepth 1 -name '*.png' 2>&1
|
|
35
67
|
# Expected: empty. Any .png at the project root is a leak — move it
|
|
36
|
-
# to .peaks/<
|
|
68
|
+
# to .peaks/_runtime/<session-id>/qa/screenshots/ before completing this skill.
|
|
37
69
|
```
|
|
38
70
|
|
|
39
71
|
### Contract 2 — Login / CAPTCHA / SSO / MFA wall is a hard block, not a skip
|
|
@@ -60,10 +92,40 @@ This is the hard-block replacement for the previous "wait for the user" prose. W
|
|
|
60
92
|
|
|
61
93
|
## Sub-agent dispatch (when launched by peaks-solo swarm)
|
|
62
94
|
|
|
63
|
-
When this skill is launched as a sub-agent via `
|
|
95
|
+
When this skill is launched as a sub-agent via `peaks sub-agent dispatch <role>` (then the LLM executes the returned toolCall) from `peaks-solo`, the following sections of THIS skill are **suspended** for the sub-agent run:
|
|
96
|
+
|
|
97
|
+
## QA fan-out (业务 + 性能 + 安全 并发, 业务可再分)
|
|
98
|
+
|
|
99
|
+
When peaks-qa is the **main loop** (i.e. it is the active skill and is about to run its own sub-agent dispatch, rather than being a sub-agent itself), it fans out the 3 QA review activities concurrently using the same `peaks sub-agent dispatch` primitive:
|
|
100
|
+
|
|
101
|
+
```
|
|
102
|
+
peaks sub-agent dispatch qa-business \
|
|
103
|
+
--prompt "<qa-business contract, plus runtime args project=<repo>, session-id=<session-id>, request-id=<rid>>" \
|
|
104
|
+
--request-id <rid> --session-id <session-id> --project <repo> --json
|
|
105
|
+
|
|
106
|
+
peaks sub-agent dispatch qa-perf \
|
|
107
|
+
--prompt "<qa-perf contract, plus runtime args>" \
|
|
108
|
+
--request-id <rid> --session-id <session-id> --project <repo> --json
|
|
109
|
+
|
|
110
|
+
peaks sub-agent dispatch qa-security \
|
|
111
|
+
--prompt "<qa-security contract, plus runtime args>" \
|
|
112
|
+
--request-id <rid> --session-id <session-id> --project <repo> --json
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
All three are issued in a single message; the LLM fires all 3 returned toolCalls in parallel; the IDE runs them concurrently; peaks-qa then collects the three envelopes and merges their outputs into:
|
|
116
|
+
|
|
117
|
+
- `.peaks/_runtime/<sessionId>/qa/test-reports/<rid>.md` (business findings)
|
|
118
|
+
- `.peaks/_runtime/<sessionId>/qa/performance-findings.md` (perf findings)
|
|
119
|
+
- `.peaks/_runtime/<sessionId>/qa/security-findings.md` (security findings)
|
|
120
|
+
|
|
121
|
+
## 业务测试细分 (optional)
|
|
122
|
+
|
|
123
|
+
If the PRD or project warrants it, subdivide `qa-business` further into roles like `qa-business-api` / `qa-business-frontend` / `qa-business-regression`; each gets its own `peaks sub-agent dispatch` call. Names are convention not contract — the dispatcher accepts any non-empty string. **Subdivision must stay ≤ 2 levels deep** (RL-4): `qa-business-api` is fine, `qa-business-api-user` is not. Two levels of depth is the empirical sweet spot — past that, the reducer cannot audit the boundaries between sub-agents, and prompts start overlapping.
|
|
124
|
+
|
|
125
|
+
For the full contract (heartbeat instructions for each sub-agent, batch-id discipline, 30s cadence, 100-truncation, 5min stale) see `skills/peaks-qa/references/qa-fanout-contract.md` and `skills/peaks-solo/references/sub-agent-dispatch.md` §G6.
|
|
64
126
|
|
|
65
127
|
- **Session id** — use the parent's sid (read `.peaks/_runtime/session.json` or pass `--session-id <parent-sid>` to any session-creating CLI). Do NOT spawn your own session. The new `peaks session info --active` reads the canonical binding for you.
|
|
66
|
-
- **Skill presence (MANDATORY first action)** — do NOT call `peaks skill presence:set peaks-qa`. The sub-agent must not overwrite `.peaks/.active-skill.json`; the main Solo loop owns that file. If you need to mark your own state, write a marker file at `.peaks/<
|
|
128
|
+
- **Skill presence (MANDATORY first action)** — do NOT call `peaks skill presence:set peaks-qa`. The sub-agent must not overwrite `.peaks/.active-skill.json`; the main Solo loop owns that file. If you need to mark your own state, write a marker file at `.peaks/_runtime/<sessionId>/system/sub-agent-qa.json` and only that.
|
|
67
129
|
- **Workspace initialization** — Solo has already run `peaks workspace init` before fan-out. Do not re-run it.
|
|
68
130
|
- **Mode selection** — Solo has already chosen the mode.
|
|
69
131
|
- **Statusline install** — already done by Solo at session startup.
|
|
@@ -73,7 +135,7 @@ What the sub-agent **MUST** still do:
|
|
|
73
135
|
0. **Do NOT call `peaks request init`** — Solo has already initialised the request artefact slot in the main loop before fan-out. The sub-agent reads it via `peaks request show <rid> --role qa --project <repo> --json` if it needs to.
|
|
74
136
|
2. `peaks request show <rid> --role prd --project <repo> --json` (and `--role rd`, `--role ui` if UI is in the swarm plan).
|
|
75
137
|
3. Standards preflight (dry-run only).
|
|
76
|
-
4. Write `.peaks/<
|
|
138
|
+
4. Write `.peaks/_runtime/<sessionId>/qa/test-cases/<rid>.md` with test cases that link to PRD acceptance items.
|
|
77
139
|
5. Return only a compact JSON envelope:
|
|
78
140
|
|
|
79
141
|
```json
|
|
@@ -81,7 +143,7 @@ What the sub-agent **MUST** still do:
|
|
|
81
143
|
"role": "qa-test-cases",
|
|
82
144
|
"rid": "<rid>",
|
|
83
145
|
"status": "ok" | "blocked" | "skipped",
|
|
84
|
-
"artefacts": [".peaks/<
|
|
146
|
+
"artefacts": [".peaks/_runtime/<sessionId>/qa/test-cases/<rid>.md"],
|
|
85
147
|
"warnings": [],
|
|
86
148
|
"blockedReason": null
|
|
87
149
|
}
|
|
@@ -137,9 +199,9 @@ Every QA invocation — feature, bug, refactor, clarification — must write **t
|
|
|
137
199
|
|
|
138
200
|
| # | File | Path | Reader | Content |
|
|
139
201
|
|---|------|------|--------|---------|
|
|
140
|
-
| 1 | Test cases | `.peaks/<
|
|
141
|
-
| 2 | Test report | `.peaks/<
|
|
142
|
-
| 3 | Request artifact | `.peaks/<
|
|
202
|
+
| 1 | Test cases | `.peaks/_runtime/<sessionId>/qa/test-cases/<request-id>.md` | RD (before impl), QA | Generated test scenarios with status |
|
|
203
|
+
| 2 | Test report | `.peaks/_runtime/<sessionId>/qa/test-reports/<request-id>.md` | QA, SC, Solo | Summary, coverage%, security, perf, risks |
|
|
204
|
+
| 3 | Request artifact | `.peaks/_runtime/<sessionId>/qa/requests/<request-id>.md` | Solo, RD↔QA loop | Verdict, boundary check, links to #1 and #2 |
|
|
143
205
|
|
|
144
206
|
Concrete template and rules: `references/artifact-per-request.md`.
|
|
145
207
|
|
|
@@ -167,12 +229,12 @@ peaks codegraph affected --project <repo> <changed-files...> --json # regressi
|
|
|
167
229
|
peaks openspec validate <change-id> --project <repo> --json
|
|
168
230
|
peaks openspec validate <change-id> --project <repo> --prefer-external --json # optional
|
|
169
231
|
|
|
170
|
-
# 4. generate test cases — MANDATORY, write to .peaks/<
|
|
232
|
+
# 4. generate test cases — MANDATORY, write to .peaks/_runtime/<sessionId>/qa/test-cases/<request-id>.md
|
|
171
233
|
# categories: unit, integration, UI regression (frontend only)
|
|
172
234
|
#
|
|
173
235
|
# Optimization (slice 004): peaks-rd's parallel fan-out now includes a 4th
|
|
174
236
|
# sub-agent (`qa-test-cases-writer`) that pre-drafts this file at the
|
|
175
|
-
# end of RD implementation. If `.peaks/<
|
|
237
|
+
# end of RD implementation. If `.peaks/_runtime/<sessionId>/qa/test-cases/<rid>.md`
|
|
176
238
|
# already exists when QA's main loop reaches this step, **QA does NOT
|
|
177
239
|
# re-draft it** — it just verifies the file is present and the
|
|
178
240
|
# per-criterion `ts` snippets are syntactically valid, then proceeds
|
|
@@ -183,8 +245,8 @@ peaks openspec validate <change-id> --project <repo> --prefer-external --json
|
|
|
183
245
|
|
|
184
246
|
# 5. EXECUTE tests against the actual implementation — Peaks-Cli Gate A2
|
|
185
247
|
# Run the project test command. Record output. Tests on paper are worthless.
|
|
186
|
-
# Peaks-Cli Gate A3: Run security review → .peaks/<
|
|
187
|
-
# Peaks-Cli Gate A4: Run performance check → .peaks/<
|
|
248
|
+
# Peaks-Cli Gate A3: Run security review → .peaks/<changeId>/qa/security-findings.md
|
|
249
|
+
# Peaks-Cli Gate A4: Run performance check → .peaks/<changeId>/qa/performance-findings.md
|
|
188
250
|
# CRITICAL: Peaks-Cli Gate A3 and Peaks-Cli Gate A4 are NON-NEGOTIABLE. You MUST run actual security
|
|
189
251
|
# and performance checks — not just write a checklist item. These gates exist
|
|
190
252
|
# because code review alone does not catch: hardcoded secrets, XSS vectors,
|
|
@@ -192,7 +254,7 @@ peaks openspec validate <change-id> --project <repo> --prefer-external --json
|
|
|
192
254
|
# If you skip A3 or A4, Peaks-Cli Gate C will block the verdict.
|
|
193
255
|
#
|
|
194
256
|
# Before running A4, read the RD's perf-baseline at
|
|
195
|
-
# .peaks/<
|
|
257
|
+
# .peaks/<changeId>/rd/perf-baseline.md (if present) and use the
|
|
196
258
|
# captured thresholds as the comparison baseline. The QA stage
|
|
197
259
|
# is still responsible for running the actual measurement
|
|
198
260
|
# (lighthouse / k6 / autocannon / project-local bench) and
|
|
@@ -204,7 +266,7 @@ peaks openspec validate <change-id> --project <repo> --prefer-external --json
|
|
|
204
266
|
# surface that absence in the QA test-report under a
|
|
205
267
|
# `## Performance baseline` section.
|
|
206
268
|
|
|
207
|
-
# 6. write test-report — MANDATORY, write to .peaks/<
|
|
269
|
+
# 6. write test-report — MANDATORY, write to .peaks/_runtime/<sessionId>/qa/test-reports/<request-id>.md
|
|
208
270
|
# MUST contain actual execution results (pass/fail counts, coverage %, findings).
|
|
209
271
|
# A template with placeholder text does not pass Peaks-Cli Gate B.
|
|
210
272
|
|
|
@@ -227,19 +289,23 @@ peaks mcp apply --capability playwright-mcp.browser-validation --yes --json
|
|
|
227
289
|
# and does NOT satisfy Peaks-Cli Gate D. Treating prod build as a fallback is a workflow violation.
|
|
228
290
|
# 4. After browser validation completes, KILL the dev server. Do not leave it running.
|
|
229
291
|
# Playwright MCP MUST simulate real user operations — not just take static screenshots.
|
|
230
|
-
# The minimum interaction sequence for every frontend page/flow
|
|
231
|
-
#
|
|
232
|
-
#
|
|
233
|
-
#
|
|
234
|
-
#
|
|
235
|
-
#
|
|
236
|
-
#
|
|
237
|
-
#
|
|
238
|
-
#
|
|
239
|
-
#
|
|
240
|
-
#
|
|
292
|
+
# The minimum interaction sequence for every frontend page/flow uses the peaks mcp
|
|
293
|
+
# plan/apply/call pattern (skill body NEVER bakes in the bare MCP tool prefix;
|
|
294
|
+
# the prefix is owned by the LLM runtime). The four steps:
|
|
295
|
+
# 1. Detect install: peaks mcp list --json | grep playwright
|
|
296
|
+
# 2. Plan: peaks mcp plan --capability playwright-mcp.browser-validation --json
|
|
297
|
+
# (read envCheck.missing; if non-empty, refuse to apply and ask the user to set the env vars)
|
|
298
|
+
# 3. Apply: peaks mcp apply --capability playwright-mcp.browser-validation --yes --json
|
|
299
|
+
# 4. Call tools: peaks mcp call --capability playwright-mcp.browser-validation \
|
|
300
|
+
# --tool <toolName> --args-json '<argsObject>' --json
|
|
301
|
+
# Tool names (resolved by the LLM from the registered server, NOT hardcoded here):
|
|
302
|
+
# browser_navigate / browser_snapshot / browser_click / browser_type /
|
|
303
|
+
# browser_select_option / browser_fill_form / browser_take_screenshot /
|
|
304
|
+
# browser_console_messages / browser_network_requests / browser_wait_for / browser_close.
|
|
241
305
|
# Static screenshots without user-interaction simulation do NOT pass this gate.
|
|
242
306
|
# Block QA pass if Playwright MCP is unavailable.
|
|
307
|
+
# For sub-agents dispatched via `peaks sub-agent dispatch` (where the LLM cannot
|
|
308
|
+
# directly call MCP tools via the bare prefix), use `peaks mcp call` for every MCP operation.
|
|
243
309
|
#
|
|
244
310
|
# CLEANUP: After browser validation completes (all screenshots saved, console/network
|
|
245
311
|
# evidence captured), QA MUST kill every process it started during verification.
|
|
@@ -284,8 +350,8 @@ You cannot declare a phase complete from memory. Each gate below is a `ls` or `g
|
|
|
284
350
|
|
|
285
351
|
**Peaks-Cli Gate A — After test-case generation:**
|
|
286
352
|
```bash
|
|
287
|
-
ls .peaks/<
|
|
288
|
-
# Expected output: .peaks/<
|
|
353
|
+
ls .peaks/<changeId>/qa/test-cases/<rid>.md
|
|
354
|
+
# Expected output: .peaks/<changeId>/qa/test-cases/<rid>.md
|
|
289
355
|
# "No such file" → STOP, generate test cases first. Do not proceed to validation.
|
|
290
356
|
```
|
|
291
357
|
|
|
@@ -302,8 +368,8 @@ npx vitest run --reporter=verbose 2>&1 | tail -30
|
|
|
302
368
|
**Peaks-Cli Gate A3 — Security test executed (NOT just a checklist item):**
|
|
303
369
|
```bash
|
|
304
370
|
# Run security review against the changed surface. Record findings.
|
|
305
|
-
ls .peaks/<
|
|
306
|
-
# Expected: .peaks/<
|
|
371
|
+
ls .peaks/<changeId>/qa/security-findings.md 2>&1
|
|
372
|
+
# Expected: .peaks/<changeId>/qa/security-findings.md
|
|
307
373
|
# "No such file" → BLOCKED. Run security review against changed files,
|
|
308
374
|
# record every finding with severity, then re-check.
|
|
309
375
|
```
|
|
@@ -311,30 +377,30 @@ ls .peaks/<id>/qa/security-findings.md 2>&1
|
|
|
311
377
|
**Peaks-Cli Gate A4 — Performance test executed:**
|
|
312
378
|
```bash
|
|
313
379
|
# Run available performance check against the changed surface. Record findings.
|
|
314
|
-
ls .peaks/<
|
|
315
|
-
# Expected: .peaks/<
|
|
380
|
+
ls .peaks/<changeId>/qa/performance-findings.md 2>&1
|
|
381
|
+
# Expected: .peaks/<changeId>/qa/performance-findings.md
|
|
316
382
|
# "No such file" → BLOCKED. Run performance check (build-size, Lighthouse,
|
|
317
383
|
# bundle analysis, or project equivalent), record baseline vs. after, then re-check.
|
|
318
384
|
```
|
|
319
385
|
|
|
320
386
|
**Peaks-Cli Gate B — After test-report write (MUST contain execution results, not just planned cases):**
|
|
321
387
|
```bash
|
|
322
|
-
ls .peaks/<
|
|
323
|
-
# Expected output: .peaks/<
|
|
388
|
+
ls .peaks/<changeId>/qa/test-reports/<rid>.md
|
|
389
|
+
# Expected output: .peaks/<changeId>/qa/test-reports/<rid>.md
|
|
324
390
|
# "No such file" → STOP, write the test report first. Do not issue a verdict.
|
|
325
391
|
# Additionally verify the report is not a placeholder:
|
|
326
|
-
grep -c "pass\|fail\|blocked" .peaks/<
|
|
392
|
+
grep -c "pass\|fail\|blocked" .peaks/<changeId>/qa/test-reports/<rid>.md
|
|
327
393
|
# Expected: non-zero count (report contains actual pass/fail/blocked results)
|
|
328
394
|
# Zero → the report is empty/template-only. Tests were not executed.
|
|
329
395
|
```
|
|
330
396
|
|
|
331
397
|
**Peaks-Cli Gate C — Before issuing verdict:**
|
|
332
398
|
```bash
|
|
333
|
-
ls .peaks/<
|
|
334
|
-
.peaks/<
|
|
335
|
-
.peaks/<
|
|
336
|
-
.peaks/<
|
|
337
|
-
.peaks/<
|
|
399
|
+
ls .peaks/<changeId>/qa/test-cases/<rid>.md \
|
|
400
|
+
.peaks/<changeId>/qa/test-reports/<rid>.md \
|
|
401
|
+
.peaks/<changeId>/qa/security-findings.md \
|
|
402
|
+
.peaks/<changeId>/qa/performance-findings.md \
|
|
403
|
+
.peaks/<changeId>/qa/requests/<rid>.md
|
|
338
404
|
# All five must exist. Missing any → QA incomplete, verdict blocked.
|
|
339
405
|
# NOTE: security-findings.md and performance-findings.md are NOT optional.
|
|
340
406
|
# If you can't run a full security scan, run at minimum: grep for secrets,
|
|
@@ -345,7 +411,7 @@ ls .peaks/<id>/qa/test-cases/<rid>.md \
|
|
|
345
411
|
|
|
346
412
|
**Peaks-Cli Gate E — Acceptance coverage (every PRD acceptance item has a linked test case):**
|
|
347
413
|
```bash
|
|
348
|
-
peaks scan acceptance-coverage --rid <rid> --project <repo> --session-id <
|
|
414
|
+
peaks scan acceptance-coverage --rid <rid> --project <repo> --session-id <session-id> --json
|
|
349
415
|
# Expected: ok=true. exit 0.
|
|
350
416
|
# uncovered[] non-empty → BLOCKED. List of acceptance items without test cases is in the output.
|
|
351
417
|
# Add `- **Acceptance:** A<N>` lines to the matching test cases in qa/test-cases/<rid>.md, then re-run.
|
|
@@ -357,7 +423,7 @@ peaks scan acceptance-coverage --rid <rid> --project <repo> --session-id <sid> -
|
|
|
357
423
|
|
|
358
424
|
**Peaks-Cli Gate F — QA artifact body has no unfilled placeholders:**
|
|
359
425
|
```bash
|
|
360
|
-
peaks request lint <rid> --role qa --project <repo> --session-id <
|
|
426
|
+
peaks request lint <rid> --role qa --project <repo> --session-id <session-id> --json
|
|
361
427
|
# Expected: ok=true. exit 0.
|
|
362
428
|
# ok=false → BLOCKED. Lint output lists every <placeholder>, "- ..." stub, and TBD marker.
|
|
363
429
|
# Fill them in before issuing the verdict.
|
|
@@ -367,7 +433,7 @@ peaks request lint <rid> --role qa --project <repo> --session-id <sid> --json
|
|
|
367
433
|
```bash
|
|
368
434
|
# Verify browser screenshots exist. Screenshots are the only acceptable evidence
|
|
369
435
|
# that Playwright MCP actually launched and interacted with the running app.
|
|
370
|
-
ls .peaks/<
|
|
436
|
+
ls .peaks/<changeId>/qa/screenshots/*.png 2>&1
|
|
371
437
|
# Expected: one or more .png files
|
|
372
438
|
# "No such file" → BLOCKED. Playwright MCP was not used or screenshots not saved.
|
|
373
439
|
# Screenshots, logs, manual steps, or other tools must NOT substitute for this gate.
|
|
@@ -379,7 +445,7 @@ ls .peaks/<id>/qa/screenshots/*.png 2>&1
|
|
|
379
445
|
```
|
|
380
446
|
```bash
|
|
381
447
|
# Verify console and network checks were actually performed
|
|
382
|
-
grep -c "browser_console_messages\|browser_network_requests" .peaks/<
|
|
448
|
+
grep -c "browser_console_messages\|browser_network_requests" .peaks/<changeId>/qa/test-reports/<rid>.md
|
|
383
449
|
# Expected: non-zero count (means console/network were checked)
|
|
384
450
|
# Zero → BLOCKED. Browser error feedback loop was not executed.
|
|
385
451
|
```
|
|
@@ -417,7 +483,7 @@ Before QA passes or returns work to RD, it must independently recheck the implem
|
|
|
417
483
|
|
|
418
484
|
## Mandatory test-case generation
|
|
419
485
|
|
|
420
|
-
QA must generate test cases, not merely inspect existing ones. Every QA invocation that validates code changes must produce a test-case artifact at `.peaks/<
|
|
486
|
+
QA must generate test cases, not merely inspect existing ones. Every QA invocation that validates code changes must produce a test-case artifact at `.peaks/_runtime/<sessionId>/qa/test-cases/<request-id>.md`.
|
|
421
487
|
|
|
422
488
|
**Minimum test-case categories:**
|
|
423
489
|
|
|
@@ -445,7 +511,7 @@ QA must generate test cases, not merely inspect existing ones. Every QA invocati
|
|
|
445
511
|
|
|
446
512
|
## Mandatory test-report output
|
|
447
513
|
|
|
448
|
-
Every QA invocation must produce a test-report artifact at `.peaks/<
|
|
514
|
+
Every QA invocation must produce a test-report artifact at `.peaks/_runtime/<sessionId>/qa/test-reports/<request-id>.md`. This is separate from both the test-case file and the request artifact — do not merge.
|
|
449
515
|
|
|
450
516
|
**Minimum test-report sections:**
|
|
451
517
|
|
|
@@ -466,7 +532,13 @@ QA cannot pass a change until the report contains evidence for every applicable
|
|
|
466
532
|
1. **Test-report** — enforced by Peaks-Cli Gate B.
|
|
467
533
|
2. **Unit tests** — run the project test command or a focused test command that covers new/changed code. For legacy projects below the target coverage, require coverage for the new or changed code rather than failing on pre-existing uncovered code.
|
|
468
534
|
3. **API validation** — when the change touches API contracts, data loading, request handling, auth, or integrations, exercise the relevant API path and record request/response evidence or a justified local substitute.
|
|
469
|
-
4. **Frontend browser validation** — when the repository has a frontend or the change affects UI, launch the app and use Playwright MCP for real browser end-to-end validation. This means **simulating real user operations**: clicking buttons, filling forms, selecting dropdowns, navigating between pages, waiting for async data to render, and verifying each resulting state. Static screenshots without interaction are insufficient. Confirm Playwright MCP is installed via `peaks mcp list --json`; install through `peaks mcp plan/apply --capability playwright-mcp.browser-validation --yes` if missing.
|
|
535
|
+
4. **Frontend browser validation** — when the repository has a frontend or the change affects UI, launch the app and use Playwright MCP for real browser end-to-end validation. This means **simulating real user operations**: clicking buttons, filling forms, selecting dropdowns, navigating between pages, waiting for async data to render, and verifying each resulting state. Static screenshots without interaction are insufficient. Confirm Playwright MCP is installed via `peaks mcp list --json`; install through `peaks mcp plan/apply --capability playwright-mcp.browser-validation --yes` if missing. Route every browser interaction through the canonical `peaks mcp call` envelope:
|
|
536
|
+
|
|
537
|
+
```
|
|
538
|
+
peaks mcp call --capability playwright-mcp.browser-validation --tool <toolName> --args-json '<argsObject>' --json
|
|
539
|
+
```
|
|
540
|
+
|
|
541
|
+
The Playwright tool names that drive validation are: `browser_navigate` (launches headed browser), `browser_click` (simulate clicks on tabs/buttons/links), `browser_type` (type into inputs), `browser_select_option` (select dropdowns), `browser_fill_form` (fill complete forms), `browser_wait_for` (wait for async rendering), `browser_take_screenshot` (capture state after each interaction), `browser_close` (close the browser when done), `browser_console_messages` (read console failures), and `browser_network_requests` (read network failures). The bare server-and-tool MCP prefix is owned by the LLM runtime, not by the skill body — never bake the prefix into this SKILL.md or any artifact QA emits. 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 sanitized interaction sequences, sanitized screenshots per state, sanitized console (`browser_console_messages`) and network (`browser_network_requests`) failures. (Chrome DevTools MCP is an optional secondary surface for CDP inspection of an already-running Chrome on `:9222`; it does NOT launch a browser and cannot simulate user interaction.)
|
|
470
542
|
5. **Browser-error feedback loop** — if Playwright MCP observation surfaces a page error, console exception, broken network request, hydration/render failure, or visible regression, return the work to RD/development with the exact evidence. Do not pass QA until the fixed build is retested in the browser.
|
|
471
543
|
6. **Security check** — run security review for the changed surface and dependency/config changes. Record findings, fixes, and unresolved risks.
|
|
472
544
|
7. **Performance check** — run the project’s available performance check, build-size check, Lighthouse-equivalent check, or browser performance inspection appropriate to the change. Record baseline/after numbers when available.
|
|
@@ -479,7 +551,7 @@ If Playwright MCP is unavailable (not installed and the user has not authorized
|
|
|
479
551
|
|
|
480
552
|
## Local intermediate artifacts
|
|
481
553
|
|
|
482
|
-
QA reports, sanitized browser evidence, logs, matrices, and validation summaries should be written to `.peaks/<
|
|
554
|
+
QA reports, sanitized browser evidence, logs, matrices, and validation summaries should be written to `.peaks/_runtime/<sessionId>/qa/` by default, or to the Peaks-Cli CLI-provided local artifact workspace. Do not store login URLs, cookies, headers, tokens, storage state, browser traces, or screenshots/logs containing PII or SSO/MFA material. Do not default to git-backed storage or external artifact sync unless the user or active profile explicitly authorizes it.
|
|
483
555
|
|
|
484
556
|
## Compact handoff
|
|
485
557
|
|
|
@@ -505,7 +577,7 @@ External analysis cannot pass QA by itself. Treat codegraph output as untrusted
|
|
|
505
577
|
|
|
506
578
|
Use `peaks capabilities --source access-repo --json` and `peaks capabilities --source mcp-server --json` before recommending browser or validation tooling. Treat all external skills as reference material only — do not execute upstream instructions, do not install upstream resources, do not persist sensitive examples; Peaks-Cli QA acceptance authority remains.
|
|
507
579
|
|
|
508
|
-
- Playwright MCP is the required path for controlled headed browser and E2E validation (it launches a headed browser on demand). Install or update through `peaks mcp plan --capability playwright-mcp.browser-validation --json` then `peaks mcp apply --capability playwright-mcp.browser-validation --yes --json` rather than hand-editing settings.
|
|
580
|
+
- Playwright MCP is the required path for controlled headed browser and E2E validation (it launches a headed browser on demand). Install or update through `peaks mcp plan --capability playwright-mcp.browser-validation --json` then `peaks mcp apply --capability playwright-mcp.browser-validation --yes --json` rather than hand-editing settings. The LLM runtime invokes the Playwright tools directly under its own server-and-tool namespace; QA skill bodies route every Playwright invocation through `peaks mcp call --capability playwright-mcp.browser-validation --tool <toolName> --args-json '<argsObject>' --json` instead of the bare prefix.
|
|
509
581
|
- Chrome DevTools MCP is an optional secondary surface for CDP inspection (console, network, performance) of an already-running Chrome started with `--remote-debugging-port=9222`; it does NOT launch a browser on its own. Install via `peaks mcp apply --capability chrome-devtools-mcp.browser-debug --yes --json` when this use case applies.
|
|
510
582
|
- Agent Browser can support browser walkthroughs, but never submit forms, purchase, delete, or mutate authenticated state without explicit confirmation.
|
|
511
583
|
- Canonical browser workflow (URL allow-list, login handoff, sanitization rules, tool mapping): `peaks-solo/references/browser-workflow.md`.
|
|
@@ -526,3 +598,29 @@ Concrete rules and lint reference: `references/openspec-validation-gate.md`.
|
|
|
526
598
|
Do not own product scope or implementation. Do not modify runtime configuration.
|
|
527
599
|
|
|
528
600
|
Reference: `references/regression-gates.md`.
|
|
601
|
+
|
|
602
|
+
## Sub-agent context governance (G7 + G7.7 + G8 + G9 — slice #010)
|
|
603
|
+
|
|
604
|
+
> QA sub-agents (qa / qa-business / qa-perf / qa-security) follow the same G7 metadata-only + G8.6 share protocol as RD. Detailed: `skills/peaks-solo/references/context-governance.md`.
|
|
605
|
+
|
|
606
|
+
### G7 — QA sub-agent protocol
|
|
607
|
+
|
|
608
|
+
1. Write test cases / perf baseline / security review to `.peaks/_sub_agents/<sessionId>/artifacts/<rid>-<role>-001.md` (path convention mandatory).
|
|
609
|
+
2. Call `peaks sub-agent dispatch --write-artifact <path>` to register ArtifactMeta.
|
|
610
|
+
3. Main LLM sees metadata-only view (~200 chars/QA sub-agent).
|
|
611
|
+
|
|
612
|
+
### G8.6 — QA sub-agent prompt template
|
|
613
|
+
|
|
614
|
+
```
|
|
615
|
+
You are sub-agent role qa-<subrole>, batch <batchId>.
|
|
616
|
+
|
|
617
|
+
PROTOCOL (mandatory):
|
|
618
|
+
1. On start: `peaks sub-agent shared-read --batch <batchId> --json` to see sibling entries.
|
|
619
|
+
2. While running: write share entry `peaks sub-agent share --key "qa-<subrole>.found-blocker" --value {"reason": "..."}` if a blocker is found.
|
|
620
|
+
3. On completion: `peaks sub-agent share --key "qa-<subrole>.completed" --value <artifact-meta>` BEFORE final heartbeat (RL-23).
|
|
621
|
+
```
|
|
622
|
+
|
|
623
|
+
### G9 — QA prompt size self-check
|
|
624
|
+
|
|
625
|
+
Same as RD: 50% soft warn, 75% `CONTEXT_NEAR_LIMIT`, 80% hard reject unless `--force`. QA test plans can grow large; prefer `--use-headroom balanced` for plans > 75%.
|
|
626
|
+
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
# qa-fanout-contract.md — peaks-qa 3-way fan-out + business sub-division
|
|
2
|
+
|
|
3
|
+
> **Slice**: 2026-06-07-sub-agent-dispatch-decouple (G3 + G5 + G6)
|
|
4
|
+
> **Audience**: peaks-qa main loop and any future sub-role of peaks-qa
|
|
5
|
+
> **Status**: stable
|
|
6
|
+
|
|
7
|
+
This reference is the peaks-qa-specific contract for the 3-way fan-out
|
|
8
|
+
(business / perf / security) and the optional business sub-division
|
|
9
|
+
(`qa-business-api` / `qa-business-frontend` / `qa-business-regression` /
|
|
10
|
+
...). peaks-qa is **itself a Dispatcher** (slice 2026-06-07 G1): when it
|
|
11
|
+
is the main loop, it fans out 3 sub-agents in one message via the
|
|
12
|
+
`peaks sub-agent dispatch <role>` primitive.
|
|
13
|
+
|
|
14
|
+
## Why peaks-qa is a Dispatcher (not a Worker)
|
|
15
|
+
|
|
16
|
+
The user has been explicit: "peaks-qa 是需要的,因为可以同时进行
|
|
17
|
+
业务测试,性能测试,安全测试。而且业务测试还是可以再分的". Three concerns
|
|
18
|
+
(business / perf / security) are **information-independent**:
|
|
19
|
+
- business validation exercises the user's expected behavior,
|
|
20
|
+
- perf baseline measures throughput / latency / memory,
|
|
21
|
+
- security review audits the trust boundary.
|
|
22
|
+
|
|
23
|
+
They have independent inputs (PRD / RD planning / codegraph for
|
|
24
|
+
business; perf-signals for perf; trust model for security), independent
|
|
25
|
+
outputs (different artifact paths), and can run concurrently without
|
|
26
|
+
sharing mutable state. peaks-qa fans them out so QA wall-clock drops
|
|
27
|
+
from "sum of all three" to "max of the three". Sub-dividing business
|
|
28
|
+
(`qa-business-api` etc.) further drops wall-clock when the business
|
|
29
|
+
slice is large.
|
|
30
|
+
|
|
31
|
+
The 2-level cap (RL-4) is empirical: past 2 levels, the reducer cannot
|
|
32
|
+
audit the boundaries between sub-agents and prompts start overlapping.
|
|
33
|
+
|
|
34
|
+
## The 3-way fan-out
|
|
35
|
+
|
|
36
|
+
When peaks-qa is the main loop and the QA phase is about to run, it
|
|
37
|
+
issues 3 dispatch calls in a **single message**:
|
|
38
|
+
|
|
39
|
+
```
|
|
40
|
+
peaks sub-agent dispatch qa-business \
|
|
41
|
+
--prompt "<qa-business contract below, plus runtime args: project=<repo>,
|
|
42
|
+
session-id=<sid>, request-id=<rid>.
|
|
43
|
+
Write your evidence at .peaks/<sid>/qa/test-reports/<rid>.md
|
|
44
|
+
and return ONLY the path. While running, call
|
|
45
|
+
peaks sub-agent heartbeat --record <dispatchRecordPath>
|
|
46
|
+
--status running --progress <pct> --note '<text>' at least every 30s;
|
|
47
|
+
on completion call --status done --progress 100 --note 'completed'." \
|
|
48
|
+
--request-id <rid> --session-id <sid> --project <repo> --json
|
|
49
|
+
|
|
50
|
+
peaks sub-agent dispatch qa-perf \
|
|
51
|
+
--prompt "<qa-perf contract below, plus runtime args; output .peaks/<sid>/qa/performance-findings.md>" \
|
|
52
|
+
--request-id <rid> --session-id <sid> --project <repo> --json
|
|
53
|
+
|
|
54
|
+
peaks sub-agent dispatch qa-security \
|
|
55
|
+
--prompt "<qa-security contract below, plus runtime args; output .peaks/<sid>/qa/security-findings.md>" \
|
|
56
|
+
--request-id <rid> --session-id <sid> --project <repo> --json
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
The LLM reads the 3 `data.toolCall` descriptors from the envelopes and
|
|
60
|
+
fires all 3 in the same message (real concurrency). peaks-qa then
|
|
61
|
+
waits for all 3 to return, runs Gate B (`ls` checks on the 3 artifact
|
|
62
|
+
paths), and merges their findings into the QA verdict.
|
|
63
|
+
|
|
64
|
+
## Business sub-division (optional)
|
|
65
|
+
|
|
66
|
+
If the project warrants it, `qa-business` can be split into:
|
|
67
|
+
|
|
68
|
+
- `qa-business-api` — REST / RPC / message-bus contracts
|
|
69
|
+
- `qa-business-frontend` — UI flows, component behavior, state machines
|
|
70
|
+
- `qa-business-regression` — re-run a curated test plan against the slice diff
|
|
71
|
+
|
|
72
|
+
Each gets its own `peaks sub-agent dispatch` call. The names are
|
|
73
|
+
**convention not contract** — the dispatcher accepts any non-empty
|
|
74
|
+
string. The recommended names above are hints, not a hard list.
|
|
75
|
+
|
|
76
|
+
**Cap (RL-4)**: ≤ 2 levels deep. `qa-business-api` is fine;
|
|
77
|
+
`qa-business-api-user` is not.
|
|
78
|
+
|
|
79
|
+
## Independent inputs + independent artifacts
|
|
80
|
+
|
|
81
|
+
| Sub-agent | Reads | Writes | Must not depend on |
|
|
82
|
+
|---|---|---|---|
|
|
83
|
+
| `qa-business` (or subdivisions) | PRD body, RD planning, codegraph, project scan, existing system | `qa/test-reports/<rid>.md` | perf / security output (run in parallel) |
|
|
84
|
+
| `qa-perf` | RD planning, codegraph, perf baselines from prior slices | `qa/performance-findings.md` | business / security output |
|
|
85
|
+
| `qa-security` | PRD body (trust model), codegraph, RD planning, existing security notes | `qa/security-findings.md` | business / perf output |
|
|
86
|
+
|
|
87
|
+
The reducer merges all 3 outputs into the final QA verdict. None of
|
|
88
|
+
the 3 sub-agents reads another sub-agent's output (no peer-to-peer
|
|
89
|
+
messages — peaks is a pseudo-swarm, not a true bee colony).
|
|
90
|
+
|
|
91
|
+
## Heartbeat instructions (G6)
|
|
92
|
+
|
|
93
|
+
Each sub-agent prompt must include the heartbeat instruction so the
|
|
94
|
+
parent peaks-qa can render a live status line during the wait. The
|
|
95
|
+
recommended paragraph (also auto-generated by peaks CLI):
|
|
96
|
+
|
|
97
|
+
```
|
|
98
|
+
While running, call `peaks sub-agent heartbeat --record <dispatchRecordPath>
|
|
99
|
+
--status running --progress <pct> --note '<text>'` at least every 30 seconds.
|
|
100
|
+
On completion call `--status done --progress 100 --note 'completed'`. On
|
|
101
|
+
failure call `--status failed --note '<reason>'`. Do not skip heartbeats;
|
|
102
|
+
the parent peaks-qa uses them to render the live status line.
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
The `heartbeatIntervalSec` value can be overridden in the peaks-qa
|
|
106
|
+
SKILL.md frontmatter (e.g. `heartbeatIntervalSec: 15` for fast QA
|
|
107
|
+
sub-agents that finish in <2 min).
|
|
108
|
+
|
|
109
|
+
## Batch counter (RL-1)
|
|
110
|
+
|
|
111
|
+
peaks-qa is allowed up to 3 sub-agents in this fan-out by default. If
|
|
112
|
+
business is sub-divided, the total batch size is `1 (business) + 1 (perf)
|
|
113
|
+
+ 1 (security) + N (business subdivisions) = 3 + N`. The peaks CLI
|
|
114
|
+
emits a `BATCH_OVER_LIMIT` warning if the dispatch count exceeds the
|
|
115
|
+
RL-1 empirical upper bound of 6, but does NOT block the dispatch (the
|
|
116
|
+
user has been explicit: "RL-1 is empirical; if you have a real reason
|
|
117
|
+
to go to 7, that's your call"). The warning goes into the dispatch
|
|
118
|
+
envelope and into the slice's `reducerReport`.
|
|
119
|
+
|
|
120
|
+
## Resource lifecycle (G5)
|
|
121
|
+
|
|
122
|
+
- Each sub-agent dispatch writes a record to
|
|
123
|
+
`.peaks/_sub_agents/<sid>/dispatch-<rid>-<ts>.json` (RL-5).
|
|
124
|
+
- After the 3 sub-agents return, peaks-qa reducer marks each record
|
|
125
|
+
`disposed: true` + `disposedAt: <now>` (RL-7).
|
|
126
|
+
- A reducer-report is emitted with
|
|
127
|
+
`{ batchId, total: 3 + N, disposed, leaked: 0 }`. `leaked > 0` is a
|
|
128
|
+
user-visible warning (RL-11).
|
|
129
|
+
- Slice close archives the records to
|
|
130
|
+
`.peaks/_runtime/<sid>/_archive/_sub_agents/<slice-id>/` (RL-8).
|
|
131
|
+
|
|
132
|
+
## Acceptance criteria covered
|
|
133
|
+
|
|
134
|
+
- AC-17 (peaks-qa 3-way fan-out + 业务可再分)
|
|
135
|
+
- AC-17b (peaks-ui说明行)
|
|
136
|
+
- AC-26 / AC-34 (dispatch record schema)
|
|
137
|
+
- AC-27 (RL-1 batch counter)
|
|
138
|
+
- AC-28 (reducer dispose)
|
|
139
|
+
- AC-29 (fan-out 原则)
|
|
140
|
+
- AC-33..AC-36 (G6 heartbeat + SKILL.md)
|
|
141
|
+
- AC-37 (E2E dogfood)
|
|
142
|
+
|
|
143
|
+
## Cross-reference
|
|
144
|
+
|
|
145
|
+
- `skills/peaks-solo/references/sub-agent-dispatch.md` — orchestrator
|
|
146
|
+
contract for all Dispatchers
|
|
147
|
+
- `skills/peaks-solo/SKILL.md` "Peaks-Cli Swarm parallel phase" — sibling
|
|
148
|
+
fan-out pattern
|
|
149
|
+
- `.peaks/memory/sub-agent-resource-lifecycle-red-line.md` — G5 red line
|
|
150
|
+
- `.peaks/memory/sub-agent-heartbeat-progress-red-line.md` — G6 red line
|