peaks-cli 1.4.1 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (219) hide show
  1. package/.claude-plugin/marketplace.json +51 -0
  2. package/CHANGELOG.md +238 -0
  3. package/README-en.md +226 -0
  4. package/README.md +142 -165
  5. package/dist/src/cli/commands/agent-commands.d.ts +20 -0
  6. package/dist/src/cli/commands/agent-commands.js +48 -0
  7. package/dist/src/cli/commands/audit-commands.d.ts +18 -0
  8. package/dist/src/cli/commands/audit-commands.js +138 -0
  9. package/dist/src/cli/commands/classify-classify-commands.d.ts +19 -0
  10. package/dist/src/cli/commands/classify-classify-commands.js +151 -0
  11. package/dist/src/cli/commands/code-review-commands.d.ts +34 -0
  12. package/dist/src/cli/commands/code-review-commands.js +83 -0
  13. package/dist/src/cli/commands/config-commands.js +90 -0
  14. package/dist/src/cli/commands/context-commands.d.ts +21 -0
  15. package/dist/src/cli/commands/context-commands.js +167 -0
  16. package/dist/src/cli/commands/core-artifact-commands.js +81 -2
  17. package/dist/src/cli/commands/hook-handle.js +50 -0
  18. package/dist/src/cli/commands/loop-commands.d.ts +21 -0
  19. package/dist/src/cli/commands/loop-commands.js +128 -0
  20. package/dist/src/cli/commands/memory-commands.d.ts +13 -0
  21. package/dist/src/cli/commands/memory-commands.js +60 -0
  22. package/dist/src/cli/commands/openspec-commands.js +37 -0
  23. package/dist/src/cli/commands/preferences-commands.d.ts +2 -0
  24. package/dist/src/cli/commands/preferences-commands.js +147 -0
  25. package/dist/src/cli/commands/retrospective-commands.d.ts +9 -0
  26. package/dist/src/cli/commands/retrospective-commands.js +58 -0
  27. package/dist/src/cli/commands/skill-conformance-commands.d.ts +9 -0
  28. package/dist/src/cli/commands/skill-conformance-commands.js +39 -0
  29. package/dist/src/cli/commands/understand-commands.js +34 -0
  30. package/dist/src/cli/commands/upgrade-commands.d.ts +23 -0
  31. package/dist/src/cli/commands/upgrade-commands.js +57 -0
  32. package/dist/src/cli/commands/workflow-commands.js +70 -0
  33. package/dist/src/cli/commands/workspace-commands.js +86 -0
  34. package/dist/src/cli/program.js +46 -22
  35. package/dist/src/services/agent/ecc-agent-service.d.ts +47 -0
  36. package/dist/src/services/agent/ecc-agent-service.js +143 -0
  37. package/dist/src/services/artifacts/request-artifact-service.js +14 -0
  38. package/dist/src/services/audit/backing-detector.d.ts +24 -0
  39. package/dist/src/services/audit/backing-detector.js +59 -0
  40. package/dist/src/services/audit/classifier.d.ts +38 -0
  41. package/dist/src/services/audit/classifier.js +127 -0
  42. package/dist/src/services/audit/enforcers/active-skill-resolver.d.ts +29 -0
  43. package/dist/src/services/audit/enforcers/active-skill-resolver.js +71 -0
  44. package/dist/src/services/audit/enforcers/design-draft-confirm.d.ts +25 -0
  45. package/dist/src/services/audit/enforcers/design-draft-confirm.js +54 -0
  46. package/dist/src/services/audit/enforcers/lint-audit-regression.d.ts +21 -0
  47. package/dist/src/services/audit/enforcers/lint-audit-regression.js +86 -0
  48. package/dist/src/services/audit/enforcers/lint-catalog-governance.d.ts +27 -0
  49. package/dist/src/services/audit/enforcers/lint-catalog-governance.js +38 -0
  50. package/dist/src/services/audit/enforcers/lint-cli-back.d.ts +16 -0
  51. package/dist/src/services/audit/enforcers/lint-cli-back.js +35 -0
  52. package/dist/src/services/audit/enforcers/lint-output-style.d.ts +11 -0
  53. package/dist/src/services/audit/enforcers/lint-output-style.js +94 -0
  54. package/dist/src/services/audit/enforcers/lint-reference-integrity.d.ts +6 -0
  55. package/dist/src/services/audit/enforcers/lint-reference-integrity.js +83 -0
  56. package/dist/src/services/audit/enforcers/lint-reference-shape.d.ts +30 -0
  57. package/dist/src/services/audit/enforcers/lint-reference-shape.js +272 -0
  58. package/dist/src/services/audit/enforcers/lint-style.d.ts +49 -0
  59. package/dist/src/services/audit/enforcers/lint-style.js +173 -0
  60. package/dist/src/services/audit/enforcers/lint-workflow-shape.d.ts +5 -0
  61. package/dist/src/services/audit/enforcers/lint-workflow-shape.js +141 -0
  62. package/dist/src/services/audit/enforcers/login-gate.d.ts +23 -0
  63. package/dist/src/services/audit/enforcers/login-gate.js +40 -0
  64. package/dist/src/services/audit/enforcers/mock-placement.d.ts +25 -0
  65. package/dist/src/services/audit/enforcers/mock-placement.js +48 -0
  66. package/dist/src/services/audit/enforcers/no-root-pollution.d.ts +21 -0
  67. package/dist/src/services/audit/enforcers/no-root-pollution.js +56 -0
  68. package/dist/src/services/audit/enforcers/pre-rd-scan.d.ts +22 -0
  69. package/dist/src/services/audit/enforcers/pre-rd-scan.js +23 -0
  70. package/dist/src/services/audit/enforcers/prototype-fidelity.d.ts +25 -0
  71. package/dist/src/services/audit/enforcers/prototype-fidelity.js +75 -0
  72. package/dist/src/services/audit/enforcers/resume-detection.d.ts +21 -0
  73. package/dist/src/services/audit/enforcers/resume-detection.js +52 -0
  74. package/dist/src/services/audit/enforcers/solo-code-ban.d.ts +23 -0
  75. package/dist/src/services/audit/enforcers/solo-code-ban.js +27 -0
  76. package/dist/src/services/audit/enforcers/sub-agent-sid.d.ts +25 -0
  77. package/dist/src/services/audit/enforcers/sub-agent-sid.js +63 -0
  78. package/dist/src/services/audit/enforcers/tech-doc-presence.d.ts +28 -0
  79. package/dist/src/services/audit/enforcers/tech-doc-presence.js +35 -0
  80. package/dist/src/services/audit/red-line-catalog-p2-a.d.ts +21 -0
  81. package/dist/src/services/audit/red-line-catalog-p2-a.js +233 -0
  82. package/dist/src/services/audit/red-line-catalog-p2-b.d.ts +19 -0
  83. package/dist/src/services/audit/red-line-catalog-p2-b.js +225 -0
  84. package/dist/src/services/audit/red-line-catalog.d.ts +51 -0
  85. package/dist/src/services/audit/red-line-catalog.js +210 -0
  86. package/dist/src/services/audit/red-lines-service.d.ts +23 -0
  87. package/dist/src/services/audit/red-lines-service.js +486 -0
  88. package/dist/src/services/audit/scanners/openspec-scanner.d.ts +15 -0
  89. package/dist/src/services/audit/scanners/openspec-scanner.js +55 -0
  90. package/dist/src/services/audit/scanners/rules-tree-scanner.d.ts +16 -0
  91. package/dist/src/services/audit/scanners/rules-tree-scanner.js +56 -0
  92. package/dist/src/services/audit/scanners/skills-tree-scanner.d.ts +17 -0
  93. package/dist/src/services/audit/scanners/skills-tree-scanner.js +46 -0
  94. package/dist/src/services/audit/static-service.d.ts +57 -0
  95. package/dist/src/services/audit/static-service.js +125 -0
  96. package/dist/src/services/audit/types.d.ts +69 -0
  97. package/dist/src/services/audit/types.js +13 -0
  98. package/dist/src/services/classify/classify-service.d.ts +42 -0
  99. package/dist/src/services/classify/classify-service.js +122 -0
  100. package/dist/src/services/classify/classify-types.d.ts +79 -0
  101. package/dist/src/services/classify/classify-types.js +90 -0
  102. package/dist/src/services/code-review/ocr-service.d.ts +129 -0
  103. package/dist/src/services/code-review/ocr-service.js +362 -0
  104. package/dist/src/services/config/config-migration.d.ts +32 -0
  105. package/dist/src/services/config/config-migration.js +92 -0
  106. package/dist/src/services/config/config-restore.d.ts +10 -0
  107. package/dist/src/services/config/config-restore.js +47 -0
  108. package/dist/src/services/config/config-rollback.d.ts +13 -0
  109. package/dist/src/services/config/config-rollback.js +26 -0
  110. package/dist/src/services/config/config-service.d.ts +35 -2
  111. package/dist/src/services/config/config-service.js +81 -0
  112. package/dist/src/services/config/config-types.d.ts +58 -0
  113. package/dist/src/services/config/config-types.js +6 -0
  114. package/dist/src/services/doctor/doctor-service.js +96 -0
  115. package/dist/src/services/fuzzy-matching/fuzzy-match-service.d.ts +15 -0
  116. package/dist/src/services/fuzzy-matching/fuzzy-match-service.js +56 -0
  117. package/dist/src/services/fuzzy-matching/types.d.ts +20 -0
  118. package/dist/src/services/fuzzy-matching/types.js +1 -0
  119. package/dist/src/services/ide/adapters/hermes-adapter.d.ts +21 -0
  120. package/dist/src/services/ide/adapters/hermes-adapter.js +51 -0
  121. package/dist/src/services/ide/adapters/openclaw-adapter.d.ts +14 -0
  122. package/dist/src/services/ide/adapters/openclaw-adapter.js +42 -0
  123. package/dist/src/services/ide/ide-registry.js +7 -0
  124. package/dist/src/services/ide/ide-types.d.ts +1 -1
  125. package/dist/src/services/memory/memory-search-service.d.ts +61 -0
  126. package/dist/src/services/memory/memory-search-service.js +80 -0
  127. package/dist/src/services/openspec/openspec-propose-from-doctor-service.d.ts +31 -0
  128. package/dist/src/services/openspec/openspec-propose-from-doctor-service.js +95 -0
  129. package/dist/src/services/preferences/preferences-service.d.ts +6 -0
  130. package/dist/src/services/preferences/preferences-service.js +43 -0
  131. package/dist/src/services/preferences/preferences-types.d.ts +90 -0
  132. package/dist/src/services/preferences/preferences-types.js +38 -0
  133. package/dist/src/services/recommendations/capability-seed-items.js +0 -1
  134. package/dist/src/services/recommendations/capability-seed-mappings.js +0 -1
  135. package/dist/src/services/recommendations/capability-seed-sources.js +0 -1
  136. package/dist/src/services/retrospective/retrospective-search-service.d.ts +37 -0
  137. package/dist/src/services/retrospective/retrospective-search-service.js +75 -0
  138. package/dist/src/services/skills/skill-conformance-service.d.ts +40 -0
  139. package/dist/src/services/skills/skill-conformance-service.js +136 -0
  140. package/dist/src/services/skills/skill-runbook-service.js +44 -10
  141. package/dist/src/services/skills/sync-service.d.ts +43 -0
  142. package/dist/src/services/skills/sync-service.js +99 -0
  143. package/dist/src/services/slice/slice-check-service.js +166 -13
  144. package/dist/src/services/slice/slice-check-types.d.ts +1 -1
  145. package/dist/src/services/standards/migrate-claude-rules-service.d.ts +19 -0
  146. package/dist/src/services/standards/migrate-claude-rules-service.js +193 -0
  147. package/dist/src/services/standards/project-context.d.ts +1 -1
  148. package/dist/src/services/standards/project-context.js +0 -4
  149. package/dist/src/services/standards/project-standards-service.js +1 -3
  150. package/dist/src/services/understand/understand-scan-service.js +15 -2
  151. package/dist/src/services/understand/understand-types.d.ts +26 -0
  152. package/dist/src/services/upgrade/1x-detector-service.d.ts +7 -0
  153. package/dist/src/services/upgrade/1x-detector-service.js +94 -0
  154. package/dist/src/services/upgrade/gitignore-migrate-service.d.ts +56 -0
  155. package/dist/src/services/upgrade/gitignore-migrate-service.js +170 -0
  156. package/dist/src/services/upgrade/upgrade-service.d.ts +47 -0
  157. package/dist/src/services/upgrade/upgrade-service.js +381 -0
  158. package/dist/src/services/workspace/migrate-1-4-1-service.js +1 -1
  159. package/dist/src/services/workspace/sid-naming-guard.d.ts +14 -0
  160. package/dist/src/services/workspace/sid-naming-guard.js +31 -0
  161. package/dist/src/services/workspace/workspace-archive-service.d.ts +19 -0
  162. package/dist/src/services/workspace/workspace-archive-service.js +32 -0
  163. package/dist/src/services/workspace/workspace-clean-service.d.ts +41 -0
  164. package/dist/src/services/workspace/workspace-clean-service.js +86 -0
  165. package/dist/src/services/workspace/workspace-state-service.d.ts +7 -0
  166. package/dist/src/services/workspace/workspace-state-service.js +43 -0
  167. package/dist/src/shared/change-id.js +4 -1
  168. package/dist/src/shared/version.d.ts +1 -1
  169. package/dist/src/shared/version.js +1 -1
  170. package/package.json +10 -8
  171. package/schemas/doctor-report.schema.json +1 -1
  172. package/scripts/install-skills.mjs +296 -12
  173. package/skills/peaks-doctor/SKILL.md +59 -0
  174. package/skills/peaks-doctor/references/doctor-check-catalog.md +31 -0
  175. package/skills/peaks-doctor/references/from-doctor-flow.md +64 -0
  176. package/skills/peaks-doctor/test_prompts.json +17 -0
  177. package/skills/peaks-ide/SKILL.md +2 -0
  178. package/skills/peaks-qa/SKILL.md +9 -7
  179. package/skills/peaks-qa/references/artifact-per-request.md +19 -5
  180. package/skills/peaks-qa/references/qa-perf-test-plan.md +6 -6
  181. package/skills/peaks-qa/references/qa-runbook.md +1 -1
  182. package/skills/peaks-rd/SKILL.md +25 -10
  183. package/skills/peaks-rd/references/ocr-integration.md +214 -0
  184. package/skills/peaks-rd/references/rd-fanout-contracts.md +70 -0
  185. package/skills/peaks-rd/references/rd-runbook.md +1 -1
  186. package/skills/peaks-solo/SKILL.md +11 -5
  187. package/skills/peaks-solo/references/completion-handoff.md +3 -1
  188. package/skills/peaks-solo/references/step-0-55-1x-detection.md +82 -0
  189. package/skills/peaks-solo/references/workflow-gates-and-types.md +9 -0
  190. package/dist/src/cli/commands/shadcn-commands.d.ts +0 -3
  191. package/dist/src/cli/commands/shadcn-commands.js +0 -35
  192. package/dist/src/cli/commands/skill-context-stats-command.d.ts +0 -40
  193. package/dist/src/cli/commands/skill-context-stats-command.js +0 -96
  194. package/dist/src/cli/commands/skill-scope-commands.d.ts +0 -51
  195. package/dist/src/cli/commands/skill-scope-commands.js +0 -310
  196. package/dist/src/services/shadcn/shadcn-service.d.ts +0 -27
  197. package/dist/src/services/shadcn/shadcn-service.js +0 -128
  198. package/dist/src/services/skill-scope/adapters/_stub-helper.d.ts +0 -39
  199. package/dist/src/services/skill-scope/adapters/_stub-helper.js +0 -98
  200. package/dist/src/services/skill-scope/adapters/claude-code.d.ts +0 -59
  201. package/dist/src/services/skill-scope/adapters/claude-code.js +0 -304
  202. package/dist/src/services/skill-scope/adapters/codex.d.ts +0 -2
  203. package/dist/src/services/skill-scope/adapters/codex.js +0 -12
  204. package/dist/src/services/skill-scope/adapters/cursor.d.ts +0 -2
  205. package/dist/src/services/skill-scope/adapters/cursor.js +0 -13
  206. package/dist/src/services/skill-scope/adapters/qoder.d.ts +0 -2
  207. package/dist/src/services/skill-scope/adapters/qoder.js +0 -13
  208. package/dist/src/services/skill-scope/adapters/tongyi.d.ts +0 -2
  209. package/dist/src/services/skill-scope/adapters/tongyi.js +0 -13
  210. package/dist/src/services/skill-scope/adapters/trae.d.ts +0 -2
  211. package/dist/src/services/skill-scope/adapters/trae.js +0 -12
  212. package/dist/src/services/skill-scope/detect.d.ts +0 -81
  213. package/dist/src/services/skill-scope/detect.js +0 -513
  214. package/dist/src/services/skill-scope/registry.d.ts +0 -41
  215. package/dist/src/services/skill-scope/registry.js +0 -83
  216. package/dist/src/services/skill-scope/source-of-truth.d.ts +0 -44
  217. package/dist/src/services/skill-scope/source-of-truth.js +0 -118
  218. package/dist/src/services/skill-scope/types.d.ts +0 -195
  219. package/dist/src/services/skill-scope/types.js +0 -97
