peaks-cli 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +52 -0
- package/README.md +417 -0
- package/bin/peaks.js +2 -0
- package/dist/src/cli/cli-helpers.d.ts +25 -0
- package/dist/src/cli/cli-helpers.js +78 -0
- package/dist/src/cli/commands/capability-commands.d.ts +5 -0
- package/dist/src/cli/commands/capability-commands.js +46 -0
- package/dist/src/cli/commands/capability-worker-config-sc-commands.d.ts +3 -0
- package/dist/src/cli/commands/capability-worker-config-sc-commands.js +10 -0
- package/dist/src/cli/commands/config-commands.d.ts +3 -0
- package/dist/src/cli/commands/config-commands.js +212 -0
- package/dist/src/cli/commands/core-artifact-commands.d.ts +3 -0
- package/dist/src/cli/commands/core-artifact-commands.js +200 -0
- package/dist/src/cli/commands/sc-commands.d.ts +3 -0
- package/dist/src/cli/commands/sc-commands.js +37 -0
- package/dist/src/cli/commands/worker-commands.d.ts +3 -0
- package/dist/src/cli/commands/worker-commands.js +52 -0
- package/dist/src/cli/commands/workflow-commands.d.ts +3 -0
- package/dist/src/cli/commands/workflow-commands.js +257 -0
- package/dist/src/cli/index.d.ts +1 -0
- package/dist/src/cli/index.js +14 -0
- package/dist/src/cli/program.d.ts +4 -0
- package/dist/src/cli/program.js +13 -0
- package/dist/src/services/artifacts/artifact-service.d.ts +43 -0
- package/dist/src/services/artifacts/artifact-service.js +97 -0
- package/dist/src/services/artifacts/workspace-service.d.ts +33 -0
- package/dist/src/services/artifacts/workspace-service.js +254 -0
- package/dist/src/services/config/config-service.d.ts +29 -0
- package/dist/src/services/config/config-service.js +501 -0
- package/dist/src/services/config/config-types.d.ts +63 -0
- package/dist/src/services/config/config-types.js +16 -0
- package/dist/src/services/config/model-routing.d.ts +4 -0
- package/dist/src/services/config/model-routing.js +15 -0
- package/dist/src/services/doctor/doctor-service.d.ts +18 -0
- package/dist/src/services/doctor/doctor-service.js +68 -0
- package/dist/src/services/memory/project-memory-service.d.ts +79 -0
- package/dist/src/services/memory/project-memory-service.js +306 -0
- package/dist/src/services/profiles/profile-service.d.ts +6 -0
- package/dist/src/services/profiles/profile-service.js +19 -0
- package/dist/src/services/providers/minimax-provider-service.d.ts +24 -0
- package/dist/src/services/providers/minimax-provider-service.js +143 -0
- package/dist/src/services/providers/minimax-worker-service.d.ts +21 -0
- package/dist/src/services/providers/minimax-worker-service.js +80 -0
- package/dist/src/services/proxy/proxy-service.d.ts +7 -0
- package/dist/src/services/proxy/proxy-service.js +31 -0
- package/dist/src/services/rd/rd-service.d.ts +88 -0
- package/dist/src/services/rd/rd-service.js +370 -0
- package/dist/src/services/recommendations/capability-availability.d.ts +5 -0
- package/dist/src/services/recommendations/capability-availability.js +40 -0
- package/dist/src/services/recommendations/capability-map-service.d.ts +7 -0
- package/dist/src/services/recommendations/capability-map-service.js +131 -0
- package/dist/src/services/recommendations/capability-seed-items.d.ts +2 -0
- package/dist/src/services/recommendations/capability-seed-items.js +131 -0
- package/dist/src/services/recommendations/capability-seed-mappings.d.ts +2 -0
- package/dist/src/services/recommendations/capability-seed-mappings.js +42 -0
- package/dist/src/services/recommendations/capability-seed-sources.d.ts +2 -0
- package/dist/src/services/recommendations/capability-seed-sources.js +35 -0
- package/dist/src/services/recommendations/recommendation-service.d.ts +8 -0
- package/dist/src/services/recommendations/recommendation-service.js +106 -0
- package/dist/src/services/recommendations/recommendation-types.d.ts +129 -0
- package/dist/src/services/recommendations/recommendation-types.js +1 -0
- package/dist/src/services/recommendations/seed-capability-catalog.d.ts +3 -0
- package/dist/src/services/recommendations/seed-capability-catalog.js +3 -0
- package/dist/src/services/refactor/refactor-service.d.ts +9 -0
- package/dist/src/services/refactor/refactor-service.js +33 -0
- package/dist/src/services/sc/index.d.ts +1 -0
- package/dist/src/services/sc/index.js +1 -0
- package/dist/src/services/sc/sc-service.d.ts +79 -0
- package/dist/src/services/sc/sc-service.js +223 -0
- package/dist/src/services/skills/skill-registry.d.ts +17 -0
- package/dist/src/services/skills/skill-registry.js +40 -0
- package/dist/src/services/standards/project-standards-service.d.ts +82 -0
- package/dist/src/services/standards/project-standards-service.js +383 -0
- package/dist/src/services/tech/tech-service.d.ts +69 -0
- package/dist/src/services/tech/tech-service.js +236 -0
- package/dist/src/services/workflow/workflow-autonomous-service.d.ts +99 -0
- package/dist/src/services/workflow/workflow-autonomous-service.js +526 -0
- package/dist/src/services/workflow/workflow-router-service.d.ts +85 -0
- package/dist/src/services/workflow/workflow-router-service.js +213 -0
- package/dist/src/shared/change-id.d.ts +15 -0
- package/dist/src/shared/change-id.js +76 -0
- package/dist/src/shared/frontmatter.d.ts +6 -0
- package/dist/src/shared/frontmatter.js +47 -0
- package/dist/src/shared/fs-utils.d.ts +4 -0
- package/dist/src/shared/fs-utils.js +16 -0
- package/dist/src/shared/fs.d.ts +4 -0
- package/dist/src/shared/fs.js +26 -0
- package/dist/src/shared/path-utils.d.ts +13 -0
- package/dist/src/shared/path-utils.js +56 -0
- package/dist/src/shared/paths.d.ts +6 -0
- package/dist/src/shared/paths.js +40 -0
- package/dist/src/shared/planner-response.d.ts +21 -0
- package/dist/src/shared/planner-response.js +26 -0
- package/dist/src/shared/platform.d.ts +6 -0
- package/dist/src/shared/platform.js +11 -0
- package/dist/src/shared/process.d.ts +5 -0
- package/dist/src/shared/process.js +12 -0
- package/dist/src/shared/result.d.ts +13 -0
- package/dist/src/shared/result.js +32 -0
- package/package.json +49 -0
- package/schemas/approval-record.schema.json +14 -0
- package/schemas/artifact-manifest.schema.json +16 -0
- package/schemas/artifact-retention-report.schema.json +17 -0
- package/schemas/artifact-workspace.schema.json +22 -0
- package/schemas/capability-availability.schema.json +36 -0
- package/schemas/capability-item.schema.json +37 -0
- package/schemas/capability-source.schema.json +30 -0
- package/schemas/change-impact.schema.json +15 -0
- package/schemas/context-capsule.schema.json +16 -0
- package/schemas/recommendation-plan.schema.json +37 -0
- package/schemas/refactor-slice-spec.schema.json +19 -0
- package/scripts/clean-dist.mjs +8 -0
- package/scripts/install-skills.mjs +76 -0
- package/scripts/watch.mjs +389 -0
- package/skills/peaks-prd/SKILL.md +42 -0
- package/skills/peaks-prd/references/artifact-contracts.md +3 -0
- package/skills/peaks-prd/references/command-migration.md +3 -0
- package/skills/peaks-prd/references/workflow.md +11 -0
- package/skills/peaks-qa/SKILL.md +45 -0
- package/skills/peaks-qa/references/artifact-contracts.md +3 -0
- package/skills/peaks-qa/references/command-migration.md +3 -0
- package/skills/peaks-qa/references/regression-gates.md +16 -0
- package/skills/peaks-rd/SKILL.md +56 -0
- package/skills/peaks-rd/references/artifact-contracts.md +3 -0
- package/skills/peaks-rd/references/command-migration.md +3 -0
- package/skills/peaks-rd/references/refactor-workflow.md +31 -0
- package/skills/peaks-sc/SKILL.md +30 -0
- package/skills/peaks-sc/references/artifact-contracts.md +3 -0
- package/skills/peaks-sc/references/artifact-retention.md +14 -0
- package/skills/peaks-sc/references/command-migration.md +3 -0
- package/skills/peaks-solo/SKILL.md +63 -0
- package/skills/peaks-solo/references/artifact-contracts.md +3 -0
- package/skills/peaks-solo/references/command-migration.md +3 -0
- package/skills/peaks-solo/references/refactor-mode.md +22 -0
- package/skills/peaks-solo/references/workflow.md +14 -0
- package/skills/peaks-txt/SKILL.md +48 -0
- package/skills/peaks-txt/references/artifact-contracts.md +3 -0
- package/skills/peaks-txt/references/command-migration.md +3 -0
- package/skills/peaks-txt/references/context-capsule.md +20 -0
- package/skills/peaks-ui/SKILL.md +35 -0
- package/skills/peaks-ui/references/artifact-contracts.md +3 -0
- package/skills/peaks-ui/references/command-migration.md +3 -0
- package/skills/peaks-ui/references/workflow.md +11 -0
|
@@ -0,0 +1,389 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { spawn } from 'node:child_process';
|
|
3
|
+
import { watch as nodeWatch } from 'node:fs';
|
|
4
|
+
import { readdir } from 'node:fs/promises';
|
|
5
|
+
import { join, resolve } from 'node:path';
|
|
6
|
+
import { pathToFileURL } from 'node:url';
|
|
7
|
+
import { installBundledSkills } from './install-skills.mjs';
|
|
8
|
+
|
|
9
|
+
export const WATCHED_INPUTS = ['src', 'schemas', 'skills'];
|
|
10
|
+
export const DEFAULT_BUILD_COMMAND = ['pnpm', ['run', 'build']];
|
|
11
|
+
|
|
12
|
+
function getErrorMessage(error) {
|
|
13
|
+
return error instanceof Error ? error.message : String(error);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
function getErrorCode(error) {
|
|
17
|
+
return typeof error === 'object' && error !== null && 'code' in error ? error.code : undefined;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
function isAbortError(error) {
|
|
21
|
+
return error instanceof Error && error.name === 'AbortError';
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
function isMissingPathError(error) {
|
|
25
|
+
return getErrorCode(error) === 'ENOENT';
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export function runCommand(command, args, options = {}) {
|
|
29
|
+
return new Promise((resolvePromise, rejectPromise) => {
|
|
30
|
+
let child;
|
|
31
|
+
|
|
32
|
+
try {
|
|
33
|
+
child = spawn(command, args, { stdio: 'inherit', ...options });
|
|
34
|
+
} catch (error) {
|
|
35
|
+
rejectPromise(error);
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
let settled = false;
|
|
40
|
+
const settle = (handler, value) => {
|
|
41
|
+
if (settled) {
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
settled = true;
|
|
46
|
+
handler(value);
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
child.once('error', (error) => {
|
|
50
|
+
if (options.signal?.aborted || isAbortError(error)) {
|
|
51
|
+
const abortError = new Error(`${command} ${args.join(' ')} was aborted`);
|
|
52
|
+
abortError.name = 'AbortError';
|
|
53
|
+
settle(rejectPromise, abortError);
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
settle(rejectPromise, error);
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
child.once('close', (code, signal) => {
|
|
61
|
+
if (code === 0) {
|
|
62
|
+
settle(resolvePromise);
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
if (options.signal?.aborted || signal) {
|
|
67
|
+
const abortError = new Error(`${command} ${args.join(' ')} was aborted`);
|
|
68
|
+
abortError.name = 'AbortError';
|
|
69
|
+
settle(rejectPromise, abortError);
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
settle(rejectPromise, new Error(`${command} ${args.join(' ')} failed with exit code ${code}`));
|
|
74
|
+
});
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
export async function collectDirectories(root) {
|
|
79
|
+
const directories = [];
|
|
80
|
+
const visited = new Set();
|
|
81
|
+
|
|
82
|
+
async function visit(directory) {
|
|
83
|
+
if (visited.has(directory)) {
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
visited.add(directory);
|
|
88
|
+
|
|
89
|
+
let entries;
|
|
90
|
+
try {
|
|
91
|
+
entries = await readdir(directory, { withFileTypes: true });
|
|
92
|
+
} catch (error) {
|
|
93
|
+
if (isMissingPathError(error)) {
|
|
94
|
+
return;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
throw error;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
directories.push(directory);
|
|
101
|
+
|
|
102
|
+
for (const entry of entries) {
|
|
103
|
+
if (!entry.isDirectory()) {
|
|
104
|
+
continue;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
await visit(join(directory, entry.name));
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
await visit(root);
|
|
112
|
+
return directories;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
export function createDirectoryTreeWatcher(root, options = {}) {
|
|
116
|
+
const watch = options.watch ?? nodeWatch;
|
|
117
|
+
const collect = options.collectDirectories ?? collectDirectories;
|
|
118
|
+
const onChange = options.onChange ?? (() => {});
|
|
119
|
+
const watchers = new Map();
|
|
120
|
+
let refreshPromise = null;
|
|
121
|
+
let refreshRequested = false;
|
|
122
|
+
let isClosed = false;
|
|
123
|
+
|
|
124
|
+
const syncWatchers = async () => {
|
|
125
|
+
const directories = await collect(root);
|
|
126
|
+
const nextDirectories = new Set(directories);
|
|
127
|
+
|
|
128
|
+
for (const [directory, watcher] of watchers) {
|
|
129
|
+
if (nextDirectories.has(directory)) {
|
|
130
|
+
continue;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
watcher.close();
|
|
134
|
+
watchers.delete(directory);
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
for (const directory of directories) {
|
|
138
|
+
if (watchers.has(directory)) {
|
|
139
|
+
continue;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
const watcher = watch(directory, () => {
|
|
143
|
+
onChange();
|
|
144
|
+
void requestRefresh();
|
|
145
|
+
});
|
|
146
|
+
watchers.set(directory, watcher);
|
|
147
|
+
}
|
|
148
|
+
};
|
|
149
|
+
|
|
150
|
+
const requestRefresh = async () => {
|
|
151
|
+
if (isClosed) {
|
|
152
|
+
return;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
refreshRequested = true;
|
|
156
|
+
if (refreshPromise) {
|
|
157
|
+
return refreshPromise;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
refreshPromise = (async () => {
|
|
161
|
+
do {
|
|
162
|
+
refreshRequested = false;
|
|
163
|
+
await syncWatchers();
|
|
164
|
+
} while (refreshRequested && !isClosed);
|
|
165
|
+
})();
|
|
166
|
+
|
|
167
|
+
try {
|
|
168
|
+
await refreshPromise;
|
|
169
|
+
} finally {
|
|
170
|
+
refreshPromise = null;
|
|
171
|
+
}
|
|
172
|
+
};
|
|
173
|
+
|
|
174
|
+
return {
|
|
175
|
+
async start() {
|
|
176
|
+
await requestRefresh();
|
|
177
|
+
},
|
|
178
|
+
async close() {
|
|
179
|
+
isClosed = true;
|
|
180
|
+
|
|
181
|
+
if (refreshPromise) {
|
|
182
|
+
await refreshPromise.catch(() => undefined);
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
for (const watcher of watchers.values()) {
|
|
186
|
+
watcher.close();
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
watchers.clear();
|
|
190
|
+
}
|
|
191
|
+
};
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
export async function rebuildOnce(options = {}) {
|
|
195
|
+
const runner = options.runner ?? runCommand;
|
|
196
|
+
const installer = options.installer ?? installBundledSkills;
|
|
197
|
+
const [command, args] = options.command ?? DEFAULT_BUILD_COMMAND;
|
|
198
|
+
|
|
199
|
+
await runner(command, args, options.runOptions);
|
|
200
|
+
return installer(options.installOptions);
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
export function createWatchMode(options = {}) {
|
|
204
|
+
const inputs = options.inputs ?? WATCHED_INPUTS;
|
|
205
|
+
const createTreeWatcher = options.createTreeWatcher ?? createDirectoryTreeWatcher;
|
|
206
|
+
const runner = options.runner ?? runCommand;
|
|
207
|
+
const installer = options.installer ?? installBundledSkills;
|
|
208
|
+
const collectDirectoriesFn = options.collectDirectories ?? collectDirectories;
|
|
209
|
+
const watch = options.watch ?? nodeWatch;
|
|
210
|
+
const stdout = options.stdout ?? process.stdout;
|
|
211
|
+
const stderr = options.stderr ?? process.stderr;
|
|
212
|
+
const debounceMs = options.debounceMs ?? 150;
|
|
213
|
+
const treeWatchers = [];
|
|
214
|
+
let debounceTimer;
|
|
215
|
+
let isBuilding = false;
|
|
216
|
+
let hasQueuedRebuild = false;
|
|
217
|
+
let isClosed = false;
|
|
218
|
+
let currentAbortController = null;
|
|
219
|
+
let currentBuildPromise = null;
|
|
220
|
+
|
|
221
|
+
const writeStatus = (message) => stdout.write(`[peaks watch] ${message}\n`);
|
|
222
|
+
const writeError = (message) => stderr.write(`[peaks watch] ${message}\n`);
|
|
223
|
+
|
|
224
|
+
const rebuild = async (reason) => {
|
|
225
|
+
if (isClosed) {
|
|
226
|
+
return;
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
if (isBuilding) {
|
|
230
|
+
hasQueuedRebuild = true;
|
|
231
|
+
return currentBuildPromise ?? undefined;
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
isBuilding = true;
|
|
235
|
+
currentAbortController = new AbortController();
|
|
236
|
+
writeStatus(`${reason}: rebuilding dist and relinking skills`);
|
|
237
|
+
|
|
238
|
+
const buildPromise = (async () => {
|
|
239
|
+
try {
|
|
240
|
+
const result = await rebuildOnce({
|
|
241
|
+
runner,
|
|
242
|
+
installer,
|
|
243
|
+
runOptions: { signal: currentAbortController.signal }
|
|
244
|
+
});
|
|
245
|
+
const installed = result?.installed?.length ?? 0;
|
|
246
|
+
const skipped = result?.skipped?.length ?? 0;
|
|
247
|
+
writeStatus(`ready (${installed} skills linked, ${skipped} skipped)`);
|
|
248
|
+
} catch (error) {
|
|
249
|
+
if (isAbortError(error)) {
|
|
250
|
+
return;
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
writeError(`rebuild failed: ${getErrorMessage(error)}`);
|
|
254
|
+
} finally {
|
|
255
|
+
isBuilding = false;
|
|
256
|
+
currentAbortController = null;
|
|
257
|
+
}
|
|
258
|
+
})();
|
|
259
|
+
|
|
260
|
+
currentBuildPromise = buildPromise;
|
|
261
|
+
|
|
262
|
+
try {
|
|
263
|
+
await buildPromise;
|
|
264
|
+
} finally {
|
|
265
|
+
currentBuildPromise = null;
|
|
266
|
+
if (!isClosed && hasQueuedRebuild) {
|
|
267
|
+
hasQueuedRebuild = false;
|
|
268
|
+
await rebuild('queued change');
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
};
|
|
272
|
+
|
|
273
|
+
const scheduleRebuild = () => {
|
|
274
|
+
if (isClosed) {
|
|
275
|
+
return;
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
if (debounceTimer) {
|
|
279
|
+
clearTimeout(debounceTimer);
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
debounceTimer = setTimeout(() => {
|
|
283
|
+
debounceTimer = undefined;
|
|
284
|
+
void rebuild('change detected');
|
|
285
|
+
}, debounceMs);
|
|
286
|
+
};
|
|
287
|
+
|
|
288
|
+
const closeTreeWatchers = async () => {
|
|
289
|
+
for (const treeWatcher of [...treeWatchers].reverse()) {
|
|
290
|
+
await treeWatcher.close();
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
treeWatchers.length = 0;
|
|
294
|
+
};
|
|
295
|
+
|
|
296
|
+
return {
|
|
297
|
+
async start() {
|
|
298
|
+
await rebuild('initial');
|
|
299
|
+
|
|
300
|
+
if (isClosed) {
|
|
301
|
+
return;
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
let startupFailed = false;
|
|
305
|
+
try {
|
|
306
|
+
for (const input of inputs) {
|
|
307
|
+
if (isClosed) {
|
|
308
|
+
break;
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
const treeWatcher = createTreeWatcher(input, {
|
|
312
|
+
watch,
|
|
313
|
+
collectDirectories: collectDirectoriesFn,
|
|
314
|
+
onChange: scheduleRebuild
|
|
315
|
+
});
|
|
316
|
+
treeWatchers.push(treeWatcher);
|
|
317
|
+
await treeWatcher.start();
|
|
318
|
+
|
|
319
|
+
if (isClosed) {
|
|
320
|
+
break;
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
} catch (error) {
|
|
324
|
+
startupFailed = true;
|
|
325
|
+
throw error;
|
|
326
|
+
} finally {
|
|
327
|
+
if (startupFailed || isClosed) {
|
|
328
|
+
await closeTreeWatchers();
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
if (!isClosed) {
|
|
333
|
+
writeStatus(`watching ${inputs.join(', ')}`);
|
|
334
|
+
}
|
|
335
|
+
},
|
|
336
|
+
async close() {
|
|
337
|
+
isClosed = true;
|
|
338
|
+
|
|
339
|
+
if (debounceTimer) {
|
|
340
|
+
clearTimeout(debounceTimer);
|
|
341
|
+
debounceTimer = undefined;
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
if (currentAbortController) {
|
|
345
|
+
currentAbortController.abort();
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
await closeTreeWatchers();
|
|
349
|
+
|
|
350
|
+
if (currentBuildPromise) {
|
|
351
|
+
await currentBuildPromise.catch(() => undefined);
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
};
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
async function main() {
|
|
358
|
+
const watchMode = createWatchMode();
|
|
359
|
+
let shuttingDown = false;
|
|
360
|
+
|
|
361
|
+
const shutdown = async () => {
|
|
362
|
+
if (shuttingDown) {
|
|
363
|
+
return;
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
shuttingDown = true;
|
|
367
|
+
|
|
368
|
+
try {
|
|
369
|
+
await watchMode.close();
|
|
370
|
+
process.stdout.write('[peaks watch] stopped\n');
|
|
371
|
+
process.exit(0);
|
|
372
|
+
} catch (error) {
|
|
373
|
+
process.stderr.write(`[peaks watch] ${getErrorMessage(error)}\n`);
|
|
374
|
+
process.exit(1);
|
|
375
|
+
}
|
|
376
|
+
};
|
|
377
|
+
|
|
378
|
+
process.once('SIGINT', () => void shutdown());
|
|
379
|
+
process.once('SIGTERM', () => void shutdown());
|
|
380
|
+
|
|
381
|
+
await watchMode.start();
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
if (process.argv[1] !== undefined && import.meta.url === pathToFileURL(resolve(process.argv[1])).href) {
|
|
385
|
+
main().catch((error) => {
|
|
386
|
+
process.stderr.write(`[peaks watch] ${getErrorMessage(error)}\n`);
|
|
387
|
+
process.exitCode = 1;
|
|
388
|
+
});
|
|
389
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: peaks-prd
|
|
3
|
+
description: Product and requirement skill for Peaks. Use when a workflow needs PRD, refactor goals, non-goals, behavior preservation, acceptance criteria, product change proposals, or user-confirmable product artifacts.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Peaks PRD
|
|
7
|
+
|
|
8
|
+
Peaks PRD turns user intent into verifiable product artifacts.
|
|
9
|
+
|
|
10
|
+
## Responsibilities
|
|
11
|
+
|
|
12
|
+
- clarify goals and non-goals;
|
|
13
|
+
- define behavior that must be preserved;
|
|
14
|
+
- write acceptance criteria;
|
|
15
|
+
- create refactor goal artifacts;
|
|
16
|
+
- produce product-side intermediate artifacts for downstream RD and QA skills.
|
|
17
|
+
|
|
18
|
+
## Refactor role
|
|
19
|
+
|
|
20
|
+
For refactor workflows, avoid writing a full product PRD unless needed. Produce a focused refactor product package:
|
|
21
|
+
|
|
22
|
+
- refactor goal;
|
|
23
|
+
- non-goals;
|
|
24
|
+
- preserved behavior;
|
|
25
|
+
- acceptance criteria;
|
|
26
|
+
- risk notes;
|
|
27
|
+
- user confirmation record.
|
|
28
|
+
|
|
29
|
+
## External capability guidance
|
|
30
|
+
|
|
31
|
+
Use `peaks capabilities --source mcp-server --json` before recommending product or workflow methodology resources.
|
|
32
|
+
|
|
33
|
+
- OpenSpec can structure spec-first product and engineering artifacts.
|
|
34
|
+
- Superpowers can inform workflow methodology and artifact sequencing.
|
|
35
|
+
- gstack can inform product-stack tradeoffs, but user goals and non-goals remain authoritative.
|
|
36
|
+
- External methods are inspiration and governance inputs, not automatic executors.
|
|
37
|
+
|
|
38
|
+
## Boundaries
|
|
39
|
+
|
|
40
|
+
Do not implement code, run tests, install hooks, or modify runtime configuration. Use Peaks CLI reports and downstream artifacts instead.
|
|
41
|
+
|
|
42
|
+
Reference: `references/workflow.md`.
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
# Peaks PRD Workflow
|
|
2
|
+
|
|
3
|
+
For refactors, produce a focused product artifact package rather than a full product PRD.
|
|
4
|
+
|
|
5
|
+
## Required refactor artifacts
|
|
6
|
+
|
|
7
|
+
- refactor goal;
|
|
8
|
+
- non-goals;
|
|
9
|
+
- behavior preservation;
|
|
10
|
+
- acceptance criteria;
|
|
11
|
+
- user confirmation record.
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: peaks-qa
|
|
3
|
+
description: QA and verification skill for Peaks. Use when a workflow needs unit-test coverage evidence, regression matrices, baseline reports, validation reports, acceptance checks, or refactor verification gates.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Peaks QA
|
|
7
|
+
|
|
8
|
+
Peaks QA proves that planned changes are protected and accepted.
|
|
9
|
+
|
|
10
|
+
## Responsibilities
|
|
11
|
+
|
|
12
|
+
- inspect unit-test coverage evidence;
|
|
13
|
+
- define regression matrices;
|
|
14
|
+
- produce baseline reports;
|
|
15
|
+
- define acceptance checks for refactor slices;
|
|
16
|
+
- validate that implementation satisfies the spec;
|
|
17
|
+
- record residual risks.
|
|
18
|
+
|
|
19
|
+
## Project standards preflight
|
|
20
|
+
|
|
21
|
+
Before QA verification in a code repository, call the Peaks CLI:
|
|
22
|
+
|
|
23
|
+
- `peaks standards init --project <path> --dry-run`
|
|
24
|
+
- `peaks standards update --project <path> --dry-run`
|
|
25
|
+
|
|
26
|
+
If the repo needs a first-time standards bundle, treat `standards init` as the creation path. If `CLAUDE.md` already exists, use `standards update` to decide whether Peaks can append a managed block or should only return review suggestions. Apply only when write authorization exists; otherwise keep the CLI output as the preflight next action. Do not hand-write standards file mutations inside the skill.
|
|
27
|
+
|
|
28
|
+
## Refactor role
|
|
29
|
+
|
|
30
|
+
For refactors, QA must be involved before implementation. It defines the regression and acceptance surface, then verifies the same surface after implementation.
|
|
31
|
+
|
|
32
|
+
## External capability guidance
|
|
33
|
+
|
|
34
|
+
Use `peaks capabilities --source access-repo --json` before recommending browser or validation MCPs.
|
|
35
|
+
|
|
36
|
+
- Playwright MCP can support controlled browser and E2E validation after the target app and environment are approved.
|
|
37
|
+
- Chrome DevTools MCP can support console, network, accessibility, and performance inspection for QA evidence.
|
|
38
|
+
- Agent Browser can support browser walkthroughs, but never submit forms, purchase, delete, or mutate authenticated state without explicit confirmation.
|
|
39
|
+
- If browser automation is unavailable, fall back to local Playwright, screenshots, logs, and manual regression steps.
|
|
40
|
+
|
|
41
|
+
## Boundaries
|
|
42
|
+
|
|
43
|
+
Do not own product scope or implementation. Do not modify runtime configuration.
|
|
44
|
+
|
|
45
|
+
Reference: `references/regression-gates.md`.
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# Peaks QA Regression Gates
|
|
2
|
+
|
|
3
|
+
QA must be involved before refactor implementation.
|
|
4
|
+
|
|
5
|
+
## Required evidence
|
|
6
|
+
|
|
7
|
+
- coverage report or reason for blocking;
|
|
8
|
+
- regression matrix;
|
|
9
|
+
- baseline report;
|
|
10
|
+
- acceptance checks;
|
|
11
|
+
- validation report;
|
|
12
|
+
- residual risk report.
|
|
13
|
+
|
|
14
|
+
## Refactor threshold
|
|
15
|
+
|
|
16
|
+
UT coverage below 95%, missing coverage, or unverifiable coverage blocks refactor implementation.
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: peaks-rd
|
|
3
|
+
description: Research and development skill for Peaks. Use for engineering analysis, refactor planning, project scanning, code standards, unit-test coverage gates, implementation contracts, task graphs, and RD handoffs. Always use this for Peaks refactor workflows.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Peaks RD
|
|
7
|
+
|
|
8
|
+
Peaks RD owns engineering analysis, implementation planning, and refactor execution contracts.
|
|
9
|
+
|
|
10
|
+
## Responsibilities
|
|
11
|
+
|
|
12
|
+
- scan the current project before changes;
|
|
13
|
+
- prefer existing project standards over built-in language standards;
|
|
14
|
+
- enforce the 95% UT coverage refactor gate;
|
|
15
|
+
- split broad refactors by minimal functional slices;
|
|
16
|
+
- generate refactor options, risk matrix, rollback plan, and task graph preview;
|
|
17
|
+
- implement only after strict specs and confirmations exist.
|
|
18
|
+
|
|
19
|
+
## Project standards preflight
|
|
20
|
+
|
|
21
|
+
Before RD planning or implementation work in a code repository, call the Peaks CLI:
|
|
22
|
+
|
|
23
|
+
- `peaks standards init --project <path> --dry-run`
|
|
24
|
+
- `peaks standards update --project <path> --dry-run`
|
|
25
|
+
|
|
26
|
+
If `CLAUDE.md` is missing, treat creation as the preferred path. If `CLAUDE.md` already exists, use `standards update` to decide whether to append a managed index block or surface review-only suggestions. Apply only when write authorization exists; otherwise keep the CLI output as a preflight next action. Do not hand-write standards file mutations inside the skill.
|
|
27
|
+
|
|
28
|
+
## Refactor hard gates
|
|
29
|
+
|
|
30
|
+
If a request is refactor, cleanup, architecture adjustment, module split, or technical debt work:
|
|
31
|
+
|
|
32
|
+
1. scan project structure and existing standards;
|
|
33
|
+
2. locate or run UT coverage;
|
|
34
|
+
3. block implementation unless coverage is >= 95%;
|
|
35
|
+
4. treat missing, unknown, or unverifiable coverage as failing;
|
|
36
|
+
5. generate intermediate artifacts before implementation;
|
|
37
|
+
6. call or consume peaks-prd and peaks-qa artifacts even in direct RD mode;
|
|
38
|
+
7. require strict slice spec before each slice;
|
|
39
|
+
8. require 100% acceptance for the slice;
|
|
40
|
+
9. require code and intermediate artifacts to be committed before continuing.
|
|
41
|
+
|
|
42
|
+
## External capability guidance
|
|
43
|
+
|
|
44
|
+
Use `peaks capabilities --source access-repo --json` and `peaks capabilities --source mcp-server --json` as the source of truth before recommending external resources.
|
|
45
|
+
|
|
46
|
+
- Context7 can support current library/API documentation lookup when the map says it is available or the user authorizes MCP access.
|
|
47
|
+
- SearchCode can support external code discovery only after confirming the query will not expose secrets or private code.
|
|
48
|
+
- everything-claude-code, Claude Code Best Practice, mattpocock/skills, and andrej-karpathy-skills are RD guidance or review references; apply project-local conventions first.
|
|
49
|
+
- OpenSpec can shape spec-first RD artifacts, but Peaks PRD/RD/QA gates remain authoritative.
|
|
50
|
+
- GitNexus remains a future proxied repository-intelligence boundary; do not install or run it directly.
|
|
51
|
+
|
|
52
|
+
## Boundaries
|
|
53
|
+
|
|
54
|
+
Do not bypass PRD/QA artifacts. Do not install hooks, agents, MCP, or settings. Ask the Peaks CLI to handle runtime side effects.
|
|
55
|
+
|
|
56
|
+
Reference: `references/refactor-workflow.md`.
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# Peaks RD Refactor Workflow
|
|
2
|
+
|
|
3
|
+
## Standards loading order
|
|
4
|
+
|
|
5
|
+
1. Existing project standards.
|
|
6
|
+
2. Peaks language standard packs.
|
|
7
|
+
3. Peaks universal engineering baseline.
|
|
8
|
+
4. Reviewer judgment.
|
|
9
|
+
|
|
10
|
+
## Hard gates
|
|
11
|
+
|
|
12
|
+
- UT coverage must be >= 95% before implementation.
|
|
13
|
+
- Missing, unknown, unverifiable, or failing coverage blocks refactoring.
|
|
14
|
+
- Coverage success only allows analysis and spec generation.
|
|
15
|
+
- Broad refactors must be split into minimal functional slices.
|
|
16
|
+
- Each slice needs a strict verifiable spec before implementation.
|
|
17
|
+
- Each slice must pass 100% acceptance.
|
|
18
|
+
- Code and intermediate artifacts must be committed before the next slice.
|
|
19
|
+
|
|
20
|
+
## Required artifacts
|
|
21
|
+
|
|
22
|
+
- `project-scan.md`
|
|
23
|
+
- `engineering-constitution.md`
|
|
24
|
+
- `coverage-report.md`
|
|
25
|
+
- `feature-slice-map.md`
|
|
26
|
+
- `refactor-options.md`
|
|
27
|
+
- `risk-matrix.md`
|
|
28
|
+
- `rollback-plan.md`
|
|
29
|
+
- `slice-spec.md`
|
|
30
|
+
- `validation-report.md`
|
|
31
|
+
- `commit-required.md`
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: peaks-sc
|
|
3
|
+
description: Source control, sync, and change-control skill for Peaks. Use when a workflow needs change impact, artifact retention, commit boundaries, GitHub artifact repository pointers, sync state, or rollback evidence.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Peaks SC
|
|
7
|
+
|
|
8
|
+
Peaks SC records how product, RD, QA, code, and artifacts move together.
|
|
9
|
+
|
|
10
|
+
## Responsibilities
|
|
11
|
+
|
|
12
|
+
- produce change-impact artifacts;
|
|
13
|
+
- record commit boundaries;
|
|
14
|
+
- ensure intermediate artifacts are retained with code changes;
|
|
15
|
+
- track artifact repository pointers;
|
|
16
|
+
- record sync state and rollback points.
|
|
17
|
+
|
|
18
|
+
## Refactor role
|
|
19
|
+
|
|
20
|
+
Each refactor slice must leave a traceable commit boundary containing code changes and PRD/RD/QA/TXT intermediate artifacts.
|
|
21
|
+
|
|
22
|
+
## Project memory backup
|
|
23
|
+
|
|
24
|
+
Project `.claude/memory` is the primary source for durable project memory. At approved checkpoints, use `peaks memory sync --project <path> --workspace <artifact-workspace> --apply` to back up the full project memory directory into the artifact repository workspace; do not treat the artifact backup as a second writable memory source.
|
|
25
|
+
|
|
26
|
+
## Boundaries
|
|
27
|
+
|
|
28
|
+
Do not implement code or test logic. Do not create GitHub repositories directly from the skill body. Use the Peaks CLI artifact commands.
|
|
29
|
+
|
|
30
|
+
Reference: `references/artifact-retention.md`.
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
# Artifact Retention
|
|
2
|
+
|
|
3
|
+
Each refactor slice must retain code and intermediate artifacts together.
|
|
4
|
+
|
|
5
|
+
## Required retained artifacts
|
|
6
|
+
|
|
7
|
+
- PRD goal and acceptance artifacts;
|
|
8
|
+
- RD slice spec and task graph;
|
|
9
|
+
- QA coverage and validation reports;
|
|
10
|
+
- TXT context capsule and lessons;
|
|
11
|
+
- SC change impact and sync state;
|
|
12
|
+
- commit boundary report.
|
|
13
|
+
|
|
14
|
+
The next slice cannot start until code and intermediate artifacts are committed or the user explicitly stops the run.
|