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
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
* 1. `.peaks/_runtime/<sessionId>/` is bound
|
|
8
8
|
* 2. Latest checkpoint mtime is from today (UTC date)
|
|
9
9
|
* 3. Latest checkpoint has a parseable `mode` field
|
|
10
|
-
* 4. The peak-
|
|
10
|
+
* 4. The peak-code skill is the active skill
|
|
11
11
|
* 5. Exactly one session has a today's checkpoint (no ambiguity)
|
|
12
12
|
*
|
|
13
13
|
* On a hit, the LLM MUST auto-resume (D7.b override of "never silently
|
|
@@ -25,7 +25,7 @@ import { existsSync, readdirSync, readFileSync, statSync } from 'node:fs';
|
|
|
25
25
|
import { join } from 'node:path';
|
|
26
26
|
import { getSkillPresence } from '../skills/skill-presence-service.js';
|
|
27
27
|
import { emitObservabilityEvent } from '../observability/observability-service.js';
|
|
28
|
-
import {
|
|
28
|
+
import { isCodeMode } from './mode-gate.js';
|
|
29
29
|
export const POST_COMPACT_RESUME_REASONS = [
|
|
30
30
|
'post-compact-match',
|
|
31
31
|
'sid-unbound',
|
|
@@ -160,7 +160,7 @@ export async function detectPostCompactResume(opts) {
|
|
|
160
160
|
// Mode: prefer the checkpoint's mode; fall back to the presence override
|
|
161
161
|
// (test seam) or to a fresh skill-presence read.
|
|
162
162
|
let mode;
|
|
163
|
-
if (
|
|
163
|
+
if (isCodeMode(checkpointMode)) {
|
|
164
164
|
mode = checkpointMode;
|
|
165
165
|
}
|
|
166
166
|
else if (opts.presenceModeOverride !== undefined) {
|
|
@@ -170,7 +170,7 @@ export async function detectPostCompactResume(opts) {
|
|
|
170
170
|
try {
|
|
171
171
|
const presence = getSkillPresence(opts.projectRoot);
|
|
172
172
|
const presenceMode = presence?.mode;
|
|
173
|
-
if (presenceMode !== undefined &&
|
|
173
|
+
if (presenceMode !== undefined && isCodeMode(presenceMode)) {
|
|
174
174
|
mode = presenceMode;
|
|
175
175
|
}
|
|
176
176
|
}
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
*
|
|
4
4
|
* Wire-installed by `peaks workspace init` (extends the existing hook
|
|
5
5
|
* installer; does NOT replace the Write|Edit|MultiEdit fact-forcing
|
|
6
|
-
* bypass). The hook runs `peaks
|
|
6
|
+
* bypass). The hook runs `peaks code gate-step-08 --project .` before
|
|
7
7
|
* every Bash tool call. Exit code is the load-bearing contract:
|
|
8
8
|
*
|
|
9
9
|
* exit 0 → allow (with structured stdout describing the decision)
|
|
@@ -29,7 +29,7 @@
|
|
|
29
29
|
* regex is the FIRST time peaks-loop accepts hardcoded keywords —
|
|
30
30
|
* explicitly scoped as a *fail-closed backup* (case 3), NOT a primary
|
|
31
31
|
* judgement. The LLM still owns the semantic call via
|
|
32
|
-
* `peaks
|
|
32
|
+
* `peaks code detect-job`. The regex is a safety net for the v3.1.1
|
|
33
33
|
* incident class (LLM under load never records the decision at all).
|
|
34
34
|
*/
|
|
35
35
|
export declare const STEP_08_GATE_FILE_NAME: "job-shape.json";
|
|
@@ -38,7 +38,7 @@ export declare const STEP_08_PROGRESS_FILE_NAME: "progress.json";
|
|
|
38
38
|
* Fail-closed backup regex — see module docstring case 3 for why this
|
|
39
39
|
* exists. Kept short and explicit; if the prompt mentions any of these
|
|
40
40
|
* triggers and `job-shape.json` is missing, the LLM is treated as
|
|
41
|
-
* having skipped `peaks
|
|
41
|
+
* having skipped `peaks code detect-job` and the gate blocks.
|
|
42
42
|
*
|
|
43
43
|
* The list mirrors the v3.1.0 / v3.1.1 incident triggers verbatim:
|
|
44
44
|
* 继续执行下个 slice (until next slice) → until / 直到
|
|
@@ -84,7 +84,7 @@ export interface EvaluateStep08Result {
|
|
|
84
84
|
}
|
|
85
85
|
/**
|
|
86
86
|
* Pure evaluator — does NOT write, does NOT exit. CLI wrapper in
|
|
87
|
-
* `src/cli/commands/
|
|
87
|
+
* `src/cli/commands/code-commands.ts` reads `allow` to set the process
|
|
88
88
|
* exit code (0 allow / 2 block) and prints the structured envelope.
|
|
89
89
|
*/
|
|
90
90
|
export declare function evaluateStep08(input: EvaluateStep08Input): EvaluateStep08Result;
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
*
|
|
4
4
|
* Wire-installed by `peaks workspace init` (extends the existing hook
|
|
5
5
|
* installer; does NOT replace the Write|Edit|MultiEdit fact-forcing
|
|
6
|
-
* bypass). The hook runs `peaks
|
|
6
|
+
* bypass). The hook runs `peaks code gate-step-08 --project .` before
|
|
7
7
|
* every Bash tool call. Exit code is the load-bearing contract:
|
|
8
8
|
*
|
|
9
9
|
* exit 0 → allow (with structured stdout describing the decision)
|
|
@@ -29,7 +29,7 @@
|
|
|
29
29
|
* regex is the FIRST time peaks-loop accepts hardcoded keywords —
|
|
30
30
|
* explicitly scoped as a *fail-closed backup* (case 3), NOT a primary
|
|
31
31
|
* judgement. The LLM still owns the semantic call via
|
|
32
|
-
* `peaks
|
|
32
|
+
* `peaks code detect-job`. The regex is a safety net for the v3.1.1
|
|
33
33
|
* incident class (LLM under load never records the decision at all).
|
|
34
34
|
*/
|
|
35
35
|
import { existsSync, readFileSync } from 'node:fs';
|
|
@@ -41,7 +41,7 @@ export const STEP_08_PROGRESS_FILE_NAME = 'progress.json';
|
|
|
41
41
|
* Fail-closed backup regex — see module docstring case 3 for why this
|
|
42
42
|
* exists. Kept short and explicit; if the prompt mentions any of these
|
|
43
43
|
* triggers and `job-shape.json` is missing, the LLM is treated as
|
|
44
|
-
* having skipped `peaks
|
|
44
|
+
* having skipped `peaks code detect-job` and the gate blocks.
|
|
45
45
|
*
|
|
46
46
|
* The list mirrors the v3.1.0 / v3.1.1 incident triggers verbatim:
|
|
47
47
|
* 继续执行下个 slice (until next slice) → until / 直到
|
|
@@ -102,7 +102,7 @@ function readPromptFromLastPromptFile(projectRoot, sessionId) {
|
|
|
102
102
|
}
|
|
103
103
|
/**
|
|
104
104
|
* Pure evaluator — does NOT write, does NOT exit. CLI wrapper in
|
|
105
|
-
* `src/cli/commands/
|
|
105
|
+
* `src/cli/commands/code-commands.ts` reads `allow` to set the process
|
|
106
106
|
* exit code (0 allow / 2 block) and prints the structured envelope.
|
|
107
107
|
*/
|
|
108
108
|
export function evaluateStep08(input) {
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* v2.15.0 follow-up — G4: user touchpoint classifier.
|
|
3
3
|
*
|
|
4
4
|
* 12 Gaps positioning memory: "user 介入 = 业务/产品审阅,不是技术决策".
|
|
5
|
-
* This service classifies every
|
|
5
|
+
* This service classifies every Code gate by the kind of decision it
|
|
6
6
|
* represents, so the CLI / status line can show user which gates
|
|
7
7
|
* actually need their attention vs which are technical defaults
|
|
8
8
|
* (AI auto-decides in full-auto).
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* v2.15.0 follow-up — G4: user touchpoint classifier.
|
|
3
3
|
*
|
|
4
4
|
* 12 Gaps positioning memory: "user 介入 = 业务/产品审阅,不是技术决策".
|
|
5
|
-
* This service classifies every
|
|
5
|
+
* This service classifies every Code gate by the kind of decision it
|
|
6
6
|
* represents, so the CLI / status line can show user which gates
|
|
7
7
|
* actually need their attention vs which are technical defaults
|
|
8
8
|
* (AI auto-decides in full-auto).
|
|
@@ -7,11 +7,11 @@ export interface DispatchIdeCompactInput {
|
|
|
7
7
|
/** Spawn timeout (ms). Default 30s — Claude Code `/compact` is sync. */
|
|
8
8
|
readonly timeoutMs?: number | undefined;
|
|
9
9
|
/**
|
|
10
|
-
* Slice 2026-06-28-
|
|
10
|
+
* Slice 2026-06-28-code-mode-bypass-fix (defect #4): which session
|
|
11
11
|
* the compact should target. Default `'main'` — the orchestrator
|
|
12
12
|
* (peaks-code body) runs in the main-session Claude Code window and
|
|
13
13
|
* wants to compress *its* context, not a sub-agent's. Sub-agent
|
|
14
|
-
* shells that spawn their own `peaks
|
|
14
|
+
* shells that spawn their own `peaks code auto-compact` flow pass
|
|
15
15
|
* `'sub-agent'` to preserve the legacy shell-spawn behaviour.
|
|
16
16
|
*
|
|
17
17
|
* Behaviour matrix (claude-code MVP):
|
|
@@ -47,7 +47,7 @@ export async function dispatchIdeCompact(input) {
|
|
|
47
47
|
// See auto-compact-reader.ts for the IdeKind→IdeId cast rationale.
|
|
48
48
|
const ideId = (detected === 'unknown' ? 'claude-code' : detected);
|
|
49
49
|
const adapter = getAdapter(ideId);
|
|
50
|
-
// Slice 2026-06-28-
|
|
50
|
+
// Slice 2026-06-28-code-mode-bypass-fix (defect #4): default to
|
|
51
51
|
// `'main'` so the orchestrator's auto-compact actually compresses
|
|
52
52
|
// the main-session context. The orchestrator passes `'sub-agent'`
|
|
53
53
|
// explicitly when a sub-agent shell dispatches the call.
|
|
@@ -123,7 +123,7 @@ export async function dispatchIdeCompact(input) {
|
|
|
123
123
|
});
|
|
124
124
|
}
|
|
125
125
|
// Lazy install: we only get here when the caller explicitly
|
|
126
|
-
// invokes `peaks
|
|
126
|
+
// invokes `peaks code auto-compact --execute`, so the user has
|
|
127
127
|
// already opted in. No zero-touch surprise on workspace init.
|
|
128
128
|
return await dispatchIdeNativeHook({
|
|
129
129
|
projectRoot: input.projectRoot,
|
|
@@ -107,7 +107,7 @@ export type AutoCompactResult = {
|
|
|
107
107
|
readonly convergencePlan?: ConvergencePlan;
|
|
108
108
|
readonly dispatch?: CompactDispatchResult;
|
|
109
109
|
/**
|
|
110
|
-
* Slice 2026-06-28-
|
|
110
|
+
* Slice 2026-06-28-code-mode-bypass-fix (defect #4): which
|
|
111
111
|
* session the compact targeted. `'main'` (default) means the
|
|
112
112
|
* main-session Claude Code window will fire `/compact` on its
|
|
113
113
|
* next turn; `'sub-agent'` means the dispatcher shell-spawned
|
|
@@ -0,0 +1,239 @@
|
|
|
1
|
+
import type Database from "better-sqlite3";
|
|
2
|
+
import { z } from "zod";
|
|
3
|
+
import { type CrystallizationEvent, type CrystallizationEventInput, type CrystallizationEventStatus, type EvidenceBrief } from "./crystallization-types.js";
|
|
4
|
+
import { listCrystallizationEvents } from "./crystallization-store.js";
|
|
5
|
+
import { type LoopReleaseInput } from "../loop/loop-release-types.js";
|
|
6
|
+
/**
|
|
7
|
+
* CrystallizationService — spec §5 (post-run crystallization)
|
|
8
|
+
* + §4.5 + §4.7 + §10 RL-2 / RL-3 / RL-7.
|
|
9
|
+
*
|
|
10
|
+
* Hard rules enforced at THIS layer (defense in depth; the Zod
|
|
11
|
+
* schemas above and the brief refine guard add the second wall):
|
|
12
|
+
*
|
|
13
|
+
* - AC-4 / RL-2: a crystallization_event is written only when the
|
|
14
|
+
* candidate task has `task_status === 'completed'` AND
|
|
15
|
+
* `gates_passed === true` AND `evidence_collected === true`.
|
|
16
|
+
* Any pre-run attempt (status !== 'completed') is rejected
|
|
17
|
+
* with `CRYSTALLIZATION_PRE_RUN`. This is the pre-run block
|
|
18
|
+
* enforced by AC-4, AC-5, AC-6, AC-15, AC-16, AC-17 of the M5
|
|
19
|
+
* slice.
|
|
20
|
+
* - AC-6 / RL-3: writing a (loop_release, main_bee_release,
|
|
21
|
+
* loop_bee_relation) pair happens in a SINGLE TRANSACTION. The
|
|
22
|
+
* brief persist on crystallization_event also lives inside
|
|
23
|
+
* the same transaction (the brief is the durable evidence;
|
|
24
|
+
* dropping either side would break consistency).
|
|
25
|
+
* - AC-7 / RL-1: this layer never asks the user to hand-author
|
|
26
|
+
* JSON / manifest / CLI verb; all inputs are typed payloads
|
|
27
|
+
* the LLM submits on the user's behalf.
|
|
28
|
+
* - AC-15 / RL-7: the brief is mandatory; the
|
|
29
|
+
* `EvidenceBriefSchema.refine` guard rejects partial briefs
|
|
30
|
+
* at the parse boundary.
|
|
31
|
+
* - AC-16 / RL-7: the brief has all 4 sections
|
|
32
|
+
* (what_happened / why_it_matters / what_learned /
|
|
33
|
+
* what_action). The service throws `BriefSectionError` if the
|
|
34
|
+
* payload fails the guard.
|
|
35
|
+
*
|
|
36
|
+
* Sub-domain error codes:
|
|
37
|
+
*
|
|
38
|
+
* - CRYSTALLIZATION_PRE_RUN: task_status / gates_passed /
|
|
39
|
+
* evidence_collected precondition failed.
|
|
40
|
+
* - CRYSTALLIZATION_INVALID_TASK_STATE: a task input field is
|
|
41
|
+
* malformed (e.g. unknown task_status).
|
|
42
|
+
* - MISSING_BRIEF_SECTION: a brief is missing at least one of
|
|
43
|
+
* its 4 sections (raised from the evidence-brief-builder
|
|
44
|
+
* refine; surfaced as-is by the service).
|
|
45
|
+
* - CRYSTALLIZATION_TX_FAILED: a transaction-side effect failed
|
|
46
|
+
* (FK constraint, duplicate key, …). The service re-raises
|
|
47
|
+
* richer domain errors first; this is the catch-all for
|
|
48
|
+
* unexpected SQL errors.
|
|
49
|
+
*/
|
|
50
|
+
export declare const CRYSTALLIZATION_TASK_STATUSES: readonly ["completed", "in_progress", "scratch", "blocked", "failed"];
|
|
51
|
+
export type CrystallizationTaskStatus = (typeof CRYSTALLIZATION_TASK_STATUSES)[number];
|
|
52
|
+
/**
|
|
53
|
+
* The pre-run task state the service requires. Crystallization is
|
|
54
|
+
* GATED on these three flags. The validator rejects any input that
|
|
55
|
+
* does not match. Adding a new flag means a schema-version bump; for
|
|
56
|
+
* now the three are required.
|
|
57
|
+
*/
|
|
58
|
+
export declare const CrystallizationTaskStateSchema: z.ZodObject<{
|
|
59
|
+
task_id: z.ZodString;
|
|
60
|
+
task_status: z.ZodLiteral<"completed">;
|
|
61
|
+
gates_passed: z.ZodLiteral<true>;
|
|
62
|
+
evidence_collected: z.ZodLiteral<true>;
|
|
63
|
+
}, "strip", z.ZodTypeAny, {
|
|
64
|
+
task_id: string;
|
|
65
|
+
task_status: "completed";
|
|
66
|
+
gates_passed: true;
|
|
67
|
+
evidence_collected: true;
|
|
68
|
+
}, {
|
|
69
|
+
task_id: string;
|
|
70
|
+
task_status: "completed";
|
|
71
|
+
gates_passed: true;
|
|
72
|
+
evidence_collected: true;
|
|
73
|
+
}>;
|
|
74
|
+
export type CrystallizationTaskState = z.infer<typeof CrystallizationTaskStateSchema>;
|
|
75
|
+
export type CrystallizationIntegrityErrorCode = "CRYSTALLIZATION_PRE_RUN" | "CRYSTALLIZATION_INVALID_TASK_STATE" | "CRYSTALLIZATION_TX_FAILED" | "MISSING_BRIEF_SECTION";
|
|
76
|
+
export declare class CrystallizationIntegrityError extends Error {
|
|
77
|
+
readonly code: CrystallizationIntegrityErrorCode | "MISSING_BRIEF_SECTION";
|
|
78
|
+
readonly findings: ReadonlyArray<{
|
|
79
|
+
path: string;
|
|
80
|
+
message: string;
|
|
81
|
+
}>;
|
|
82
|
+
constructor(code: CrystallizationIntegrityErrorCode, message: string, findings?: ReadonlyArray<{
|
|
83
|
+
path: string;
|
|
84
|
+
message: string;
|
|
85
|
+
}>);
|
|
86
|
+
}
|
|
87
|
+
export interface CrystallizePayload {
|
|
88
|
+
/** The candidate task state. Must satisfy the pre-run gate. */
|
|
89
|
+
task: CrystallizationTaskState;
|
|
90
|
+
/** The loop_release to create (new). Must include main bee via relation. */
|
|
91
|
+
loop_input: LoopReleaseInput;
|
|
92
|
+
/**
|
|
93
|
+
* The main bee_release to create. Note: bee_release requires a
|
|
94
|
+
* manifest row to keep the existing 4.x schema consistent;
|
|
95
|
+
* `bee_input` here carries ONLY the manifest-level fields the
|
|
96
|
+
* service uses. A future slice will swap in the full
|
|
97
|
+
* retainRelease() flow.
|
|
98
|
+
*/
|
|
99
|
+
bee_input: BeeCrystallizeInput;
|
|
100
|
+
/**
|
|
101
|
+
* Optional NL reason the LLM authored; surfaced on the
|
|
102
|
+
* loop_bee_relation row (spec §4.6 `reason`).
|
|
103
|
+
*/
|
|
104
|
+
bee_relation_reason: string;
|
|
105
|
+
/**
|
|
106
|
+
* The 4-section evidence brief (spec §4.7).
|
|
107
|
+
*/
|
|
108
|
+
evidence_brief: EvidenceBrief;
|
|
109
|
+
/** Optional structured bullets (RL-7: counts may support the brief, not replace it). */
|
|
110
|
+
evidence_bullets?: string[];
|
|
111
|
+
/** Source trace pointers for the brief (spec §4.5). */
|
|
112
|
+
source_trace_pointers?: string[];
|
|
113
|
+
/** Optional evaluator summary (independent scorers — spec §4.5). */
|
|
114
|
+
evaluator_summary?: string;
|
|
115
|
+
/** Optional user decision summary (spec §4.5). */
|
|
116
|
+
user_decision_summary?: string;
|
|
117
|
+
/** Trigger classification (spec §5.4). */
|
|
118
|
+
trigger: CrystallizationEventInput["trigger"];
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Minimum bee_release payload the service needs to create a main bee
|
|
122
|
+
* alongside a loop. The full bee_release schema (see
|
|
123
|
+
* `src/services/skillhub/release-retain.ts`) carries manifest rows,
|
|
124
|
+
* segment refs, file rows, etc.; M5 only writes the bee_release header
|
|
125
|
+
* + a single bee_manifest row sufficient to keep the 4.x FK
|
|
126
|
+
* constraints green. Full bee retaining lands in a future slice.
|
|
127
|
+
*
|
|
128
|
+
* Schema definition is hoisted above the interface so the typed
|
|
129
|
+
* interface can reference the inferred Zod type without forward-
|
|
130
|
+
* reference gymnastics.
|
|
131
|
+
*/
|
|
132
|
+
declare const BeeNameSchema: z.ZodString;
|
|
133
|
+
export interface BeeCrystallizeInput {
|
|
134
|
+
bee_name: z.infer<typeof BeeNameSchema>;
|
|
135
|
+
version: string;
|
|
136
|
+
description: string;
|
|
137
|
+
user_intent_raw?: string;
|
|
138
|
+
parent_version?: string;
|
|
139
|
+
changelog?: string;
|
|
140
|
+
}
|
|
141
|
+
/**
|
|
142
|
+
* The crystallization result. The brief is returned AS PERSISTED
|
|
143
|
+
* (re-parsed through the schema) so callers receive the canonical
|
|
144
|
+
* shape, not the loose payload.
|
|
145
|
+
*/
|
|
146
|
+
export interface CrystallizationResult {
|
|
147
|
+
loop_release_id: string;
|
|
148
|
+
bee_release_id: number;
|
|
149
|
+
loop_bee_relation_id: number;
|
|
150
|
+
crystallization_event_id: string;
|
|
151
|
+
loop_release_lifecycle_status: CrystallizationEventStatus;
|
|
152
|
+
}
|
|
153
|
+
/**
|
|
154
|
+
* Service interface for the post-run crystallization flow.
|
|
155
|
+
*/
|
|
156
|
+
export declare class CrystallizationService {
|
|
157
|
+
private readonly db;
|
|
158
|
+
constructor(db: Database.Database);
|
|
159
|
+
/**
|
|
160
|
+
* Read a CrystallizationEvent by id.
|
|
161
|
+
*/
|
|
162
|
+
read(id: string): CrystallizationEvent | undefined;
|
|
163
|
+
/**
|
|
164
|
+
* List events. Filter by lifecycle_status and/or the FK pointer
|
|
165
|
+
* columns. When no filters are supplied, lists ALL events
|
|
166
|
+
* (newest-first).
|
|
167
|
+
*/
|
|
168
|
+
list(opts?: Parameters<typeof listCrystallizationEvents>[1]): {
|
|
169
|
+
schema_version: "peaks.crystallization/1";
|
|
170
|
+
id: string;
|
|
171
|
+
lifecycle_status: "candidate" | "stable" | "retired";
|
|
172
|
+
trigger: "user_explicit" | "llm_suggested" | "success_default_prompt" | "similar_task_recurrence";
|
|
173
|
+
evidence_brief: {
|
|
174
|
+
what_happened: string;
|
|
175
|
+
why_it_matters: string;
|
|
176
|
+
what_learned: string;
|
|
177
|
+
what_action: string;
|
|
178
|
+
};
|
|
179
|
+
evidence_bullets: string[];
|
|
180
|
+
source_trace_pointers: string[];
|
|
181
|
+
evaluator_summary: string;
|
|
182
|
+
user_decision_summary: string;
|
|
183
|
+
created_at: string;
|
|
184
|
+
created_loop_release_id?: string | undefined;
|
|
185
|
+
updated_loop_release_id?: string | undefined;
|
|
186
|
+
created_bee_release_id?: number | undefined;
|
|
187
|
+
updated_bee_release_id?: number | undefined;
|
|
188
|
+
}[];
|
|
189
|
+
/**
|
|
190
|
+
* Update a crystallization event's lifecycle_status. Always allowed
|
|
191
|
+
* (no schema-version gate). Returns the updated row or undefined if
|
|
192
|
+
* the id is absent.
|
|
193
|
+
*
|
|
194
|
+
* A `stable` transition is the natural post-crystallization state;
|
|
195
|
+
* the service does NOT enforce user-confirmation here (per spec
|
|
196
|
+
* §5.6 promotion happens on a separate `peaks loop promote` path).
|
|
197
|
+
* `retired` is the dispose path (`peaks asset dispose`).
|
|
198
|
+
*/
|
|
199
|
+
updateStatus(id: string, next: CrystallizationEventStatus): CrystallizationEvent | undefined;
|
|
200
|
+
/**
|
|
201
|
+
* Pre-run gate: throws if any of `task_status`, `gates_passed`,
|
|
202
|
+
* `evidence_collected` is not as required. Called from
|
|
203
|
+
* `crystallize` BEFORE the transaction begins.
|
|
204
|
+
*
|
|
205
|
+
* Reachable as a public method so the CLI / tests can probe the
|
|
206
|
+
* gate in isolation.
|
|
207
|
+
*/
|
|
208
|
+
assertReady(task: CrystallizationTaskState): CrystallizationTaskState;
|
|
209
|
+
/**
|
|
210
|
+
* Run the post-run crystallization flow.
|
|
211
|
+
*
|
|
212
|
+
* Steps (all in ONE better-sqlite3 transaction, atomic):
|
|
213
|
+
*
|
|
214
|
+
* 1. Pre-run gate (task must be completed / gates_passed /
|
|
215
|
+
* evidence_collected).
|
|
216
|
+
* 2. Re-validate the 4-section brief (EvidenceBriefSchema.parse,
|
|
217
|
+
* EvidenceBriefSchema.refine).
|
|
218
|
+
* 3. Insert loop_release.
|
|
219
|
+
* 4. Insert bee_release header (+ a single bee_manifest row to
|
|
220
|
+
* keep the 4.x FK contract).
|
|
221
|
+
* 5. Insert loop_bee_relation row with role='main'.
|
|
222
|
+
* 6. Insert crystallization_event with the brief persisted.
|
|
223
|
+
*
|
|
224
|
+
* Returns the four ids + the new loop's lifecycle_status. On any
|
|
225
|
+
* failure the transaction is rolled back and the partial rows
|
|
226
|
+
* disappear.
|
|
227
|
+
*
|
|
228
|
+
* Throws:
|
|
229
|
+
* - CrystallizationIntegrityError(CRYSTALLIZATION_PRE_RUN) on
|
|
230
|
+
* the pre-run gate.
|
|
231
|
+
* - BriefSectionError or ZodError if the brief is malformed;
|
|
232
|
+
* surfaced as
|
|
233
|
+
* CrystallizationIntegrityError(MISSING_BRIEF_SECTION).
|
|
234
|
+
* - CrystallizationIntegrityError(CRYSTALLIZATION_TX_FAILED)
|
|
235
|
+
* on any SQL transaction failure.
|
|
236
|
+
*/
|
|
237
|
+
crystallize(payload: CrystallizePayload): CrystallizationResult;
|
|
238
|
+
}
|
|
239
|
+
export {};
|