peaks-cli 1.3.6 → 1.3.8
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/dist/src/cli/commands/core-artifact-commands.js +119 -14
- package/dist/src/cli/commands/request-commands.js +31 -1
- package/dist/src/cli/commands/slice-commands.js +9 -5
- package/dist/src/cli/commands/workspace-commands.js +46 -2
- package/dist/src/services/artifacts/request-artifact-service.d.ts +16 -0
- package/dist/src/services/artifacts/request-artifact-service.js +18 -2
- package/dist/src/services/session/caller-binding-service.d.ts +70 -0
- package/dist/src/services/session/caller-binding-service.js +148 -0
- package/dist/src/services/session/caller-id-types.d.ts +77 -0
- package/dist/src/services/session/caller-id-types.js +46 -0
- package/dist/src/services/session/index.d.ts +4 -0
- package/dist/src/services/session/index.js +5 -0
- package/dist/src/services/session/platform-fallbacks.d.ts +31 -0
- package/dist/src/services/session/platform-fallbacks.js +35 -0
- package/dist/src/services/session/resolve-caller-id.d.ts +57 -0
- package/dist/src/services/session/resolve-caller-id.js +88 -0
- package/dist/src/services/session/session-manager.d.ts +55 -0
- package/dist/src/services/session/session-manager.js +68 -0
- package/dist/src/services/skills/skill-presence-service.d.ts +21 -4
- package/dist/src/services/skills/skill-presence-service.js +75 -11
- package/dist/src/services/slice/slice-check-service.js +36 -18
- package/dist/src/services/slice/slice-check-types.d.ts +40 -6
- package/dist/src/services/slice/slice-check-types.js +11 -1
- package/dist/src/shared/version.d.ts +1 -1
- package/dist/src/shared/version.js +1 -1
- package/package.json +1 -1
- package/skills/peaks-qa/SKILL.md +5 -2
- package/skills/peaks-rd/SKILL.md +18 -133
- package/skills/peaks-rd/references/rd-transition-gates.md +148 -0
- package/skills/peaks-solo/SKILL.md +18 -209
- package/skills/peaks-solo/references/frontend-only-mode.md +73 -0
- package/skills/peaks-solo/references/micro-cycle.md +4 -2
- package/skills/peaks-solo/references/project-scan-checklist.md +136 -0
|
@@ -141,11 +141,10 @@ The instant Peaks-Cli Solo is invoked, **before** the mode-selection question, b
|
|
|
141
141
|
```bash
|
|
142
142
|
# Session ID is auto-generated when omitted; the command returns it in the JSON output.
|
|
143
143
|
# Do NOT pass --session-id manually — the CLI is the single source of truth for the
|
|
144
|
-
# project session binding.
|
|
145
|
-
#
|
|
146
|
-
# the
|
|
147
|
-
#
|
|
148
|
-
# CLI auto-generate.
|
|
144
|
+
# project session binding. To look up the active session id from a skill / sub-agent,
|
|
145
|
+
# use `peaks session info --active --json` (read-only, no side effects). To avoid
|
|
146
|
+
# the "two sessions in .peaks/" confusion that bites Solo, always omit --session-id
|
|
147
|
+
# here and let the CLI auto-generate.
|
|
149
148
|
peaks workspace init --project <repo> --json
|
|
150
149
|
peaks skill presence:set peaks-solo --project <repo> --gate startup
|
|
151
150
|
```
|
|
@@ -170,8 +169,9 @@ After Step 0 has anchored the workspace and presence, before Step 1 mode selecti
|
|
|
170
169
|
**Detection logic** (all read-only, no side effects; uses only existing CLIs):
|
|
171
170
|
|
|
172
171
|
```bash
|
|
173
|
-
# 1. Confirm the current session id
|
|
174
|
-
|
|
172
|
+
# 1. Confirm the current session id via the read-only CLI primitive
|
|
173
|
+
# (the on-disk binding file is internal — never `cat` it directly)
|
|
174
|
+
sid=$(peaks session info --active --project "$(git rev-parse --show-toplevel)" --json | python3 -c "import sys,json; print(json.load(sys.stdin)['data']['sessionId'])")
|
|
175
175
|
|
|
176
176
|
# 2. Enumerate the session's artifact tree (one `find` call, no new CLI)
|
|
177
177
|
find ".peaks/$sid/" -type f 2>/dev/null | sort
|
|
@@ -287,7 +287,7 @@ Filter with `--kind <decision|convention|module|rule|reference|project|lesson>`
|
|
|
287
287
|
Extract a short (8-20 Chinese characters, or 4-10 English words) descriptive title from the user's first request. The title should capture the core task — e.g. "修复登录页OAuth回调异常", "添加暗色模式开关", "搭建项目基础架构". Then run:
|
|
288
288
|
|
|
289
289
|
```bash
|
|
290
|
-
peaks session title $(
|
|
290
|
+
peaks session title $(peaks session info --active --project "$(git rev-parse --show-toplevel)" --json | python3 -c "import sys,json; print(json.load(sys.stdin)['data']['sessionId'])") "<title>"
|
|
291
291
|
```
|
|
292
292
|
|
|
293
293
|
If the session directory already has a title (check via `peaks session list --json`), skip this step — the title is already set.
|
|
@@ -332,7 +332,7 @@ For frontend workflows, RD and QA must use Playwright MCP for real browser E2E.
|
|
|
332
332
|
|
|
333
333
|
The workspace is created in Step 0 (Startup sequence) as a mandatory first action — before any analysis, role handoff, or artifact write, and regardless of how lightweight the request is. Session IDs are now **auto-generated** with the format `YYYY-MM-DD-session-<6位hex>` (e.g. `2026-05-26-session-a3f8b1`). The user does not provide a session ID — the system creates and persists it in `.peaks/_runtime/session.json` (the canonical home as of slice `2026-06-05-peaks-runtime-layer`; the legacy `.peaks/.session.json` is read-only back-compat for one minor release).
|
|
334
334
|
|
|
335
|
-
When `peaks workspace init` is run without `--session-id`, it automatically generates a new session ID using today's date and a random hex suffix. If a valid session binding exists at `.peaks/_runtime/session.json` (
|
|
335
|
+
When `peaks workspace init` is run without `--session-id`, it automatically generates a new session ID using today's date and a random hex suffix. If a valid session binding exists at `.peaks/_runtime/session.json` (the canonical home, slice 2026-06-05-peaks-runtime-layer; the legacy `.peaks/.session.json` is read-only back-compat for one minor release), the existing session is reused. To read the active session id from a skill or sub-agent, use the `peaks session info --active --json` primitive — never `cat` the on-disk file directly (the path is internal).
|
|
336
336
|
|
|
337
337
|
**Existing old-session cleanup**: If `.peaks/` contains numeric-only or generic session directories from prior runs (e.g. `2026-05-25-auth-system`), create the new correctly-named session, migrate any reusable artifacts into it, and note the migration in the TXT handoff. Delete empty old-session directories.
|
|
338
338
|
|
|
@@ -346,9 +346,13 @@ The workspace initialization creates this structure under `.peaks/`:
|
|
|
346
346
|
# Canonical home for all per-project ephemeral state (active-skill
|
|
347
347
|
# marker, session binding, sop-state). All writes go here; reads also
|
|
348
348
|
# tolerate the legacy paths (`.peaks/.active-skill.json`,
|
|
349
|
-
# `.peaks/.session.json
|
|
350
|
-
# so a fresh upgrade does
|
|
351
|
-
# are auto-migrated by
|
|
349
|
+
# `.peaks/.session.json` — read-only back-compat for one minor release,
|
|
350
|
+
# `.peaks/sop-state/`) for one minor release so a fresh upgrade does
|
|
351
|
+
# not break in-flight workflows. Older trees are auto-migrated by
|
|
352
|
+
# `peaks workspace reconcile --apply`. Skills and sub-agents MUST
|
|
353
|
+
# NOT `cat` any of these files directly — use `peaks session info
|
|
354
|
+
# --active --json` (and the matching read-only primitives for the
|
|
355
|
+
# other two) to discover session-id / active-skill / sop-state.
|
|
352
356
|
.peaks/_runtime/
|
|
353
357
|
├── active-skill.json # orchestrator presence marker (peaks-solo / -rd / -qa / -ui / -sc / -sop / -txt)
|
|
354
358
|
├── session.json # project → session binding (the only single-session source of truth)
|
|
@@ -404,208 +408,13 @@ Do not default to git-backed storage or automatic commits for intermediate artif
|
|
|
404
408
|
|
|
405
409
|
Before handing off to `peaks-rd`, scan the project and record findings to `.peaks/_runtime/<sessionId>/rd/project-scan.md`. RD and UI roles read this before starting work. **project-scan.md is a session-scoped singleton** — check if it already exists before regenerating (e.g. via `ls .peaks/_runtime/<sessionId>/rd/project-scan.md`). If it exists and is complete (has `## Archetype` and `## Project mode` sections), reuse it. Only regenerate if missing or incomplete.
|
|
406
410
|
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
Run the CLI; do NOT infer the archetype from prompts. Record the JSON output as `## Archetype` and `## Project mode` in `project-scan.md`. Later gates (frontend-only mode, visual system extraction, standards generation) read these fields.
|
|
410
|
-
|
|
411
|
-
```bash
|
|
412
|
-
peaks scan archetype --project <repo> --json
|
|
413
|
-
```
|
|
414
|
-
|
|
415
|
-
The command emits a stable JSON envelope with these fields you copy verbatim into `project-scan.md`:
|
|
416
|
-
|
|
417
|
-
- `archetype`: `greenfield | legacy-frontend | legacy-fullstack | frontend-monorepo | unknown`
|
|
418
|
-
- `confidence`: `high | medium | low`
|
|
419
|
-
- `frontendOnly`: `true | false`
|
|
420
|
-
- `frontendOnlyReason`: short string explaining the decision
|
|
421
|
-
- `signals[]`: each signal's name, matched flag, and detail (paste under `## Archetype → Signals matched`)
|
|
422
|
-
- `detected`: raw filesystem facts (package.json presence, backend frameworks, swagger paths, monorepo configs, src file count, lockfile age)
|
|
423
|
-
|
|
424
|
-
If `archetype` is `unknown`, STOP and surface to the user as an open question in the TXT handoff — do NOT guess. If `confidence` is `low`, note the uncertainty in `project-scan.md` and confirm the choice with the user before proceeding.
|
|
425
|
-
|
|
426
|
-
The CLI is the sole source of truth for archetype and frontend-only-mode decisions. Manual heuristics in older versions of this skill are superseded by the CLI output.
|
|
427
|
-
|
|
428
|
-
### 1. Build tool: inspect config files for the framework
|
|
429
|
-
|
|
430
|
-
| Config file | Framework |
|
|
431
|
-
|---|---|
|
|
432
|
-
| `.umirc.ts`, `config/config.ts` | Umi (Ant Design Pro) |
|
|
433
|
-
| `next.config.*` | Next.js |
|
|
434
|
-
| `vite.config.*` | Vite |
|
|
435
|
-
| `rsbuild.config.*` | Rsbuild |
|
|
436
|
-
| `rspack.config.*` | Rspack |
|
|
437
|
-
| `farm.config.*` | Farm |
|
|
438
|
-
| `craco.config.*` | CRA + craco |
|
|
439
|
-
| `webpack.config.*` | Webpack |
|
|
440
|
-
| `gulpfile.*` | Gulp (legacy) |
|
|
441
|
-
| `angular.json` | Angular |
|
|
442
|
-
| Custom `build/` or `scripts/build.*` only | Bespoke pipeline — record as `custom` and capture entry script path |
|
|
443
|
-
|
|
444
|
-
If multiple build configs coexist (e.g. `webpack.config.js` + `vite.config.ts`), record ALL of them and mark `build.mixed: true`. Mixed builds are a constraint, not an error — do not silently pick one.
|
|
445
|
-
|
|
446
|
-
### 2. Component library: check `package.json` dependencies
|
|
447
|
-
|
|
448
|
-
| Package | Library |
|
|
449
|
-
|---|---|
|
|
450
|
-
| `antd` (capture major version: v3/v4/v5) | Ant Design |
|
|
451
|
-
| `@ant-design/pro-components`, `@ant-design/pro-*` | Ant Design Pro suite |
|
|
452
|
-
| `@mui/material` | Material UI |
|
|
453
|
-
| `tailwindcss` + `radix-ui` | shadcn/ui |
|
|
454
|
-
| `element-plus` / `element-ui` | Element UI/Plus |
|
|
455
|
-
| `@arco-design/web-react` | Arco Design |
|
|
456
|
-
| `tdesign-react` / `tdesign-vue-next` | TDesign |
|
|
457
|
-
| `@douyinfe/semi-ui` | Semi Design |
|
|
458
|
-
| `@nextui-org/react` | NextUI |
|
|
459
|
-
| `@chakra-ui/react` | Chakra UI |
|
|
460
|
-
| `vant` | Vant (mobile) |
|
|
461
|
-
| Workspace package (`workspace:*`) or private-registry scope matching internal design system | In-house design system — record package name and entry path |
|
|
462
|
-
|
|
463
|
-
**CRITICAL**: Never add a second component library to a project that already has one. Do not introduce shadcn/ui to an antd project or vice versa. For antd, ALSO record the major version — v3 / v4 / v5 have incompatible APIs and tokens; mixing component code across majors is a blocker.
|
|
464
|
-
|
|
465
|
-
### 3. CSS framework: check for conflicts
|
|
466
|
-
|
|
467
|
-
- **antd + TailwindCSS**: High conflict risk (preflight reset overrides base styles). Resolution:
|
|
468
|
-
- Both already in `package.json` → coexist; use Tailwind for layout, antd for components.
|
|
469
|
-
- Tailwind breaks antd styles → add `corePlugins: { preflight: false }` or `important: '#root'`.
|
|
470
|
-
- Only antd, user wants Tailwind → **Block**; propose antd `ConfigProvider` tokens or CSS Modules.
|
|
471
|
-
- **Less/Sass**: Standard for Umi+antd projects; compatible with CSS Modules.
|
|
472
|
-
- **CSS-in-JS (@emotion, styled-components)**: Check if component library already uses one internally; don't add competing solutions.
|
|
473
|
-
|
|
474
|
-
### 4. State management, routing, data fetching: detect from `package.json`
|
|
475
|
-
|
|
476
|
-
State: `zustand`, `jotai`, `redux`/`@reduxjs/toolkit`, `valtio`, `mobx`, `hox`
|
|
477
|
-
Routing: `react-router-dom`, `@umijs/max`, Next.js file-based, `vue-router`
|
|
478
|
-
Data fetching: `@tanstack/react-query`, `swr`, `ahooks` (`useRequest`), `umi-request`
|
|
479
|
-
|
|
480
|
-
### 5. Legacy signals (legacy-frontend / legacy-fullstack only)
|
|
481
|
-
|
|
482
|
-
Grep `src/` for outdated patterns and list them as constraints in `project-scan.md` under `## Legacy constraints`. RD must preserve these patterns for new code in the same file/module unless PRD explicitly authorizes modernization.
|
|
483
|
-
|
|
484
|
-
| Signal | Detection |
|
|
485
|
-
|---|---|
|
|
486
|
-
| Class components | `extends React.Component` / `extends Component` in `.tsx`/`.jsx` |
|
|
487
|
-
| `moment` instead of dayjs/date-fns | `package.json` dep |
|
|
488
|
-
| Enzyme test suite | `package.json` dep `enzyme*` |
|
|
489
|
-
| redux-saga / redux-thunk | `package.json` dep |
|
|
490
|
-
| HOC-heavy patterns | `withRouter`, `connect()`, `compose(` frequency in `src/` |
|
|
491
|
-
| Legacy lifecycle | `componentWillMount`/`componentWillReceiveProps` occurrences |
|
|
492
|
-
| jQuery / Backbone / Vue 2 | `package.json` dep |
|
|
493
|
-
| Inline styles dominant | `style={{` occurrences ≥ 50 |
|
|
494
|
-
|
|
495
|
-
### 6. Project-scan artifact template
|
|
496
|
-
|
|
497
|
-
```markdown
|
|
498
|
-
# Project Scan: <project-name>
|
|
499
|
-
**Date:** YYYY-MM-DD
|
|
500
|
-
**Session:** <session-id>
|
|
501
|
-
|
|
502
|
-
## Archetype
|
|
503
|
-
- Type: <greenfield | legacy-frontend | legacy-fullstack | frontend-monorepo | unknown>
|
|
504
|
-
- Signals matched: <bullet list of signals that drove the decision>
|
|
505
|
-
|
|
506
|
-
## Project mode
|
|
507
|
-
- Frontend-only: <true | false>
|
|
508
|
-
- Reason: <archetype-derived | user-stated | backend-detected>
|
|
509
|
-
|
|
510
|
-
## Build tool
|
|
511
|
-
- Framework: <name> <version>
|
|
512
|
-
- Config file: <path>
|
|
513
|
-
- Mixed builds: <true | false; list all configs if true>
|
|
514
|
-
|
|
515
|
-
## Component library
|
|
516
|
-
- Library: <name> <version (major matters for antd)>
|
|
517
|
-
- Design-system packages: <list>
|
|
518
|
-
- In-house design system: <package name | none>
|
|
519
|
-
|
|
520
|
-
## CSS solution
|
|
521
|
-
- Primary: <Less/Sass/CSS-in-JS/TailwindCSS/CSS Modules>
|
|
522
|
-
- Conflicts detected: <none | description and recommendation>
|
|
523
|
-
|
|
524
|
-
## State management, routing, data fetching
|
|
525
|
-
- State: <name>
|
|
526
|
-
- Routing: <name>
|
|
527
|
-
- Data fetching: <name>
|
|
528
|
-
|
|
529
|
-
## Library versions
|
|
530
|
-
- Source: output of `peaks scan libraries --project <repo> --json` (see Gate A; cross-check diff imports against `schemas/library-breaking-changes.data.json` in `peaks-rd` preflight)
|
|
531
|
-
- Total: <count from scan.libraries.totalCount>
|
|
532
|
-
- Notable: <bullet list of libraries with major >= a known breaking change in `schemas/library-breaking-changes.data.json`; e.g. "- antd@^5.18.0 (major=5) — see breaking-change rule for antd v4→v5 if any code uses Drawer.width">
|
|
533
|
-
|
|
534
|
-
## Legacy constraints
|
|
535
|
-
- <bullet list of legacy signals from section 5; empty for greenfield>
|
|
536
|
-
```
|
|
411
|
+
**Full checklist lives in [`references/project-scan-checklist.md`](references/project-scan-checklist.md)**: project archetype detection (Peaks-Cli Gate from `peaks scan archetype`), build-tool / component-library / CSS-framework / state-routing-data tables, legacy signals, and the project-scan artifact template. Read that file before doing the scan.
|
|
537
412
|
|
|
538
413
|
## Peaks-Cli Frontend-only development mode
|
|
539
414
|
|
|
540
415
|
When the project has no live backend (no swagger.json, no API server), Solo must activate frontend-only mode.
|
|
541
416
|
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
The CLI decision is authoritative. Read `frontendOnly` and `frontendOnlyReason` directly from the `peaks scan archetype --json` output and copy both into `project-scan.md` under `## Project mode`. Do NOT re-derive the decision from user phrasing.
|
|
545
|
-
|
|
546
|
-
User-stated intent is **only** consulted when it conflicts with the CLI result. The two conflict cases:
|
|
547
|
-
|
|
548
|
-
- **CLI says `frontendOnly=false` but the user says "前端项目 / 没有后端 / 先 mock 数据"**: STOP and `AskUserQuestion` to confirm whether to override the scan (the repo probably contains a backend folder the user wants to ignore). Record the override decision and reason in `project-scan.md`.
|
|
549
|
-
- **CLI says `frontendOnly=true` but the user says "需要做后端 / 加 API"**: STOP and `AskUserQuestion` to confirm whether the request actually targets the missing backend (the user may be confused about repo scope, or there is a separate backend repo Solo should switch to).
|
|
550
|
-
|
|
551
|
-
When there is no conflict, do not ask — the CLI value wins and the workflow proceeds.
|
|
552
|
-
|
|
553
|
-
### Mock data strategy selection
|
|
554
|
-
|
|
555
|
-
Solo records the chosen mock strategy in `.peaks/_runtime/<sessionId>/rd/tech-doc.md` under a `## Mock Data Strategy` section. The choice depends on the project scan results:
|
|
556
|
-
|
|
557
|
-
| Project data-fetching pattern | Recommended mock approach | Rationale |
|
|
558
|
-
|---|---|---|
|
|
559
|
-
| Umi + `umi-request` / `@umijs/plugins` request | Umi mock directory (`mock/*.ts`) | Built-in, zero-config, auto-reload on file change |
|
|
560
|
-
| `@tanstack/react-query` + custom fetcher | Service-layer mock with `Promise.resolve()` stubs in the service file | Keeps query hooks unchanged; swap fetcher target later |
|
|
561
|
-
| `ahooks` `useRequest` + service functions | Service-layer mock: replace HTTP call with `Promise.resolve(mockData)` | Matches existing service-function pattern |
|
|
562
|
-
| MSW (Mock Service Worker) already configured | Add new handlers to existing MSW setup | Consistent with project convention |
|
|
563
|
-
| No existing pattern (greenfield) | Service-layer mock with a `mock/` directory and typed fixture files | Clean separation, easy to delete later |
|
|
564
|
-
| Existing `src/services/*` but no fetcher abstraction | Inline mock inside the service file; preserve the function signature | Keeps existing call-sites unchanged |
|
|
565
|
-
| Mixed data-fetching styles (e.g. react-query + raw fetch in legacy files) | Match the style of the most recently added code in the same module | Avoid introducing a third style |
|
|
566
|
-
| Cannot decide from scan alone | STOP and `AskUserQuestion` | Asking once beats picking differently on every run |
|
|
567
|
-
|
|
568
|
-
**Mock data rules:**
|
|
569
|
-
|
|
570
|
-
1. Every mock response must match the shape of the expected real API response. Define a TypeScript interface for the response type first, then create mock data that satisfies it.
|
|
571
|
-
2. Mock data should be realistic (not `"test"`, `"foo"`, `123`) — use plausible Chinese/English content that resembles production data.
|
|
572
|
-
3. Each mock must export its TypeScript interface so RD implementation and QA test-cases can import the same types.
|
|
573
|
-
4. Mark every mock file with a header comment: `// MOCK: Replace with real API call when swagger.json is available`.
|
|
574
|
-
5. Before producing any mock file, register the plan in `.peaks/_runtime/<sessionId>/rd/mock-plan.md` with: chosen strategy (from the table above), planned file paths, and a one-line rationale per file. This file is the source of truth for mock locations across runs — RD must read it before writing code, QA must read it before writing test cases.
|
|
575
|
-
|
|
576
|
-
### API contract placeholder pattern
|
|
577
|
-
|
|
578
|
-
When no swagger.json exists, RD defines API contracts as TypeScript interfaces with a mock-then-real service layer:
|
|
579
|
-
|
|
580
|
-
```
|
|
581
|
-
src/services/types/<feature>-api.types.ts ← API request/response interfaces
|
|
582
|
-
src/services/<feature>-service.ts ← Service functions (mock → real)
|
|
583
|
-
mock/<feature>-mock.ts ← Mock data satisfying interfaces
|
|
584
|
-
```
|
|
585
|
-
|
|
586
|
-
Each service function returns a typed mock response marked with `// MOCK: Replace with real API call when swagger.json is available`.
|
|
587
|
-
|
|
588
|
-
### Mock-to-real migration path
|
|
589
|
-
|
|
590
|
-
When swagger.json becomes available later, the migration follows this sequence:
|
|
591
|
-
|
|
592
|
-
1. Generate typed API client from swagger.json (e.g. via `openapi-typescript` or manual mapping).
|
|
593
|
-
2. Replace mock imports with generated API calls, one service file at a time.
|
|
594
|
-
3. Remove corresponding mock files.
|
|
595
|
-
4. Run QA regression to verify the real API responses match the mock interface contracts.
|
|
596
|
-
|
|
597
|
-
Solo records the migration readiness in the TXT handoff capsule under a `## API Migration` section listing: mock file paths, the corresponding swagger endpoints (when known), and the migration status for each.
|
|
598
|
-
|
|
599
|
-
### Feishu document access fallback
|
|
600
|
-
|
|
601
|
-
When the PRD source is a Feishu/Lark document that requires authentication:
|
|
602
|
-
|
|
603
|
-
1. **Primary path**: Playwright MCP headed browser → user completes login → Solo reads document content via `browser_snapshot`.
|
|
604
|
-
2. **Fallback A (user cannot login)**: Ask user to copy-paste the document content or export as Markdown/PDF. Solo creates the PRD artifact from the pasted content.
|
|
605
|
-
3. **Fallback B (user provides export)**: User drops a `.md` or `.pdf` export into `.peaks/_runtime/<sessionId>/prd/source/`. Solo reads and processes it.
|
|
606
|
-
4. **Fallback C (none of the above)**: Mark PRD as `blocked` with reason `doc-inaccessible`, list the exact next steps for the user, and pause the workflow.
|
|
607
|
-
|
|
608
|
-
Never silently fall back to unauthenticated `fetch` or `WebFetch` for authenticated documents.
|
|
417
|
+
**Full frontend-only contract lives in [`references/frontend-only-mode.md`](references/frontend-only-mode.md)**: mode determination (CLI is authoritative), mock-data strategy table by project data-fetching pattern, mock data rules, API contract placeholder pattern (`src/services/types/` + `src/services/` + `mock/`), mock-to-real migration path, and the Feishu document access fallback chain. Read that file before producing any mock files.
|
|
609
418
|
|
|
610
419
|
## Peaks-Cli Request type classification + Workflow order + Transition verification gates
|
|
611
420
|
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
# Peaks-Cli Frontend-only development mode
|
|
2
|
+
|
|
3
|
+
> Extracted from `skills/peaks-solo/SKILL.md` on 2026-06-09 (slice 019 — slim skill files to references) to keep SKILL.md under the 800-line cap from `common/coding-style.md`. The content below is the verbatim Frontend-only development mode section that was previously inline; nothing was paraphrased, just relocated.
|
|
4
|
+
|
|
5
|
+
When the project has no live backend (no swagger.json, no API server), Solo must activate frontend-only mode.
|
|
6
|
+
|
|
7
|
+
### Mode determination (deterministic — CLI is the source of truth)
|
|
8
|
+
|
|
9
|
+
The CLI decision is authoritative. Read `frontendOnly` and `frontendOnlyReason` directly from the `peaks scan archetype --json` output and copy both into `project-scan.md` under `## Project mode`. Do NOT re-derive the decision from user phrasing.
|
|
10
|
+
|
|
11
|
+
User-stated intent is **only** consulted when it conflicts with the CLI result. The two conflict cases:
|
|
12
|
+
|
|
13
|
+
- **CLI says `frontendOnly=false` but the user says "前端项目 / 没有后端 / 先 mock 数据"**: STOP and `AskUserQuestion` to confirm whether to override the scan (the repo probably contains a backend folder the user wants to ignore). Record the override decision and reason in `project-scan.md`.
|
|
14
|
+
- **CLI says `frontendOnly=true` but the user says "需要做后端 / 加 API"**: STOP and `AskUserQuestion` to confirm whether the request actually targets the missing backend (the user may be confused about repo scope, or there is a separate backend repo Solo should switch to).
|
|
15
|
+
|
|
16
|
+
When there is no conflict, do not ask — the CLI value wins and the workflow proceeds.
|
|
17
|
+
|
|
18
|
+
### Mock data strategy selection
|
|
19
|
+
|
|
20
|
+
Solo records the chosen mock strategy in `.peaks/_runtime/<sessionId>/rd/tech-doc.md` under a `## Mock Data Strategy` section. The choice depends on the project scan results:
|
|
21
|
+
|
|
22
|
+
| Project data-fetching pattern | Recommended mock approach | Rationale |
|
|
23
|
+
|---|---|---|
|
|
24
|
+
| Umi + `umi-request` / `@umijs/plugins` request | Umi mock directory (`mock/*.ts`) | Built-in, zero-config, auto-reload on file change |
|
|
25
|
+
| `@tanstack/react-query` + custom fetcher | Service-layer mock with `Promise.resolve()` stubs in the service file | Keeps query hooks unchanged; swap fetcher target later |
|
|
26
|
+
| `ahooks` `useRequest` + service functions | Service-layer mock: replace HTTP call with `Promise.resolve(mockData)` | Matches existing service-function pattern |
|
|
27
|
+
| MSW (Mock Service Worker) already configured | Add new handlers to existing MSW setup | Consistent with project convention |
|
|
28
|
+
| No existing pattern (greenfield) | Service-layer mock with a `mock/` directory and typed fixture files | Clean separation, easy to delete later |
|
|
29
|
+
| Existing `src/services/*` but no fetcher abstraction | Inline mock inside the service file; preserve the function signature | Keeps existing call-sites unchanged |
|
|
30
|
+
| Mixed data-fetching styles (e.g. react-query + raw fetch in legacy files) | Match the style of the most recently added code in the same module | Avoid introducing a third style |
|
|
31
|
+
| Cannot decide from scan alone | STOP and `AskUserQuestion` | Asking once beats picking differently on every run |
|
|
32
|
+
|
|
33
|
+
**Mock data rules:**
|
|
34
|
+
|
|
35
|
+
1. Every mock response must match the shape of the expected real API response. Define a TypeScript interface for the response type first, then create mock data that satisfies it.
|
|
36
|
+
2. Mock data should be realistic (not `"test"`, `"foo"`, `123`) — use plausible Chinese/English content that resembles production data.
|
|
37
|
+
3. Each mock must export its TypeScript interface so RD implementation and QA test-cases can import the same types.
|
|
38
|
+
4. Mark every mock file with a header comment: `// MOCK: Replace with real API call when swagger.json is available`.
|
|
39
|
+
5. Before producing any mock file, register the plan in `.peaks/_runtime/<sessionId>/rd/mock-plan.md` with: chosen strategy (from the table above), planned file paths, and a one-line rationale per file. This file is the source of truth for mock locations across runs — RD must read it before writing code, QA must read it before writing test cases.
|
|
40
|
+
|
|
41
|
+
### API contract placeholder pattern
|
|
42
|
+
|
|
43
|
+
When no swagger.json exists, RD defines API contracts as TypeScript interfaces with a mock-then-real service layer:
|
|
44
|
+
|
|
45
|
+
```
|
|
46
|
+
src/services/types/<feature>-api.types.ts ← API request/response interfaces
|
|
47
|
+
src/services/<feature>-service.ts ← Service functions (mock → real)
|
|
48
|
+
mock/<feature>-mock.ts ← Mock data satisfying interfaces
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
Each service function returns a typed mock response marked with `// MOCK: Replace with real API call when swagger.json is available`.
|
|
52
|
+
|
|
53
|
+
### Mock-to-real migration path
|
|
54
|
+
|
|
55
|
+
When swagger.json becomes available later, the migration follows this sequence:
|
|
56
|
+
|
|
57
|
+
1. Generate typed API client from swagger.json (e.g. via `openapi-typescript` or manual mapping).
|
|
58
|
+
2. Replace mock imports with generated API calls, one service file at a time.
|
|
59
|
+
3. Remove corresponding mock files.
|
|
60
|
+
4. Run QA regression to verify the real API responses match the mock interface contracts.
|
|
61
|
+
|
|
62
|
+
Solo records the migration readiness in the TXT handoff capsule under a `## API Migration` section listing: mock file paths, the corresponding swagger endpoints (when known), and the migration status for each.
|
|
63
|
+
|
|
64
|
+
### Feishu document access fallback
|
|
65
|
+
|
|
66
|
+
When the PRD source is a Feishu/Lark document that requires authentication:
|
|
67
|
+
|
|
68
|
+
1. **Primary path**: Playwright MCP headed browser → user completes login → Solo reads document content via `browser_snapshot`.
|
|
69
|
+
2. **Fallback A (user cannot login)**: Ask user to copy-paste the document content or export as Markdown/PDF. Solo creates the PRD artifact from the pasted content.
|
|
70
|
+
3. **Fallback B (user provides export)**: User drops a `.md` or `.pdf` export into `.peaks/_runtime/<sessionId>/prd/source/`. Solo reads and processes it.
|
|
71
|
+
4. **Fallback C (none of the above)**: Mark PRD as `blocked` with reason `doc-inaccessible`, list the exact next steps for the user, and pause the workflow.
|
|
72
|
+
|
|
73
|
+
Never silently fall back to unauthenticated `fetch` or `WebFetch` for authenticated documents.
|
|
@@ -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
|
|
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
|
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
# Peaks-Cli Pre-RD project scan checklist
|
|
2
|
+
|
|
3
|
+
> Extracted from `skills/peaks-solo/SKILL.md` on 2026-06-09 (slice 019 — slim skill files to references) to keep SKILL.md under the 800-line cap from `common/coding-style.md`. The content below is the verbatim Pre-RD project scan checklist that was previously inline; nothing was paraphrased, just relocated.
|
|
4
|
+
|
|
5
|
+
Before handing off to `peaks-rd`, scan the project and record findings to `.peaks/_runtime/<sessionId>/rd/project-scan.md`. RD and UI roles read this before starting work. **project-scan.md is a session-scoped singleton** — check if it already exists before regenerating (e.g. via `ls .peaks/_runtime/<sessionId>/rd/project-scan.md`). If it exists and is complete (has `## Archetype` and `## Project mode` sections), reuse it. Only regenerate if missing or incomplete.
|
|
6
|
+
|
|
7
|
+
### 0. Project archetype detection (MANDATORY — run FIRST, deterministic CLI)
|
|
8
|
+
|
|
9
|
+
Run the CLI; do NOT infer the archetype from prompts. Record the JSON output as `## Archetype` and `## Project mode` in `project-scan.md`. Later gates (frontend-only mode, visual system extraction, standards generation) read these fields.
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
peaks scan archetype --project <repo> --json
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
The command emits a stable JSON envelope with these fields you copy verbatim into `project-scan.md`:
|
|
16
|
+
|
|
17
|
+
- `archetype`: `greenfield | legacy-frontend | legacy-fullstack | frontend-monorepo | unknown`
|
|
18
|
+
- `confidence`: `high | medium | low`
|
|
19
|
+
- `frontendOnly`: `true | false`
|
|
20
|
+
- `frontendOnlyReason`: short string explaining the decision
|
|
21
|
+
- `signals[]`: each signal's name, matched flag, and detail (paste under `## Archetype → Signals matched`)
|
|
22
|
+
- `detected`: raw filesystem facts (package.json presence, backend frameworks, swagger paths, monorepo configs, src file count, lockfile age)
|
|
23
|
+
|
|
24
|
+
If `archetype` is `unknown`, STOP and surface to the user as an open question in the TXT handoff — do NOT guess. If `confidence` is `low`, note the uncertainty in `project-scan.md` and confirm the choice with the user before proceeding.
|
|
25
|
+
|
|
26
|
+
The CLI is the sole source of truth for archetype and frontend-only-mode decisions. Manual heuristics in older versions of this skill are superseded by the CLI output.
|
|
27
|
+
|
|
28
|
+
### 1. Build tool: inspect config files for the framework
|
|
29
|
+
|
|
30
|
+
| Config file | Framework |
|
|
31
|
+
|---|---|
|
|
32
|
+
| `.umirc.ts`, `config/config.ts` | Umi (Ant Design Pro) |
|
|
33
|
+
| `next.config.*` | Next.js |
|
|
34
|
+
| `vite.config.*` | Vite |
|
|
35
|
+
| `rsbuild.config.*` | Rsbuild |
|
|
36
|
+
| `rspack.config.*` | Rspack |
|
|
37
|
+
| `farm.config.*` | Farm |
|
|
38
|
+
| `craco.config.*` | CRA + craco |
|
|
39
|
+
| `webpack.config.*` | Webpack |
|
|
40
|
+
| `gulpfile.*` | Gulp (legacy) |
|
|
41
|
+
| `angular.json` | Angular |
|
|
42
|
+
| Custom `build/` or `scripts/build.*` only | Bespoke pipeline — record as `custom` and capture entry script path |
|
|
43
|
+
|
|
44
|
+
If multiple build configs coexist (e.g. `webpack.config.js` + `vite.config.ts`), record ALL of them and mark `build.mixed: true`. Mixed builds are a constraint, not an error — do not silently pick one.
|
|
45
|
+
|
|
46
|
+
### 2. Component library: check `package.json` dependencies
|
|
47
|
+
|
|
48
|
+
| Package | Library |
|
|
49
|
+
|---|---|
|
|
50
|
+
| `antd` (capture major version: v3/v4/v5) | Ant Design |
|
|
51
|
+
| `@ant-design/pro-components`, `@ant-design/pro-*` | Ant Design Pro suite |
|
|
52
|
+
| `@mui/material` | Material UI |
|
|
53
|
+
| `tailwindcss` + `radix-ui` | shadcn/ui |
|
|
54
|
+
| `element-plus` / `element-ui` | Element UI/Plus |
|
|
55
|
+
| `@arco-design/web-react` | Arco Design |
|
|
56
|
+
| `tdesign-react` / `tdesign-vue-next` | TDesign |
|
|
57
|
+
| `@douyinfe/semi-ui` | Semi Design |
|
|
58
|
+
| `@nextui-org/react` | NextUI |
|
|
59
|
+
| `@chakra-ui/react` | Chakra UI |
|
|
60
|
+
| `vant` | Vant (mobile) |
|
|
61
|
+
| Workspace package (`workspace:*`) or private-registry scope matching internal design system | In-house design system — record package name and entry path |
|
|
62
|
+
|
|
63
|
+
**CRITICAL**: Never add a second component library to a project that already has one. Do not introduce shadcn/ui to an antd project or vice versa. For antd, ALSO record the major version — v3 / v4 / v5 have incompatible APIs and tokens; mixing component code across majors is a blocker.
|
|
64
|
+
|
|
65
|
+
### 3. CSS framework: check for conflicts
|
|
66
|
+
|
|
67
|
+
- **antd + TailwindCSS**: High conflict risk (preflight reset overrides base styles). Resolution:
|
|
68
|
+
- Both already in `package.json` → coexist; use Tailwind for layout, antd for components.
|
|
69
|
+
- Tailwind breaks antd styles → add `corePlugins: { preflight: false }` or `important: '#root'`.
|
|
70
|
+
- Only antd, user wants Tailwind → **Block**; propose antd `ConfigProvider` tokens or CSS Modules.
|
|
71
|
+
- **Less/Sass**: Standard for Umi+antd projects; compatible with CSS Modules.
|
|
72
|
+
- **CSS-in-JS (@emotion, styled-components)**: Check if component library already uses one internally; don't add competing solutions.
|
|
73
|
+
|
|
74
|
+
### 4. State management, routing, data fetching: detect from `package.json`
|
|
75
|
+
|
|
76
|
+
State: `zustand`, `jotai`, `redux`/`@reduxjs/toolkit`, `valtio`, `mobx`, `hox`
|
|
77
|
+
Routing: `react-router-dom`, `@umijs/max`, Next.js file-based, `vue-router`
|
|
78
|
+
Data fetching: `@tanstack/react-query`, `swr`, `ahooks` (`useRequest`), `umi-request`
|
|
79
|
+
|
|
80
|
+
### 5. Legacy signals (legacy-frontend / legacy-fullstack only)
|
|
81
|
+
|
|
82
|
+
Grep `src/` for outdated patterns and list them as constraints in `project-scan.md` under `## Legacy constraints`. RD must preserve these patterns for new code in the same file/module unless PRD explicitly authorizes modernization.
|
|
83
|
+
|
|
84
|
+
| Signal | Detection |
|
|
85
|
+
|---|---|
|
|
86
|
+
| Class components | `extends React.Component` / `extends Component` in `.tsx`/`.jsx` |
|
|
87
|
+
| `moment` instead of dayjs/date-fns | `package.json` dep |
|
|
88
|
+
| Enzyme test suite | `package.json` dep `enzyme*` |
|
|
89
|
+
| redux-saga / redux-thunk | `package.json` dep |
|
|
90
|
+
| HOC-heavy patterns | `withRouter`, `connect()`, `compose(` frequency in `src/` |
|
|
91
|
+
| Legacy lifecycle | `componentWillMount`/`componentWillReceiveProps` occurrences |
|
|
92
|
+
| jQuery / Backbone / Vue 2 | `package.json` dep |
|
|
93
|
+
| Inline styles dominant | `style={{` occurrences ≥ 50 |
|
|
94
|
+
|
|
95
|
+
### 6. Project-scan artifact template
|
|
96
|
+
|
|
97
|
+
```markdown
|
|
98
|
+
# Project Scan: <project-name>
|
|
99
|
+
**Date:** YYYY-MM-DD
|
|
100
|
+
**Session:** <session-id>
|
|
101
|
+
|
|
102
|
+
## Archetype
|
|
103
|
+
- Type: <greenfield | legacy-frontend | legacy-fullstack | frontend-monorepo | unknown>
|
|
104
|
+
- Signals matched: <bullet list of signals that drove the decision>
|
|
105
|
+
|
|
106
|
+
## Project mode
|
|
107
|
+
- Frontend-only: <true | false>
|
|
108
|
+
- Reason: <archetype-derived | user-stated | backend-detected>
|
|
109
|
+
|
|
110
|
+
## Build tool
|
|
111
|
+
- Framework: <name> <version>
|
|
112
|
+
- Config file: <path>
|
|
113
|
+
- Mixed builds: <true | false; list all configs if true>
|
|
114
|
+
|
|
115
|
+
## Component library
|
|
116
|
+
- Library: <name> <version (major matters for antd)>
|
|
117
|
+
- Design-system packages: <list>
|
|
118
|
+
- In-house design system: <package name | none>
|
|
119
|
+
|
|
120
|
+
## CSS solution
|
|
121
|
+
- Primary: <Less/Sass/CSS-in-JS/TailwindCSS/CSS Modules>
|
|
122
|
+
- Conflicts detected: <none | description and recommendation>
|
|
123
|
+
|
|
124
|
+
## State management, routing, data fetching
|
|
125
|
+
- State: <name>
|
|
126
|
+
- Routing: <name>
|
|
127
|
+
- Data fetching: <name>
|
|
128
|
+
|
|
129
|
+
## Library versions
|
|
130
|
+
- Source: output of `peaks scan libraries --project <repo> --json` (see Gate A; cross-check diff imports against `schemas/library-breaking-changes.data.json` in `peaks-rd` preflight)
|
|
131
|
+
- Total: <count from scan.libraries.totalCount>
|
|
132
|
+
- Notable: <bullet list of libraries with major >= a known breaking change in `schemas/library-breaking-changes.data.json`; e.g. "- antd@^5.18.0 (major=5) — see breaking-change rule for antd v4→v5 if any code uses Drawer.width">
|
|
133
|
+
|
|
134
|
+
## Legacy constraints
|
|
135
|
+
- <bullet list of legacy signals from section 5; empty for greenfield>
|
|
136
|
+
```
|