peaks-loop 4.0.0-beta → 4.0.0-beta.3
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 +105 -87
- package/README-en.md +17 -4
- package/README.md +17 -4
- package/dist/src/cli/commands/asset-commands.d.ts +45 -0
- package/dist/src/cli/commands/asset-commands.js +404 -0
- package/dist/src/cli/commands/bee-commands.d.ts +26 -0
- package/dist/src/cli/commands/bee-commands.js +169 -0
- package/dist/src/cli/commands/{solo-commands.d.ts → code-commands.d.ts} +24 -24
- package/dist/src/cli/commands/{solo-commands.js → code-commands.js} +78 -78
- package/dist/src/cli/commands/core/skill-command.js +1 -1
- package/dist/src/cli/commands/dispatch-from-dag.js +1 -1
- package/dist/src/cli/commands/evolution-commands.d.ts +27 -0
- package/dist/src/cli/commands/evolution-commands.js +393 -0
- package/dist/src/cli/commands/hook-handle.js +7 -7
- package/dist/src/cli/commands/job-commands.js +2 -2
- package/dist/src/cli/commands/loop-commands.d.ts +19 -13
- package/dist/src/cli/commands/loop-commands.js +147 -13
- package/dist/src/cli/commands/sediment-commands.js +9 -0
- package/dist/src/cli/commands/session-auto-compact-hook-command.js +2 -2
- package/dist/src/cli/commands/skill-loop-engineering-readiness-commands.d.ts +67 -0
- package/dist/src/cli/commands/skill-loop-engineering-readiness-commands.js +173 -0
- package/dist/src/cli/commands/sub-agent-shared.d.ts +1 -1
- package/dist/src/cli/commands/user-touchpoint-commands.d.ts +4 -4
- package/dist/src/cli/commands/user-touchpoint-commands.js +14 -14
- package/dist/src/cli/commands/workflow-commands.js +22 -22
- package/dist/src/cli/program.js +23 -6
- package/dist/src/services/artifacts/repair-cycle-service.js +1 -1
- package/dist/src/services/audit/enforcers/active-skill-resolver.d.ts +1 -1
- package/dist/src/services/audit/enforcers/active-skill-resolver.js +1 -1
- package/dist/src/services/audit/enforcers/{solo-code-ban.d.ts → code-ban.d.ts} +6 -6
- package/dist/src/services/audit/enforcers/{solo-code-ban.js → code-ban.js} +6 -6
- package/dist/src/services/audit/red-line-catalog.d.ts +2 -2
- package/dist/src/services/audit/red-line-catalog.js +5 -5
- package/dist/src/services/audit/types.d.ts +2 -2
- package/dist/src/services/{solo → code}/auto-compact-orchestrator.d.ts +1 -1
- package/dist/src/services/{solo → code}/auto-compact-orchestrator.js +3 -3
- package/dist/src/services/{solo → code}/dag-orchestrator.d.ts +1 -1
- package/dist/src/services/{solo → code}/dag-orchestrator.js +1 -1
- package/dist/src/services/{solo → code}/emit-handoff.d.ts +1 -1
- package/dist/src/services/{solo → code}/emit-handoff.js +1 -1
- package/dist/src/services/{solo → code}/job-shape-decision.d.ts +1 -1
- package/dist/src/services/{solo → code}/job-shape-decision.js +5 -5
- package/dist/src/services/{solo → code}/mode-gate.d.ts +9 -9
- package/dist/src/services/{solo → code}/mode-gate.js +5 -5
- package/dist/src/services/{solo → code}/post-compact-detector.d.ts +3 -3
- package/dist/src/services/{solo → code}/post-compact-detector.js +4 -4
- package/dist/src/services/{solo → code}/step-08-gate.d.ts +4 -4
- package/dist/src/services/{solo → code}/step-08-gate.js +4 -4
- package/dist/src/services/{solo → code}/user-touchpoint-classifier.d.ts +1 -1
- package/dist/src/services/{solo → code}/user-touchpoint-classifier.js +1 -1
- package/dist/src/services/context/auto-compact-dispatcher.d.ts +2 -2
- package/dist/src/services/context/auto-compact-dispatcher.js +2 -2
- package/dist/src/services/context/auto-compact-types.d.ts +1 -1
- package/dist/src/services/crystallization/crystallization-service.d.ts +239 -0
- package/dist/src/services/crystallization/crystallization-service.js +397 -0
- package/dist/src/services/crystallization/crystallization-store.d.ts +75 -0
- package/dist/src/services/crystallization/crystallization-store.js +193 -0
- package/dist/src/services/crystallization/crystallization-types.d.ts +313 -0
- package/dist/src/services/crystallization/crystallization-types.js +299 -0
- package/dist/src/services/crystallization/evidence-brief-builder.d.ts +237 -0
- package/dist/src/services/crystallization/evidence-brief-builder.js +240 -0
- package/dist/src/services/dispatch/slice-dag.d.ts +2 -2
- package/dist/src/services/dispatch/test-tool-detection.d.ts +1 -1
- package/dist/src/services/dispatch/test-tool-detection.js +1 -1
- package/dist/src/services/evolution/evolution-service.d.ts +137 -0
- package/dist/src/services/evolution/evolution-service.js +281 -0
- package/dist/src/services/evolution/evolution-store.d.ts +57 -0
- package/dist/src/services/evolution/evolution-store.js +232 -0
- package/dist/src/services/evolution/evolution-types.d.ts +706 -0
- package/dist/src/services/evolution/evolution-types.js +286 -0
- package/dist/src/services/evolution/independent-evaluator-runner.d.ts +90 -0
- package/dist/src/services/evolution/independent-evaluator-runner.js +106 -0
- package/dist/src/services/evolution/regression-skeptic-runner.d.ts +64 -0
- package/dist/src/services/evolution/regression-skeptic-runner.js +113 -0
- package/dist/src/services/feedback/feedback-promotion-service.js +2 -2
- package/dist/src/services/job/job-progress-store.d.ts +1 -1
- package/dist/src/services/job/job-progress-store.js +1 -1
- package/dist/src/services/loop/loop-bee-relation-service.d.ts +107 -0
- package/dist/src/services/loop/loop-bee-relation-service.js +211 -0
- package/dist/src/services/loop/loop-bee-relation-store.d.ts +53 -0
- package/dist/src/services/loop/loop-bee-relation-store.js +130 -0
- package/dist/src/services/loop/loop-bee-relation-types.d.ts +118 -0
- package/dist/src/services/loop/loop-bee-relation-types.js +114 -0
- package/dist/src/services/loop/loop-release-service.d.ts +46 -0
- package/dist/src/services/loop/loop-release-service.js +66 -0
- package/dist/src/services/loop/loop-release-store.d.ts +55 -0
- package/dist/src/services/loop/loop-release-store.js +134 -0
- package/dist/src/services/loop/loop-release-types.d.ts +250 -0
- package/dist/src/services/loop/loop-release-types.js +162 -0
- package/dist/src/services/preferences/preferences-service.d.ts +1 -1
- package/dist/src/services/preferences/preferences-types.d.ts +1 -1
- package/dist/src/services/rd/standards-diagnostic.d.ts +1 -1
- package/dist/src/services/rd/standards-diagnostic.js +2 -2
- package/dist/src/services/recommendations/capability-seed-items.js +1 -1
- package/dist/src/services/recommendations/capability-seed-mappings.js +1 -1
- package/dist/src/services/recommendations/recommendation-service.js +1 -1
- package/dist/src/services/refactor/refactor-service.d.ts +1 -1
- package/dist/src/services/share/bundle-reader.d.ts +100 -0
- package/dist/src/services/share/bundle-reader.js +434 -0
- package/dist/src/services/share/bundle-types.d.ts +392 -0
- package/dist/src/services/share/bundle-types.js +318 -0
- package/dist/src/services/share/bundle-writer.d.ts +97 -0
- package/dist/src/services/share/bundle-writer.js +429 -0
- package/dist/src/services/share/run-state-contract.d.ts +133 -0
- package/dist/src/services/share/run-state-contract.js +138 -0
- package/dist/src/services/signal/cancel-handler.js +3 -3
- package/dist/src/services/skill/resume-detector.js +1 -1
- package/dist/src/services/skillhub/release-import.js +7 -2
- package/dist/src/services/skillhub/release-retain.js +6 -1
- package/dist/src/services/skillhub/sqlite-store.js +17 -1
- package/dist/src/services/skillhub/types.d.ts +10 -0
- package/dist/src/services/skills/skill-presence-service.d.ts +1 -1
- package/dist/src/services/standards/loop-engineering-lint.d.ts +38 -0
- package/dist/src/services/standards/loop-engineering-lint.js +101 -0
- package/dist/src/services/standards/loop-engineering-readiness-lint.d.ts +111 -0
- package/dist/src/services/standards/loop-engineering-readiness-lint.js +248 -0
- package/dist/src/services/upgrade/1x-detector-service.js +1 -1
- package/dist/src/services/workflow/pipeline-verify-service.d.ts +1 -1
- package/dist/src/services/workflow/pipeline-verify-service.js +3 -3
- package/dist/src/services/workflow/workflow-autonomous-service.d.ts +3 -3
- package/dist/src/services/workflow/workflow-autonomous-service.js +2 -2
- package/dist/src/services/workflow/workflow-router-service.d.ts +6 -6
- package/dist/src/services/workflow/workflow-router-service.js +33 -33
- package/dist/src/services/workspace/claude-settings-template.d.ts +1 -1
- package/dist/src/services/workspace/claude-settings-template.js +5 -5
- package/dist/src/shared/version.d.ts +1 -1
- package/dist/src/shared/version.js +1 -1
- package/examples/video-demo/README.md +57 -0
- 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
- package/output-styles/peaks-skill-swarm.md +3 -3
- package/package.json +6 -2
- package/skills/bee/peaks-qa/SKILL.md +1 -1
- package/skills/bee/peaks-qa/references/artifact-per-request.md +3 -3
- package/skills/bee/peaks-qa/references/qa-sub-agent-dispatch.md +6 -6
- package/skills/bee/peaks-rd/references/rd-fanout-contracts.md +1 -1
- package/skills/bee/peaks-rd/references/rd-runbook.md +1 -1
- package/skills/bee/peaks-rd/references/rd-sub-agent-dispatch.md +11 -11
- package/skills/bee/peaks-rd/references/rd-transition-gates.md +1 -1
- package/skills/bee/peaks-sc/SKILL.md +1 -1
- package/skills/bee/peaks-txt/SKILL.md +3 -3
- package/skills/bee/peaks-ui/SKILL.md +8 -8
- package/skills/peaks-code/SKILL.md +34 -21
- package/skills/peaks-code/references/anchoring-and-session-info.md +2 -2
- package/skills/peaks-code/references/artifact-contracts.md +1 -1
- package/skills/peaks-code/references/boundaries.md +3 -3
- package/skills/peaks-code/references/codegraph-orchestration.md +1 -1
- package/skills/peaks-code/references/dag-orchestrator.md +7 -7
- package/skills/peaks-code/references/external-references.md +2 -2
- package/skills/peaks-code/references/fanout-mandatory.md +3 -3
- package/skills/peaks-code/references/fast-mode.md +2 -2
- package/skills/peaks-code/references/frontend-only-mode.md +9 -9
- package/skills/peaks-code/references/job-loop.md +1 -1
- package/skills/peaks-code/references/local-artifact-workspace.md +2 -2
- package/skills/peaks-code/references/micro-cycle.md +14 -14
- package/skills/peaks-code/references/mode-selection-with-stale-presence.md +5 -5
- package/skills/peaks-code/references/mode-selection.md +3 -3
- package/skills/peaks-code/references/openspec-workflow.md +16 -16
- package/skills/peaks-code/references/periodic-checkpoint.md +4 -4
- package/skills/peaks-code/references/quality-gate-cheatsheet.md +1 -1
- package/skills/peaks-code/references/refactor-mode.md +1 -1
- package/skills/peaks-code/references/runbook.md +15 -15
- package/skills/peaks-code/references/step-0-55-1x-detection.md +1 -1
- package/skills/peaks-code/references/step-0-8-gate.md +11 -11
- package/skills/peaks-code/references/sub-agent-dispatch.md +8 -8
- package/skills/peaks-code/references/swarm-dispatch-contract.md +17 -17
- package/skills/peaks-code/references/workflow-gates-and-types.md +2 -2
- package/skills/peaks-code/references/workflow.md +5 -5
- package/skills/peaks-content/SKILL.md +272 -0
- package/skills/peaks-issue-fix-orchestrator/SKILL.md +307 -0
- package/skills/peaks-resume/SKILL.md +2 -2
- package/skills/peaks-status/SKILL.md +2 -2
- package/skills/peaks-test/SKILL.md +2 -2
- /package/dist/src/services/{solo → code}/batch-heartbeat-poller.d.ts +0 -0
- /package/dist/src/services/{solo → code}/batch-heartbeat-poller.js +0 -0
- /package/dist/src/services/{solo → code}/status-line-renderer.d.ts +0 -0
- /package/dist/src/services/{solo → code}/status-line-renderer.js +0 -0
|
@@ -0,0 +1,248 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Loop Engineering Readiness linter (M6 — peak-spec §7.5 + §8.4).
|
|
3
|
+
*
|
|
4
|
+
* Pure function: takes the raw markdown text of a peaks-* SKILL.md
|
|
5
|
+
* file and returns either
|
|
6
|
+
* { ok: true, findings: [] }
|
|
7
|
+
* or
|
|
8
|
+
* { ok: false, findings: string[] }.
|
|
9
|
+
*
|
|
10
|
+
* The lint asserts three structural properties the spec binds every
|
|
11
|
+
* Loop-Engineering-participating peaks-* skill to:
|
|
12
|
+
*
|
|
13
|
+
* 1. The skill references the shared guideline file
|
|
14
|
+
* `.peaks/standards/loop-engineering-guidelines.md` (or its
|
|
15
|
+
* alias `.peaks/standards/loop-engineering-guidelines.md`).
|
|
16
|
+
* Reference may appear anywhere in the body — code fence,
|
|
17
|
+
* plain prose, or list item — as long as the literal token is
|
|
18
|
+
* present.
|
|
19
|
+
*
|
|
20
|
+
* 2. The skill does NOT introduce a CLI verb that bypasses the
|
|
21
|
+
* LLM-coordinated model. We flag lines that look like
|
|
22
|
+
* "Run `peaks <verb>` to …" where `<verb>` is not in the
|
|
23
|
+
* allowlist of LLM-owned sediment / asset / evolution verbs.
|
|
24
|
+
* The user types NL; the LLM runs the CLI on the user's behalf
|
|
25
|
+
* (RL-1 / Human-NL-Choice-Only).
|
|
26
|
+
*
|
|
27
|
+
* 3. The skill does NOT introduce a JSON / manifest
|
|
28
|
+
* hand-authoring surface. We flag lines containing phrases
|
|
29
|
+
* like "Edit the manifest", "write the JSON", "fill the JSON
|
|
30
|
+
* file", etc., when they are not part of an explicit allowlist
|
|
31
|
+
* (allowlist only references; never an instructional phrase).
|
|
32
|
+
*
|
|
33
|
+
* Each finding is a single line of the form:
|
|
34
|
+
* "<rule>: <offending excerpt>"
|
|
35
|
+
* so a downstream CLI can render it directly without further
|
|
36
|
+
* parsing.
|
|
37
|
+
*
|
|
38
|
+
* The lint intentionally does NOT touch any application-level
|
|
39
|
+
* code; it only parses a SKILL.md text. The peaks CLI command
|
|
40
|
+
* `peaks skill lint --category loop-engineering-readiness
|
|
41
|
+
* --path <skill-dir>`
|
|
42
|
+
* (registered in src/cli/commands/skill-loop-engineering-readiness.ts)
|
|
43
|
+
* reads the SKILL.md from disk and calls this function.
|
|
44
|
+
*
|
|
45
|
+
* Per RL-1 / Human-NL-Choice-Only and
|
|
46
|
+
* `.peaks/memory/two-forms-only-rule.md`, the user only ever picks
|
|
47
|
+
* via AskUserQuestion or describes in NL; the LLM runs the CLI.
|
|
48
|
+
* This lint is what stops a future peaks-* skill from regressing
|
|
49
|
+
* that rule at the textual layer.
|
|
50
|
+
*/
|
|
51
|
+
/**
|
|
52
|
+
* The shared guideline file that every Loop-Engineering-participating
|
|
53
|
+
* peaks-* skill must reference. Both the canonical path and the
|
|
54
|
+
* common alias are accepted.
|
|
55
|
+
*
|
|
56
|
+
* The alias is intentionally identical to the canonical path here:
|
|
57
|
+
* the spec sometimes renders it as
|
|
58
|
+
* `.peaks/standards/loop-engineering-guidelines.md`
|
|
59
|
+
* with a slash prefix and sometimes without. We accept both.
|
|
60
|
+
*/
|
|
61
|
+
export const LOOP_ENGINEERING_GUIDELINE_PATHS = [
|
|
62
|
+
'.peaks/standards/loop-engineering-guidelines.md',
|
|
63
|
+
];
|
|
64
|
+
/**
|
|
65
|
+
* The allowlist of CLI verbs that a peaks-* SKILL.md may legitimately
|
|
66
|
+
* instruct an LLM to invoke on the user's behalf. These are the
|
|
67
|
+
* sediment / asset / evolution surface verbs introduced in
|
|
68
|
+
* 2026-07-07-loop-engineering-crystallization-design §7.4 plus the
|
|
69
|
+
* 18-verb sediment pool from 2026-07-04-peaks-maker-dynamic-skill-
|
|
70
|
+
* sediment-design §4.2.
|
|
71
|
+
*
|
|
72
|
+
* Any other `peaks <verb>` token that appears in the form
|
|
73
|
+
* "Run `peaks <verb>` to …"
|
|
74
|
+
* is treated as a CLI-verb-bypass attempt and flagged.
|
|
75
|
+
*/
|
|
76
|
+
export const ALLOWED_CLI_VERBS = new Set([
|
|
77
|
+
// sediment pool verbs (M6 reference; peak-maker's owned surface)
|
|
78
|
+
'add-segment',
|
|
79
|
+
'add-bee',
|
|
80
|
+
'refine-bee',
|
|
81
|
+
'clone-bee',
|
|
82
|
+
'promote',
|
|
83
|
+
'retire',
|
|
84
|
+
'dispose',
|
|
85
|
+
'releases',
|
|
86
|
+
'release-show',
|
|
87
|
+
'release-diff',
|
|
88
|
+
'export',
|
|
89
|
+
'import',
|
|
90
|
+
'gc-blobs',
|
|
91
|
+
'list',
|
|
92
|
+
'show',
|
|
93
|
+
'search',
|
|
94
|
+
'recent',
|
|
95
|
+
'rebuild-index',
|
|
96
|
+
// loop crystallizer surface (§7.4)
|
|
97
|
+
'loop',
|
|
98
|
+
'crystallize',
|
|
99
|
+
// evolution ratchet surface (§7.4)
|
|
100
|
+
'evolution',
|
|
101
|
+
'propose',
|
|
102
|
+
'evaluate',
|
|
103
|
+
'revert',
|
|
104
|
+
'mark-keep',
|
|
105
|
+
// umbrella asset surface (§7.4)
|
|
106
|
+
'asset',
|
|
107
|
+
'status',
|
|
108
|
+
// adapter surface (peaks-maker's owned skill runtime)
|
|
109
|
+
'adapter',
|
|
110
|
+
// lint surface (this command's own kind)
|
|
111
|
+
'lint',
|
|
112
|
+
'standards',
|
|
113
|
+
'skill',
|
|
114
|
+
'ready',
|
|
115
|
+
]);
|
|
116
|
+
/**
|
|
117
|
+
* Phrases that constitute a JSON / manifest hand-authoring surface.
|
|
118
|
+
* If a SKILL.md instructs the user to perform one of these actions,
|
|
119
|
+
* it violates RL-1 / Human-NL-Choice-Only and is flagged.
|
|
120
|
+
*
|
|
121
|
+
* Each entry is a lowercase substring matched against each line of
|
|
122
|
+
* the SKILL.md. The match is case-insensitive; the surrounding
|
|
123
|
+
* `<verb>` placeholders in the original spec are matched literally.
|
|
124
|
+
*/
|
|
125
|
+
export const JSON_HAND_AUTHORING_PHRASES = [
|
|
126
|
+
'edit the manifest',
|
|
127
|
+
'edit your manifest',
|
|
128
|
+
'edit the json',
|
|
129
|
+
'edit the .json file',
|
|
130
|
+
'write the json',
|
|
131
|
+
'write the json manifest',
|
|
132
|
+
'write the manifest json',
|
|
133
|
+
'fill the json',
|
|
134
|
+
'fill in the json',
|
|
135
|
+
'fill in the manifest',
|
|
136
|
+
'fill in the manifest.json',
|
|
137
|
+
'hand-author the manifest',
|
|
138
|
+
'hand-author the json',
|
|
139
|
+
'open the manifest and',
|
|
140
|
+
'open the manifest.json and',
|
|
141
|
+
'manually edit the manifest',
|
|
142
|
+
'manually edit the json',
|
|
143
|
+
];
|
|
144
|
+
/**
|
|
145
|
+
* Phrases that explicitly reference a JSON / manifest surface but
|
|
146
|
+
* in an ALLOWED way — e.g. "the manifest is written by the CLI" or
|
|
147
|
+
* "see manifest schema for details". A line that contains one of
|
|
148
|
+
* these allowlisted phrases is NOT flagged even if it contains a
|
|
149
|
+
* JSON-hand-authoring phrase elsewhere on the same line.
|
|
150
|
+
*
|
|
151
|
+
* The allowlist is intentionally narrow; it must mention either
|
|
152
|
+
* the CLI as the writer OR a schema reference, NOT an instructional
|
|
153
|
+
* verb targeting the user.
|
|
154
|
+
*/
|
|
155
|
+
export const JSON_REFERENCE_ALLOWLIST = [
|
|
156
|
+
'the cli writes',
|
|
157
|
+
'written by the cli',
|
|
158
|
+
'written by peaks',
|
|
159
|
+
'manifest schema',
|
|
160
|
+
'see the manifest schema',
|
|
161
|
+
'see manifest schema',
|
|
162
|
+
'schema_version',
|
|
163
|
+
'peaks.bundle/1',
|
|
164
|
+
'peaks.loop/1',
|
|
165
|
+
'peaks.bee/1',
|
|
166
|
+
];
|
|
167
|
+
// ---------------------------------------------------------------------------
|
|
168
|
+
// Pure function
|
|
169
|
+
// ---------------------------------------------------------------------------
|
|
170
|
+
/**
|
|
171
|
+
* Lint a SKILL.md text for Loop Engineering readiness.
|
|
172
|
+
*
|
|
173
|
+
* @param skillMdText raw markdown text of a peaks-* SKILL.md
|
|
174
|
+
* @returns a ReadinessLintResult
|
|
175
|
+
*/
|
|
176
|
+
export function lintSkillLoopEngineeringReadiness(skillMdText) {
|
|
177
|
+
const findings = [];
|
|
178
|
+
if (typeof skillMdText !== 'string' || skillMdText.trim().length === 0) {
|
|
179
|
+
return {
|
|
180
|
+
ok: false,
|
|
181
|
+
findings: ['skill-md-empty: SKILL.md text is empty or missing'],
|
|
182
|
+
};
|
|
183
|
+
}
|
|
184
|
+
checkGuidelineReference(skillMdText, findings);
|
|
185
|
+
checkCliVerbBypass(skillMdText, findings);
|
|
186
|
+
checkJsonHandAuthoring(skillMdText, findings);
|
|
187
|
+
if (findings.length > 0) {
|
|
188
|
+
return { ok: false, findings };
|
|
189
|
+
}
|
|
190
|
+
return { ok: true, findings: [] };
|
|
191
|
+
}
|
|
192
|
+
// ---------------------------------------------------------------------------
|
|
193
|
+
// Individual checks
|
|
194
|
+
// ---------------------------------------------------------------------------
|
|
195
|
+
function checkGuidelineReference(text, findings) {
|
|
196
|
+
// Strip code fences before checking — references inside ``` blocks
|
|
197
|
+
// are still valid references (the lint accepts them), but we strip
|
|
198
|
+
// so the substring match is unambiguous.
|
|
199
|
+
const stripped = text;
|
|
200
|
+
for (const ref of LOOP_ENGINEERING_GUIDELINE_PATHS) {
|
|
201
|
+
if (stripped.includes(ref)) {
|
|
202
|
+
return;
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
findings.push(`missing-guideline-reference: SKILL.md must reference ${LOOP_ENGINEERING_GUIDELINE_PATHS[0]} (spec §7.5 / §8.4 / RL-8)`);
|
|
206
|
+
}
|
|
207
|
+
function checkCliVerbBypass(text, findings) {
|
|
208
|
+
// Match lines that contain `peaks <verb>` in a run-this-command
|
|
209
|
+
// pattern: "Run `peaks <verb>` to …" or "`peaks <verb>` to …" or
|
|
210
|
+
// "use `peaks <verb>` to …".
|
|
211
|
+
//
|
|
212
|
+
// The regex is intentionally narrow: it requires backticks around
|
|
213
|
+
// `peaks <verb>` so prose that mentions "peaks <verb>" as a noun
|
|
214
|
+
// (e.g. "peaks skill sediment list") is not flagged. The verb
|
|
215
|
+
// token is captured as the first `[a-z][a-z0-9-]*` chunk after
|
|
216
|
+
// "peaks "; everything between the verb and the closing backtick
|
|
217
|
+
// is allowed (e.g. `peaks custom-evolve my-bee` — verb is
|
|
218
|
+
// "custom-evolve", args are "my-bee").
|
|
219
|
+
const lineRegex = /^\s*[-*]?\s*(?:Run|Use|Type|Execute)\s+`peaks\s+([a-z][a-z0-9-]*)[^`]*`/gim;
|
|
220
|
+
const lines = text.split(/\r?\n/);
|
|
221
|
+
for (let i = 0; i < lines.length; i++) {
|
|
222
|
+
const line = lines[i];
|
|
223
|
+
let m;
|
|
224
|
+
lineRegex.lastIndex = 0;
|
|
225
|
+
while ((m = lineRegex.exec(line)) !== null) {
|
|
226
|
+
const verb = m[1];
|
|
227
|
+
if (!ALLOWED_CLI_VERBS.has(verb)) {
|
|
228
|
+
const excerpt = line.trim().slice(0, 120);
|
|
229
|
+
findings.push(`cli-verb-bypass: line ${i + 1} introduces CLI verb \`peaks ${verb}\` to be typed by the user (${excerpt}) — only LLM-coordinated verbs from the sediment/asset/evolution surface are allowed (RL-1)`);
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
function checkJsonHandAuthoring(text, findings) {
|
|
235
|
+
const lines = text.split(/\r?\n/);
|
|
236
|
+
for (let i = 0; i < lines.length; i++) {
|
|
237
|
+
const line = lines[i];
|
|
238
|
+
const lowered = line.toLowerCase();
|
|
239
|
+
const matchedPhrase = JSON_HAND_AUTHORING_PHRASES.find((p) => lowered.includes(p));
|
|
240
|
+
if (!matchedPhrase)
|
|
241
|
+
continue;
|
|
242
|
+
const isAllowlisted = JSON_REFERENCE_ALLOWLIST.some((p) => lowered.includes(p));
|
|
243
|
+
if (isAllowlisted)
|
|
244
|
+
continue;
|
|
245
|
+
const excerpt = line.trim().slice(0, 120);
|
|
246
|
+
findings.push(`json-hand-authoring: line ${i + 1} introduces JSON / manifest hand-authoring surface ("${matchedPhrase}") — ${excerpt} (RL-1: user only picks or describes in NL)`);
|
|
247
|
+
}
|
|
248
|
+
}
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* 1.x → 2.0 detection service — TypeScript mirror of
|
|
3
3
|
* `scripts/install-skills.mjs:detect1xProjectState`.
|
|
4
4
|
*
|
|
5
|
-
* Slice: 2026-06-12-
|
|
5
|
+
* Slice: 2026-06-12-code-step-0-55-1x-detection.
|
|
6
6
|
*
|
|
7
7
|
* The canonical implementation lives in the .mjs postinstall
|
|
8
8
|
* (because the postinstall runs before any TS compile step).
|
|
@@ -63,7 +63,7 @@ export type PipelineVerification = {
|
|
|
63
63
|
*/
|
|
64
64
|
gateH?: 'pass' | 'fail';
|
|
65
65
|
/**
|
|
66
|
-
* Slice 2026-06-28-
|
|
66
|
+
* Slice 2026-06-28-code-mode-bypass-fix (defect #3): `true` when
|
|
67
67
|
* every evidence file resolved on the canonical path
|
|
68
68
|
* (`.peaks/_runtime/change/<sessionId>/...`). `false` when at least
|
|
69
69
|
* one evidence file resolved via a legacy fallback (`.peaks/<sessionId>/...`
|
|
@@ -26,7 +26,7 @@ async function findRequestFile(projectRoot, role, rid) {
|
|
|
26
26
|
const artifact = await showRequestArtifact({ projectRoot, role: role, requestId: rid });
|
|
27
27
|
if (artifact === null)
|
|
28
28
|
return null;
|
|
29
|
-
// Slice 2026-06-28-
|
|
29
|
+
// Slice 2026-06-28-code-mode-bypass-fix (defect #3): the legacy
|
|
30
30
|
// `showRequestArtifact` returns the FULL SCOPE (`_runtime/<sid>`)
|
|
31
31
|
// as `sessionId`, not just the trailing id segment. The canonical
|
|
32
32
|
// evidence lookup needs only the bare id (`.peaks/_runtime/change/<id>/`).
|
|
@@ -158,7 +158,7 @@ export async function verifyPipeline(options) {
|
|
|
158
158
|
// preferred filesystem scope; falling through to `options.rid` would
|
|
159
159
|
// make every missing-evidence path look like a per-rid scope dir.
|
|
160
160
|
const rdEvidenceDir = resolvedChangeId || options.sessionId || getSessionIdCanonical(options.projectRoot) || options.rid;
|
|
161
|
-
// Slice 2026-06-28-
|
|
161
|
+
// Slice 2026-06-28-code-mode-bypass-fix (defect #3): track whether
|
|
162
162
|
// every resolved evidence file landed on the canonical path. Drives
|
|
163
163
|
// the `usedCanonicalPath` envelope field. The flag stays `true` if
|
|
164
164
|
// no evidence file was resolved at all (nothing to be non-canonical
|
|
@@ -410,7 +410,7 @@ export async function verifyPipeline(options) {
|
|
|
410
410
|
: 'suffixed';
|
|
411
411
|
const gateC = allQaGatesPassed ? 'pass' : 'fail';
|
|
412
412
|
const gateH = allFeedbackGatesPassed ? 'pass' : 'fail';
|
|
413
|
-
// Slice 2026-06-28-
|
|
413
|
+
// Slice 2026-06-28-code-mode-bypass-fix (defect #3): `true` when
|
|
414
414
|
// every gate resolved on the canonical path; `false` when at least
|
|
415
415
|
// one fell back to a legacy form. QA / TXT surface the value so the
|
|
416
416
|
// user knows the legacy content must be moved into the canonical
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { CapabilityItemType } from '../recommendations/recommendation-types.js';
|
|
2
2
|
import type { ModelProviderConfig, WorkspaceConfig } from '../config/config-types.js';
|
|
3
3
|
import { type RdPlanResult } from '../rd/rd-service.js';
|
|
4
|
-
import { type
|
|
4
|
+
import { type CodeMode, type WorkflowMode, type WorkflowRouterPlan } from './workflow-router-service.js';
|
|
5
5
|
export { getResumeRequiredArtifacts, getResumeArtifactsStatus, createResumePlan } from './workflow-autonomous-resume-helpers.js';
|
|
6
6
|
export type CapabilitySurface = 'skill' | 'mcp' | 'plugin' | 'expert';
|
|
7
7
|
export type CapabilityPurpose = 'code-review' | 'security-review' | 'coding-standards' | 'docs-lookup' | 'browser-validation' | 'browser-debug' | 'design-context' | 'design-source' | 'code-search' | 'database-inspection' | 'browser-agent' | 'worker-guidance' | 'memory' | 'context-management' | 'ui-components' | 'spec-workflow' | 'repo-intelligence' | 'openspec' | 'workflow-methodology' | 'workflow-reference' | 'workflow-guidance' | 'product-guidance' | 'design-reference' | 'ui-reference' | 'engineering-guidance' | 'typescript-guidance' | 'quality-guidance' | 'skill-pack' | 'external-skill' | 'design-critique' | 'design-guidance' | 'cloud-skill-pack';
|
|
@@ -20,7 +20,7 @@ export type CapabilityCandidate = {
|
|
|
20
20
|
};
|
|
21
21
|
export type AutonomousWorkflowRequest = {
|
|
22
22
|
readonly mode: WorkflowMode;
|
|
23
|
-
readonly
|
|
23
|
+
readonly codeMode?: CodeMode;
|
|
24
24
|
readonly sessionId: string;
|
|
25
25
|
readonly goal: string;
|
|
26
26
|
readonly maxWorkers?: number;
|
|
@@ -68,7 +68,7 @@ export type AutonomousStoragePlan = {
|
|
|
68
68
|
};
|
|
69
69
|
export type AutonomousMvpPackage = {
|
|
70
70
|
readonly mode: WorkflowMode;
|
|
71
|
-
readonly
|
|
71
|
+
readonly codeMode: CodeMode | undefined;
|
|
72
72
|
readonly executionMode: 'preview';
|
|
73
73
|
readonly dryRun: true;
|
|
74
74
|
readonly routePolicy: WorkflowRouterPlan['routePolicy'];
|
|
@@ -205,7 +205,7 @@ function createCapabilityPlan(request) {
|
|
|
205
205
|
function createMvpPackage(request, routePlan, rdPlan, capabilityPlan, ready) {
|
|
206
206
|
return {
|
|
207
207
|
mode: request.mode,
|
|
208
|
-
|
|
208
|
+
codeMode: routePlan.codeMode,
|
|
209
209
|
executionMode: 'preview',
|
|
210
210
|
dryRun: true,
|
|
211
211
|
routePolicy: routePlan.routePolicy,
|
|
@@ -240,7 +240,7 @@ export function createAutonomousWorkflowPlan(request) {
|
|
|
240
240
|
const available = hasArtifactWorkspace(request, artifactWorkspacePath);
|
|
241
241
|
const routePlan = createWorkflowRouterPlan({
|
|
242
242
|
mode: request.mode,
|
|
243
|
-
...(request.
|
|
243
|
+
...(request.codeMode !== undefined ? { codeMode: request.codeMode } : {}),
|
|
244
244
|
sessionId: request.sessionId,
|
|
245
245
|
goal,
|
|
246
246
|
maxWorkers,
|
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
import { type ModelProviderConfig, type WorkspaceConfig } from '../config/config-types.js';
|
|
2
2
|
import { type RdPlanResult } from '../rd/rd-service.js';
|
|
3
3
|
import { type TechPlanResult, type TechStatus } from '../tech/tech-service.js';
|
|
4
|
-
export type WorkflowMode = '
|
|
5
|
-
export type
|
|
4
|
+
export type WorkflowMode = 'code' | 'team';
|
|
5
|
+
export type CodeMode = 'full-auto' | 'guided' | 'rnd';
|
|
6
6
|
export type ModelTier = 'top-tier' | 'mid-tier';
|
|
7
7
|
export type ModelRole = 'strongest' | 'execution';
|
|
8
|
-
export type WorkflowRoutePolicy = '
|
|
8
|
+
export type WorkflowRoutePolicy = 'code-broad-multi-model' | 'team-rd-limited-multi-model';
|
|
9
9
|
export type WorkflowStepStage = 'product-direction' | 'design-direction' | 'tech-direction' | 'tech-review' | 'rd-planning' | 'coding-execution' | 'unit-test-execution' | 'quality-review';
|
|
10
10
|
export type WorkflowStepOwner = 'peaks-code' | 'peaks-rd' | 'peaks-tech' | 'human';
|
|
11
11
|
export type WorkflowRouterRequest = {
|
|
12
12
|
sessionId: string;
|
|
13
13
|
goal: string;
|
|
14
14
|
mode: WorkflowMode;
|
|
15
|
-
|
|
15
|
+
codeMode?: CodeMode;
|
|
16
16
|
maxWorkers?: number;
|
|
17
17
|
dryRun: true;
|
|
18
18
|
artifactWorkspacePath?: string;
|
|
@@ -64,7 +64,7 @@ export type WorkflowRouterPlan = {
|
|
|
64
64
|
readonly sessionId: string;
|
|
65
65
|
readonly goal: string;
|
|
66
66
|
readonly mode: WorkflowMode;
|
|
67
|
-
readonly
|
|
67
|
+
readonly codeMode?: CodeMode;
|
|
68
68
|
readonly executionMode: 'autonomous';
|
|
69
69
|
readonly decisionProfile: string;
|
|
70
70
|
readonly dryRun: true;
|
|
@@ -81,5 +81,5 @@ export type WorkflowRouterPlan = {
|
|
|
81
81
|
readonly constraints: readonly string[];
|
|
82
82
|
};
|
|
83
83
|
export declare function isWorkflowMode(mode: string): mode is WorkflowMode;
|
|
84
|
-
export declare function
|
|
84
|
+
export declare function isCodeMode(value: string): value is CodeMode;
|
|
85
85
|
export declare function createWorkflowRouterPlan(request: WorkflowRouterRequest): WorkflowRouterPlan;
|
|
@@ -18,7 +18,7 @@ const EXECUTION_STAGES = ['coding-execution', 'unit-test-execution'];
|
|
|
18
18
|
const GUIDED_DECISION_STAGES = ['product-direction', 'design-direction'];
|
|
19
19
|
const GOVERNED_DECISION_STAGES = ['product-direction', 'design-direction', 'tech-direction', 'tech-review'];
|
|
20
20
|
export function isWorkflowMode(mode) {
|
|
21
|
-
return mode === '
|
|
21
|
+
return mode === 'code' || mode === 'team';
|
|
22
22
|
}
|
|
23
23
|
function assertSupportedMode(mode) {
|
|
24
24
|
if (!isWorkflowMode(mode)) {
|
|
@@ -32,9 +32,9 @@ function normalizeGoal(goal) {
|
|
|
32
32
|
}
|
|
33
33
|
return normalized;
|
|
34
34
|
}
|
|
35
|
-
function
|
|
36
|
-
if (mode !== '
|
|
37
|
-
throw new Error('
|
|
35
|
+
function assertCodeModeAllowed(mode, codeMode) {
|
|
36
|
+
if (mode !== 'code' && codeMode !== undefined) {
|
|
37
|
+
throw new Error('codeMode requires code workflow mode');
|
|
38
38
|
}
|
|
39
39
|
}
|
|
40
40
|
function step(input, executionModelId) {
|
|
@@ -48,29 +48,29 @@ function step(input, executionModelId) {
|
|
|
48
48
|
writesArtifacts: false
|
|
49
49
|
};
|
|
50
50
|
}
|
|
51
|
-
export function
|
|
51
|
+
export function isCodeMode(value) {
|
|
52
52
|
return value === 'full-auto' || value === 'guided' || value === 'rnd';
|
|
53
53
|
}
|
|
54
|
-
function getDecisionProfileSummary(mode,
|
|
54
|
+
function getDecisionProfileSummary(mode, codeMode) {
|
|
55
55
|
if (mode === 'team') {
|
|
56
56
|
return 'Team mode keeps product and design governance on a human-controlled path while RD execution follows recommended defaults.';
|
|
57
57
|
}
|
|
58
|
-
if (
|
|
58
|
+
if (codeMode === 'guided') {
|
|
59
59
|
return 'Guided mode keeps the user in the decision loop for the early recommended defaults, while later execution remains bounded by the routing plan.';
|
|
60
60
|
}
|
|
61
|
-
if (
|
|
61
|
+
if (codeMode === 'rnd') {
|
|
62
62
|
return 'R&D mode asks for technical confirmation up front, then applies recommended defaults for implementation, testing, review, and safety checks.';
|
|
63
63
|
}
|
|
64
64
|
return 'Full-auto mode applies recommended defaults for product, design, and tech decisions, then runs the engineering pipeline end to end under routing gates.';
|
|
65
65
|
}
|
|
66
|
-
function annotateSteps(steps,
|
|
67
|
-
const decisionStages =
|
|
66
|
+
function annotateSteps(steps, codeMode) {
|
|
67
|
+
const decisionStages = codeMode === 'guided'
|
|
68
68
|
? GUIDED_DECISION_STAGES
|
|
69
69
|
: GOVERNED_DECISION_STAGES;
|
|
70
70
|
return steps.map((currentStep) => {
|
|
71
71
|
const isDecisionStage = decisionStages.includes(currentStep.stage);
|
|
72
72
|
const reasonPrefix = isDecisionStage
|
|
73
|
-
? `[${
|
|
73
|
+
? `[${codeMode}] decision stage`
|
|
74
74
|
: '[routed] execution stage';
|
|
75
75
|
return {
|
|
76
76
|
...currentStep,
|
|
@@ -80,18 +80,18 @@ function annotateSteps(steps, soloMode) {
|
|
|
80
80
|
}
|
|
81
81
|
function createSoloSteps(executionModelId) {
|
|
82
82
|
return [
|
|
83
|
-
step({ id: '
|
|
84
|
-
step({ id: '
|
|
85
|
-
step({ id: '
|
|
86
|
-
step({ id: '
|
|
87
|
-
step({ id: '
|
|
88
|
-
step({ id: '
|
|
89
|
-
step({ id: '
|
|
90
|
-
step({ id: '
|
|
83
|
+
step({ id: 'code-product-direction', stage: 'product-direction', owner: 'peaks-code', modelTier: 'top-tier', reason: 'Product direction needs strong judgment before execution work is delegated.', dependsOn: [] }, executionModelId),
|
|
84
|
+
step({ id: 'code-design-direction', stage: 'design-direction', owner: 'peaks-code', modelTier: 'top-tier', reason: 'Design direction uses the recommended default before cheaper implementation work.', dependsOn: ['code-product-direction'] }, executionModelId),
|
|
85
|
+
step({ id: 'code-tech-direction', stage: 'tech-direction', owner: 'peaks-tech', modelTier: 'top-tier', reason: 'Technical boundaries and approval gates use the recommended default with high-confidence planning.', dependsOn: ['code-design-direction'] }, executionModelId),
|
|
86
|
+
step({ id: 'code-tech-review', stage: 'tech-review', owner: 'peaks-tech', modelTier: 'top-tier', reason: 'Tech artifacts and gate decisions require strong review and a recommended default path.', dependsOn: ['code-tech-direction'] }, executionModelId),
|
|
87
|
+
step({ id: 'code-rd-planning', stage: 'rd-planning', owner: 'peaks-rd', modelTier: 'top-tier', reason: 'RD task decomposition and acceptance criteria use the recommended default before execution delegation.', dependsOn: ['code-tech-review'] }, executionModelId),
|
|
88
|
+
step({ id: 'code-coding-execution', stage: 'coding-execution', owner: 'peaks-rd', modelTier: executionModelId === STRONGEST_MODEL_ID ? 'top-tier' : 'mid-tier', reason: `Coding and routine refactoring must use the configured execution worker model ${executionModelId}.`, dependsOn: ['code-rd-planning'] }, executionModelId),
|
|
89
|
+
step({ id: 'code-unit-test-execution', stage: 'unit-test-execution', owner: 'peaks-rd', modelTier: executionModelId === STRONGEST_MODEL_ID ? 'top-tier' : 'mid-tier', reason: `Unit test authoring and focused test runs must use the configured execution worker model ${executionModelId}.`, dependsOn: ['code-coding-execution'] }, executionModelId),
|
|
90
|
+
step({ id: 'code-quality-review', stage: 'quality-review', owner: 'peaks-code', modelTier: 'top-tier', reason: 'Reducer and final quality gates need strong synthesis and risk review.', dependsOn: ['code-unit-test-execution'] }, executionModelId)
|
|
91
91
|
];
|
|
92
92
|
}
|
|
93
|
-
function createSoloStepsForMode(
|
|
94
|
-
return annotateSteps(createSoloSteps(executionModelId),
|
|
93
|
+
function createSoloStepsForMode(codeMode, executionModelId) {
|
|
94
|
+
return annotateSteps(createSoloSteps(executionModelId), codeMode);
|
|
95
95
|
}
|
|
96
96
|
function createTeamSteps(executionModelId) {
|
|
97
97
|
return [
|
|
@@ -150,21 +150,21 @@ function createModeStatus(economyMode, swarmMode, executionModelId, executionMod
|
|
|
150
150
|
summary: `${economySummary} ${swarmSummary}`
|
|
151
151
|
};
|
|
152
152
|
}
|
|
153
|
-
function
|
|
154
|
-
if (mode !== '
|
|
153
|
+
function getCodeMode(mode, codeMode) {
|
|
154
|
+
if (mode !== 'code') {
|
|
155
155
|
return undefined;
|
|
156
156
|
}
|
|
157
|
-
if (
|
|
157
|
+
if (codeMode === undefined) {
|
|
158
158
|
return 'full-auto';
|
|
159
159
|
}
|
|
160
|
-
if (!
|
|
161
|
-
throw new Error('Unsupported
|
|
160
|
+
if (!isCodeMode(codeMode)) {
|
|
161
|
+
throw new Error('Unsupported code mode');
|
|
162
162
|
}
|
|
163
|
-
return
|
|
163
|
+
return codeMode;
|
|
164
164
|
}
|
|
165
165
|
export function createWorkflowRouterPlan(request) {
|
|
166
166
|
assertSupportedMode(request.mode);
|
|
167
|
-
|
|
167
|
+
assertCodeModeAllowed(request.mode, request.codeMode);
|
|
168
168
|
// Slice 2026-06-29-change-id-root-removal: change-id is metadata-only;
|
|
169
169
|
// no structural validation gate fires here.
|
|
170
170
|
const goal = normalizeGoal(request.goal);
|
|
@@ -185,8 +185,8 @@ export function createWorkflowRouterPlan(request) {
|
|
|
185
185
|
const effectiveProviders = request.config?.providers ?? { minimax: { model: 'minimax-2.7' } };
|
|
186
186
|
const executionModelId = economyMode !== false ? getConfiguredExecutionModelId(effectiveProviders) : STRONGEST_MODEL_ID;
|
|
187
187
|
const modeStatus = createModeStatus(economyMode, swarmMode, executionModelId, economyMode ? 'config.providers' : 'planner-reviewer-strongest-model');
|
|
188
|
-
const
|
|
189
|
-
const decisionProfile = getDecisionProfileSummary(request.mode,
|
|
188
|
+
const codeMode = getCodeMode(request.mode, request.codeMode);
|
|
189
|
+
const decisionProfile = getDecisionProfileSummary(request.mode, codeMode);
|
|
190
190
|
const artifactWorkspacePath = request.artifactWorkspacePath ?? (request.workspace ? getLocalArtifactPath(request.workspace) : undefined);
|
|
191
191
|
const sharedWorkspaceOptions = {
|
|
192
192
|
...(artifactWorkspacePath ? { artifactWorkspacePath } : {}),
|
|
@@ -195,7 +195,7 @@ export function createWorkflowRouterPlan(request) {
|
|
|
195
195
|
const techStatus = getTechStatus({ sessionId: request.sessionId, ...sharedWorkspaceOptions });
|
|
196
196
|
const techPlan = createTechPlan({ sessionId: request.sessionId, goal, swarm: swarmMode, dryRun: true, ...sharedWorkspaceOptions });
|
|
197
197
|
const rdPlan = createRdSwarmPlan({ skill: 'rd', sessionId: request.sessionId, goal, maxWorkers, swarmMode, executionModelId, dryRun: true, ...sharedWorkspaceOptions });
|
|
198
|
-
const steps =
|
|
198
|
+
const steps = codeMode ? createSoloStepsForMode(codeMode, executionModelId) : createTeamSteps(executionModelId);
|
|
199
199
|
const blockedReasons = uniqueStrings([
|
|
200
200
|
...techStatus.blockedReasons,
|
|
201
201
|
...getTechPlanBlockedReasons(techPlan),
|
|
@@ -208,11 +208,11 @@ export function createWorkflowRouterPlan(request) {
|
|
|
208
208
|
sessionId: request.sessionId,
|
|
209
209
|
goal,
|
|
210
210
|
mode: request.mode,
|
|
211
|
-
...(
|
|
211
|
+
...(codeMode ? { codeMode } : {}),
|
|
212
212
|
executionMode: 'autonomous',
|
|
213
213
|
decisionProfile,
|
|
214
214
|
dryRun: true,
|
|
215
|
-
routePolicy: request.mode === '
|
|
215
|
+
routePolicy: request.mode === 'code' ? 'code-broad-multi-model' : 'team-rd-limited-multi-model',
|
|
216
216
|
modelRouting: createModelRouting(steps, executionModelId),
|
|
217
217
|
modelAssignments: createModelAssignments(steps),
|
|
218
218
|
modeStatus,
|
|
@@ -51,7 +51,7 @@ export declare const CLAUDE_SETTINGS_LOCAL_FILENAME = ".claude/settings.local.js
|
|
|
51
51
|
* bypass is the only emit. Bash enforcement is owned by
|
|
52
52
|
* `peaks gate enforce` in `settings.json`.
|
|
53
53
|
* 1.3.0 — added the v3.1.2 `Bash` PreToolUse matcher that runs
|
|
54
|
-
* `peaks
|
|
54
|
+
* `peaks code gate-step-08 --project .` (Step 0.8 mechanical
|
|
55
55
|
* gate). The existing Write|Edit|MultiEdit matcher is
|
|
56
56
|
* preserved. The new matcher's exit code is the load-bearing
|
|
57
57
|
* signal: 0 = allow, 2 = block (with stderr BLOCKED reason).
|
|
@@ -51,7 +51,7 @@ export const CLAUDE_SETTINGS_LOCAL_FILENAME = '.claude/settings.local.json';
|
|
|
51
51
|
* bypass is the only emit. Bash enforcement is owned by
|
|
52
52
|
* `peaks gate enforce` in `settings.json`.
|
|
53
53
|
* 1.3.0 — added the v3.1.2 `Bash` PreToolUse matcher that runs
|
|
54
|
-
* `peaks
|
|
54
|
+
* `peaks code gate-step-08 --project .` (Step 0.8 mechanical
|
|
55
55
|
* gate). The existing Write|Edit|MultiEdit matcher is
|
|
56
56
|
* preserved. The new matcher's exit code is the load-bearing
|
|
57
57
|
* signal: 0 = allow, 2 = block (with stderr BLOCKED reason).
|
|
@@ -216,7 +216,7 @@ export function buildClaudeSettingsLocalJson() {
|
|
|
216
216
|
},
|
|
217
217
|
{
|
|
218
218
|
// v3.1.2 Step 0.8 — Mechanical PreToolUse gate. Runs
|
|
219
|
-
// `peaks
|
|
219
|
+
// `peaks code gate-step-08 --project .` before every Bash
|
|
220
220
|
// tool call. Exit 0 = allow (with structured stdout
|
|
221
221
|
// describing the decision + optional `Next: slice #N+1 of
|
|
222
222
|
// M (<currentSlice>)` line when progress.json exists). Exit
|
|
@@ -235,7 +235,7 @@ export function buildClaudeSettingsLocalJson() {
|
|
|
235
235
|
};
|
|
236
236
|
}
|
|
237
237
|
/**
|
|
238
|
-
* v3.1.2: build the Bash matcher command that runs `peaks
|
|
238
|
+
* v3.1.2: build the Bash matcher command that runs `peaks code
|
|
239
239
|
* gate-step-08`. We invoke the CLI directly (not via `node -e "..."`)
|
|
240
240
|
* because the CLI is the only legitimate source of the structured
|
|
241
241
|
* decision + Next: slice context. Exit code is the load-bearing
|
|
@@ -246,9 +246,9 @@ export function buildClaudeSettingsLocalJson() {
|
|
|
246
246
|
*/
|
|
247
247
|
function buildBashGateStep08Command() {
|
|
248
248
|
// The hook receives the tool call on stdin. We ignore stdin and
|
|
249
|
-
// delegate entirely to `peaks
|
|
249
|
+
// delegate entirely to `peaks code gate-step-08`, which reads
|
|
250
250
|
// .peaks/_runtime/<sessionId>/job-shape.json and last-prompt.txt.
|
|
251
251
|
// `${CLAUDE_PROJECT_DIR}` resolves to the consumer project's root
|
|
252
252
|
// (Claude Code's standard convention).
|
|
253
|
-
return 'peaks
|
|
253
|
+
return 'peaks code gate-step-08 --project "${CLAUDE_PROJECT_DIR}"';
|
|
254
254
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const CLI_VERSION = "4.0.0-beta";
|
|
1
|
+
export declare const CLI_VERSION = "4.0.0-beta.3";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export const CLI_VERSION = "4.0.0-beta";
|
|
1
|
+
export const CLI_VERSION = "4.0.0-beta.3";
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
# peaks-loop video demo
|
|
2
|
+
|
|
3
|
+
Remotion-based 30-second brand walk-through for peaks-loop 4.0. Mirrors `README.md`.
|
|
4
|
+
|
|
5
|
+
## Composition
|
|
6
|
+
|
|
7
|
+
- Two compositions, one per locale:
|
|
8
|
+
- `peaks-loop-demo` — 30 seconds @ 30fps (900 frames), 1920×1080 — Chinese primary.
|
|
9
|
+
- `peaks-loop-demo-en` — same frame budget, English primary.
|
|
10
|
+
- Scene timeline (frozen in `src/Root.tsx`):
|
|
11
|
+
- 0–90 — **TitleScene** (`peaks-loop`, no ·, no emoji)
|
|
12
|
+
- 90–240 — **PhilosophyScene** — 5 hero philosophy items, bilingual
|
|
13
|
+
- 240–540 — **DemoScene × 3** — `写长任务代码` / `修 bug 当天发` / `接一个长跑的需求`
|
|
14
|
+
- 540–780 — **SedimentScene** — 3-beat `NL → MANIFEST → BEE`
|
|
15
|
+
- 780–900 — **ClosingScene** — `npm i -g peaks-loop` + repo-name vs skill-name arc + 5,439 tests stats
|
|
16
|
+
|
|
17
|
+
## Visual style
|
|
18
|
+
|
|
19
|
+
- Background: `#0f172a` (slate-900) via `bg-brand-bg`
|
|
20
|
+
- Primary text: `#f8fafc` (slate-50) via `text-brand-fg`
|
|
21
|
+
- Accent: `#6366f1` (indigo-500) via `text-brand-accent`
|
|
22
|
+
- Stable badge: `#22c55e` (green-500)
|
|
23
|
+
- Mono font for kickers / install chip / chat bubbles; sans font for headlines
|
|
24
|
+
|
|
25
|
+
## Public preview files (tracked)
|
|
26
|
+
|
|
27
|
+
The READMEs embed `<video>` tags that point at:
|
|
28
|
+
|
|
29
|
+
- `preview/peaks-loop-demo.mp4` (zh, 4.9 MB)
|
|
30
|
+
- `preview/peaks-loop-demo-en.mp4` (en, 5.0 MB)
|
|
31
|
+
|
|
32
|
+
These are produced by the render command below and committed to git so a clone (and the GitHub rendering) sees the same path. The shell snippet under **Render** keeps `preview/` in sync after a fresh build.
|
|
33
|
+
|
|
34
|
+
## Render
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
cd examples/video-demo
|
|
38
|
+
pnpm install
|
|
39
|
+
npx remotion render peaks-loop-demo out/peaks-loop-demo.mp4
|
|
40
|
+
npx remotion render peaks-loop-demo-en out/peaks-loop-demo-en.mp4
|
|
41
|
+
|
|
42
|
+
mkdir -p preview
|
|
43
|
+
cp out/peaks-loop-demo.mp4 preview/peaks-loop-demo.mp4
|
|
44
|
+
cp out/peaks-loop-demo-en.mp4 preview/peaks-loop-demo-en.mp4
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
Fallback (no Chromium available):
|
|
48
|
+
|
|
49
|
+
```bash
|
|
50
|
+
npx remotion still peaks-loop-demo out/still.png --frame=120
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
## Preview during dev
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
npx remotion studio # http://localhost:3000
|
|
57
|
+
```
|
|
Binary file
|