peaks-loop 4.0.0-beta.5 → 4.0.0-beta.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (58) hide show
  1. package/CHANGELOG.md +62 -0
  2. package/dist/src/cli/commands/adapter-commands-s2a.d.ts +34 -0
  3. package/dist/src/cli/commands/adapter-commands-s2a.js +92 -0
  4. package/dist/src/cli/commands/ide-commands.d.ts +25 -0
  5. package/dist/src/cli/commands/ide-commands.js +42 -0
  6. package/dist/src/cli/commands/polyrepo-commands.d.ts +37 -0
  7. package/dist/src/cli/commands/polyrepo-commands.js +155 -0
  8. package/dist/src/cli/commands/runtime-commands.d.ts +52 -0
  9. package/dist/src/cli/commands/runtime-commands.js +150 -0
  10. package/dist/src/cli/program.js +23 -0
  11. package/dist/src/services/adapter/adapter-registry.d.ts +48 -0
  12. package/dist/src/services/adapter/adapter-registry.js +186 -0
  13. package/dist/src/services/config/model-routing.d.ts +55 -2
  14. package/dist/src/services/config/model-routing.js +79 -3
  15. package/dist/src/services/ide/adapters/zcode-adapter.d.ts +40 -0
  16. package/dist/src/services/ide/adapters/zcode-adapter.js +220 -0
  17. package/dist/src/services/ide/current-model-detector.d.ts +14 -0
  18. package/dist/src/services/ide/current-model-detector.js +60 -0
  19. package/dist/src/services/ide/ide-registry.js +3 -0
  20. package/dist/src/services/ide/ide-types.d.ts +24 -1
  21. package/dist/src/services/polyrepo/polyrepo-dispatcher.d.ts +34 -0
  22. package/dist/src/services/polyrepo/polyrepo-dispatcher.js +119 -0
  23. package/dist/src/services/polyrepo/polyrepo-scanner.d.ts +9 -0
  24. package/dist/src/services/polyrepo/polyrepo-scanner.js +94 -0
  25. package/dist/src/services/polyrepo/polyrepo-service.d.ts +34 -0
  26. package/dist/src/services/polyrepo/polyrepo-service.js +49 -0
  27. package/dist/src/services/polyrepo/polyrepo-types.d.ts +55 -0
  28. package/dist/src/services/polyrepo/polyrepo-types.js +1 -0
  29. package/dist/src/services/preferences/preferences-types.d.ts +1 -1
  30. package/dist/src/services/providers/minimax-worker-service.d.ts +1 -1
  31. package/dist/src/services/providers/minimax-worker-service.js +1 -1
  32. package/dist/src/services/rd/rd-service.js +7 -4
  33. package/dist/src/services/runtime/runtime-detector.d.ts +15 -0
  34. package/dist/src/services/runtime/runtime-detector.js +62 -0
  35. package/dist/src/services/runtime/runtime-service.d.ts +59 -0
  36. package/dist/src/services/runtime/runtime-service.js +51 -0
  37. package/dist/src/services/runtime/vendor-adapter.d.ts +59 -0
  38. package/dist/src/services/runtime/vendor-adapter.js +1 -0
  39. package/dist/src/services/runtime/vendors/claude-code.d.ts +7 -0
  40. package/dist/src/services/runtime/vendors/claude-code.js +39 -0
  41. package/dist/src/services/runtime/vendors/codex.d.ts +7 -0
  42. package/dist/src/services/runtime/vendors/codex.js +43 -0
  43. package/dist/src/services/runtime/vendors/copilot.d.ts +7 -0
  44. package/dist/src/services/runtime/vendors/copilot.js +40 -0
  45. package/dist/src/services/workflow/workflow-router-service.d.ts +1 -1
  46. package/dist/src/services/workflow/workflow-router-service.js +37 -31
  47. package/dist/src/shared/version.d.ts +1 -1
  48. package/dist/src/shared/version.js +1 -1
  49. package/package.json +1 -1
  50. package/scripts/install-skills.mjs +13 -10
  51. package/skills/peaks-code/SKILL.md +26 -12
  52. package/skills/peaks-code/references/external-references.md +1 -3
  53. package/skills/peaks-code/references/external-skill-invocation.md +1 -1
  54. package/skills/peaks-code/references/runbook.md +1 -3
  55. package/skills/peaks-code/references/step-0-55-1x-detection.md +2 -1
  56. package/skills/peaks-code/references/workflow-gates-and-types.md +1 -1
  57. package/skills/peaks-slice-decompose/SKILL.md +61 -1
  58. package/skills/peaks-code/references/openspec-workflow.md +0 -81
@@ -1,4 +1,4 @@
1
- import { getConfiguredExecutionModelId, STRONGEST_MODEL_ID } from '../config/model-routing.js';
1
+ import { getConfiguredExecutionModelId, getStrongestModelId } from '../config/model-routing.js';
2
2
  import { getLocalArtifactPath } from '../artifacts/workspace-service.js';
3
3
  import { createRdSwarmPlan } from '../rd/rd-service.js';
4
4
  import { createTechPlan, getTechStatus } from '../tech/tech-service.js';
@@ -37,12 +37,12 @@ function assertCodeModeAllowed(mode, codeMode) {
37
37
  throw new Error('codeMode requires code workflow mode');
38
38
  }
39
39
  }
40
- function step(input, executionModelId) {
40
+ function step(input, executionModelId, strongestModelId) {
41
41
  const modelRole = EXECUTION_STAGES.includes(input.stage) ? 'execution' : 'strongest';
42
42
  return {
43
43
  ...input,
44
44
  modelRole,
45
- modelId: modelRole === 'execution' ? executionModelId : STRONGEST_MODEL_ID,
45
+ modelId: modelRole === 'execution' ? executionModelId : strongestModelId,
46
46
  dryRunOnly: true,
47
47
  invokesAgents: false,
48
48
  writesArtifacts: false
@@ -78,40 +78,40 @@ function annotateSteps(steps, codeMode) {
78
78
  };
79
79
  });
80
80
  }
