peaks-loop 4.0.0-beta.10 → 4.0.0-beta.11
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 +18 -11
- package/dist/cli/cli-helpers.d.ts +0 -5
- package/dist/cli/cli-helpers.js +0 -24
- package/dist/cli/commands/audit-commands.js +1 -1
- package/dist/cli/commands/capability-worker-config-sc-commands.js +0 -2
- package/dist/cli/commands/code-commands.js +1 -1
- package/dist/cli/commands/code-review-commands.js +1 -1
- package/dist/cli/commands/config-commands.js +3 -74
- package/dist/cli/commands/core/skill-command.js +5 -2
- package/dist/cli/commands/dispatch-commands.js +14 -0
- package/dist/cli/commands/ecc-commands.d.ts +30 -0
- package/dist/cli/commands/ecc-commands.js +119 -0
- package/dist/cli/commands/perf-audit-commands.js +1 -1
- package/dist/cli/commands/prd-commands.js +3 -1
- package/dist/cli/commands/qa-commands.js +1 -1
- package/dist/cli/commands/sc-commands.js +3 -1
- package/dist/cli/commands/security-audit-commands.js +1 -1
- package/dist/cli/commands/skill-search-commands.js +3 -0
- package/dist/cli/commands/upgrade-commands.js +1 -1
- package/dist/cli/program.js +12 -4
- package/dist/services/agent/ecc-cache-service.d.ts +97 -0
- package/dist/services/agent/ecc-cache-service.js +491 -0
- package/dist/services/audit/static-service.d.ts +32 -25
- package/dist/services/audit/static-service.js +30 -109
- package/dist/services/config/config-service.d.ts +1 -12
- package/dist/services/config/config-service.js +3 -72
- package/dist/services/config/config-types.d.ts +2 -4
- package/dist/services/context/context-schema.d.ts +2 -2
- package/dist/services/job/job-types.d.ts +3 -3
- package/dist/services/log/retention.d.ts +16 -0
- package/dist/services/log/retention.js +17 -0
- package/dist/services/migrate-skill-name/schema.d.ts +2 -2
- package/dist/services/rd/rd-service.js +10 -11
- package/dist/services/rd/types.d.ts +2 -2
- package/dist/services/recommendations/capability-seed-items.js +0 -1
- package/dist/services/recommendations/capability-seed-mappings.js +0 -1
- package/dist/services/recommendations/capability-seed-sources.js +0 -1
- package/dist/services/skill/skill-search-service.d.ts +5 -0
- package/dist/services/skill/skill-search-service.js +6 -2
- package/dist/services/skills/skill-registry.d.ts +1 -0
- package/dist/services/skills/skill-registry.js +4 -2
- package/dist/services/workflow/workflow-router-service.js +7 -7
- package/dist/shared/version.d.ts +1 -1
- package/dist/shared/version.js +1 -1
- package/package.json +1 -1
- package/skills/bee/peaks-perf-audit/SKILL.md +1 -0
- package/skills/bee/peaks-rd/SKILL.md +1 -24
- package/skills/bee/peaks-reviewer/SKILL.md +1 -0
- package/skills/bee/peaks-security-audit/SKILL.md +1 -0
- package/skills/peaks-code/SKILL.md +1 -99
- package/skills/peaks-code/references/startup-sequence.md +110 -0
- package/skills/peaks-doctor/SKILL.md +1 -1
- package/skills/peaks-ide/SKILL.md +1 -1
- package/dist/cli/commands/agent-commands.d.ts +0 -20
- package/dist/cli/commands/agent-commands.js +0 -48
- package/dist/cli/commands/worker-commands.d.ts +0 -3
- package/dist/cli/commands/worker-commands.js +0 -52
- package/dist/services/agent/ecc-agent-service.d.ts +0 -47
- package/dist/services/agent/ecc-agent-service.js +0 -143
- package/dist/services/config/provider-service.d.ts +0 -48
- package/dist/services/config/provider-service.js +0 -143
- package/dist/services/providers/minimax-provider-service.d.ts +0 -24
- package/dist/services/providers/minimax-provider-service.js +0 -143
- package/dist/services/providers/minimax-worker-service.d.ts +0 -21
- package/dist/services/providers/minimax-worker-service.js +0 -83
package/CHANGELOG.md
CHANGED
|
@@ -2,20 +2,27 @@
|
|
|
2
2
|
|
|
3
3
|
## [Unreleased]
|
|
4
4
|
|
|
5
|
-
## 4.0.0-beta.
|
|
5
|
+
## 4.0.0-beta.11 — 2026-07-16
|
|
6
6
|
|
|
7
|
-
### Status:
|
|
7
|
+
### Status: RELEASED (release of `4.0.0-beta.10` contract; same source tree)
|
|
8
8
|
|
|
9
|
-
> **This CHANGELOG entry documents the
|
|
10
|
-
>
|
|
11
|
-
>
|
|
12
|
-
>
|
|
13
|
-
> for the pre-implementation gate (9/9 gates PASS).
|
|
9
|
+
> **This CHANGELOG entry documents the SHIPPED 4.0.0-beta.11.
|
|
10
|
+
> It is the post-implementation release of the 4.0.0-beta.10 contract
|
|
11
|
+
> documented at `docs/release/4.0.0-beta.10.md` (runbook filename
|
|
12
|
+
> preserved for cross-reference stability).
|
|
14
13
|
>
|
|
15
|
-
>
|
|
16
|
-
>
|
|
17
|
-
>
|
|
18
|
-
>
|
|
14
|
+
> The 3 slices (del-minimax-worker, hide-role-skills, on-demand-ecc)
|
|
15
|
+
> all landed PASS in this branch — see `peaks workflow verify-pipeline
|
|
16
|
+
> --rid 2026-07-15-cli-surface-cleanup` and the Slice 1/2/3 sediment
|
|
17
|
+
> memories in `.peaks/memory/`.
|
|
18
|
+
>
|
|
19
|
+
> **Version bump rationale** (D-016): 4.0.0-beta.10 was the pre-impl
|
|
20
|
+
> contract name; 4.0.0-beta.11 is the actual release of that contract.
|
|
21
|
+
> One-line summary: **"CLI surface cleanup + on-demand ECC"**.
|
|
22
|
+
>
|
|
23
|
+
> **Verdict**: 10/12 AC PASS + 2 PASS-WITH-DEFERRED (D-013 wrapper
|
|
24
|
+
> exit-code bug, separate follow-up slice after publish).
|
|
25
|
+
> Ice-cola baseline gate: 27/27 AC functionally pass.
|
|
19
26
|
|
|
20
27
|
### Removed — `peaks minimax-worker` (Slice 1)
|
|
21
28
|
|
|
@@ -2,8 +2,6 @@ import { Command } from 'commander';
|
|
|
2
2
|
import { getErrorMessage, ok, redactSensitiveErrorMessage, type ResultEnvelope } from '../shared/result.js';
|
|
3
3
|
import type { ArtifactProvider, GuidedArtifactSetup } from '../services/artifacts/artifact-service.js';
|
|
4
4
|
import type { ConfigLayer } from '../services/config/config-service.js';
|
|
5
|
-
import type { MiniMaxProviderSmokeResult } from '../services/providers/minimax-provider-service.js';
|
|
6
|
-
import type { MiniMaxWorkerResult } from '../services/providers/minimax-worker-service.js';
|
|
7
5
|
import type { RecommendationWorkflow } from '../services/recommendations/recommendation-service.js';
|
|
8
6
|
export type ProgramIO = {
|
|
9
7
|
stdout: (text: string) => void;
|
|
@@ -34,10 +32,7 @@ export declare function isRecommendationWorkflow(value: string): value is Recomm
|
|
|
34
32
|
export declare function isArtifactProvider(value: string): value is ArtifactProvider;
|
|
35
33
|
export declare function isArtifactSetupStep(value: string): value is GuidedArtifactSetup['step'];
|
|
36
34
|
export declare function isArtifactRepoSegment(value: string): boolean;
|
|
37
|
-
export declare function isMiniMaxHttpsUrl(value: string): boolean;
|
|
38
35
|
export declare function parseConfigLayer(value: string | undefined): ConfigLayer | undefined | null;
|
|
39
36
|
export declare function printInvalidConfigLayer(io: ProgramIO, command: string, asJson?: boolean): void;
|
|
40
37
|
export declare function multipleOption(value: string, previous: string[]): string[];
|
|
41
|
-
export declare function summarizeMiniMaxSmokeResult(result: MiniMaxProviderSmokeResult): MiniMaxProviderSmokeResult;
|
|
42
|
-
export declare function summarizeMiniMaxWorkerResult(result: MiniMaxWorkerResult): MiniMaxWorkerResult;
|
|
43
38
|
export { getErrorMessage, ok, redactSensitiveErrorMessage };
|
package/dist/cli/cli-helpers.js
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { fail, getErrorMessage, ok, redactSensitiveErrorMessage } from '../shared/result.js';
|
|
2
|
-
const MINIMAX_API_HOST = 'api.minimaxi.com';
|
|
3
2
|
export function printResult(io, result, asJson = false) {
|
|
4
3
|
if (asJson) {
|
|
5
4
|
io.stdout(JSON.stringify(result, null, 2));
|
|
@@ -47,15 +46,6 @@ export function isArtifactSetupStep(value) {
|
|
|
47
46
|
export function isArtifactRepoSegment(value) {
|
|
48
47
|
return /^[A-Za-z0-9][A-Za-z0-9._-]*$/.test(value) && !value.includes('..') && !value.endsWith('.');
|
|
49
48
|
}
|
|
50
|
-
export function isMiniMaxHttpsUrl(value) {
|
|
51
|
-
try {
|
|
52
|
-
const url = new URL(value);
|
|
53
|
-
return url.protocol === 'https:' && url.hostname === MINIMAX_API_HOST && url.username.length === 0 && url.password.length === 0 && url.search.length === 0 && url.hash.length === 0;
|
|
54
|
-
}
|
|
55
|
-
catch {
|
|
56
|
-
return false;
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
49
|
export function parseConfigLayer(value) {
|
|
60
50
|
if (value === undefined) {
|
|
61
51
|
return undefined;
|
|
@@ -69,18 +59,4 @@ export function printInvalidConfigLayer(io, command, asJson) {
|
|
|
69
59
|
export function multipleOption(value, previous) {
|
|
70
60
|
return [...(previous || []), value];
|
|
71
61
|
}
|
|
72
|
-
export function summarizeMiniMaxSmokeResult(result) {
|
|
73
|
-
return { ...result, responseText: null, summary: null };
|
|
74
|
-
}
|
|
75
|
-
export function summarizeMiniMaxWorkerResult(result) {
|
|
76
|
-
const provider = summarizeMiniMaxSmokeResult(result.provider);
|
|
77
|
-
return {
|
|
78
|
-
...result,
|
|
79
|
-
provider,
|
|
80
|
-
reviewHandoff: {
|
|
81
|
-
model: result.reviewHandoff.model,
|
|
82
|
-
prompt: '[redacted]'
|
|
83
|
-
}
|
|
84
|
-
};
|
|
85
|
-
}
|
|
86
62
|
export { getErrorMessage, ok, redactSensitiveErrorMessage };
|
|
@@ -49,7 +49,7 @@ function validateProjectRoot(projectArg) {
|
|
|
49
49
|
}
|
|
50
50
|
export function registerAuditCommands(program, io) {
|
|
51
51
|
const audit = program
|
|
52
|
-
.command('audit')
|
|
52
|
+
.command('audit', { hidden: true })
|
|
53
53
|
.description('Audit a project for compliance with peaks-loop red lines (P0 / P1 / P2 tiers)');
|
|
54
54
|
addJsonOption(audit
|
|
55
55
|
.command('red-lines')
|
|
@@ -1,10 +1,8 @@
|
|
|
1
1
|
import { registerCapabilityCommands } from './capability-commands.js';
|
|
2
2
|
import { registerConfigCommands } from './config-commands.js';
|
|
3
3
|
import { registerSCCommands } from './sc-commands.js';
|
|
4
|
-
import { registerWorkerCommands } from './worker-commands.js';
|
|
5
4
|
export function registerCapabilityWorkerConfigAndSCCommands(program, io) {
|
|
6
5
|
registerCapabilityCommands(program, io);
|
|
7
|
-
registerWorkerCommands(program, io);
|
|
8
6
|
registerConfigCommands(program, io);
|
|
9
7
|
registerSCCommands(program, io);
|
|
10
8
|
}
|
|
@@ -108,7 +108,7 @@ export async function runCodeFast(opts) {
|
|
|
108
108
|
*/
|
|
109
109
|
export function registerCodeCommands(program, io) {
|
|
110
110
|
const code = program
|
|
111
|
-
.command('code')
|
|
111
|
+
.command('code', { hidden: true })
|
|
112
112
|
.description('peaks-code LLM-side workflow planner (slice 2 fast mode)');
|
|
113
113
|
code
|
|
114
114
|
.command('plan')
|
|
@@ -4,7 +4,7 @@ import { addJsonOption, getErrorMessage, printResult } from '../cli-helpers.js';
|
|
|
4
4
|
import { fail, ok } from '../../shared/result.js';
|
|
5
5
|
export function registerCodeReviewCommands(program, io) {
|
|
6
6
|
const codeReview = program
|
|
7
|
-
.command('code-review')
|
|
7
|
+
.command('code-review', { hidden: true })
|
|
8
8
|
.description('Code-review primitives for peaks-rd Gate B3. Wraps the soft-optional `@alibaba-group/open-code-review` (ocr) tool when it is installed + configured; peaks-rd uses the structured JSON output as a second-opinion review alongside its own LLM review. ocr is a peerDependency of peaks-loop 2.8.2+ (was briefly promoted to a hard dependency in 2.0.1/2.0.2, then demoted to optionalDependencies 2.0.3+ — peer in 2.8.2 because its postinstall downloads a Go binary via HTTPS and would otherwise slow `npm i -g peaks-loop` in restricted environments). Install manually with `npm i -g @alibaba-group/open-code-review` if you want second-opinion reviews. LLM endpoint config lives under `peaksConfig.ocr.llm` in the user config — run `peaks code-review config-template` to see the JSON snippet to paste.');
|
|
9
9
|
addJsonOption(codeReview
|
|
10
10
|
.command('detect-ocr')
|
|
@@ -1,15 +1,13 @@
|
|
|
1
1
|
import { executeMigration, planMigration } from '../../services/config/config-migration.js';
|
|
2
|
-
import { getConfig,
|
|
2
|
+
import { getConfig, isSensitiveConfigPath, redactConfigSecrets, setConfig } from '../../services/config/config-service.js';
|
|
3
3
|
import { listAvailableFields, restoreField } from '../../services/config/config-restore.js';
|
|
4
4
|
import { executeRollback, planRollback } from '../../services/config/config-rollback.js';
|
|
5
|
-
import { testMiniMaxProvider } from '../../services/providers/minimax-provider-service.js';
|
|
6
5
|
import { fail, ok } from '../../shared/result.js';
|
|
7
|
-
import { addJsonOption, getErrorMessage,
|
|
6
|
+
import { addJsonOption, getErrorMessage, parseConfigLayer, printInvalidConfigLayer, printResult } from '../cli-helpers.js';
|
|
8
7
|
export function registerConfigCommands(program, io) {
|
|
9
8
|
const config = program.command('config').description('Manage Peaks configuration');
|
|
10
9
|
registerConfigGetSetCommands(config, io);
|
|
11
10
|
registerConfigMigrationCommands(config, io);
|
|
12
|
-
registerMiniMaxProviderCommands(config, io);
|
|
13
11
|
}
|
|
14
12
|
function registerConfigGetSetCommands(config, io) {
|
|
15
13
|
addJsonOption(config.command('get').description('Get current config or a specific key').option('--key <path>', 'dot-notation key path').option('--layer <layer>', 'user or project')).action((options) => {
|
|
@@ -137,7 +135,7 @@ function registerConfigMigrationCommands(config, io) {
|
|
|
137
135
|
function printConfigSetError(io, error, asJson) {
|
|
138
136
|
const message = getErrorMessage(error);
|
|
139
137
|
if (message === 'Sensitive config keys must be stored in the user config layer') {
|
|
140
|
-
printResult(io, fail('config.set', 'SECRET_CONFIG_REQUIRES_USER_LAYER', message, {}, ['Use --layer user
|
|
138
|
+
printResult(io, fail('config.set', 'SECRET_CONFIG_REQUIRES_USER_LAYER', message, {}, ['Use --layer user for sensitive config keys']), asJson);
|
|
141
139
|
process.exitCode = 1;
|
|
142
140
|
return;
|
|
143
141
|
}
|
|
@@ -146,75 +144,6 @@ function printConfigSetError(io, error, asJson) {
|
|
|
146
144
|
process.exitCode = 1;
|
|
147
145
|
return;
|
|
148
146
|
}
|
|
149
|
-
if (message === 'MiniMax base URL must be the MiniMax HTTPS endpoint without embedded credentials') {
|
|
150
|
-
printResult(io, fail('config.set', 'INVALID_MINIMAX_BASE_URL', message, {}, ['Use a MiniMax Anthropic-compatible HTTPS endpoint']), asJson);
|
|
151
|
-
process.exitCode = 1;
|
|
152
|
-
return;
|
|
153
|
-
}
|
|
154
147
|
printResult(io, fail('config.set', 'CONFIG_SET_FAILED', message, {}, ['Check the config key and layer, then retry']), asJson);
|
|
155
148
|
process.exitCode = 1;
|
|
156
149
|
}
|
|
157
|
-
function registerMiniMaxProviderCommands(config, io) {
|
|
158
|
-
const minimaxProvider = config.command('provider').description('Manage model provider settings').command('minimax').description('Manage MiniMax provider settings');
|
|
159
|
-
addJsonOption(minimaxProvider.command('set').description('Set MiniMax provider settings in user config').option('--base-url <url>', 'MiniMax Anthropic-compatible base URL')).action((options) => {
|
|
160
|
-
const baseUrl = options.baseUrl?.trim();
|
|
161
|
-
const apiKey = process.env.MINIMAX_API_KEY?.trim();
|
|
162
|
-
if (!baseUrl && !apiKey) {
|
|
163
|
-
printResult(io, fail('config.provider.minimax.set', 'MINIMAX_PROVIDER_NO_VALUES', 'Provide --base-url and set MINIMAX_API_KEY', {}, ['Export MINIMAX_API_KEY and rerun peaks config provider minimax set --base-url <url>']), options.json);
|
|
164
|
-
process.exitCode = 1;
|
|
165
|
-
return;
|
|
166
|
-
}
|
|
167
|
-
if (baseUrl && !isMiniMaxHttpsUrl(baseUrl)) {
|
|
168
|
-
printResult(io, fail('config.provider.minimax.set', 'INVALID_MINIMAX_BASE_URL', 'MiniMax base URL must be the MiniMax HTTPS endpoint without embedded credentials', {}, ['Use a MiniMax Anthropic-compatible HTTPS endpoint']), options.json);
|
|
169
|
-
process.exitCode = 1;
|
|
170
|
-
return;
|
|
171
|
-
}
|
|
172
|
-
try {
|
|
173
|
-
const input = {};
|
|
174
|
-
if (baseUrl)
|
|
175
|
-
input.baseUrl = baseUrl;
|
|
176
|
-
if (apiKey)
|
|
177
|
-
input.apiKey = apiKey;
|
|
178
|
-
const status = setMiniMaxProviderConfig(input);
|
|
179
|
-
printResult(io, ok('config.provider.minimax.set', status), options.json);
|
|
180
|
-
}
|
|
181
|
-
catch (error) {
|
|
182
|
-
printMiniMaxProviderSetError(io, error, options.json);
|
|
183
|
-
}
|
|
184
|
-
});
|
|
185
|
-
addJsonOption(minimaxProvider.command('get').description('Show redacted MiniMax provider settings')).action((options) => {
|
|
186
|
-
const configValue = getMiniMaxProviderConfig();
|
|
187
|
-
const status = getMiniMaxProviderStatus();
|
|
188
|
-
printResult(io, ok('config.provider.minimax.get', { ...redactConfigSecrets(configValue, 'providers.minimax'), ...status }), options.json);
|
|
189
|
-
});
|
|
190
|
-
addJsonOption(minimaxProvider.command('status').description('Show MiniMax provider configuration status')).action((options) => {
|
|
191
|
-
printResult(io, ok('config.provider.minimax.status', getMiniMaxProviderStatus()), options.json);
|
|
192
|
-
});
|
|
193
|
-
addJsonOption(minimaxProvider.command('test').description('Run a redacted MiniMax provider smoke test').option('--model <model>', 'model name for the smoke test', 'MiniMax-M2.7')).action(async (options) => {
|
|
194
|
-
try {
|
|
195
|
-
const result = await testMiniMaxProvider(getMiniMaxProviderConfig(), { model: options.model });
|
|
196
|
-
const safeResult = summarizeMiniMaxSmokeResult(result);
|
|
197
|
-
if (!result.configured) {
|
|
198
|
-
printResult(io, fail('config.provider.minimax.test', 'MINIMAX_PROVIDER_NOT_CONFIGURED', 'MiniMax provider requires baseUrl and apiKey in user config', safeResult, ['Export MINIMAX_API_KEY or set MINIMAX_API_KEY']), options.json);
|
|
199
|
-
process.exitCode = 1;
|
|
200
|
-
return;
|
|
201
|
-
}
|
|
202
|
-
printResult(io, result.ok ? ok('config.provider.minimax.test', safeResult) : fail('config.provider.minimax.test', 'MINIMAX_PROVIDER_TEST_FAILED', 'MiniMax provider smoke test failed', safeResult, ['Check the MiniMax base URL, API key, and model name']), options.json);
|
|
203
|
-
if (!result.ok)
|
|
204
|
-
process.exitCode = 1;
|
|
205
|
-
}
|
|
206
|
-
catch (error) {
|
|
207
|
-
printResult(io, fail('config.provider.minimax.test', 'MINIMAX_PROVIDER_TEST_FAILED', redactSensitiveErrorMessage(getErrorMessage(error)), {}, ['Check network connectivity and MiniMax provider settings']), options.json);
|
|
208
|
-
process.exitCode = 1;
|
|
209
|
-
}
|
|
210
|
-
});
|
|
211
|
-
}
|
|
212
|
-
function printMiniMaxProviderSetError(io, error, asJson) {
|
|
213
|
-
if (getErrorMessage(error) === 'MiniMax base URL must be the MiniMax HTTPS endpoint without embedded credentials') {
|
|
214
|
-
printResult(io, fail('config.provider.minimax.set', 'INVALID_MINIMAX_BASE_URL', 'MiniMax base URL must be the MiniMax HTTPS endpoint without embedded credentials', {}, ['Use a MiniMax Anthropic-compatible HTTPS endpoint']), asJson);
|
|
215
|
-
process.exitCode = 1;
|
|
216
|
-
return;
|
|
217
|
-
}
|
|
218
|
-
printResult(io, fail('config.provider.minimax.set', 'MINIMAX_PROVIDER_SET_FAILED', getErrorMessage(error), {}, ['Check MiniMax provider settings and retry']), asJson);
|
|
219
|
-
process.exitCode = 1;
|
|
220
|
-
}
|
|
@@ -20,8 +20,11 @@ import { addJsonOption, getErrorMessage, printResult } from '../../cli-helpers.j
|
|
|
20
20
|
import { registerSkillSearchCommand } from '../skill-search-commands.js';
|
|
21
21
|
export function registerSkillCommand(program, io) {
|
|
22
22
|
const skill = program.command('skill').description('Manage Peaks skills');
|
|
23
|
-
addJsonOption(skill.command('list').description('List skills derived from skills/*/SKILL.md')).action(async (options) => {
|
|
24
|
-
|
|
23
|
+
addJsonOption(skill.command('list').description('List skills derived from skills/*/SKILL.md').option('--include-internal', 'include skills with visibility: internal (default: hide them)')).action(async (options) => {
|
|
24
|
+
let skills = await listSkills();
|
|
25
|
+
if (options.includeInternal !== true) {
|
|
26
|
+
skills = skills.filter((s) => s.visibility !== 'internal');
|
|
27
|
+
}
|
|
25
28
|
if (options.json === true) {
|
|
26
29
|
printResult(io, ok('skill.list', { skills }), true);
|
|
27
30
|
}
|
|
@@ -78,6 +78,20 @@ export function registerDispatchCommand(parent, io) {
|
|
|
78
78
|
process.exitCode = 1;
|
|
79
79
|
return;
|
|
80
80
|
}
|
|
81
|
+
// Slice 3 (on-demand-ecc) D-012: the `agent` role was removed in
|
|
82
|
+
// 4.0.0-beta.11 — there is no longer a subprocess path for it
|
|
83
|
+
// (the upstream ECC v2.0.0 ships no `ecc` binary). This guard
|
|
84
|
+
// sits AFTER role validation but BEFORE the missing-prompt
|
|
85
|
+
// check so an action-path dispatch with a valid prompt still
|
|
86
|
+
// returns a clear ROLE_REMOVED envelope + exit 1. Note that
|
|
87
|
+
// Commander short-circuits `--help` BEFORE `.action()` fires,
|
|
88
|
+
// so `peaks sub-agent dispatch agent --help` continues to
|
|
89
|
+
// exit 0 with the help text — that is intentional, not a bug.
|
|
90
|
+
if (role === 'agent') {
|
|
91
|
+
printResult(io, fail('sub-agent.dispatch', 'ROLE_REMOVED', 'The agent role was removed in Slice 3', { role, reason: 'role-removed-in-slice-3', toolCall: null, dispatchRecordPath: null }, []), asJson);
|
|
92
|
+
process.exitCode = 1;
|
|
93
|
+
return;
|
|
94
|
+
}
|
|
81
95
|
if (!options.prompt || options.prompt.length === 0) {
|
|
82
96
|
printResult(io, fail('sub-agent.dispatch', 'MISSING_PROMPT', '--prompt is required when --from-dag is not provided', { role, toolCall: null, dispatchRecordPath: null }, [
|
|
83
97
|
'Re-run with either:',
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `peaks ecc install|status|ls|show` — Slice 3 of 4.0.0-beta.11.
|
|
3
|
+
*
|
|
4
|
+
* Drop-in replacement for the deleted `peaks agent run|list`
|
|
5
|
+
* surface. The pre-Slice-3 implementation shelled out to
|
|
6
|
+
* `npx ecc agent run ...`, but the upstream `affaan-m/everything-claude-code`
|
|
7
|
+
* v2.0.0 release has NO `ecc` binary — the repo is `agents/*.md`
|
|
8
|
+
* flat files plus SKILL.md descriptors.
|
|
9
|
+
*
|
|
10
|
+
* The new flow:
|
|
11
|
+
* - `peaks ecc install [--ref <tag>]` downloads the ECC tarball
|
|
12
|
+
* into `~/.peaks/cache/ecc-<sha>/agents/` (selective extract,
|
|
13
|
+
* agents/*.md only).
|
|
14
|
+
* - `peaks ecc status` reports the cache manifest state.
|
|
15
|
+
* - `peaks ecc ls` lists cached agents from `<cache>/agents/*.md`,
|
|
16
|
+
* parsing YAML frontmatter (with D-009 fallback to filename +
|
|
17
|
+
* first body line when frontmatter is malformed).
|
|
18
|
+
* - `peaks ecc show <name> [--section H] [--max-lines N]` prints
|
|
19
|
+
* the SKILL.md body to stdout — this is the Skill-first path
|
|
20
|
+
* the LLM consumes directly.
|
|
21
|
+
*
|
|
22
|
+
* The `--section` filter extracts a single H1 (`# heading`)
|
|
23
|
+
* through the next H1 — useful when the SKILL.md is large.
|
|
24
|
+
*
|
|
25
|
+
* Per the "Enhancement, not new AI CLI" tenet: this command is a
|
|
26
|
+
* download + read-only access layer. There is no `peaks ecc run`.
|
|
27
|
+
*/
|
|
28
|
+
import { Command } from 'commander';
|
|
29
|
+
import { type ProgramIO } from '../cli-helpers.js';
|
|
30
|
+
export declare function registerEccCommands(program: Command, io: ProgramIO): void;
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
import { downloadToCache, listCachedAgents, readAgentSkill, readCacheManifest, } from '../../services/agent/ecc-cache-service.js';
|
|
2
|
+
import { addJsonOption, getErrorMessage, printResult } from '../cli-helpers.js';
|
|
3
|
+
import { fail, ok } from '../../shared/result.js';
|
|
4
|
+
export function registerEccCommands(program, io) {
|
|
5
|
+
const ecc = program
|
|
6
|
+
.command('ecc')
|
|
7
|
+
.description('affaan-m/everything-claude-code cache: download + read-only access for the LLM (no subprocess; no peaks agent run).');
|
|
8
|
+
addJsonOption(ecc
|
|
9
|
+
.command('install')
|
|
10
|
+
.description('Download affaan-m/ECC to ~/.peaks/cache/ecc-<sha>/ (selective extract: agents/ subtree only).')
|
|
11
|
+
.option('--ref <tag>', 'release tag (default: latest)')).action(async (options) => {
|
|
12
|
+
const asJson = options.json === true;
|
|
13
|
+
try {
|
|
14
|
+
const result = await downloadToCache(options.ref !== undefined && options.ref.length > 0 ? { ref: options.ref } : {});
|
|
15
|
+
const envelope = ok('ecc.install', result, [], [
|
|
16
|
+
`Cache landed at ~/.peaks/cache/ecc-${result.sha}/agents/`,
|
|
17
|
+
`Inspect with: peaks ecc ls`,
|
|
18
|
+
`Consume one agent with: peaks ecc show <name>`,
|
|
19
|
+
]);
|
|
20
|
+
printResult(io, envelope, asJson);
|
|
21
|
+
}
|
|
22
|
+
catch (error) {
|
|
23
|
+
const message = getErrorMessage(error);
|
|
24
|
+
printResult(io, fail('ecc.install', 'FETCH_FAILED', message, { ref: options.ref ?? 'latest' }, [
|
|
25
|
+
'Network failure during ECC download. Manual fallback:',
|
|
26
|
+
' git clone https://github.com/affaan-m/everything-claude-code.git',
|
|
27
|
+
' Copy <repo>/agents/*.md into ~/.peaks/cache/ecc-<sha>/agents/.',
|
|
28
|
+
' Drop a minimal ecc-installed.json manifest into ~/.peaks/cache/.',
|
|
29
|
+
]), asJson);
|
|
30
|
+
process.exitCode = 1;
|
|
31
|
+
}
|
|
32
|
+
});
|
|
33
|
+
addJsonOption(ecc
|
|
34
|
+
.command('status')
|
|
35
|
+
.description('Show ECC cache state (version, sha, fetchedAt, agent count).')).action((options) => {
|
|
36
|
+
const asJson = options.json === true;
|
|
37
|
+
const manifest = readCacheManifest();
|
|
38
|
+
if (manifest === null) {
|
|
39
|
+
printResult(io, fail('ecc.status', 'NO_CACHE', 'No ECC cache found. Run `peaks ecc install` first.', { installed: false }, ['Run `peaks ecc install [--ref <tag>]` to populate ~/.peaks/cache/ecc-<sha>/agents/.']), asJson);
|
|
40
|
+
process.exitCode = 1;
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
printResult(io, ok('ecc.status', manifest, [], [
|
|
44
|
+
`Inspect agents with: peaks ecc ls`,
|
|
45
|
+
`Print one agent with: peaks ecc show <name>`,
|
|
46
|
+
]), asJson);
|
|
47
|
+
});
|
|
48
|
+
addJsonOption(ecc
|
|
49
|
+
.command('ls')
|
|
50
|
+
.description('List cached agents from <cache>/agents/*.md with parsed frontmatter.')).action((options) => {
|
|
51
|
+
const asJson = options.json === true;
|
|
52
|
+
const agents = listCachedAgents();
|
|
53
|
+
printResult(io, ok('ecc.ls', { agents }, [], [
|
|
54
|
+
'Print one with: `peaks ecc show <name>`',
|
|
55
|
+
]), asJson);
|
|
56
|
+
});
|
|
57
|
+
addJsonOption(ecc
|
|
58
|
+
.command('show <name>')
|
|
59
|
+
.description('Print agent SKILL.md to stdout (LLM-consumable; Skill-first path).')
|
|
60
|
+
.option('--section <heading>', 'extract only the named H1 section (# <heading> through next # )')
|
|
61
|
+
.option('--max-lines <n>', 'cap stdout at N lines (default: unlimited)')).action((name, options) => {
|
|
62
|
+
const asJson = options.json === true;
|
|
63
|
+
if (!/^[a-z][a-z0-9-]*$/.test(name)) {
|
|
64
|
+
printResult(io, fail('ecc.show', 'INVALID_NAME', `agent name must match ^[a-z][a-z0-9-]*$ (got "${name}")`, { name }, [
|
|
65
|
+
'Run `peaks ecc ls` to see valid agent names.',
|
|
66
|
+
]), asJson);
|
|
67
|
+
process.exitCode = 1;
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
const body = readAgentSkill(name);
|
|
71
|
+
if (body === null) {
|
|
72
|
+
printResult(io, fail('ecc.show', 'NOT_FOUND', `agent "${name}" is not in the cache`, { name }, [
|
|
73
|
+
'Run `peaks ecc ls` to see available agents.',
|
|
74
|
+
'Or run `peaks ecc install` to (re-)populate the cache.',
|
|
75
|
+
]), asJson);
|
|
76
|
+
process.exitCode = 1;
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
79
|
+
let filtered = body;
|
|
80
|
+
if (typeof options.section === 'string' && options.section.length > 0) {
|
|
81
|
+
const heading = options.section.trim();
|
|
82
|
+
const lines = body.split(/\r?\n/);
|
|
83
|
+
const startIdx = lines.findIndex((line) => new RegExp(`^#\\s+${escapeRegExp(heading)}\\s*$`).test(line));
|
|
84
|
+
if (startIdx === -1) {
|
|
85
|
+
printResult(io, fail('ecc.show', 'SECTION_NOT_FOUND', `section "# ${heading}" not found in ${name}.md`, { name, section: heading }, [
|
|
86
|
+
'Open the file directly to see section names.',
|
|
87
|
+
]), asJson);
|
|
88
|
+
process.exitCode = 1;
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
91
|
+
let endIdx = lines.length;
|
|
92
|
+
for (let i = startIdx + 1; i < lines.length; i += 1) {
|
|
93
|
+
const line = lines[i] ?? '';
|
|
94
|
+
if (/^#\s+/.test(line)) {
|
|
95
|
+
endIdx = i;
|
|
96
|
+
break;
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
filtered = lines.slice(startIdx, endIdx).join('\n');
|
|
100
|
+
}
|
|
101
|
+
if (typeof options.maxLines === 'string' && options.maxLines.length > 0) {
|
|
102
|
+
const cap = Number.parseInt(options.maxLines, 10);
|
|
103
|
+
if (Number.isInteger(cap) && cap > 0) {
|
|
104
|
+
const lines = filtered.split(/\r?\n/);
|
|
105
|
+
if (lines.length > cap)
|
|
106
|
+
filtered = lines.slice(0, cap).join('\n');
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
if (asJson) {
|
|
110
|
+
printResult(io, ok('ecc.show', { name, body: filtered }, [], []), asJson);
|
|
111
|
+
return;
|
|
112
|
+
}
|
|
113
|
+
// Human-readable path: raw SKILL.md body to stdout (LLM-consumable).
|
|
114
|
+
io.stdout(filtered);
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
function escapeRegExp(value) {
|
|
118
|
+
return value.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
119
|
+
}
|
|
@@ -36,7 +36,7 @@ function readStdinSync() {
|
|
|
36
36
|
}
|
|
37
37
|
export function registerPerfAuditCommands(program, io) {
|
|
38
38
|
const perfAudit = program
|
|
39
|
-
.command('perf-audit')
|
|
39
|
+
.command('perf-audit', { hidden: true })
|
|
40
40
|
.description('Independent performance audit skill driver. Reads the immutable peaks-prd handoff (sha256-locked) + the project-level perf-template.md, then writes a structured perf-<rid>.md artifact. Decoupled from peaks-rd 5-way fan-out per slice v2.12.0 (Group A, Tier 3). See skills/bee/peaks-perf-audit/SKILL.md for the full workflow.');
|
|
41
41
|
addJsonOption(perfAudit
|
|
42
42
|
.command('detect')
|
|
@@ -37,7 +37,9 @@ async function resolveBody(bodyArg) {
|
|
|
37
37
|
return bodyArg;
|
|
38
38
|
}
|
|
39
39
|
export function registerPrdCommands(program, io) {
|
|
40
|
-
const prd = program
|
|
40
|
+
const prd = program
|
|
41
|
+
.command('prd', { hidden: true })
|
|
42
|
+
.description('peaks-prd role: artifact + handoff primitives');
|
|
41
43
|
const handoff = prd.command('handoff').description('Write / verify / show the immutable PRD handoff (sha256-locked, schemaVersion: 2)');
|
|
42
44
|
// peaks prd handoff init
|
|
43
45
|
addJsonOption(handoff
|
|
@@ -200,7 +200,7 @@ export function readQaRunOptions(options) {
|
|
|
200
200
|
}
|
|
201
201
|
export function registerQaCommands(program, io) {
|
|
202
202
|
const qa = program
|
|
203
|
-
.command('qa')
|
|
203
|
+
.command('qa', { hidden: true })
|
|
204
204
|
.description('peaks-qa slice: run QA gates (functional / security / browser E2E / mutation) for the active project');
|
|
205
205
|
addJsonOption(qa
|
|
206
206
|
.command('run')
|
|
@@ -2,7 +2,9 @@ import { createArtifactRetentionReport, createChangeImpact, getChangeTraceabilit
|
|
|
2
2
|
import { ok } from '../../shared/result.js';
|
|
3
3
|
import { addJsonOption, multipleOption, printResult } from '../cli-helpers.js';
|
|
4
4
|
export function registerSCCommands(program, io) {
|
|
5
|
-
const sc = program
|
|
5
|
+
const sc = program
|
|
6
|
+
.command('sc', { hidden: true })
|
|
7
|
+
.description('Source control and change traceability (peaks-sc integration)');
|
|
6
8
|
registerSCStatusCommands(sc, io);
|
|
7
9
|
registerSCArtifactCommands(sc, io);
|
|
8
10
|
}
|
|
@@ -36,7 +36,7 @@ function readStdinSync() {
|
|
|
36
36
|
}
|
|
37
37
|
export function registerSecurityAuditCommands(program, io) {
|
|
38
38
|
const securityAudit = program
|
|
39
|
-
.command('security-audit')
|
|
39
|
+
.command('security-audit', { hidden: true })
|
|
40
40
|
.description('Independent security audit skill driver. Reads the immutable peaks-prd handoff (sha256-locked) + the project-level security-template.md, then writes a structured security-<rid>.md artifact. Decoupled from peaks-rd 5-way fan-out per slice v2.12.0 (Group A, Tier 2). See skills/bee/peaks-security-audit/SKILL.md for the full workflow.');
|
|
41
41
|
addJsonOption(securityAudit
|
|
42
42
|
.command('detect')
|
|
@@ -28,6 +28,7 @@ export function registerSkillSearchCommand(program, io) {
|
|
|
28
28
|
.option('-t, --tag <tag>', 'exact match on metadata.tags (e.g. "orchestrator", "loop-engineering")')
|
|
29
29
|
.option('-d, --domain <domain>', 'exact match on metadata.domain (locked enum: code | content | doctor | research | triage | sop | audit | final-review | resume | status | test | ide | slice-decompose | issue-fix-orchestrator | perf-audit | security-audit | reviewer)')
|
|
30
30
|
.option('-l, --limit <n>', 'max results returned (1..100, default 20)', (v) => Number.parseInt(v, 10))
|
|
31
|
+
.option('--include-internal', 'include skills with visibility: internal (default: hide them)')
|
|
31
32
|
.action(async (options) => {
|
|
32
33
|
// 1) Coerce + validate input via the service's Zod schema.
|
|
33
34
|
// The schema's refine rejects empty input — that is the
|
|
@@ -41,6 +42,8 @@ export function registerSkillSearchCommand(program, io) {
|
|
|
41
42
|
raw['domain'] = options.domain;
|
|
42
43
|
if (options.limit !== undefined)
|
|
43
44
|
raw['limit'] = options.limit;
|
|
45
|
+
if (options.includeInternal === true)
|
|
46
|
+
raw['includeInternal'] = true;
|
|
44
47
|
const parsed = SkillSearchInputSchema.safeParse(raw);
|
|
45
48
|
if (!parsed.success) {
|
|
46
49
|
// Exit code 1 = invalid args. Emit a human-readable message
|
|
@@ -7,7 +7,7 @@ import { addJsonOption, getErrorMessage, printResult } from '../cli-helpers.js';
|
|
|
7
7
|
import { fail, ok } from '../../shared/result.js';
|
|
8
8
|
export function registerUpgradeCommands(program, io) {
|
|
9
9
|
addJsonOption(program
|
|
10
|
-
.command('upgrade')
|
|
10
|
+
.command('upgrade', { hidden: true })
|
|
11
11
|
.description('Upgrade a peaks-loop 1.x project to 2.0. Umbrella that orquestrates 7 sub-commands: config-migrate / standards-migrate / memory-extract / hooks-install / skill-sync / audit-verify + write-upgrade-record. Per the "one-key completion" tenet, prefer letting `npm i -g peaks-loop@2.0` postinstall run this for you. Use `--detect-1x` for a read-only probe (no file writes) that the peaks-code skill uses to gate the 1.x → 2.0 AskUserQuestion.')
|
|
12
12
|
.option('--to <version>', 'target version (only "2.0" supported)', '2.0')
|
|
13
13
|
.option('--project <path>', 'project root to upgrade (default: cwd)')
|
package/dist/cli/program.js
CHANGED
|
@@ -58,7 +58,7 @@ import { registerWorkflowEvalCommands } from './commands/loop-eval-commands.js';
|
|
|
58
58
|
import { registerEvolutionCommands } from './commands/evolution-commands.js';
|
|
59
59
|
import { registerAssetCommands } from './commands/asset-commands.js';
|
|
60
60
|
import { registerBeeCommands } from './commands/bee-commands.js';
|
|
61
|
-
import {
|
|
61
|
+
import { registerEccCommands } from './commands/ecc-commands.js';
|
|
62
62
|
import { registerUpgradeCommands } from './commands/upgrade-commands.js';
|
|
63
63
|
import { registerCodeReviewCommands } from './commands/code-review-commands.js';
|
|
64
64
|
import { registerSecurityAuditCommands } from './commands/security-audit-commands.js';
|
|
@@ -99,7 +99,7 @@ import { registerAdapterS2ACommands } from './commands/adapter-commands-s2a.js';
|
|
|
99
99
|
// Slice RD-2 S2-b: `peaks polyrepo *` (init / status / dispatch).
|
|
100
100
|
import { registerPolyrepoCommands } from './commands/polyrepo-commands.js';
|
|
101
101
|
import { registerSkillVisibilityCommand } from './commands/skill-visibility.js';
|
|
102
|
-
import { applyRetention } from '../services/log/retention.js';
|
|
102
|
+
import { applyRetention, cleanupEccCache } from '../services/log/retention.js';
|
|
103
103
|
import { writeLogEntry, maybeWriteStderr } from '../services/log/logger.js';
|
|
104
104
|
export { printResult } from './cli-helpers.js';
|
|
105
105
|
/**
|
|
@@ -120,6 +120,13 @@ function bootstrapLogger(verbose) {
|
|
|
120
120
|
catch { // TODO(g2): legacy silent catch — grace: 1 minor release (v2.14.0)
|
|
121
121
|
/* best-effort retention sweep; never block the CLI */
|
|
122
122
|
}
|
|
123
|
+
// Slice 3 (on-demand-ecc): 7-day TTL sweep over ecc-<sha>/ cache dirs.
|
|
124
|
+
try {
|
|
125
|
+
cleanupEccCache({ retentionDays: 7, nowMs: Date.now() });
|
|
126
|
+
}
|
|
127
|
+
catch { // TODO(g2): legacy silent catch — grace: 1 minor release (v2.14.0)
|
|
128
|
+
/* best-effort ECC retention sweep; never block the CLI */
|
|
129
|
+
}
|
|
123
130
|
const dateOverride = process.env.PEAKS_LOG_DATE_OVERRIDE;
|
|
124
131
|
const entry = {
|
|
125
132
|
ts: new Date().toISOString(),
|
|
@@ -329,8 +336,9 @@ Run peaks (no arguments) for a quickstart. You likely want one of:
|
|
|
329
336
|
// M7 (2026-07-07 spec §7A.2 / §10 RL-9): `peaks bee export|import`
|
|
330
337
|
// — cross-user share surface for bee_release rows.
|
|
331
338
|
registerBeeCommands(program, io);
|
|
332
|
-
// Slice
|
|
333
|
-
|
|
339
|
+
// Slice 3 (on-demand-ecc): `peaks ecc install|status|ls|show` replaces the
|
|
340
|
+
// deleted `peaks agent run|list` subprocess surface.
|
|
341
|
+
registerEccCommands(program, io);
|
|
334
342
|
// Slice: 1.x → 2.0 umbrella (per "one-key completion" + "minimal-user-operation" tenets).
|
|
335
343
|
registerUpgradeCommands(program, io);
|
|
336
344
|
// Slice: ocr soft-optional integration (peaks-rd Gate B3 augmentation).
|