@@ -0,0 +1,43 @@
1
+ import { existsSync, mkdirSync, readFileSync, renameSync } from 'node:fs';
2
+ import { join, posix } from 'node:path';
3
+ /**
4
+ * Spec §8.4 + §8.5 — `.peaks/_state/` collects one-time decision dotfiles.
5
+ * Migrates from legacy `.peaks/<name>` flat layout.
6
+ *
7
+ * `stateDirPath` returns a POSIX-normalized logical path so callers and tests
8
+ * can compare against a platform-independent string (the .peaks tree is a
9
+ * config key, not a direct fs call). `mkdirSync` / `renameSync` below use
10
+ * the platform-native `join` so files actually land on disk.
11
+ */
12
+ const LEGACY_DOTFILES = [
13
+ '.peaks-init-hooks-decision.json',
14
+ '.peaks-openspec-opt-in.json',
15
+ ];
16
+ const STATE_DIR_NAME = '_state';
17
+ export function isLegacyDecisionDotfile(name) {
18
+ return LEGACY_DOTFILES.includes(name);
19
+ }
20
+ export function stateDirPath(projectRoot) {
21
+ return posix.join(projectRoot, '.peaks', STATE_DIR_NAME);
22
+ }
23
+ export function collectLegacyDecisionDotfiles(projectRoot) {
24
+ const peaksDir = join(projectRoot, '.peaks');
25
+ // Use the platform-native join for actual filesystem operations;
26
+ // `stateDirPath` (POSIX) is only the public/portable surface for callers.
27
+ const stateDir = join(projectRoot, '.peaks', STATE_DIR_NAME);
28
+ mkdirSync(stateDir, { recursive: true });
29
+ const moved = [];
30
+ const skipped = [];
31
+ for (const name of LEGACY_DOTFILES) {
32
+ const from = join(peaksDir, name);
33
+ const to = join(stateDir, name);
34
+ if (!existsSync(from))
35
+ continue;
36
+ if (existsSync(to)) {
37
+ throw new Error(`DOTFILE_COLLISION: ${name} already exists in ${stateDir} (${readFileSync(to, 'utf8').length} bytes); refusing to overwrite`);
38
+ }
39
+ renameSync(from, to);
40
+ moved.push(name);
41
+ }
42
+ return { moved, skipped };
43
+ }
@@ -303,7 +303,10 @@ export function setCurrentChangeId(projectRoot, changeId, options = {}) {
303
303
  catch { /* best effort */ }
304
304
  }
