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.
- package/CHANGELOG.md +62 -0
- package/dist/src/cli/commands/adapter-commands-s2a.d.ts +34 -0
- package/dist/src/cli/commands/adapter-commands-s2a.js +92 -0
- package/dist/src/cli/commands/ide-commands.d.ts +25 -0
- package/dist/src/cli/commands/ide-commands.js +42 -0
- package/dist/src/cli/commands/polyrepo-commands.d.ts +37 -0
- package/dist/src/cli/commands/polyrepo-commands.js +155 -0
- package/dist/src/cli/commands/runtime-commands.d.ts +52 -0
- package/dist/src/cli/commands/runtime-commands.js +150 -0
- package/dist/src/cli/program.js +23 -0
- package/dist/src/services/adapter/adapter-registry.d.ts +48 -0
- package/dist/src/services/adapter/adapter-registry.js +186 -0
- package/dist/src/services/config/model-routing.d.ts +55 -2
- package/dist/src/services/config/model-routing.js +79 -3
- package/dist/src/services/ide/adapters/zcode-adapter.d.ts +40 -0
- package/dist/src/services/ide/adapters/zcode-adapter.js +220 -0
- package/dist/src/services/ide/current-model-detector.d.ts +14 -0
- package/dist/src/services/ide/current-model-detector.js +60 -0
- package/dist/src/services/ide/ide-registry.js +3 -0
- package/dist/src/services/ide/ide-types.d.ts +24 -1
- package/dist/src/services/polyrepo/polyrepo-dispatcher.d.ts +34 -0
- package/dist/src/services/polyrepo/polyrepo-dispatcher.js +119 -0
- package/dist/src/services/polyrepo/polyrepo-scanner.d.ts +9 -0
- package/dist/src/services/polyrepo/polyrepo-scanner.js +94 -0
- package/dist/src/services/polyrepo/polyrepo-service.d.ts +34 -0
- package/dist/src/services/polyrepo/polyrepo-service.js +49 -0
- package/dist/src/services/polyrepo/polyrepo-types.d.ts +55 -0
- package/dist/src/services/polyrepo/polyrepo-types.js +1 -0
- package/dist/src/services/preferences/preferences-types.d.ts +1 -1
- package/dist/src/services/providers/minimax-worker-service.d.ts +1 -1
- package/dist/src/services/providers/minimax-worker-service.js +1 -1
- package/dist/src/services/rd/rd-service.js +7 -4
- package/dist/src/services/runtime/runtime-detector.d.ts +15 -0
- package/dist/src/services/runtime/runtime-detector.js +62 -0
- package/dist/src/services/runtime/runtime-service.d.ts +59 -0
- package/dist/src/services/runtime/runtime-service.js +51 -0
- package/dist/src/services/runtime/vendor-adapter.d.ts +59 -0
- package/dist/src/services/runtime/vendor-adapter.js +1 -0
- package/dist/src/services/runtime/vendors/claude-code.d.ts +7 -0
- package/dist/src/services/runtime/vendors/claude-code.js +39 -0
- package/dist/src/services/runtime/vendors/codex.d.ts +7 -0
- package/dist/src/services/runtime/vendors/codex.js +43 -0
- package/dist/src/services/runtime/vendors/copilot.d.ts +7 -0
- package/dist/src/services/runtime/vendors/copilot.js +40 -0
- package/dist/src/services/workflow/workflow-router-service.d.ts +1 -1
- package/dist/src/services/workflow/workflow-router-service.js +37 -31
- package/dist/src/shared/version.d.ts +1 -1
- package/dist/src/shared/version.js +1 -1
- package/package.json +1 -1
- package/scripts/install-skills.mjs +13 -10
- package/skills/peaks-code/SKILL.md +26 -12
- package/skills/peaks-code/references/external-references.md +1 -3
- package/skills/peaks-code/references/external-skill-invocation.md +1 -1
- package/skills/peaks-code/references/runbook.md +1 -3
- package/skills/peaks-code/references/step-0-55-1x-detection.md +2 -1
- package/skills/peaks-code/references/workflow-gates-and-types.md +1 -1
- package/skills/peaks-slice-decompose/SKILL.md +61 -1
- package/skills/peaks-code/references/openspec-workflow.md +0 -81
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { getConfiguredExecutionModelId,
|
|
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 :
|
|
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 ===
|
|
89
|
-
step({ id: 'code-unit-test-execution', stage: 'unit-test-execution', owner: 'peaks-rd', modelTier: 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 ===
|
|
104
|
-
step({ id: 'team-unit-test-execution', stage: 'unit-test-execution', owner: 'peaks-rd', modelTier: 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:
|
|
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 ${
|
|
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
|
-
|
|
187
|
-
|
|
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.
|
|
1
|
+
export declare const CLI_VERSION = "4.0.0-beta.7";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export const CLI_VERSION = "4.0.0-beta.
|
|
1
|
+
export const CLI_VERSION = "4.0.0-beta.7";
|
package/package.json
CHANGED
|
@@ -172,21 +172,15 @@ function readPackageVersion(packageRoot = resolvePackageRoot()) {
|
|
|
172
172
|
}
|
|
173
173
|
|
|
174
174
|
function createConfigDefaults(packageRoot) {
|
|
175
|
-
|
|
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
|
-
|
|
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 *`.
|
|
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
|
|
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
|
-
**
|
|
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
|
|
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/
|
|
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
|
|
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
|
|
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
|
|
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.
|