peaks-loop 4.0.0-beta.14 → 4.0.0-beta.16
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 +230 -148
- package/README-en.md +1 -1
- package/README.md +32 -1
- package/bin/peaks.js +0 -0
- package/dist/cli/cli-helpers.d.ts +1 -1
- package/dist/cli/cli-helpers.js +1 -1
- package/dist/cli/commands/adapter-commands-s2a.js +1 -1
- package/dist/cli/commands/asset-commands.js +33 -16
- package/dist/cli/commands/audit-commands.js +1 -1
- package/dist/cli/commands/bee-commands.js +1 -1
- package/dist/cli/commands/capability-commands.js +1 -1
- package/dist/cli/commands/classify-classify-commands.js +1 -1
- package/dist/cli/commands/code-commands.js +1 -1
- package/dist/cli/commands/code-review-commands.js +1 -1
- package/dist/cli/commands/codegraph-commands.js +1 -1
- package/dist/cli/commands/compact-command.js +1 -1
- package/dist/cli/commands/complexity-commands.js +1 -1
- package/dist/cli/commands/config-commands.js +1 -1
- package/dist/cli/commands/context-commands.js +1 -1
- package/dist/cli/commands/contract-commands.js +1 -1
- package/dist/cli/commands/core/artifacts-command.js +1 -1
- package/dist/cli/commands/core/binding-commands.js +1 -1
- package/dist/cli/commands/core/doctor-command.js +63 -3
- package/dist/cli/commands/core/memory-command.js +1 -1
- package/dist/cli/commands/core/profile-command.js +1 -1
- package/dist/cli/commands/core/proxy-command.js +1 -1
- package/dist/cli/commands/core/session-command.js +1 -1
- package/dist/cli/commands/core/skill-command.js +2 -2
- package/dist/cli/commands/core/standards-command.js +1 -1
- package/dist/cli/commands/dispatch-commands.js +2 -2
- package/dist/cli/commands/dispatch-from-dag.js +1 -1
- package/dist/cli/commands/doc-commands.js +1 -1
- package/dist/cli/commands/ecc-commands.js +2 -2
- package/dist/cli/commands/evolution-commands.js +1 -1
- package/dist/cli/commands/feedback-commands.js +1 -1
- package/dist/cli/commands/final-review-commands.js +1 -1
- package/dist/cli/commands/fixture-commands.js +1 -1
- package/dist/cli/commands/fork-commands.js +1 -1
- package/dist/cli/commands/gate-commands.js +1 -1
- package/dist/cli/commands/heartbeat-commands.js +1 -1
- package/dist/cli/commands/hook-handle.js +1 -1
- package/dist/cli/commands/hooks-commands.js +1 -1
- package/dist/cli/commands/ide-commands.js +1 -1
- package/dist/cli/commands/impact-commands.js +1 -1
- package/dist/cli/commands/job-commands.js +1 -1
- package/dist/cli/commands/legacy-commands.js +1 -1
- package/dist/cli/commands/log-commands.js +1 -1
- package/dist/cli/commands/loop-commands.js +1 -1
- package/dist/cli/commands/loop-eval-commands.js +1 -1
- package/dist/cli/commands/memory-commands.js +1 -1
- package/dist/cli/commands/migrate-1-4-1-command.js +1 -1
- package/dist/cli/commands/migrate-v2-10-to-v2-11-command.js +1 -1
- package/dist/cli/commands/mut-commands.d.ts +1 -1
- package/dist/cli/commands/mut-commands.js +1 -5
- package/dist/cli/commands/observability-commands.js +1 -1
- package/dist/cli/commands/openspec-commands.js +2 -2
- package/dist/cli/commands/perf-audit-commands.js +2 -2
- package/dist/cli/commands/perf-commands.js +1 -1
- package/dist/cli/commands/polyrepo-commands.js +1 -1
- package/dist/cli/commands/prd-blocks-commands.js +1 -1
- package/dist/cli/commands/prd-commands.js +1 -1
- package/dist/cli/commands/project-commands.js +1 -1
- package/dist/cli/commands/qa-business-review-commands.js +1 -1
- package/dist/cli/commands/qa-commands.d.ts +1 -1
- package/dist/cli/commands/qa-commands.js +2 -2
- package/dist/cli/commands/release-commands.js +1 -1
- package/dist/cli/commands/request-commands.js +1 -1
- package/dist/cli/commands/retrospective-commands.js +1 -1
- package/dist/cli/commands/reviewer-commands.js +1 -1
- package/dist/cli/commands/role-commands.js +1 -1
- package/dist/cli/commands/runtime-commands.js +1 -2
- package/dist/cli/commands/sc-commands.js +1 -1
- package/dist/cli/commands/scan-commands.js +1 -1
- package/dist/cli/commands/security-audit-commands.js +2 -2
- package/dist/cli/commands/share-commands.d.ts +19 -0
- package/dist/cli/commands/share-commands.js +121 -2
- package/dist/cli/commands/skill-conformance-commands.js +1 -1
- package/dist/cli/commands/skill-loop-engineering-readiness-commands.js +1 -1
- package/dist/cli/commands/skill-search-commands.js +1 -1
- package/dist/cli/commands/slice-commands.js +1 -1
- package/dist/cli/commands/slice-integrate-commands.js +1 -1
- package/dist/cli/commands/slice-review-commands.js +1 -1
- package/dist/cli/commands/smoke-commands.js +1 -1
- package/dist/cli/commands/sop-commands.js +1 -1
- package/dist/cli/commands/statusline-commands.js +1 -1
- package/dist/cli/commands/sub-agent-commands.js +2 -1
- package/dist/cli/commands/understand-commands.js +1 -1
- package/dist/cli/commands/upgrade-commands.js +1 -1
- package/dist/cli/commands/user-touchpoint-commands.js +1 -1
- package/dist/cli/commands/verdict-aggregate-command.js +1 -1
- package/dist/cli/commands/workflow-commands.js +1 -1
- package/dist/cli/commands/workflow-plan-commands.js +1 -1
- package/dist/cli/commands/workspace/init-command.js +1 -1
- package/dist/cli/commands/workspace/migrate-command.js +1 -1
- package/dist/cli/commands/workspace/reconcile-command.js +1 -1
- package/dist/cli/index.js +1 -1
- package/dist/cli/program.js +2 -2
- package/dist/services/artifacts/artifact-prerequisites.js +1 -1
- package/dist/services/artifacts/request-artifact-service.js +1 -1
- package/dist/services/artifacts/workspace-service.js +1 -1
- package/dist/services/code/auto-compact-orchestrator.js +5 -2
- package/dist/services/code-review/ocr-service.d.ts +1 -1
- package/dist/services/code-review/ocr-service.js +6 -3
- package/dist/services/config/config-types.js +1 -1
- package/dist/services/dashboard/project-dashboard-service.js +2 -2
- package/dist/services/dispatch/batch-counter.js +1 -1
- package/dist/services/dispatch/dispatch-record-writer.js +1 -1
- package/dist/services/job/job-progress-store.d.ts +2 -2
- package/dist/services/job/job-types.d.ts +27 -27
- package/dist/services/log/retention.js +1 -1
- package/dist/services/openspec/openspec-archive-service.js +1 -1
- package/dist/services/openspec/openspec-bridge-service.js +1 -1
- package/dist/services/openspec/openspec-init-service.js +1 -1
- package/dist/services/openspec/openspec-propose-from-doctor-service.js +1 -1
- package/dist/services/openspec/openspec-render-service.js +1 -1
- package/dist/services/openspec/openspec-scan-service.js +1 -1
- package/dist/services/openspec/openspec-validate-service.js +1 -1
- package/dist/services/scan/acceptance-coverage-service.js +1 -1
- package/dist/services/scan/archetype-service.js +1 -1
- package/dist/services/scan/existing-system-service.js +1 -1
- package/dist/services/scan/libraries-service.js +1 -1
- package/dist/services/skill/skill-search-service.d.ts +5 -5
- package/dist/services/skill/skill-search-service.js +2 -2
- package/dist/services/skills/skill-registry.js +2 -2
- package/dist/services/skills/skill-runbook-service.js +1 -1
- package/dist/services/slice/slice-check-service.js +1 -1
- package/dist/services/understand/understand-hybrid-service.js +1 -1
- package/dist/services/understand/understand-scan-service.js +2 -2
- package/dist/services/upgrade/upgrade-service.js +4 -3
- package/dist/services/verdict/envelopes.d.ts +2 -2
- package/dist/services/verdict/envelopes.js +2 -2
- package/dist/services/verdict/verdict-aggregator.d.ts +3 -3
- package/dist/services/workflow/autonomous-resume-writer.js +1 -1
- package/dist/services/workflow/plan-reader.d.ts +1 -1
- package/dist/services/workflow/plan-reader.js +1 -1
- package/dist/services/workflow/plan-refresher.d.ts +1 -1
- package/dist/services/workflow/plan-refresher.js +1 -1
- package/dist/services/workflow/plan-trigger-detector.d.ts +1 -1
- package/dist/services/workflow/plan-trigger-detector.js +1 -1
- package/dist/services/workflow/workflow-router-service.js +11 -9
- package/dist/services/workspace/migrate-service.js +1 -1
- package/dist/services/workspace/workspace-service.js +1 -1
- package/package.json +13 -8
- package/scripts/sync-version.mjs +8 -1
- package/skills/bee/peaks-rd/SKILL.md +14 -1
- package/skills/peaks-code/SKILL.md +44 -0
- package/skills/peaks-code/references/sub-agent-dispatch.md +30 -0
- package/dist/services/agent/ecc-cache-service.d.ts +0 -97
- package/dist/services/agent/ecc-cache-service.js +0 -491
- package/dist/services/audit-independent/perf-audit-service.d.ts +0 -151
- package/dist/services/audit-independent/perf-audit-service.js +0 -316
- package/dist/services/audit-independent/security-audit-service.d.ts +0 -155
- package/dist/services/audit-independent/security-audit-service.js +0 -316
- package/dist/services/context/dispatch-context-guard.d.ts +0 -27
- package/dist/services/context/dispatch-context-guard.js +0 -192
- package/dist/services/context/shared-channel.d.ts +0 -93
- package/dist/services/context/shared-channel.js +0 -308
- package/dist/services/crystallization/crystallization-service.d.ts +0 -239
- package/dist/services/crystallization/crystallization-service.js +0 -397
- package/dist/services/crystallization/crystallization-store.d.ts +0 -75
- package/dist/services/crystallization/crystallization-store.js +0 -193
- package/dist/services/crystallization/crystallization-types.d.ts +0 -313
- package/dist/services/crystallization/crystallization-types.js +0 -299
- package/dist/services/crystallization/evidence-brief-builder.d.ts +0 -237
- package/dist/services/crystallization/evidence-brief-builder.js +0 -240
- package/dist/services/doctor/doctor-service.d.ts +0 -149
- package/dist/services/doctor/doctor-service.js +0 -929
- package/dist/services/filesystem/file-lock.d.ts +0 -11
- package/dist/services/filesystem/file-lock.js +0 -152
- package/dist/services/final-review/final-review-service.d.ts +0 -12
- package/dist/services/final-review/final-review-service.js +0 -52
- package/dist/services/final-review/final-review-types.d.ts +0 -42
- package/dist/services/final-review/final-review-types.js +0 -18
- package/dist/services/job/job-resource-snapshot.d.ts +0 -7
- package/dist/services/job/job-resource-snapshot.js +0 -75
- package/dist/services/mut/assert-scanner.d.ts +0 -6
- package/dist/services/mut/assert-scanner.js +0 -116
- package/dist/services/mut/index.d.ts +0 -8
- package/dist/services/mut/index.js +0 -7
- package/dist/services/mut/mut-runner.d.ts +0 -39
- package/dist/services/mut/mut-runner.js +0 -29
- package/dist/services/mut/production-stryker.d.ts +0 -2
- package/dist/services/mut/production-stryker.js +0 -75
- package/dist/services/mut/report-builder.d.ts +0 -11
- package/dist/services/mut/report-builder.js +0 -110
- package/dist/services/mut/report-loader.d.ts +0 -31
- package/dist/services/mut/report-loader.js +0 -78
- package/dist/services/mut/thresholds.d.ts +0 -21
- package/dist/services/mut/thresholds.js +0 -22
- package/dist/services/mut/types.d.ts +0 -336
- package/dist/services/mut/types.js +0 -59
- package/dist/shared/fs.d.ts +0 -4
- package/dist/shared/fs.js +0 -26
- package/dist/shared/paths.d.ts +0 -6
- package/dist/shared/paths.js +0 -50
- package/dist/shared/result.d.ts +0 -22
- package/dist/shared/result.js +0 -46
- package/dist/shared/version.d.ts +0 -1
- package/dist/shared/version.js +0 -1
- package/examples/video-demo/README.md +0 -142
- package/examples/video-demo/out/en-closing-960.png +0 -0
- package/examples/video-demo/out/zh-closing-960.png +0 -0
- package/examples/video-demo/preview/peaks-loop-demo-en.mp4 +0 -0
- package/examples/video-demo/preview/peaks-loop-demo.mp4 +0 -0
|
@@ -1,316 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* peaks-perf-audit service — independent performance audit skill driver.
|
|
3
|
-
*
|
|
4
|
-
* Slice v2.12.0 (Group A, Tier 3). Symmetric to security-audit-service.ts:
|
|
5
|
-
* - 5-state detection of the perf-audit runtime
|
|
6
|
-
* - Loading + sha256 verification of the prd/handoff.md
|
|
7
|
-
* - Loading the project-level perf-template.md
|
|
8
|
-
* - Producing the audit envelope (verdict + violations) to write
|
|
9
|
-
* to `.peaks/_runtime/<sid>/audit/perf-<rid>.md`
|
|
10
|
-
*
|
|
11
|
-
* The actual LLM-in-loop audit step is NOT in this service — the
|
|
12
|
-
* parent LLM (peaks-perf-audit skill prompt) reads the template,
|
|
13
|
-
* runs the audit, and returns a structured envelope. This service
|
|
14
|
-
* is the pure I/O + validation core; the LLM is the judgement core.
|
|
15
|
-
*
|
|
16
|
-
* Cross-references:
|
|
17
|
-
* - PRD: `.peaks/_runtime/<sid>/prd/handoff.md` (sha256-locked, schemaVersion: 2)
|
|
18
|
-
* - Template: `.peaks/project-scan/perf-template.md`
|
|
19
|
-
* - Output: `.peaks/_runtime/<sid>/audit/perf-<rid>.md`
|
|
20
|
-
* - Schema: `.peaks/project-scan/audit-output-schema.md` (schemaVersion: 1)
|
|
21
|
-
* - Companion: `src/services/audit-independent/security-audit-service.ts`
|
|
22
|
-
*/
|
|
23
|
-
import { existsSync, readFileSync, writeFileSync, mkdirSync } from 'node:fs';
|
|
24
|
-
import { join, resolve, isAbsolute } from 'node:path';
|
|
25
|
-
import { createHash } from 'node:crypto';
|
|
26
|
-
/**
|
|
27
|
-
* Validate a raw value as a PerfAuditEnvelope. Mirrors the
|
|
28
|
-
* `isSecurityAuditEnvelope` strict-shape pattern.
|
|
29
|
-
*/
|
|
30
|
-
export function isPerfAuditEnvelope(value) {
|
|
31
|
-
if (value === null || typeof value !== 'object')
|
|
32
|
-
return false;
|
|
33
|
-
const obj = value;
|
|
34
|
-
if (typeof obj.verdict !== 'string')
|
|
35
|
-
return false;
|
|
36
|
-
if (obj.verdict !== 'pass' && obj.verdict !== 'warn' && obj.verdict !== 'block') {
|
|
37
|
-
return false;
|
|
38
|
-
}
|
|
39
|
-
if (!Array.isArray(obj.violations))
|
|
40
|
-
return false;
|
|
41
|
-
if (typeof obj.summary !== 'string')
|
|
42
|
-
return false;
|
|
43
|
-
for (const v of obj.violations) {
|
|
44
|
-
if (v === null || typeof v !== 'object')
|
|
45
|
-
return false;
|
|
46
|
-
const vo = v;
|
|
47
|
-
if (typeof vo.dimension !== 'string')
|
|
48
|
-
return false;
|
|
49
|
-
if (typeof vo.severity !== 'string')
|
|
50
|
-
return false;
|
|
51
|
-
if (vo.severity !== 'CRITICAL' && vo.severity !== 'HIGH' && vo.severity !== 'MED' && vo.severity !== 'LOW') {
|
|
52
|
-
return false;
|
|
53
|
-
}
|
|
54
|
-
if (typeof vo.file !== 'string')
|
|
55
|
-
return false;
|
|
56
|
-
if (typeof vo.line !== 'number' || !Number.isFinite(vo.line))
|
|
57
|
-
return false;
|
|
58
|
-
if (typeof vo.hint !== 'string')
|
|
59
|
-
return false;
|
|
60
|
-
}
|
|
61
|
-
return true;
|
|
62
|
-
}
|
|
63
|
-
/**
|
|
64
|
-
* Read the peaks-prd handoff frontmatter + body, verify sha256 matches
|
|
65
|
-
* the body. Returns null on missing file or sha256 mismatch; otherwise
|
|
66
|
-
* returns the parsed frontmatter + body string.
|
|
67
|
-
*
|
|
68
|
-
* Defensive: we read frontmatter via a 1-line regex match, not via
|
|
69
|
-
* a YAML parser. The handoff service (`src/services/prd/handoff-service.ts`)
|
|
70
|
-
* is the canonical writer; we only consume its output here.
|
|
71
|
-
*/
|
|
72
|
-
export function readAndVerifyHandoff(handoffPath, projectRoot) {
|
|
73
|
-
if (!handoffPath || !isAbsolute(handoffPath)) {
|
|
74
|
-
const absolutePath = resolve(projectRoot, handoffPath);
|
|
75
|
-
if (!existsSync(absolutePath))
|
|
76
|
-
return null;
|
|
77
|
-
return readAndVerifyHandoff(absolutePath, projectRoot);
|
|
78
|
-
}
|
|
79
|
-
if (!existsSync(handoffPath))
|
|
80
|
-
return null;
|
|
81
|
-
let raw;
|
|
82
|
-
try {
|
|
83
|
-
raw = readFileSync(handoffPath, 'utf8');
|
|
84
|
-
}
|
|
85
|
-
catch { // TODO(g2): legacy silent catch — grace: 1 minor release (v2.14.0)
|
|
86
|
-
return null;
|
|
87
|
-
}
|
|
88
|
-
// Frontmatter pattern: `---` line, then key: value pairs, then `---` line.
|
|
89
|
-
const match = raw.match(/^---\n([\s\S]*?)\n---\n([\s\S]*)$/);
|
|
90
|
-
if (match === null)
|
|
91
|
-
return null;
|
|
92
|
-
const frontmatterRaw = match[1];
|
|
93
|
-
const body = match[2];
|
|
94
|
-
const sha256Match = frontmatterRaw.match(/^sha256:\s*([a-f0-9]{64})\s*$/m);
|
|
95
|
-
const schemaVersionMatch = frontmatterRaw.match(/^schemaVersion:\s*(\d+)\s*$/m);
|
|
96
|
-
if (sha256Match === null || schemaVersionMatch === null)
|
|
97
|
-
return null;
|
|
98
|
-
const sha256Expected = sha256Match[1];
|
|
99
|
-
const schemaVersion = parseInt(schemaVersionMatch[1], 10);
|
|
100
|
-
const sha256Actual = createHash('sha256').update(body, 'utf8').digest('hex');
|
|
101
|
-
if (sha256Expected !== sha256Actual)
|
|
102
|
-
return null;
|
|
103
|
-
return {
|
|
104
|
-
frontmatter: { sha256: sha256Expected, schemaVersion },
|
|
105
|
-
body,
|
|
106
|
-
};
|
|
107
|
-
}
|
|
108
|
-
/**
|
|
109
|
-
* Read the project-level perf-template.md. Returns the body
|
|
110
|
-
* string (with frontmatter stripped) or null if the file is absent.
|
|
111
|
-
* Does NOT validate the template content; the parent LLM validates
|
|
112
|
-
* by reading.
|
|
113
|
-
*/
|
|
114
|
-
export function readPerfTemplate(projectRoot) {
|
|
115
|
-
const templatePath = join(projectRoot, '.peaks', 'project-scan', 'perf-template.md');
|
|
116
|
-
if (!existsSync(templatePath))
|
|
117
|
-
return null;
|
|
118
|
-
try {
|
|
119
|
-
return readFileSync(templatePath, 'utf8');
|
|
120
|
-
}
|
|
121
|
-
catch { // TODO(g2): legacy silent catch — grace: 1 minor release (v2.14.0)
|
|
122
|
-
return null;
|
|
123
|
-
}
|
|
124
|
-
}
|
|
125
|
-
/**
|
|
126
|
-
* 5-state detector. The parent skill inspects the state and either
|
|
127
|
-
* proceeds (when `ready`) or records a degradation note and falls
|
|
128
|
-
* back (when any other state).
|
|
129
|
-
*
|
|
130
|
-
* Soft-fail policy mirrors `detectEcc` (slice 7 Group D) and
|
|
131
|
-
* `detectSecurityAudit`: the CLI never throws; it returns a typed
|
|
132
|
-
* detect result.
|
|
133
|
-
*/
|
|
134
|
-
export function detectPerfAudit(input) {
|
|
135
|
-
const warnings = [];
|
|
136
|
-
const nextActions = [];
|
|
137
|
-
const handoffPath = join(input.projectRoot, '.peaks', '_runtime', input.sessionId, 'prd', 'handoff.md');
|
|
138
|
-
const handoffPresent = existsSync(handoffPath);
|
|
139
|
-
const templatePath = join(input.projectRoot, '.peaks', 'project-scan', 'perf-template.md');
|
|
140
|
-
const templatePresent = existsSync(templatePath);
|
|
141
|
-
if (!handoffPresent) {
|
|
142
|
-
return {
|
|
143
|
-
state: 'handoff-missing',
|
|
144
|
-
handoffPresent: false,
|
|
145
|
-
templatePresent,
|
|
146
|
-
warnings: [`peaks-prd handoff not found at ${handoffPath}`],
|
|
147
|
-
nextActions: [
|
|
148
|
-
'Run peaks-prd handoff init to produce a sha256-locked handoff before running peaks perf-audit.',
|
|
149
|
-
'Until the handoff exists, peaks-perf-audit cannot start (gate fail).'
|
|
150
|
-
]
|
|
151
|
-
};
|
|
152
|
-
}
|
|
153
|
-
if (!templatePresent) {
|
|
154
|
-
return {
|
|
155
|
-
state: 'template-missing',
|
|
156
|
-
handoffPresent: true,
|
|
157
|
-
templatePresent: false,
|
|
158
|
-
warnings: [`perf-template.md not found at ${templatePath}`],
|
|
159
|
-
nextActions: [
|
|
160
|
-
'Run peaks project template init to bootstrap the 3 audit templates (security-template, perf-template, audit-output-schema).',
|
|
161
|
-
'Until the template exists, peaks-perf-audit cannot start (gate fail).'
|
|
162
|
-
]
|
|
163
|
-
};
|
|
164
|
-
}
|
|
165
|
-
if (input.dispatchError !== undefined) {
|
|
166
|
-
return {
|
|
167
|
-
state: 'dispatch-failed',
|
|
168
|
-
handoffPresent: true,
|
|
169
|
-
templatePresent: true,
|
|
170
|
-
warnings: [
|
|
171
|
-
`Audit dispatch failed: ${input.dispatchError instanceof Error ? input.dispatchError.message : String(input.dispatchError)}`
|
|
172
|
-
],
|
|
173
|
-
nextActions: [
|
|
174
|
-
'Inspect the audit prompt template for the failure cause.',
|
|
175
|
-
'peaks-perf-audit falls back to inline LLM review (degradation note: perf-audit-dispatch-failed).'
|
|
176
|
-
]
|
|
177
|
-
};
|
|
178
|
-
}
|
|
179
|
-
if (input.envelope !== undefined && !isPerfAuditEnvelope(input.envelope)) {
|
|
180
|
-
return {
|
|
181
|
-
state: 'envelope-malformed',
|
|
182
|
-
handoffPresent: true,
|
|
183
|
-
templatePresent: true,
|
|
184
|
-
warnings: [
|
|
185
|
-
'Perf-audit returned a value that failed envelope validation (expected { verdict, violations, summary }).'
|
|
186
|
-
],
|
|
187
|
-
nextActions: [
|
|
188
|
-
'Verify the perf-audit skill prompt matches PRD AC-3.x output shape.',
|
|
189
|
-
'If the envelope shape is intentionally different, file a bug at the peaks-loop repo.'
|
|
190
|
-
]
|
|
191
|
-
};
|
|
192
|
-
}
|
|
193
|
-
return {
|
|
194
|
-
state: 'ready',
|
|
195
|
-
handoffPresent: true,
|
|
196
|
-
templatePresent: true,
|
|
197
|
-
warnings,
|
|
198
|
-
nextActions
|
|
199
|
-
};
|
|
200
|
-
}
|
|
201
|
-
/**
|
|
202
|
-
* Render a PerfAuditEnvelope to the canonical audit artifact body
|
|
203
|
-
* (markdown). Mirrors `renderSecurityAuditArtifact` in
|
|
204
|
-
* `security-audit-service.ts` and `adaptEccEnvelopeToRdCodeReview`
|
|
205
|
-
* in ecc-bridge.ts: produce a markdown body with all required
|
|
206
|
-
* sections, ready to write to
|
|
207
|
-
* `.peaks/_runtime/<sid>/audit/perf-<rid>.md`.
|
|
208
|
-
*/
|
|
209
|
-
export function renderPerfAuditArtifact(env, opts) {
|
|
210
|
-
const counts = {};
|
|
211
|
-
for (const v of env.violations) {
|
|
212
|
-
counts[v.severity] = (counts[v.severity] ?? 0) + 1;
|
|
213
|
-
}
|
|
214
|
-
const criticalCount = counts['CRITICAL'] ?? 0;
|
|
215
|
-
const findingsBullets = env.violations.length === 0
|
|
216
|
-
? '- (none)'
|
|
217
|
-
: env.violations.map((v) => `- [${v.severity}] ${v.dimension} @ ${v.file}:${v.line} — ${v.hint}`).join('\n');
|
|
218
|
-
const requiredFixes = env.violations.length === 0
|
|
219
|
-
? ''
|
|
220
|
-
: [
|
|
221
|
-
'## Required fixes',
|
|
222
|
-
'',
|
|
223
|
-
...env.violations.map((v) => `- [${v.severity}] ${v.file}:${v.line} — ${v.hint}`),
|
|
224
|
-
''
|
|
225
|
-
].join('\n');
|
|
226
|
-
const body = [
|
|
227
|
-
'## Summary',
|
|
228
|
-
'',
|
|
229
|
-
env.summary,
|
|
230
|
-
'',
|
|
231
|
-
'## Baseline reference',
|
|
232
|
-
'',
|
|
233
|
-
'N/A — no prior baseline (slice v2.12.0 first-run bootstrap)',
|
|
234
|
-
`audited at: ${opts.generatedAt}`,
|
|
235
|
-
`verdict: ${env.verdict}`,
|
|
236
|
-
`handoffHash: ${opts.handoffHash}`,
|
|
237
|
-
'',
|
|
238
|
-
'## Measurement result',
|
|
239
|
-
'',
|
|
240
|
-
'(see Findings; per-dimension method declared in template)',
|
|
241
|
-
'',
|
|
242
|
-
'## Threshold check',
|
|
243
|
-
'',
|
|
244
|
-
'(see Findings; per-dimension threshold table declared in template)',
|
|
245
|
-
'',
|
|
246
|
-
'## Findings',
|
|
247
|
-
'',
|
|
248
|
-
findingsBullets,
|
|
249
|
-
'',
|
|
250
|
-
requiredFixes,
|
|
251
|
-
'## Verdict',
|
|
252
|
-
'',
|
|
253
|
-
`verdict: ${env.verdict}`,
|
|
254
|
-
`CRITICAL: ${criticalCount}`,
|
|
255
|
-
''
|
|
256
|
-
].filter((s) => s.length > 0).join('\n');
|
|
257
|
-
return {
|
|
258
|
-
body,
|
|
259
|
-
violationsCount: env.violations.length,
|
|
260
|
-
verdict: env.verdict,
|
|
261
|
-
};
|
|
262
|
-
}
|
|
263
|
-
/**
|
|
264
|
-
* Write the rendered audit artifact to
|
|
265
|
-
* `.peaks/_runtime/<sid>/audit/perf-<rid>.md`.
|
|
266
|
-
*
|
|
267
|
-
* Atomic write (tmp + rename) to avoid partial writes on crash.
|
|
268
|
-
* Returns the absolute path on success.
|
|
269
|
-
*/
|
|
270
|
-
export function writePerfAuditArtifact(projectRoot, sessionId, rid, body) {
|
|
271
|
-
const targetDir = join(projectRoot, '.peaks', '_runtime', sessionId, 'audit');
|
|
272
|
-
mkdirSync(targetDir, { recursive: true });
|
|
273
|
-
const targetPath = join(targetDir, `perf-${rid}.md`);
|
|
274
|
-
// tmp + rename for atomicity
|
|
275
|
-
const tmpPath = `${targetPath}.tmp`;
|
|
276
|
-
writeFileSync(tmpPath, body, 'utf8');
|
|
277
|
-
// Sync rename: on Windows, fs.renameSync overwrites if target exists (Node 22+)
|
|
278
|
-
const { renameSync } = require('node:fs');
|
|
279
|
-
renameSync(tmpPath, targetPath);
|
|
280
|
-
return targetPath;
|
|
281
|
-
}
|
|
282
|
-
/**
|
|
283
|
-
* Convenience: run `detectPerfAudit` + `renderPerfAuditArtifact`
|
|
284
|
-
* + `writePerfAuditArtifact` in one call.
|
|
285
|
-
*
|
|
286
|
-
* Returns `{ detect, artifactPath, violationsCount, verdict }` or
|
|
287
|
-
* `{ detect, artifactPath: null, ... }` when not ready.
|
|
288
|
-
*/
|
|
289
|
-
export function runPerfAudit(input) {
|
|
290
|
-
const detect = detectPerfAudit({
|
|
291
|
-
projectRoot: input.projectRoot,
|
|
292
|
-
sessionId: input.sessionId,
|
|
293
|
-
...(input.dispatchError !== undefined ? { dispatchError: input.dispatchError } : {}),
|
|
294
|
-
...(input.envelope !== undefined ? { envelope: input.envelope } : {})
|
|
295
|
-
});
|
|
296
|
-
if (detect.state !== 'ready' || input.envelope === undefined) {
|
|
297
|
-
return { detect, artifactPath: null, violationsCount: 0, verdict: null };
|
|
298
|
-
}
|
|
299
|
-
// detect.state === 'ready' implies input.envelope passed isPerfAuditEnvelope.
|
|
300
|
-
const env = input.envelope;
|
|
301
|
-
const handoffPath = join(input.projectRoot, '.peaks', '_runtime', input.sessionId, 'prd', 'handoff.md');
|
|
302
|
-
const verified = readAndVerifyHandoff(handoffPath, input.projectRoot);
|
|
303
|
-
const handoffHash = verified?.frontmatter.sha256 ?? 'unknown';
|
|
304
|
-
const rendered = renderPerfAuditArtifact(env, {
|
|
305
|
-
rid: input.rid,
|
|
306
|
-
handoffHash,
|
|
307
|
-
generatedAt: input.generatedAt
|
|
308
|
-
});
|
|
309
|
-
const artifactPath = writePerfAuditArtifact(input.projectRoot, input.sessionId, input.rid, rendered.body);
|
|
310
|
-
return {
|
|
311
|
-
detect,
|
|
312
|
-
artifactPath,
|
|
313
|
-
violationsCount: rendered.violationsCount,
|
|
314
|
-
verdict: rendered.verdict
|
|
315
|
-
};
|
|
316
|
-
}
|
|
@@ -1,155 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* peaks-security-audit service — independent security audit skill driver.
|
|
3
|
-
*
|
|
4
|
-
* Slice v2.12.0 (Group A, Tier 2). The skill is decoupled from the
|
|
5
|
-
* peaks-rd 5-way fan-out (per PRD AC-2.x) and lives as a standalone
|
|
6
|
-
* CLI surface: `peaks security-audit run --rid <id> ...`.
|
|
7
|
-
*
|
|
8
|
-
* The service owns:
|
|
9
|
-
* - 5-state detection of the security-audit runtime
|
|
10
|
-
* (handoff-missing / template-missing / dispatch-failed / template-malformed / ready)
|
|
11
|
-
* - Loading + sha256 verification of the prd/handoff.md
|
|
12
|
-
* - Loading the project-level security-template.md
|
|
13
|
-
* - Producing the audit envelope (verdict + violations) to write
|
|
14
|
-
* to `.peaks/_runtime/<sid>/audit/security-<rid>.md`
|
|
15
|
-
*
|
|
16
|
-
* The actual LLM-in-loop audit step is NOT in this service — the
|
|
17
|
-
* parent LLM (peaks-security-audit skill prompt) reads the template,
|
|
18
|
-
* runs the audit, and returns a structured envelope. This service
|
|
19
|
-
* is the pure I/O + validation core; the LLM is the judgement core.
|
|
20
|
-
*
|
|
21
|
-
* Why a service (not inlined in the CLI):
|
|
22
|
-
* - Unit-testable in isolation (6 case per PRD AC-2.8)
|
|
23
|
-
* - The 5-state detector mirrors the ecc-bridge detectEcc pattern
|
|
24
|
-
* (slice 7 Group D), keeping the surface uniform
|
|
25
|
-
* - Future migration to peaks sub-agent dispatch (peaks-rd main
|
|
26
|
-
* loop can opt to call this service directly without re-implementing
|
|
27
|
-
* the handoff verification)
|
|
28
|
-
*
|
|
29
|
-
* Cross-references:
|
|
30
|
-
* - PRD: `.peaks/_runtime/<sid>/prd/handoff.md` (sha256-locked, schemaVersion: 2)
|
|
31
|
-
* - Template: `.peaks/project-scan/security-template.md`
|
|
32
|
-
* - Output: `.peaks/_runtime/<sid>/audit/security-<rid>.md`
|
|
33
|
-
* - Schema: `.peaks/project-scan/audit-output-schema.md` (schemaVersion: 1)
|
|
34
|
-
*/
|
|
35
|
-
/**
|
|
36
|
-
* 5-state detection result. Mirrors `detectEcc` in `services/code-review/ecc-bridge.ts`.
|
|
37
|
-
*
|
|
38
|
-
* - `ready` — handoff + template + project all present
|
|
39
|
-
* - `handoff-missing` — `.peaks/_runtime/<sid>/prd/handoff.md` absent
|
|
40
|
-
* - `template-missing` — `.peaks/project-scan/security-template.md` absent
|
|
41
|
-
* - `dispatch-failed` — parent LLM threw before returning the audit envelope
|
|
42
|
-
* - `envelope-malformed` — parent LLM returned a value that fails `isSecurityAuditEnvelope`
|
|
43
|
-
*/
|
|
44
|
-
export type SecurityAuditDetectState = 'ready' | 'handoff-missing' | 'template-missing' | 'dispatch-failed' | 'envelope-malformed';
|
|
45
|
-
export interface SecurityAuditDetectResult {
|
|
46
|
-
readonly state: SecurityAuditDetectState;
|
|
47
|
-
readonly handoffPresent: boolean;
|
|
48
|
-
readonly templatePresent: boolean;
|
|
49
|
-
readonly warnings: readonly string[];
|
|
50
|
-
readonly nextActions: readonly string[];
|
|
51
|
-
}
|
|
52
|
-
export type SecurityAuditVerdict = 'pass' | 'warn' | 'block';
|
|
53
|
-
export interface SecurityAuditViolation {
|
|
54
|
-
readonly dimension: string;
|
|
55
|
-
readonly severity: 'CRITICAL' | 'HIGH' | 'MED' | 'LOW';
|
|
56
|
-
readonly file: string;
|
|
57
|
-
readonly line: number;
|
|
58
|
-
readonly hint: string;
|
|
59
|
-
}
|
|
60
|
-
export interface SecurityAuditEnvelope {
|
|
61
|
-
readonly verdict: SecurityAuditVerdict;
|
|
62
|
-
readonly violations: ReadonlyArray<SecurityAuditViolation>;
|
|
63
|
-
readonly summary: string;
|
|
64
|
-
}
|
|
65
|
-
/**
|
|
66
|
-
* Validate a raw value as a SecurityAuditEnvelope. Mirrors the
|
|
67
|
-
* `isEccEnvelope` strict-shape pattern.
|
|
68
|
-
*/
|
|
69
|
-
export declare function isSecurityAuditEnvelope(value: unknown): value is SecurityAuditEnvelope;
|
|
70
|
-
/**
|
|
71
|
-
* Handoff frontmatter — minimal projection of peaks-prd v2.11.0 handoff
|
|
72
|
-
* frontmatter. We only need sha256 for verification; the rest of the
|
|
73
|
-
* handoff body is consumed by the parent LLM, not by this service.
|
|
74
|
-
*/
|
|
75
|
-
export interface HandoffFrontmatter {
|
|
76
|
-
readonly sha256: string;
|
|
77
|
-
readonly schemaVersion: number;
|
|
78
|
-
}
|
|
79
|
-
/**
|
|
80
|
-
* Read the peaks-prd handoff frontmatter + body, verify sha256 matches
|
|
81
|
-
* the body. Returns null on missing file or sha256 mismatch; otherwise
|
|
82
|
-
* returns the parsed frontmatter + body string.
|
|
83
|
-
*
|
|
84
|
-
* Defensive: we read frontmatter via a 1-line regex match, not via
|
|
85
|
-
* a YAML parser. The handoff service (`src/services/prd/handoff-service.ts`)
|
|
86
|
-
* is the canonical writer; we only consume its output here.
|
|
87
|
-
*/
|
|
88
|
-
export declare function readAndVerifyHandoff(handoffPath: string, projectRoot: string): {
|
|
89
|
-
frontmatter: HandoffFrontmatter;
|
|
90
|
-
body: string;
|
|
91
|
-
} | null;
|
|
92
|
-
/**
|
|
93
|
-
* Read the project-level security-template.md. Returns the body
|
|
94
|
-
* string (with frontmatter stripped) or null if the file is absent.
|
|
95
|
-
* Does NOT validate the template content; the parent LLM validates
|
|
96
|
-
* by reading.
|
|
97
|
-
*/
|
|
98
|
-
export declare function readSecurityTemplate(projectRoot: string): string | null;
|
|
99
|
-
/**
|
|
100
|
-
* 5-state detector. The parent skill inspects the state and either
|
|
101
|
-
* proceeds (when `ready`) or records a degradation note and falls
|
|
102
|
-
* back (when any other state).
|
|
103
|
-
*
|
|
104
|
-
* Soft-fail policy mirrors `detectEcc` (slice 7 Group D): the CLI
|
|
105
|
-
* never throws; it returns a typed detect result.
|
|
106
|
-
*/
|
|
107
|
-
export declare function detectSecurityAudit(input: {
|
|
108
|
-
readonly projectRoot: string;
|
|
109
|
-
readonly sessionId: string;
|
|
110
|
-
readonly dispatchError?: unknown;
|
|
111
|
-
readonly envelope?: unknown;
|
|
112
|
-
}): SecurityAuditDetectResult;
|
|
113
|
-
/**
|
|
114
|
-
* Render a SecurityAuditEnvelope to the canonical audit artifact body
|
|
115
|
-
* (markdown). Mirrors `adaptEccEnvelopeToRdCodeReview` in ecc-bridge.ts:
|
|
116
|
-
* produce a markdown body with all required sections, ready to write
|
|
117
|
-
* to `.peaks/_runtime/<sid>/audit/security-<rid>.md`.
|
|
118
|
-
*/
|
|
119
|
-
export declare function renderSecurityAuditArtifact(env: SecurityAuditEnvelope, opts: {
|
|
120
|
-
rid: string;
|
|
121
|
-
handoffHash: string;
|
|
122
|
-
generatedAt: string;
|
|
123
|
-
}): {
|
|
124
|
-
body: string;
|
|
125
|
-
violationsCount: number;
|
|
126
|
-
verdict: SecurityAuditVerdict;
|
|
127
|
-
};
|
|
128
|
-
/**
|
|
129
|
-
* Write the rendered audit artifact to
|
|
130
|
-
* `.peaks/_runtime/<sid>/audit/security-<rid>.md`.
|
|
131
|
-
*
|
|
132
|
-
* Atomic write (tmp + rename) to avoid partial writes on crash.
|
|
133
|
-
* Returns the absolute path on success.
|
|
134
|
-
*/
|
|
135
|
-
export declare function writeSecurityAuditArtifact(projectRoot: string, sessionId: string, rid: string, body: string): string;
|
|
136
|
-
/**
|
|
137
|
-
* Convenience: run `detectSecurityAudit` + `renderSecurityAuditArtifact`
|
|
138
|
-
* + `writeSecurityAuditArtifact` in one call.
|
|
139
|
-
*
|
|
140
|
-
* Returns `{ detect, artifactPath, violationsCount, verdict }` or
|
|
141
|
-
* `{ detect, artifactPath: null, ... }` when not ready.
|
|
142
|
-
*/
|
|
143
|
-
export declare function runSecurityAudit(input: {
|
|
144
|
-
readonly projectRoot: string;
|
|
145
|
-
readonly sessionId: string;
|
|
146
|
-
readonly rid: string;
|
|
147
|
-
readonly generatedAt: string;
|
|
148
|
-
readonly dispatchError?: unknown;
|
|
149
|
-
readonly envelope?: unknown;
|
|
150
|
-
}): {
|
|
151
|
-
detect: SecurityAuditDetectResult;
|
|
152
|
-
artifactPath: string | null;
|
|
153
|
-
violationsCount: number;
|
|
154
|
-
verdict: SecurityAuditVerdict | null;
|
|
155
|
-
};
|