305
305
  }
306
- symlinkSync(targetDir, bindingPath);
306
+ // On Windows, use a 'junction' (directory hard link) which doesn't
307
+ // require developer mode / admin. POSIX uses a regular 'dir' symlink.
308
+ const linkType = process.platform === 'win32' ? 'junction' : 'dir';
309
+ symlinkSync(targetDir, bindingPath, linkType);
307
310
  }
308
311
  /**
309
312
  * Canonical on-disk path to a change-id's reviewable artifacts
@@ -1 +1 @@
1
- export declare const CLI_VERSION = "1.4.1";
1
+ export declare const CLI_VERSION = "2.0.0";
@@ -1 +1 @@
1
- export const CLI_VERSION = "1.4.1";
1
+ export const CLI_VERSION = "2.0.0";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "peaks-cli",
3
- "version": "1.4.1",
3
+ "version": "2.0.0",
4
4
  "description": "Cross-AI-IDE workflow-gating CLI + skill family (Claude Code shipped, Trae in progress; Codex / Cursor / Qoder / Tongyi Lingma on the roadmap).",
5
5
  "author": "SquabbyZ",
6
6
  "license": "MIT",
@@ -33,7 +33,12 @@
33
33
  "!skills/**/test-prompts.json",
34
34
  "!skills/**/.DS_Store",