81
- function createSoloSteps(executionModelId) {
81
+ function createSoloSteps(executionModelId, strongestModelId) {
82
82
  return [
83
- step({ id: 'code-product-direction', stage: 'product-direction', owner: 'peaks-code', modelTier: 'top-tier', reason: 'Product direction needs strong judgment before execution work is delegated.', dependsOn: [] }, executionModelId),
84
- step({ id: 'code-design-direction', stage: 'design-direction', owner: 'peaks-code', modelTier: 'top-tier', reason: 'Design direction uses the recommended default before cheaper implementation work.', dependsOn: ['code-product-direction'] }, executionModelId),
85
- step({ id: 'code-tech-direction', stage: 'tech-direction', owner: 'peaks-tech', modelTier: 'top-tier', reason: 'Technical boundaries and approval gates use the recommended default with high-confidence planning.', dependsOn: ['code-design-direction'] }, executionModelId),
86
- step({ id: 'code-tech-review', stage: 'tech-review', owner: 'peaks-tech', modelTier: 'top-tier', reason: 'Tech artifacts and gate decisions require strong review and a recommended default path.', dependsOn: ['code-tech-direction'] }, executionModelId),
87
- step({ id: 'code-rd-planning', stage: 'rd-planning', owner: 'peaks-rd', modelTier: 'top-tier', reason: 'RD task decomposition and acceptance criteria use the recommended default before execution delegation.', dependsOn: ['code-tech-review'] }, executionModelId),
88
- step({ id: 'code-coding-execution', stage: 'coding-execution', owner: 'peaks-rd', modelTier: executionModelId === STRONGEST_MODEL_ID ? 'top-tier' : 'mid-tier', reason: `Coding and routine refactoring must use the configured execution worker model ${executionModelId}.`, dependsOn: ['code-rd-planning'] }, executionModelId),
89
- step({ id: 'code-unit-test-execution', stage: 'unit-test-execution', owner: 'peaks-rd', modelTier: executionModelId === STRONGEST_MODEL_ID ? 'top-tier' : 'mid-tier', reason: `Unit test authoring and focused test runs must use the configured execution worker model ${executionModelId}.`, dependsOn: ['code-coding-execution'] }, executionModelId),
90
- step({ id: 'code-quality-review', stage: 'quality-review', owner: 'peaks-code', modelTier: 'top-tier', reason: 'Reducer and final quality gates need strong synthesis and risk review.', dependsOn: ['code-unit-test-execution'] }, executionModelId)
83
+ step({ id: 'code-product-direction', stage: 'product-direction', owner: 'peaks-code', modelTier: 'top-tier', reason: 'Product direction needs strong judgment before execution work is delegated.', dependsOn: [] }, executionModelId, strongestModelId),
84
+ step({ id: 'code-design-direction', stage: 'design-direction', owner: 'peaks-code', modelTier: 'top-tier', reason: 'Design direction uses the recommended default before cheaper implementation work.', dependsOn: ['code-product-direction'] }, executionModelId, strongestModelId),
85
+ step({ id: 'code-tech-direction', stage: 'tech-direction', owner: 'peaks-tech', modelTier: 'top-tier', reason: 'Technical boundaries and approval gates use the recommended default with high-confidence planning.', dependsOn: ['code-design-direction'] }, executionModelId, strongestModelId),
86
+ step({ id: 'code-tech-review', stage: 'tech-review', owner: 'peaks-tech', modelTier: 'top-tier', reason: 'Tech artifacts and gate decisions require strong review and a recommended default path.', dependsOn: ['code-tech-direction'] }, executionModelId, strongestModelId),
87
+ step({ id: 'code-rd-planning', stage: 'rd-planning', owner: 'peaks-rd', modelTier: 'top-tier', reason: 'RD task decomposition and acceptance criteria use the recommended default before execution delegation.', dependsOn: ['code-tech-review'] }, executionModelId, strongestModelId),
88
+ step({ id: 'code-coding-execution', stage: 'coding-execution', owner: 'peaks-rd', modelTier: executionModelId === strongestModelId ? 'top-tier' : 'mid-tier', reason: `Coding and routine refactoring must use the configured execution worker model ${executionModelId}.`, dependsOn: ['code-rd-planning'] }, executionModelId, strongestModelId),
89
+ step({ id: 'code-unit-test-execution', stage: 'unit-test-execution', owner: 'peaks-rd', modelTier: executionModelId === strongestModelId ? 'top-tier' : 'mid-tier', reason: `Unit test authoring and focused test runs must use the configured execution worker model ${executionModelId}.`, dependsOn: ['code-coding-execution'] }, executionModelId, strongestModelId),
90
+ step({ id: 'code-quality-review', stage: 'quality-review', owner: 'peaks-code', modelTier: 'top-tier', reason: 'Reducer and final quality gates need strong synthesis and risk review.', dependsOn: ['code-unit-test-execution'] }, executionModelId, strongestModelId)
91
91
  ];
92
92
  }
93
- function createSoloStepsForMode(codeMode, executionModelId) {
94
- return annotateSteps(createSoloSteps(executionModelId), codeMode);
93
+ function createSoloStepsForMode(codeMode, executionModelId, strongestModelId) {
94
+ return annotateSteps(createSoloSteps(executionModelId, strongestModelId), codeMode);
95
95
  }
96
- function createTeamSteps(executionModelId) {
96
+ function createTeamSteps(executionModelId, strongestModelId) {
97
97
  return [
98
- step({ id: 'team-product-direction', stage: 'product-direction', owner: 'human', modelTier: 'top-tier', reason: 'Team product direction should stay on the governed planning path.', dependsOn: [] }, executionModelId),
99
- step({ id: 'team-design-direction', stage: 'design-direction', owner: 'human', modelTier: 'top-tier', reason: 'Team design direction should preserve reviewability and accountability.', dependsOn: ['team-product-direction'] }, executionModelId),
100
- step({ id: 'team-tech-direction', stage: 'tech-direction', owner: 'peaks-tech', modelTier: 'top-tier', reason: 'Team technical plans should remain strongly governed before RD execution.', dependsOn: ['team-design-direction'] }, executionModelId),
101
- step({ id: 'team-tech-review', stage: 'tech-review', owner: 'peaks-tech', modelTier: 'top-tier', reason: 'Team tech approval requires strong review before execution.', dependsOn: ['team-tech-direction'] }, executionModelId),
102
- step({ id: 'team-rd-planning', stage: 'rd-planning', owner: 'peaks-rd', modelTier: 'top-tier', reason: 'Team RD task decomposition remains on the governed strongest-model path.', dependsOn: ['team-tech-review'] }, executionModelId),
103
- step({ id: 'team-coding-execution', stage: 'coding-execution', owner: 'peaks-rd', modelTier: executionModelId === STRONGEST_MODEL_ID ? 'top-tier' : 'mid-tier', reason: `Bounded coding tasks must use the configured execution worker model ${executionModelId}.`, dependsOn: ['team-rd-planning'] }, executionModelId),
104
- step({ id: 'team-unit-test-execution', stage: 'unit-test-execution', owner: 'peaks-rd', modelTier: executionModelId === STRONGEST_MODEL_ID ? 'top-tier' : 'mid-tier', reason: `Unit-test tasks must use the configured execution worker model ${executionModelId}.`, dependsOn: ['team-coding-execution'] }, executionModelId),
105
- step({ id: 'team-quality-review', stage: 'quality-review', owner: 'peaks-rd', modelTier: 'top-tier', reason: 'Team RD outputs still need reducer and quality review gates.', dependsOn: ['team-unit-test-execution'] }, executionModelId)
98
+ step({ id: 'team-product-direction', stage: 'product-direction', owner: 'human', modelTier: 'top-tier', reason: 'Team product direction should stay on the governed planning path.', dependsOn: [] }, executionModelId, strongestModelId),
99
+ step({ id: 'team-design-direction', stage: 'design-direction', owner: 'human', modelTier: 'top-tier', reason: 'Team design direction should preserve reviewability and accountability.', dependsOn: ['team-product-direction'] }, executionModelId, strongestModelId),
100
+ step({ id: 'team-tech-direction', stage: 'tech-direction', owner: 'peaks-tech', modelTier: 'top-tier', reason: 'Team technical plans should remain strongly governed before RD execution.', dependsOn: ['team-design-direction'] }, executionModelId, strongestModelId),
101
+ step({ id: 'team-tech-review', stage: 'tech-review', owner: 'peaks-tech', modelTier: 'top-tier', reason: 'Team tech approval requires strong review before execution.', dependsOn: ['team-tech-direction'] }, executionModelId, strongestModelId),
102
+ step({ id: 'team-rd-planning', stage: 'rd-planning', owner: 'peaks-rd', modelTier: 'top-tier', reason: 'Team RD task decomposition remains on the governed strongest-model path.', dependsOn: ['team-tech-review'] }, executionModelId, strongestModelId),
103
+ step({ id: 'team-coding-execution', stage: 'coding-execution', owner: 'peaks-rd', modelTier: executionModelId === strongestModelId ? 'top-tier' : 'mid-tier', reason: `Bounded coding tasks must use the configured execution worker model ${executionModelId}.`, dependsOn: ['team-rd-planning'] }, executionModelId, strongestModelId),
104
+ step({ id: 'team-unit-test-execution', stage: 'unit-test-execution', owner: 'peaks-rd', modelTier: executionModelId === strongestModelId ? 'top-tier' : 'mid-tier', reason: `Unit-test tasks must use the configured execution worker model ${executionModelId}.`, dependsOn: ['team-coding-execution'] }, executionModelId, strongestModelId),
105
+ step({ id: 'team-quality-review', stage: 'quality-review', owner: 'peaks-rd', modelTier: 'top-tier', reason: 'Team RD outputs still need reducer and quality review gates.', dependsOn: ['team-unit-test-execution'] }, executionModelId, strongestModelId)
106
106
  ];
107
107
  }
108
108
  function uniqueStrings(values) {
109
109
  return [...new Set(values)];
110
110
  }
111
- function createModelRouting(steps, executionModelId) {
111
+ function createModelRouting(steps, executionModelId, strongestModelId) {
112
112
  return {
113
113
  strongestModel: {
114
- modelId: STRONGEST_MODEL_ID,
114
+ modelId: strongestModelId,
115
115
  uses: steps.filter((step) => step.modelRole === 'strongest').map((step) => step.stage)
116
116
  },
117
117
  executionModel: {
@@ -135,10 +135,10 @@ function getTechPlanBlockedReasons(techPlan) {
135
135
  function getTechPlanNextActions(techPlan) {
136
136
  return [...techPlan.nextActions];
137
137
  }
138
- function createModeStatus(economyMode, swarmMode, executionModelId, executionModelSource) {
138
+ function createModeStatus(economyMode, swarmMode, executionModelId, executionModelSource, strongestModelId) {
139
139
  const economySummary = economyMode
140
140
  ? `Economy mode enabled: code worker and test worker strictly use ${executionModelId} from config providers.`
141
- : `Economy mode disabled: code worker and test worker use ${STRONGEST_MODEL_ID}, matching planner/reviewer.`;
141
+ : `Economy mode disabled: code worker and test worker use ${strongestModelId}, matching planner/reviewer.`;
142
142
  const swarmSummary = swarmMode
143
143
  ? 'Swarm mode enabled: peaks-rd coding, unit-test, and peaks-qa quality work must be represented as swarm worker tasks.'
144
144
  : 'Swarm mode disabled: swarm worker graph generation is bypassed.';
@@ -183,8 +183,14 @@ export function createWorkflowRouterPlan(request) {
183
183
  // object (`config: { providers: {} }`) still surfaces the "must be
184
184
  // configured" error from `getConfiguredExecutionModelId`.
185
185
  const effectiveProviders = request.config?.providers ?? { minimax: { model: 'minimax-2.7' } };
186
- const executionModelId = economyMode !== false ? getConfiguredExecutionModelId(effectiveProviders) : STRONGEST_MODEL_ID;
187
- const modeStatus = createModeStatus(economyMode, swarmMode, executionModelId, economyMode ? 'config.providers' : 'planner-reviewer-strongest-model');
186
+ // Slice 2026-07-09 add-zcode-adapter (A.3): the strongest
187
+ // planner/reviewer model is now resolved via `getStrongestModelId`,
188
+ // which reads `config.model` (if present) or falls back to the
189
+ // env-var-overridable default. This decouples the strongest-model
190
+ // pick from any specific vendor constant.
191
+ const strongestModelId = getStrongestModelId(request.config);
192
+ const executionModelId = economyMode !== false ? getConfiguredExecutionModelId(effectiveProviders) : strongestModelId;
193
+ const modeStatus = createModeStatus(economyMode, swarmMode, executionModelId, economyMode ? 'config.providers' : 'planner-reviewer-strongest-model', strongestModelId);
188
194
  const codeMode = getCodeMode(request.mode, request.codeMode);
189
195
  const decisionProfile = getDecisionProfileSummary(request.mode, codeMode);
190
196
  const artifactWorkspacePath = request.artifactWorkspacePath ?? (request.workspace ? getLocalArtifactPath(request.workspace) : undefined);
@@ -195,7 +201,7 @@ export function createWorkflowRouterPlan(request) {
195
201
  const techStatus = getTechStatus({ sessionId: request.sessionId, ...sharedWorkspaceOptions });
196
202
  const techPlan = createTechPlan({ sessionId: request.sessionId, goal, swarm: swarmMode, dryRun: true, ...sharedWorkspaceOptions });
197
203
  const rdPlan = createRdSwarmPlan({ skill: 'rd', sessionId: request.sessionId, goal, maxWorkers, swarmMode, executionModelId, dryRun: true, ...sharedWorkspaceOptions });
198
- const steps = codeMode ? createSoloStepsForMode(codeMode, executionModelId) : createTeamSteps(executionModelId);
204
+ const steps = codeMode ? createSoloStepsForMode(codeMode, executionModelId, strongestModelId) : createTeamSteps(executionModelId, strongestModelId);
199
205
  const blockedReasons = uniqueStrings([
200
206
  ...techStatus.blockedReasons,
201
207
  ...getTechPlanBlockedReasons(techPlan),
@@ -213,7 +219,7 @@ export function createWorkflowRouterPlan(request) {
213
219
  decisionProfile,
214
220
  dryRun: true,
215
221
  routePolicy: request.mode === 'code' ? 'code-broad-multi-model' : 'team-rd-limited-multi-model',
216
- modelRouting: createModelRouting(steps, executionModelId),
222
+ modelRouting: createModelRouting(steps, executionModelId, strongestModelId),
217
223
  modelAssignments: createModelAssignments(steps),
218
224
  modeStatus,
219
225
  techStatus,
@@ -1 +1 @@
1
- export declare const CLI_VERSION = "4.0.0-beta.5";
1
+ export declare const CLI_VERSION = "4.0.0-beta.7";
@@ -1 +1 @@
1
- export const CLI_VERSION = "4.0.0-beta.5";
1
+ export const CLI_VERSION = "4.0.0-beta.7";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "peaks-loop",
3
- "version": "4.0.0-beta.5",
3
+ "version": "4.0.0-beta.7",
4
4
  "description": "Loop Engineering CLI — workflow primitive / loop guards / evaluators / slice orchestration",
5
5
  "author": "SquabbyZ",
6
6
  "license": "MIT",
@@ -172,21 +172,15 @@ function readPackageVersion(packageRoot = resolvePackageRoot()) {
172
172
  }
173
173
 
174
174
  function createConfigDefaults(packageRoot) {
175
- return {
175
+ return {
176
176
  version: readPackageVersion(packageRoot),
177
177
  currentWorkspace: null,
178
178
  workspaces: [],
179
179
  language: 'en',
180
- model: 'sonnet',
181
180
  economyMode: true,
182
181
  swarmMode: true,
183
182
  tokens: {},
184
- providers: {
185
- minimax: {
186
- model: 'minimax-2.7'
187
- }
188
- },
189
- proxy: {}
183
+ proxy: {}
190
184
  };
191
185
  }
192
186
 
@@ -381,7 +375,7 @@ function resolveProjectRoot(options) {
381
375
  * overrides `PEAKS_CLAUDE_SKILLS_DIR` / `PEAKS_CLAUDE_OUTPUT_STYLES_DIR`
382
376
  * continue to work, and the legacy default is preserved.
383
377
  */
384
- const IDE_DETECTION_DIRS = [
378
+ export const IDE_DETECTION_DIRS = [
385
379
  { id: 'claude-code', dir: '.claude' },
386
380
  { id: 'trae', dir: '.trae' },
387
381
  { id: 'trae-cn', dir: '.trae-cn' },
@@ -389,6 +383,7 @@ const IDE_DETECTION_DIRS = [
389
383
  { id: 'cursor', dir: '.cursor' },
390
384
  { id: 'qoder', dir: '.qoder' },
391
385
  { id: 'tongyi-lingma', dir: '.tongyi-lingma' },
386
+ { id: 'zcode', dir: '.zcode' },
392
387
  ];
393
388
 
394
389
  /**
@@ -404,7 +399,7 @@ const IDE_DETECTION_DIRS = [
404
399
  * directory was never populated. 2.0 fixes this by giving
405
400
  * all 8 platforms canonical install paths.
406
401
  */
407
- const IDE_SKILL_INSTALL_PROFILES = {
402
+ export const IDE_SKILL_INSTALL_PROFILES = {
408
403
  'claude-code': {
409
404
  skillsDir: join(homedir(), '.claude', 'skills'),
410
405
  outputStylesDir: join(homedir(), '.claude', 'output-styles'),
@@ -469,6 +464,14 @@ const IDE_SKILL_INSTALL_PROFILES = {
469
464
  envVar: 'PEAKS_OPENCLAW_SKILLS_DIR',
470
465
  outputStylesEnvVar: 'PEAKS_OPENCLAW_OUTPUT_STYLES_DIR',
471
466
  },
467
+ 'zcode': {
468
+ skillsDir: join(homedir(), '.zcode', 'skills'),
469
+ outputStylesDir: join(homedir(), '.zcode', 'output-styles'),
470
+ agentsDir: join(homedir(), '.zcode', 'agents'),
471
+ envVar: 'PEAKS_ZCODE_SKILLS_DIR',
472
+ outputStylesEnvVar: 'PEAKS_ZCODE_OUTPUT_STYLES_DIR',
473
+ agentsEnvVar: 'PEAKS_ZCODE_AGENTS_DIR',
474
+ },
472
475
  };
473
476
 
474
477
  function detectInstalledIdeId(projectRoot) {
@@ -18,7 +18,7 @@ The boundary is closed under this slice:
18
18
 
19
19
  ## Single-scope-axis naming convention (2.7.1)
20
20
 
21
- The `.peaks/` workspace has a **single scope axis** (session-id) plus a nested **sub-agent axis** under `.peaks/_sub_agents/<sessionId>/...`. Use `<sessionId>` (NEVER bare `<sid>`). Reviewable artifacts live at `.peaks/_runtime/<sessionId>/<role>/...` (gitignored); the change-id is an optional filename slug and does NOT route filesystem writes. CLI: session-id → `peaks session *`; sub-agent → `peaks sub-agent *`. OpenSpec's `openspec/changes/<change-id>/` vocabulary (L4) is preserved. Test `skills-skill-md-naming.test.ts` enforces (a) zero bare `<sid>`, (b) axis labels, (c) this callout.
21
+ The `.peaks/` workspace has a **single scope axis** (session-id) plus a nested **sub-agent axis** under `.peaks/_sub_agents/<sessionId>/...`. Use `<sessionId>` (NEVER bare `<sid>`). Reviewable artifacts live at `.peaks/_runtime/<sessionId>/<role>/...` (gitignored); the change-id is an optional filename slug and does NOT route filesystem writes. CLI: session-id → `peaks session *`; sub-agent → `peaks sub-agent *`. Test `skills-skill-md-naming.test.ts` enforces (a) zero bare `<sid>`, (b) axis labels, (c) this callout.
22
22
 
23
23
  ## Karpathy guidance (Slice 1/6 — karpathy prompt-injection-lift)
24
24
 
@@ -58,12 +58,6 @@ When a NEW conversation opens on a session whose `lastActivity` is from today AN
58
58
 
59
59
  Proactive context-overflow defense. CLI: `peaks session checkpoint [--reason <r>] [...flags]`. Fire `--reason periodic` every 20 tool calls (G1 hard-coded), `--reason artifact-written` per PRD/RD/QA/TXT write. See `references/periodic-checkpoint.md` (otherwise `tests/unit/code/checkpoint-periodic-frequency.test.ts` fails).
60
60
 
61
- ### Peaks-Loop Step 0.5: OpenSpec first-run opt-in (conditional)
62
-
63
- Run when `openspec/` is absent and `.peaks/.peaks-openspec-opt-in.json` is missing. Asks once and persists the decision.
64
-
65
- → see `references/openspec-workflow.md` for the full opt-in flow + lifecycle.
66
-
67
61
  ### Peaks-Loop Step 0.6: Audit + Goal (NEW)
68
62
 
69
63
  Invoke peaks-audit after need expressed; store approved goal at `.peaks/_runtime/<sessionId>/audit-goal/<rid>.json`. **All autonomous work requires approved goal.** → `references/audit-goal-gate.md`.
@@ -104,9 +98,13 @@ After Step 0.7 returns "fresh", run `peaks upgrade --detect-1x --project <root>
104
98
 
105
99
  ### Peaks-Loop Step 0.8 — Job 启动 (BLOCKING on LLM judgement — v3.1.1 patch + v3.1.2 mechanical gates)
106
100
 
107
- The CLI is a **recorder + gate** for job-shape (the LLM judges). LLM calls `peaks code detect-job --is-job <bool> --rationale <text> --suggested-job-id <jid> --suggested-strategy <single|rotating> --confidence <high|medium|low>`, which writes `.peaks/_runtime/<sessionId>/job-shape.json`. Downstream steps call `read-job-shape` and refuse if missing.
101
+ > **CLI reality check (D-001 sediment, 2026-07-09):** The CLI surface has changed since this section was last verified. The actual command is **`peaks job init --job-id <jid> --slice-list <list> --main-loop-strategy <single|rotating> [--parallelism-hint <serial|llm-decides>] [--exit-policy <strict|best-effort>] [--project <repo>]`**. The legacy `peaks code detect-job --is-job/--suggested-job-id/--confidence` form described below is **no longer present** in 4.0.0-beta.6. If you find `--is-job` rejected, fall back to `peaks job init`.
108
102
 
109
- **Hard rule (v3.1.1 red-line #10):** LLM MUST NOT skip `peaks code detect-job`. If `read-job-shape` throws `JOB_SHAPE_NOT_DECIDED`, record a decision before proceeding.
103
+ The CLI is a **recorder + gate** for job-shape (the LLM judges). LLM calls `peaks job init --job-id <jid> --slice-list <list> --main-loop-strategy <single|rotating>` (with `--caller-id <id>` and `--project <repo>` in non-Claude-Code environments), which writes `.peaks/_runtime/<sessionId>/job/<jid>/state.json` and emits a `[job-event] {kind: job-started, jobId, total, strategy}` line. Downstream steps call `peaks job status --job-id <jid>` to read state.
104
+
105
+ **Hard rule (v3.1.1 red-line #10):** LLM MUST NOT skip the job-init call. If `peaks job status` reports `done: 0` and the slice work has begun, the LLM forgot to initialize — re-call `peaks job init` immediately.
106
+
107
+ > **D-003 sediment (2026-07-09):** The historical `JOB_SHAPE_NOT_DECIDED` exception thrown by `read-job-shape` is no longer wired in 4.0.0-beta.6. The current CLI uses `peaks job status` which reports a passive `done: 0` instead of throwing. Both behaviors enforce the same intent (no work may begin before init) but the failure mode is a soft warning rather than a hard exception. LLM should treat `done: 0` after Step 0.8 as a recoverable miss, not an unrecoverable error.
110
108
 
111
109
  **v3.1.2 mechanical gates** (recorder-only was bypassed twice):
112
110
 
@@ -149,7 +147,9 @@ Run `peaks project memories --project <repo> --json` to read decisions / convent
149
147
 
150
148
  ### Peaks-Loop Step 2.5: Set session title
151
149
 
152
- Extract a short title from the user's first request (8-20 Chinese chars or 4-10 English words). Run `peaks session title` with the active sid. Skip if a title is already set. → `references/skill-presence-and-title.md` (same file as Step 2).
150
+ Extract a short title from the user's first request (8-20 Chinese chars or 4-10 English words). Run `peaks session title <sid> "<title>" --json`. Skip if a title is already set. → `references/skill-presence-and-title.md` (same file as Step 2).
151
+
152
+ > **CLI reality check (D-002 sediment, 2026-07-09):** The session id is a **positional argument**, not a `--session-id` flag. Correct invocation is `peaks session title 2026-07-08-session-17918f "add-zcode-adapter — peaks-loop 第 9 IDE 接入" --json`. Passing `--session-id` will be rejected with `error: unknown option '--session-id'`.
153
153
 
154
154
  ## Sub-agent session sharing (MANDATORY — one conversation = one sid)
155
155
 
@@ -159,6 +159,19 @@ When peaks-code dispatches a sub-agent (peaks-rd, peaks-qa, peaks-ui, peaks-txt,
159
159
 
160
160
  Peaks-Loop Code may: identify scenarios, recommend profiles, coordinate role skills through artifacts, coordinate project memory extraction, request user confirmation at risk/commit boundaries. Peaks-Loop Code must NOT silently install hooks / create agents / enable MCP / modify Claude settings / create GitHub repos / bypass role-skill artifacts. → `references/boundaries.md`.
161
161
 
162
+ ## CLI Drift Index (sediment 2026-07-09)
163
+
164
+ > **Reading guide:** This document was last verified against CLI surface in **peaks-loop 4.0.0-beta.6**. The CLI has drifted in 4 places since this SKILL.md was last fully aligned. Each drift below is annotated **inline at the relevant step** with a `> CLI reality check` blockquote. When you hit a `error: unknown option ...` error, **read the inline reality check first** before guessing.
165
+
166
+ | Drift ID | Step | Symptom | Fix | Inline location |
167
+ |---|---|---|---|---|
168
+ | **D-001** | 0.8 | `peaks code detect-job --is-job ...` rejected with `error: unknown option '--is-job'` | Use `peaks job init --job-id <jid> --slice-list <list> --main-loop-strategy <single\|rotating>` | §Step 0.8 first paragraph |
169
+ | **D-002** | 2.5 | `peaks session title --session-id <sid> ...` rejected with `error: unknown option '--session-id'` | sid is positional: `peaks session title <sid> "<title>" --json` | §Step 2.5 |
170
+ | **D-003** | 0.8 | `JOB_SHAPE_NOT_DECIDED` exception expected but never thrown | Current behavior is `peaks job status` reports `done: 0` passively — treat as recoverable miss, not hard error | §Step 0.8 third paragraph |
171
+ | **D-010** | 11c | `peaks memory extract` returns `extractedCount: 0` despite `<!-- peaks-memory:start -->` existing | Block requires YAML frontmatter (`title:` + `kind:` + `---`) + closing `<!-- peaks-memory:end -->`. Bare `peaks-memory:start` is parsed silently but produces no writes | §Step 11c + 11d |
172
+
173
+ > **Sediment lesson (master record):** `.peaks/memory/peaks-code-runbook-4-0-0-beta-6-skill-md-cli-d-001-d-002-d-003-d-010.md`
174
+
162
175
  ## Peaks-Loop GStack integration
163
176
 
164
177
  Map gstack stages to Peaks-Loop role artifacts; preserve confirmation gates. → `references/gstack-integration.md` + `references/browser-workflow.md`.
@@ -239,11 +252,13 @@ After final validation, refresh project-local standards via `peaks standards ini
239
252
 
240
253
  **11c — Canonical extract** (the only CLI that writes `.peaks/memory/`): `peaks memory extract --project <repo> --artifact .peaks/_runtime/<sessionId>/txt/handoff.md --apply --json`. `--apply` is REQUIRED (without it the command only previews — no files land).
241
254
 
255
+ > **CLI reality check (D-010 sediment, 2026-07-09):** The `<!-- peaks-memory:start -->` block must be followed immediately by a **YAML frontmatter** (`title: ...`, `kind: lesson | decision | convention`) and a `---` separator. Each block must close with `<!-- peaks-memory:end -->`. A bare `peaks-memory:start` without the YAML fields is parsed but produces no `plannedWrites` — the CLI silently returns `extractedCount: 0`. Full format reference: see any successful extract output (e.g. `.peaks/_runtime/2026-07-08-session-17918f/txt/handoff-003-add-zcode-adapter.md`).
256
+
242
257
  **11d — Gate C (zero-write outcome):** If `extractedCount === 0` after 11c, fire AskUserQuestion:
243
258
 
244
259
  > "本次 code 未沉淀任何 `.peaks/memory` 文件。可选: (a) 回去在 handoff.md 嵌入至少 1 个 `peaks-memory:start` block 后重试; (b) 显式接受 no-sediment 并记录为 lesson; (c) 取消完成。"
245
260
 
246
- Default option = (a). Code MUST NOT silently accept (b) without user pick. Full bash + flow at `references/runbook.md` §Step 11.
261
+ > **D-010 fix root cause check:** When firing 11d, first inspect whether the block has the YAML frontmatter (`title:` + `kind:` + `---`). If the `<!-- peaks-memory:start -->` exists but no `title:` line follows, fix the block format and re-run 11c — don't ask the user yet. Default option = (a). Code MUST NOT silently accept (b) without user pick. Full bash + flow at `references/runbook.md` §Step 11.
247
262
 
248
263
  **Why this step exists:** audit 2026-07-03 confirmed 2 consecutive sessions produced zero `.peaks/memory/` files despite completing RD + QA + handoff artifacts; `assisted` mode silently skipped runbook Step 10 (no STOP condition). **Why `peaks memory extract` (not `peaks project memories:extract`):** the artifact-scoped extract is canonical; the batch-scoped sibling is for non-handoff flows. Always use `peaks memory extract --apply`.
249
264
 
@@ -288,7 +303,6 @@ Index of every `references/` file. Read on demand.
288
303
  | `references/local-artifact-workspace.md` | Workspace tree + root-prohibition. |
289
304
  | `references/micro-cycle.md` | RD micro-cycle + repair loop. |
290
305
  | `references/mode-selection.md` | Step 1 mode + `--mode`. |
291
- | `references/openspec-workflow.md` | Step 0.5 OpenSpec. |
292
306
  | `references/playwright-mcp-multi-terminal.md` | Multi-terminal Playwright MCP. |
293
307
  | `references/project-memory-loading.md` | Step 2.3 memories. |
294
308
  | `references/project-scan-checklist.md` | Pre-RD scan + template. |
@@ -10,8 +10,6 @@ Do not run upstream installer flows, mutate agent settings, or commit `.codegrap
10
10
 
11
11
  **External skills**: All external skill references (`mattpocock/skills`, `awesome-design-md`, `taste-skill`, `shadcn/ui`, `Chrome DevTools MCP`, `Figma Context MCP`, `Context7`, etc.) follow the three-stage pattern: capability discovery via `peaks capabilities` before naming, references only (no execute/install/persist), Peaks-Loop CLI for all side effects. Do not execute upstream installers, do not install upstream resources, do not persist sensitive examples — Peaks-Loop gates remain authoritative. External skills inform, they do not approve.
12
12
 
13
- **OpenSpec lifecycle**: `render → validate → show → to-rd → validate → archive`. Code's default runbook handles the exit gate (validate → archive after QA pass). Entry-gate validation (to-rd before slicing) is available when `openspec/` exists pre-workflow; Code delegates it to `peaks-rd` during implementation.
14
-
15
13
  **MCP lifecycle**: `list → plan → apply --yes → call → rollback`. `apply` backs up settings and refuses non-peaks entries unless `--claim` is passed.
16
14
 
17
- Detailed rules: `references/external-skill-invocation.md`, `references/openspec-mcp-workflow.md`, `references/workflow.md`, `references/existing-system-extraction.md`. For an informational mapping of peaks artefact paths to the A2A (Agent2Agent) protocol's Task / Artifact / Part / Message / AgentCard vocabulary (no A2A implementation, just a shared naming layer), see `references/a2a-artifact-mapping.md`.
15
+ Detailed rules: `references/external-skill-invocation.md`, `references/workflow.md`, `references/existing-system-extraction.md`. For an informational mapping of peaks artefact paths to the A2A (Agent2Agent) protocol's Task / Artifact / Part / Message / AgentCard vocabulary (no A2A implementation, just a shared naming layer), see `references/a2a-artifact-mapping.md`.
@@ -40,7 +40,7 @@ The skill body must not silently:
40
40
  - commit or sync intermediate artifacts;
41
41
  - create remote repositories.
42
42
 
43
- All of these must route through the Peaks CLI under the appropriate command (`peaks artifacts …`, `peaks memory …`, `peaks openspec …`, `peaks standards …`, `peaks codegraph …`, `peaks capabilities …`), with dry-run preview where supported and `--yes` / `--apply` where a real write is required. The `peaks mcp …` command tree was retired in slice #016; MCP install / dispatch is the LLM runtime's job, not the CLI's.
43
+ All of these must route through the Peaks CLI under the appropriate command (`peaks artifacts …`, `peaks memory …`, `peaks standards …`, `peaks codegraph …`, `peaks capabilities …`), with dry-run preview where supported and `--yes` / `--apply` where a real write is required. The `peaks mcp …` command tree was retired in slice #016; MCP install / dispatch is the LLM runtime's job, not the CLI's. Note: peaks-code's 11-step workflow does NOT route through any external artifact lifecycle (OpenSpec or otherwise) — all reads/writes are confined to the LLM-authored artifact workspace under `.peaks/_runtime/<sessionId>/<role>/`. External CLI surfaces remain available for users who call them directly, but Code never calls them on the user's behalf as of the 2026-07-08 RR decoupling slice.
44
44
 
45
45
  ## Allowed in-process references
46
46
 
@@ -149,9 +149,7 @@ peaks sc retention --slice-id <rid> --prd <prd> --rd <rd> --qa <qa> --json
149
149
  peaks sc validate --slice-id <rid> --json
150
150
  peaks sc boundary --slice-id <rid> --artifact <artifact> --code <file> --json
151
151
 
152
- # 9. Peaks-Loop OpenSpec archive (exit gate; only after QA pass, when openspec/ exists)
153
- peaks openspec validate <cid> --project <repo> --json
154
- peaks openspec archive <cid> --project <repo> --apply --json
152
+ # 9. Peaks-Loop Workspace reconcile (slate cleanup)
155
153
  peaks workspace reconcile --project <repo> --apply --older-than 7
156
154
 
157
155
  # 10. Peaks-Loop TXT handoff — invoke peaks-txt which embeds memory markers (BLOCKING)
@@ -73,10 +73,11 @@ The decision is persisted via `peaks preferences set --project <root> --key auto
73
73
 
74
74
  ## How this integrates with the rest of the workflow
75
75
 
76
- - Step 0.5 (OpenSpec opt-in) — runs first if `openspec/` is missing.
77
76
  - Step 0 (anchor) — runs always.
78
77
  - Step 0.7 (resume detection) — runs after Step 0.
79
78
  - **Step 0.55 (1.x detection) — runs after Step 0.7, only when the project is not on a 2.0 layout.**
80
79
  - Step 1 (mode selection) — runs after Step 0.55.
81
80
 
82
81
  The 1.x detection is intentionally placed AFTER Step 0.7 because the user might already have a 1.x-converted in-flight slice; the resume flow takes precedence over the upgrade prompt.
82
+
83
+ > **Historical note (prior to 2026-07-08 RR slice):** an OpenSpec first-run opt-in step (Step 0.5) used to sit between Step 0 and Step 0.7. peaks-code is now decoupled from OpenSpec and does not surface that step; this reference still preserves the historical ordering for context.
@@ -44,7 +44,7 @@ When Peaks-Loop Code coordinates development in a code repository, keep this ord
44
44
  6. **Peaks-Loop QA validation** (auto-proceed from RD in full-auto) — execute test cases + API checks + Playwright MCP headed browser E2E for frontend + security/perf checks + test report;
45
45
  7. **Peaks-Loop RD↔QA repair loop** — if QA verdict is `return-to-rd`, loop back to step 4 (RD implementation) and re-run through QA; max 3 repair cycles, then emit blocked TXT regardless;
46
46
  8. **Peaks-Loop SC phase** — change-control evidence: impact, retention, validate, boundary;
47
- 9. **Peaks-Loop OpenSpec archive** — exit gate: validate → archive only after QA verdict=pass (when `openspec/` exists);
47
+ 9. **Peaks-Loop Workspace reconcile** — slate cleanup;
48
48
  10. **Peaks-Loop TXT handoff capsule** — mode, validated decisions, artifact paths, standards deltas, open questions, next action;
49
49
  11. **Peaks-Loop Final snapshot** — `peaks project dashboard` + `peaks skill doctor` to confirm the workflow closed cleanly.
50
50
 
@@ -108,4 +108,64 @@ This skill does NOT modify source code. It documents the v2 envelope produced by
108
108
  |---|---|
109
109
  | `references/v2-schema.md` | Field-by-field table for `DecompositionResultV2`, `PassResult`, `SliceV2`, `CrossPassEdge.arbitratedBy`, `LlmArbitration`. |
110
110
  | `references/granularity-decision.md` | Decision tree for the 4 `--granularity` modes; `shouldSubdivide()` thresholds + tie-break semantics. |
111
- | `references/cross-pass-edge-interpretation.md` | The 4 edge kinds and how `peaks-rd` should use them for dispatch ordering; `LlmArbitration` trace reader. |
111
+ | `references/cross-pass-edge-interpretation.md` | The 4 edge kinds and how `peaks-rd` should use them for dispatch ordering; `LlmArbitration` trace reader. |
112
+
113
+ ---
114
+
115
+ ## SC template hard rules (sediment 2026-07-09)
116
+
117
+ These rules are added in response to **D-009a + D-009c** discovered while running RID 003-add-zcode-adapter. They prevent the same class of mistake from re-occurring in future SC drafts.
118
+
119
+ ### Rule 1 — Pre-flight: detect ESM vs CJS before writing export syntax (D-009c)
120
+
121
+ Before specifying `--caller-id` / export guard syntax in any SC task, run:
122
+
123
+ ```bash
124
+ head -3 package.json | grep '"type"'
125
+ ```
126
+
127
+ - `"type": "module"` → ESM. Use `export const FOO = ...` for any constant that tests need to import. **Do NOT** write `if (typeof module !== 'undefined' && module.exports) { module.exports = { FOO }; }` — that pattern is CJS-only.
128
+ - No `"type"` field (or `"type": "commonjs"`) → CJS. Use the `module.exports` guard.
129
+
130
+ Why: RID-003 SC §3.5 originally specified the CJS guard for `scripts/install-skills.mjs`. The script is actually ESM (`"type": "module"`). The RD agent had to backtrack and the SC lost 5 minutes of spec clarity.
131
+
132
+ ### Rule 2 — Whitelist fixture sync is NOT collateral (D-009a)
133
+
134
+ When a slice adds a new entry to a **whitelist fixture** (e.g. `tests/unit/ide/ide-registry.test.ts` asserting `expect(adapters).toHaveLength(7)` after adding the 8th adapter), that fixture sync is a **primary task**, not a "by the way" footnote.
135
+
136
+ Mandatory structure for any slice that adds to a known set:
137
+
138
+ ```markdown
139
+ ### Tasks
140
+
141
+ | Task | File | Change |
142
+ |---|---|---|
143
+ | T-1 | `src/services/ide/ide-types.ts` | Add `'zcode'` to IdeId |
144
+ | T-2 | `src/services/ide/ide-registry.ts` | Register ZCODE_ADAPTER |
145
+ | T-3 | `tests/unit/ide/ide-registry.test.ts` | Update whitelist: 7 → 8 adapters, add 'zcode' |
146
+ | T-4 | `tests/unit/install-skills-script.test.ts` | Update whitelist: 5 → 6 platforms, add 'zcode' |
147
+ ```
148
+
149
+ If you find a whitelist fixture during execution but didn't pre-list it as a task, treat it as a **NEW TASK** and run the SC ↔ QA repair loop, not as "necessary collateral". Pre-listing prevents surprises at Gate 1.
150
+
151
+ ### Rule 3 — Adapter interface optional fields (D-009b reciprocal)
152
+
153
+ When extending `IdeAdapter` (or any plugin-interface in `src/services/**/ide/`), prefer **optional fields** over required fields so existing implementations don't need stub updates:
154
+
155
+ ```ts
156
+ // ✅ Optional — back-compat safe
157
+ interface IdeAdapter {
158
+ readonly detectCurrentModel?: () => Promise<string | undefined>;
159
+ }
160
+
161
+ // ❌ Required — every existing adapter must add a stub
162
+ interface IdeAdapter {
163
+ readonly detectCurrentModel: () => Promise<string | undefined>;
164
+ }
165
+ ```
166
+
167
+ If a field MUST be required, document in the SC why each existing implementation must be updated inline, and pre-list those updates as primary tasks (Rule 2 pattern).
168
+
169
+ ---
170
+
171
+ **Sediment source:** `.peaks/_runtime/2026-07-08-session-17918f/qa/003-add-zcode-adapter/{slice-A-completion,slice-B-completion}.md` D-009a/b/c sections. Master lesson: `.peaks/memory/peaks-code-runbook-4-0-0-beta-6-skill-md-cli-d-001-d-002-d-003-d-010.md`.
@@ -1,81 +0,0 @@
1
- # OpenSpec Lifecycle for Peaks Code
2
-
3
- Peaks Code orchestrates RD, QA, and SC. When the target repository uses OpenSpec, Code must drive the full lifecycle through the Peaks CLI so each role works against the same stable surface.
4
-
5
- > **Slice #016 (2026-06-09)**: this document used to live at `openspec-mcp-workflow.md` and contained a section on the `peaks mcp *` lifecycle. The MCP subsystem was retired in slice #016; that section is gone. The OpenSpec lifecycle described below is unchanged.
6
-
7
- ## OpenSpec change lifecycle
8
-
9
- ```text
10
- peaks openspec render → RD authors a change pack (dry-run, then --apply)
11
- peaks openspec validate → Code gates RD output before slicing starts
12
- peaks openspec show → any role reads parsed proposal/tasks state
13
- peaks openspec to-rd → RD projects the pack into refactor slice input
14
- SC projects it into commit boundary candidates
15
- peaks openspec validate → QA gates the final state before sign-off
16
- peaks openspec archive → Code moves the change under changes/archive/<id>/
17
- ```
18
-
19
- Rules Code applies:
20
-
21
- - `render --apply` is the only Peaks-managed way to write a change pack. Other roles must not hand-edit `openspec/changes/**`.
22
- - `validate` is run twice per change in a refactor flow: once before slicing (RD entry gate) and once before archive (QA exit gate). Both must end with `data.valid === true`.
23
- - `archive --apply` is the lifecycle terminator; Code only invokes it after QA acceptance and SC commit.
24
-
25
- ## Refactor workflow wiring
26
-
27
- For `peaks-code refactor` runs against a repository with `openspec/`:
28
-
29
- 1. RD entry gate — `peaks openspec validate <id>` must pass and `peaks openspec to-rd <id>` must return `acceptance.length > 0`.
30
- 2. Each slice must reference one OpenSpec tasks section as its commit boundary (per `references/openspec-commit-boundaries.md` in peaks-sc).
31
- 3. QA exit gate — re-run `peaks openspec validate <id>` after implementation; record the result in the QA validation report.
32
- 4. Archive — `peaks openspec archive <id> --apply` only after QA passes the exit gate and SC closes the final commit.
33
-
34
- If the consuming LLM needs an MCP server for docs lookup or research (e.g. Context7), it checks its own tool list for `mcp__<server>__*` and tells the user the install command if absent. peaks-loop is no longer in the install path; the LLM is the executor, the IDE is the dispatcher.
35
-
36
- ## Boundary
37
-
38
- Code must not write `openspec/changes/**` or `~/.claude/settings.json` directly. Every mutation goes through the CLI commands above. The CLI returns stable envelopes; Code captures them as artifact links rather than re-explaining their content in the handoff.
39
-
40
- ---
41
-
42
- # Step 0.5 — OpenSpec first-run opt-in (conditional)
43
-
44
- > Body of `### Peaks-Loop Step 0.5`. After the workspace is anchored, before project scan, Code checks whether
45
- the project already has an `openspec/` directory. The lifecycle
46
- (`render → validate → show → to-rd → validate → archive`) only applies
47
- when `openspec/` exists; without it, RD/QA/SC silently skip the
48
- openspec-aware paths and you lose change-proposal tracking, commit
49
- boundaries from `tasks.md`, and the historical archive.
50
-
51
- To make that opt-in visible instead of silent, Code runs:
52
-
53
- ```bash
54
- # 1. Detect whether the project already has openspec/.
55
- ls <repo>/openspec/changes 2>&1
56
- # 2. If absent, ask the user once — only on the first Code run in this
57
- # project. The decision is sticky: write it to .peaks/.peaks-openspec-opt-in.json
58
- # so subsequent Code invocations do not re-ask.
59
- test -f <repo>/.peaks/.peaks-openspec-opt-in.json || \
60
- echo "{\"enabled\": <bool>}" > <repo>/.peaks/.peaks-openspec-opt-in.json
61
- ```
62
-
63
- **AskUserQuestion** (only when `openspec/` is absent and the opt-in
64
- file is missing):
65
-
66
- | Option | What it does |
67
- |---|---|
68
- | Enable OpenSpec for this project (Recommended) | Run `peaks openspec init --project <repo> --apply`. After that, every Code run uses the change-proposal lifecycle for the same project. |
69
- | Skip for now | Do nothing. Code proceeds without openspec; the question is re-asked on the next first-run detection. |
70
- | Never ask again for this project | Write `{enabled: false, sticky: true}`. Code stops asking. The user can re-enable later by removing `.peaks/.peaks-openspec-opt-in.json` and re-running. |
71
-
72
- The first option is the recommended default because it gives Code the
73
- full change-proposal lifecycle (proposal / tasks / design / specs
74
- deltas, archive on ship, commit boundaries from `tasks.md`). It costs
75
- only a single scaffolded directory and pays back the first time the
76
- project needs a real review trail.
77
-
78
- If the user picks "Enable", the only required follow-up is to make
79
- sure `openspec/changes/` is added to git (it is part of the project
80
- repo, not a tool-managed artefact). Code does not run `git add` for
81
- the user; that is the user's commit boundary.