35
35
  "output-styles/**",
36
- "schemas/*.json"
36
+ "schemas/*.json",
37
+ ".claude-plugin/**",
38
+ "README.md",
39
+ "README-en.md",
40
+ "CHANGELOG.md",
41
+ "LICENSE"
37
42
  ],
38
43
  "scripts": {
39
44
  "build": "node ./scripts/sync-version.mjs && node ./scripts/clean-dist.mjs && tsc -p tsconfig.json",
@@ -54,16 +59,13 @@
54
59
  "node": ">=20.0.0"
55
60
  },
56
61
  "dependencies": {
62
+ "@alibaba-group/open-code-review": "1.3.1",
57
63
  "@colbymchenry/codegraph": "0.7.10",
58
- "chalk": "^5.6.2",
59
64
  "commander": "^12.1.0",
60
- "headroom-ai": "0.22.4",
61
- "ora": "^8.2.0",
62
- "shadcn": "4.7.0",
63
- "terminal-kit": "^3.1.2"
65
+ "fzf": "^0.5.2",
66
+ "headroom-ai": "0.22.4"
64
67
  },
65
68
  "devDependencies": {
66
- "@types/chalk": "^2.2.4",
67
69
  "@types/node": "^22.10.2",
68
70
  "@vitest/coverage-v8": "^2.1.8",
69
71
  "tsx": "^4.19.2",
@@ -13,7 +13,7 @@
13
13
  "properties": {
14
14
  "id": {
15
15
  "type": "string",
16
- "pattern": "^(skill|skill-name|skill-parse|skill-runbook|skill-apply-note|skill-presence|statusline|schema|config|doctor-self|capability|build|integration):[A-Za-z0-9][A-Za-z0-9._-]*$",
16
+ "pattern": "^(skill|skill-name|skill-parse|skill-runbook|skill-apply-note|skill-presence|statusline|schema|config|doctor-self|capability|build|integration|L3):[A-Za-z0-9][A-Za-z0-9._-]*$",
17
17
  "description": "Stable check id. Known prefixes: skill:<name> (required skill present), skill-name:<dir> (directory matches declared name), skill-parse:<dir> (skill metadata parsed), skill-runbook:<name> (Default runbook section exists), skill-apply-note:<name> (destructive --apply lines carry an authorization/--dry-run note), skill-presence:<topic> (status of .peaks/.active-skill.json — current/freshness/workspace), statusline:<topic> (out-of-band Claude Code statusLine — install/runtime), schema:<file> (schema file exists and is valid JSON), config:<scope> (optional config locations), doctor-self:<topic> (doctor validates its own output against this schema), capability:<name> (third-party capability is resolvable at the pinned version), build:<topic> (build-hygiene checks — dist/source version consistency), integration:<name> (third-party integration probe — e.g. gateguard-fact-force PreToolUse hook conflict on .peaks/**)."
18
18
  },
19
19
  "ok": { "type": "boolean" },
@@ -1,5 +1,6 @@
1
1
  #!/usr/bin/env node
2
2
  import { closeSync, constants, existsSync, fchmodSync, fstatSync, lstatSync, mkdirSync, openSync, readFileSync, readlinkSync, realpathSync, readdirSync, renameSync, symlinkSync, unlinkSync, writeFileSync } from 'node:fs';
3
+ import { spawnSync } from 'node:child_process';
3
4
  import { createHash, randomUUID } from 'node:crypto';
4
5
  import { homedir } from 'node:os';
5
6
  import { basename, dirname, isAbsolute, join, relative, resolve } from 'node:path';
@@ -389,6 +390,19 @@ const IDE_DETECTION_DIRS = [
389
390
  { id: 'tongyi-lingma', dir: '.tongyi-lingma' },
390
391
  ];
391
392
 
393
+ /**
394
+ * Per-IDE skill install paths. Per peaks-cli tenet
395
+ * "minimal-user-operation" (2026-06-11), the user should
396
+ * never have to run a per-platform install command — the
397
+ * `npm i -g peaks-cli` postinstall iterates ALL of these
398
+ * and symlinks the peaks-* skill family to every platform
399
+ * the user might be on.
400
+ *
401
+ * 1.x had only `claude-code` (the other 5 entries were
402
+ * `null`); real Trae users reported the Trae skill
403
+ * directory was never populated. 2.0 fixes this by giving
404
+ * all 8 platforms canonical install paths.
405
+ */
392
406
  const IDE_SKILL_INSTALL_PROFILES = {
393
407
  'claude-code': {
394
408
  skillsDir: join(homedir(), '.claude', 'skills'),
@@ -396,11 +410,48 @@ const IDE_SKILL_INSTALL_PROFILES = {
396
410
  envVar: 'PEAKS_CLAUDE_SKILLS_DIR',
397
411
  outputStylesEnvVar: 'PEAKS_CLAUDE_OUTPUT_STYLES_DIR',
398
412
  },
399
- 'trae': null,
400
- 'codex': null,
401
- 'cursor': null,
402
- 'qoder': null,
403
- 'tongyi-lingma': null,
413
+ 'trae': {
414
+ skillsDir: join(homedir(), '.trae', 'skills'),
415
+ outputStylesDir: join(homedir(), '.trae', 'output-styles'),
416
+ envVar: 'PEAKS_TRAE_SKILLS_DIR',
417
+ outputStylesEnvVar: 'PEAKS_TRAE_OUTPUT_STYLES_DIR',
418
+ },
419
+ 'codex': {
420
+ skillsDir: join(homedir(), '.codex', 'skills'),
421
+ outputStylesDir: join(homedir(), '.codex', 'output-styles'),
422
+ envVar: 'PEAKS_CODEX_SKILLS_DIR',
423
+ outputStylesEnvVar: 'PEAKS_CODEX_OUTPUT_STYLES_DIR',
424
+ },
425
+ 'cursor': {
426
+ skillsDir: join(homedir(), '.cursor', 'skills'),
427
+ outputStylesDir: join(homedir(), '.cursor', 'output-styles'),
428
+ envVar: 'PEAKS_CURSOR_SKILLS_DIR',
429
+ outputStylesEnvVar: 'PEAKS_CURSOR_OUTPUT_STYLES_DIR',
430
+ },
431
+ 'qoder': {
432
+ skillsDir: join(homedir(), '.qoder', 'skills'),
433
+ outputStylesDir: join(homedir(), '.qoder', 'output-styles'),
434
+ envVar: 'PEAKS_QODER_SKILLS_DIR',
435
+ outputStylesEnvVar: 'PEAKS_QODER_OUTPUT_STYLES_DIR',
436
+ },
437
+ 'tongyi-lingma': {
438
+ skillsDir: join(homedir(), '.tongyi-lingma', 'skills'),
439
+ outputStylesDir: join(homedir(), '.tongyi-lingma', 'output-styles'),
440
+ envVar: 'PEAKS_TONGYI_SKILLS_DIR',
441
+ outputStylesEnvVar: 'PEAKS_TONGYI_OUTPUT_STYLES_DIR',
442
+ },
443
+ 'hermes': {
444
+ skillsDir: join(homedir(), '.hermes', 'skills'),
445
+ outputStylesDir: join(homedir(), '.hermes', 'output-styles'),
446
+ envVar: 'PEAKS_HERMES_SKILLS_DIR',
447
+ outputStylesEnvVar: 'PEAKS_HERMES_OUTPUT_STYLES_DIR',
448
+ },
449
+ 'openclaw': {
450
+ skillsDir: join(homedir(), '.openclaw', 'skills'),
451
+ outputStylesDir: join(homedir(), '.openclaw', 'output-styles'),
452
+ envVar: 'PEAKS_OPENCLAW_SKILLS_DIR',
453
+ outputStylesEnvVar: 'PEAKS_OPENCLAW_OUTPUT_STYLES_DIR',
454
+ },
404
455
  };
405
456
 
406
457
  function detectInstalledIdeId(projectRoot) {
@@ -657,9 +708,228 @@ export function installBundledOutputStyles(options = {}) {
657
708
  return { installed, skipped };
658
709
  }
659
710
 
711
+ /**
712
+ * Per-platform fan-out — iterate ALL 8 IdeIds and call
713
+ * `installBundledSkills` for each. Per peaks-cli tenet
714
+ * "minimal-user-operation" (2026-06-11): the user should
715
+ * never have to run a per-platform install command. The
716
+ * 1.x postinstall only handled the auto-detected single
717
+ * IDE; 2.0 fixes this so the peaks-* skill family is
718
+ * symlinked to every platform the user might be on.
719
+ *
720
+ * Returns an array of { ideId, skillsDir, installed, skipped }
721
+ * per platform. Symlink failures are soft (logged to stderr,
722
+ * never throw) so one platform's failure doesn't block the
723
+ * other 7.
724
+ */
725
+ export function installBundledSkillsForAllPlatforms(options = {}) {
726
+ const platforms = Object.keys(IDE_SKILL_INSTALL_PROFILES);
727
+ const perPlatform = [];
728
+ // Back-compat precedence (regression fix 2026-06-12,
729
+ // slice 2026-06-12-postinstall-1x-detector-tdd):
730
+ // when iterating the 8 platforms, the claude-code install
731
+ // must still honor the PEAKS_CLAUDE_SKILLS_DIR env var
732
+ // (the legacy back-compat surface from 1.x). The other 7
733
+ // platforms use their per-IDE profile paths unconditionally.
734
+ // Without this fix the 8-IDE fan-out regresses the
735
+ // `peaks install-skills` env-var override contract that
736
+ // user CI / 1.x → 2.0 migration scripts depend on.
737
+ const claudeEnv = process.env.PEAKS_CLAUDE_SKILLS_DIR;
738
+ for (const ideId of platforms) {
739
+ try {
740
+ const platformOpts =
741
+ ideId === 'claude-code' && claudeEnv !== undefined && claudeEnv.length > 0
742
+ ? { ...options, ideId, targetRoot: claudeEnv }
743
+ : { ...options, ideId };
744
+ const result = installBundledSkills(platformOpts);
745
+ perPlatform.push({
746
+ ideId,
747
+ skillsDir: IDE_SKILL_INSTALL_PROFILES[ideId]?.skillsDir ?? '(unknown)',
748
+ installed: result.installed,
749
+ skipped: result.skipped,
750
+ });
751
+ } catch (err) {
752
+ const message = err instanceof Error ? err.message : String(err);
753
+ process.stderr.write(
754
+ `peaks install-skills: ${ideId} platform failed (continuing): ${message}\n`
755
+ );
756
+ perPlatform.push({
757
+ ideId,
758
+ skillsDir: IDE_SKILL_INSTALL_PROFILES[ideId]?.skillsDir ?? '(unknown)',
759
+ installed: [],
760
+ skipped: [],
761
+ error: message,
762
+ });
763
+ }
764
+ }
765
+ return perPlatform;
766
+ }
767
+
768
+ /**
769
+ * 1.x → 2.0 detection — sniff for legacy 1.x project state
770
+ * in `cwd`. Returns a 1.x detection envelope with the
771
+ * detected signals (so the postinstall can decide whether
772
+ * to auto-upgrade).
773
+ *
774
+ * 1.x signals (any one fires the detection):
775
+ * - `~/.peaks/config.json` exists with `version: '1.4.2'` (or
776
+ * any '1.x' version that predates the 2.0 schema)
777
+ * - `.claude/rules/common/dev-preference.md` exists and
778
+ * references "peaks progress" (the 1.x CLI surface
779
+ * removed in slice #014)
780
+ * - `<cwd>/.peaks/preferences.json` missing OR has no
781
+ * `schema_version: '2.0.0'` field
782
+ *
783
+ * Returns:
784
+ * { isOneX: boolean, signals: string[], projectRoot: string|null,
785
+ * configPath: string|null }
786
+ */
787
+ export function detect1xProjectState(cwd = process.cwd()) {
788
+ const home = homedir();
789
+ const signals = [];
790
+ let projectRoot = null;
791
+ let configPath = null;
792
+
793
+ // Walk up from cwd looking for .peaks/_runtime (signals
794
+ // we're inside a peaks project).
795
+ let dir = cwd;
796
+ for (let i = 0; i < 8; i += 1) {
797
+ const peaksRuntime = join(dir, '.peaks', '_runtime');
798
+ if (existsSync(peaksRuntime)) {
799
+ projectRoot = dir;
800
+ break;
801
+ }
802
+ const parent = dirname(dir);
803
+ if (parent === dir) break;
804
+ dir = parent;
805
+ }
806
+
807
+ // Signal 1: ~/.peaks/config.json with 1.x version
808
+ const globalConfig = join(home, '.peaks', 'config.json');
809
+ if (existsSync(globalConfig)) {
810
+ try {
811
+ const raw = JSON.parse(readFileSync(globalConfig, 'utf8'));
812
+ if (typeof raw.version === 'string' && /^1\./.test(raw.version)) {
813
+ signals.push(`global config at ${globalConfig} is 1.x (${raw.version})`);
814
+ if (configPath === null) configPath = globalConfig;
815
+ }
816
+ } catch {
817
+ // ignore parse error — the 1.x detection is best-effort
818
+ }
819
+ }
820
+
821
+ // Signal 2: .claude/rules/common/dev-preference.md with peaks progress
822
+ if (projectRoot !== null) {
823
+ const devPref = join(projectRoot, '.claude', 'rules', 'common', 'dev-preference.md');
824
+ if (existsSync(devPref)) {
825
+ try {
826
+ const body = readFileSync(devPref, 'utf8');
827
+ if (/peaks progress/i.test(body)) {
828
+ signals.push(`${devPref} references "peaks progress" (1.x CLI surface, removed in slice #014)`);
829
+ }
830
+ } catch {
831
+ // ignore
832
+ }
833
+ }
834
+ // Signal 3: project preferences.json missing or 1.x
835
+ const prefs = join(projectRoot, '.peaks', 'preferences.json');
836
+ if (!existsSync(prefs)) {
837
+ signals.push(`${prefs} does not exist (1.x project never migrated)`);
838
+ } else {
839
+ try {
840
+ const raw = JSON.parse(readFileSync(prefs, 'utf8'));
841
+ if (raw.schema_version !== '2.0.0') {
842
+ signals.push(`${prefs} has schema_version ${JSON.stringify(raw.schema_version)}, expected '2.0.0'`);
843
+ }
844
+ } catch {
845
+ signals.push(`${prefs} exists but is not valid JSON`);
846
+ }
847
+ }
848
+ }
849
+
850
+ return {
851
+ isOneX: signals.length > 0,
852
+ signals,
853
+ projectRoot,
854
+ configPath,
855
+ };
856
+ }
857
+
858
+ /**
859
+ * Postinstall auto-upgrade — when the user just ran
860
+ * `npm i -g peaks-cli@2.0` and `cwd` is a 1.x peaks-cli
861
+ * project, this shells out to the installed `peaks`
862
+ * binary to run the umbrella `peaks upgrade --to 2.0 --auto`.
863
+ *
864
+ * Per the "minimal-user-operation" tenet, the user should
865
+ * never have to run a second command after `npm i -g`. The
866
+ * upgrade CLI (if installed) is at the resolved `peaks`
867
+ * binary path; if not, the user gets a hint to run it
868
+ * manually.
869
+ *
870
+ * The auto-upgrade is opt-out via:
871
+ * PEAKS_SKIP_AUTO_UPGRADE=1
872
+ * (so a CI box that installs 2.0 but never wants the
873
+ * project-level migration can suppress the auto-step).
874
+ */
875
+ export async function autoUpgrade1xProjectIfPresent(options = {}) {
876
+ if (process.env.PEAKS_SKIP_AUTO_UPGRADE === '1') {
877
+ return { ran: false, reason: 'PEAKS_SKIP_AUTO_UPGRADE=1' };
878
+ }
879
+ const state = detect1xProjectState(options.cwd ?? process.cwd());
880
+ if (!state.isOneX) {
881
+ return { ran: false, reason: 'no 1.x project state detected' };
882
+ }
883
+ if (state.projectRoot === null) {
884
+ return { ran: false, reason: 'cwd is not a peaks project (no .peaks/_runtime/)' };
885
+ }
886
+ // The peaks binary should be on PATH after `npm i -g`.
887
+ // We shell out via spawnSync (synchronous; the postinstall
888
+ // is already synchronous and the umbrella is fast).
889
+ try {
890
+ const result = spawnSync('peaks', ['upgrade', '--to', '2.0', '--auto', '--project', state.projectRoot], {
891
+ encoding: 'utf8',
892
+ stdio: ['ignore', 'pipe', 'pipe'],
893
+ timeout: 120_000,
894
+ });
895
+ return {
896
+ ran: true,
897
+ reason: 'auto-upgrade dispatched',
898
+ signals: state.signals,
899
+ projectRoot: state.projectRoot,
900
+ exitCode: result.status,
901
+ stdout: result.stdout ?? '',
902
+ stderr: result.stderr ?? '',
903
+ };
904
+ } catch (err) {
905
+ return {
906
+ ran: true,
907
+ reason: 'auto-upgrade dispatched but failed',
908
+ signals: state.signals,
909
+ projectRoot: state.projectRoot,
910
+ error: err instanceof Error ? err.message : String(err),
911
+ };
912
+ }
913
+ }
914
+
660
915
  if (process.argv[1] !== undefined && import.meta.url === pathToFileURL(resolve(process.argv[1])).href) {
661
916
  try {
662
- const skillsResult = installBundledSkills();
917
+ // 2.0 fix for the 1.x Trae bug (per real user feedback
918
+ // 2026-06-11): iterate ALL 8 platforms, not just the
919
+ // auto-detected one. Per the "minimal-user-operation"
920
+ // tenet, the user should never have to run a
921
+ // per-platform install command.
922
+ const perPlatform = installBundledSkillsForAllPlatforms();
923
+ let totalInstalled = 0;
924
+ for (const p of perPlatform) {
925
+ totalInstalled += p.installed.length;
926
+ }
927
+ if (totalInstalled > 0) {
928
+ process.stdout.write(
929
+ `Peaks skills linked across ${perPlatform.length} platforms ` +
930
+ `(${totalInstalled} total symlinks)\n`
931
+ );
932
+ }
663
933
  const outputStylesResult = installBundledOutputStyles();
664
934
  let userConfigResult = createConfigResult({ skipped: true });
665
935
  try {
@@ -668,12 +938,6 @@ if (process.argv[1] !== undefined && import.meta.url === pathToFileURL(resolve(p
668
938
  const message = error instanceof Error ? error.message : String(error);
669
939
  process.stderr.write(`Peaks user config was not installed: ${message}\n`);
670
940
  }
671
- if (skillsResult.installed.length > 0) {
672
- process.stdout.write(`Peaks skills linked: ${skillsResult.installed.join(', ')}\n`);
673
- }
674
- if (skillsResult.skipped.length > 0) {
675
- process.stderr.write(`Peaks skills skipped because local files already exist: ${skillsResult.skipped.join(', ')}\n`);
676
- }
677
941
  if (outputStylesResult.installed.length > 0) {
678
942
  process.stdout.write(`Peaks output styles installed: ${outputStylesResult.installed.join(', ')}\n`);
679
943
  }
@@ -683,6 +947,26 @@ if (process.argv[1] !== undefined && import.meta.url === pathToFileURL(resolve(p
683
947
  if (userConfigResult.created) {
684
948
  process.stdout.write('Peaks user config created: ~/.peaks/config.json\n');
685
949
  }
950
+
951
+ // 2.0 postinstall: auto-detect 1.x project state in cwd
952
+ // and dispatch the upgrade umbrella. This makes the
953
+ // user's `npm i -g peaks-cli@2.0` truly one-key.
954
+ if (process.env.PEAKS_SKIP_AUTO_UPGRADE !== '1') {
955
+ // Fire-and-forget; the upgrade is async by design so
956
+ // the npm install output isn't blocked. We print a
957
+ // one-line hint so the user knows the auto-step
958
+ // happened.
959
+ autoUpgrade1xProjectIfPresent().then((result) => {
960
+ if (result.ran) {
961
+ process.stdout.write(
962
+ `\n✓ Detected 1.x peaks-cli project at ${result.projectRoot}\n` +
963
+ ` → auto-upgraded to 2.0 (${result.signals?.length ?? 0} signals resolved)\n` +
964
+ ` Run \`peaks audit red-lines --project .\` to verify.\n`
965
+ );
966
+ }
967
+ // When !result.ran we say nothing — silent on success.
968
+ });
969
+ }
686
970
  if (userConfigResult.updated) {
687
971
  process.stdout.write('Peaks user config updated: ~/.peaks/config.json\n');
688
972
  }
@@ -0,0 +1,59 @@
1
+ ---
2
+ name: peaks-doctor
3
+ description: Orchestrate peaks-cli's L3 doctor (peaks audit + peaks doctor + peaks openspec from-doctor) for project health. Use when the user asks for a project health check, doctor report, audit, or wants to convert doctor findings into OpenSpec change records. Coordinates the L2 audit framework + the L3.2 doctor + the L3.3 from-doctor proposal generator. Triggers on `/peaks-doctor`, "peaks doctor", "项目健康", "doctor report", "health check", "check the project", "audit my repo".
4
+ internal: true
5
+ ---
6
+ ---
7
+
8
+ # Peaks-Cli Doctor
9
+
10
+ Peaks-Cli Doctor is the orchestration facade for the L3 doctor workflow. It runs the L2 audit framework (`peaks audit red-lines`) + the L3.2 doctor checks (`peaks doctor`) + the L3.3 from-doctor proposal generator (`peaks openspec from-doctor`). Use it when the user wants a project health check, a red-line audit, or to convert doctor findings into OpenSpec change records.
11
+
12
+ ## Skill-first architecture note (read once, internalise)
13
+
14
+ This skill is the **primary surface**. The `peaks <cmd>` CLI is **auxiliary** — invoked by the skill prompt only when a primitive is the right tool. Behaviour only an LLM in a skill prompt would use lives **here in the SKILL.md**, not as a new CLI command. See `.claude/rules/common/dev-preference.md` for the decision template.
15
+
16
+ ## Code-Change Red Line (BLOCKING — read before ANY tool call)
17
+
18
+ **Peaks-Cli Doctor is a doctor orchestrator, NOT an implementer. You MUST NOT write, edit, or modify any application source code directly.**
19
+
20
+ The doctor workflow is read-only by design. It produces:
21
+ - `peaks audit red-lines` report (121 red lines in the current repo, 6 cli-backed)
22
+ - `peaks doctor` report (69 checks: 68 pass, 1 fail — L3:l3-memory-health)
23
+ - Optional OpenSpec change records via `peaks openspec from-doctor`
24
+
25
+ If a doctor finding requires a code change, the workflow hands off to `peaks-rd` (or `peaks-solo` for the full pipeline). The doctor itself does NOT modify code.
26
+
27
+ ## Workflow (5 steps)
28
+
29
+ 1. **Anchor**: `peaks workspace init --project <repo> --json` (idempotent; same as every peaks-* skill).
30
+ 2. **Run audit**: `peaks audit red-lines --project <repo> --json` — returns the red-line audit (catalog-matched markers + live enforcer findings). Inspect the `enforcerFindings` array for runtime-detected issues.
31
+ 3. **Run doctor**: `peaks doctor --json` — returns 69 checks. Pay special attention to:
32
+ - `L3:l3-orphan-sessions` — invalid sids in .peaks/_runtime/
33
+ - `L3:l3-memory-health` — .peaks/memory/index.json shape
34
+ - `integration:gateguard-peaks-conflict` — third-party Edit/Write hook interference
35
+ - `build:workspace-layout-canonical` — workspace layout
36
+ 4. **Triage findings**: For each FAIL check, decide:
37
+ - **Real bug requiring fix** → hand off to peaks-rd (run `peaks openspec from-doctor` first to generate a draft proposal; then peaks-rd to implement)
38
+ - **Acceptable false positive** → document in the handoff; do not act
39
+ - **Configuration drift** → run the suggested recovery command (e.g. `peaks workspace clean`)
40
+ 5. **Generate proposals** (per FAIL finding): `peaks openspec from-doctor --project <repo> --check-id <id>` writes `openspec/changes/<date>-fix-<slug>/proposal.md`. Hand off to peaks-rd for implementation.
41
+
42
+ ## CLI primitives the skill composes
43
+
44
+ - `peaks workspace init` — anchor the workspace (Step 0)
45
+ - `peaks audit red-lines` — L2 audit
46
+ - `peaks doctor` — L3.2 doctor
47
+ - `peaks openspec from-doctor` — L3.3 proposal generator
48
+ - `peaks openspec validate` — gate a draft proposal
49
+
50
+ ## Boundaries
51
+
52
+ - The doctor is read-only. It does NOT modify code, fix bugs, or clean up sessions.
53
+ - The doctor does NOT install UA or any third-party tool. The opt-in UX is surfaced via `peaks understand opt-in`; the doctor just reports state.
54
+ - The doctor does NOT generate change records automatically; it surfaces findings + the LLM calls `peaks openspec from-doctor` to generate them.
55
+
56
+ ## References
57
+
58
+ - `references/doctor-check-catalog.md` — every doctor check id + what it means
59
+ - `references/from-doctor-flow.md` — the end-to-end "finding → proposal" path
@@ -0,0 +1,31 @@
1
+ # Doctor check catalog (peaks-doctor skill reference)
2
+
3
+ Slice L3.2 ships 69 doctor checks. The most user-relevant ones:
4
+
5
+ ## L2 audit (slice #2)
6
+
7
+ - **`L2:audit:cli-backed`** — count of red lines whose catalog match has a real enforcer
8
+ - **`L2:audit:prose-only`** — count of red lines that need a future enforcer
9
+
10
+ ## L3.2 (slice #9)
11
+
12
+ - **`L3:l3-orphan-sessions`** — directories in `.peaks/_runtime/` that fail `isValidSessionId`. Recover with `peaks workspace clean`.
13
+ - **`L3:l3-memory-health`** — `.peaks/memory/index.json` must be well-formed JSON with a `schema_version` field and an array `entries`. Recovers by re-running `peaks memory extract`.
14
+
15
+ ## Build / workspace
16
+
17
+ - **`build:dist-version-matches-source`** — `dist/src/shared/version.js` matches the source `package.json` version
18
+ - **`build:workspace-layout-canonical`** — `.peaks/` follows the canonical `._archive` / `_runtime` / `_sub_agents` layout
19
+ - **`build:workspace-migrate-not-needed`** — when the layout is already canonical
20
+
21
+ ## Integration (third-party hooks)
22
+
23
+ - **`integration:gateguard-peaks-conflict`** — warns when `gateguard-fact-force` is installed without a `.peaks/**` skip pattern (the 3rd-party hook would block all peaks-qa .peaks/ artifact writes)
24
+
25
+ ## Skills
26
+
27
+ - **`skill:<required-skill>`** — each required skill (peaks-ide, peaks-prd, peaks-rd, peaks-qa, peaks-sc, peaks-solo, peaks-sop, peaks-txt, peaks-ui, peaks-doctor) must be installed in the bundled skills dir
28
+
29
+ ## Doctor self
30
+
31
+ - **`doctor-self:check-id-pattern`** — all check IDs match the `doctor-report.schema.json` regex pattern (prevents typos like `L3:l3-orphan-sesions`)
@@ -0,0 +1,64 @@
1
+ # from-doctor flow (peaks-doctor skill reference)
2
+
3
+ End-to-end path from a doctor finding to an OpenSpec change record.
4
+
5
+ ## Flow
6
+
7
+ ```
8
+ peaks doctor --json # 1. discover findings
9
+
10
+ match: any check where ok=false
11
+
12
+ peaks openspec from-doctor \
13
+ --project <repo> \
14
+ --check-id <id> # 2. generate draft proposal
15
+
16
+ openspec/changes/<date>-fix-<slug>/proposal.md # 3. LLM reviews + edits
17
+
18
+ peaks openspec validate <change-id> # 4. gate
19
+
20
+ [next slice: peaks-rd implements the change per the proposal]
21
+ ```
22
+
23
+ ## Example
24
+
25
+ ```bash
26
+ # Discover
27
+ $ peaks doctor --json | jq '.data.checks[] | select(.ok==false) | .id'
28
+ "L3:l3-memory-health"
29
+
30
+ # Generate draft
31
+ $ peaks openspec from-doctor \
32
+ --project . \
33
+ --check-id L3:l3-memory-health \
34
+ --json
35
+ {
36
+ "ok": true,
37
+ "command": "openspec.from-doctor",
38
+ "data": {
39
+ "changeId": "2026-06-11-fix-l3-l3-memory-health",
40
+ "proposalPath": ".../openspec/changes/2026-06-11-fix-l3-l3-memory-health/proposal.md",
41
+ "created": true
42
+ }
43
+ }
44
+
45
+ # LLM reviews + edits the draft (in this case: add a Why section
46
+ # explaining the missing schema_version field; add an Acceptance
47
+ # Criterion that requires peaks doctor to return ok=true for the check)
48
+
49
+ # Validate
50
+ $ peaks openspec validate 2026-06-11-fix-l3-l3-memory-health --json
51
+ {
52
+ "ok": true,
53
+ "data": { "valid": true, "issues": [] }
54
+ }
55
+
56
+ # Implement (peaks-rd)
57
+ $ /peaks-rd 2026-06-11-fix-l3-l3-memory-health
58
+ ```
59
+
60
+ ## Edge cases
61
+
62
+ - **CHECK_ALREADY_PASSING**: `--check-id` matches a passing check. The CLI returns code CHECK_ALREADY_PASSING. Pick a failing check.
63
+ - **CHECK_NOT_FOUND**: `--check-id` doesn't match any check id. Run `peaks doctor --json | jq '.data.checks[].id'` to list.
64
+ - **OPENSPEC_FROM_DOCTOR_FAILED**: filesystem write error (e.g. openspec/ not initialized). Run `peaks openspec init --apply` first.
@@ -0,0 +1,17 @@
1
+ [
2
+ {
3
+ "id": "doctor-baseline",
4
+ "prompt": "/peaks-doctor",
5
+ "expectedOutcome": "Runs peaks workspace init + peaks audit + peaks doctor; returns a triage of FAIL checks with hand-off suggestions."
6
+ },
7
+ {
8
+ "id": "doctor-from-finding",
9
+ "prompt": "peaks doctor flagged L3:l3-memory-health. Generate an OpenSpec change record from it.",
10
+ "expectedOutcome": "Calls peaks openspec from-doctor --check-id L3:l3-memory-health; verifies the proposal.md was written; suggests next step (peaks-rd)."
11
+ },
12
+ {
13
+ "id": "doctor-only-audit",
14
+ "prompt": "Run only the audit (not the full doctor).",
15
+ "expectedOutcome": "Calls peaks audit red-lines --project . --json; summarizes the enforcerFindings and the prose-only ratio."
16
+ }
17
+ ]
@@ -1,6 +1,8 @@
1
1
  ---
2
2
  name: peaks-ide
3
3
  description: Orchestrate peaks-cli's IDE-aware behavior (hooks + statusline + handle) for a user's specific IDE. Detects the current state (which IDE the user is on, what peaks has already installed), plans the install / switch / status / uninstall actions, and invokes the existing peaks CLI primitives. Triggers on `/peaks-ide`, "set up peaks for my IDE", "switch peaks to Trae", "what did peaks install", "uninstall peaks hooks". Sits between the user and `peaks hooks install` / `peaks statusline install` / `peaks hook handle` — those are the CLI primitives; this skill is the user-facing surface.
4
+ internal: true
5
+ ---
4
6
  ---
5
7
 
6
8
  # Peaks-Cli IDE Setup (peaks-ide)