peaks-loop 4.1.2 → 4.1.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/.claude-plugin/marketplace.json +136 -47
- package/CHANGELOG.md +56 -0
- package/README-en.md +1 -1
- package/README.md +1 -1
- package/contracts/readonly-argv-whitelist.json +211 -0
- package/dist/cli/commands/audit-artifact-runners.d.ts +16 -0
- package/dist/cli/commands/audit-artifact-runners.js +170 -0
- package/dist/cli/commands/audit-command-shared.d.ts +97 -0
- package/dist/cli/commands/audit-command-shared.js +60 -0
- package/dist/cli/commands/audit-commands.d.ts +7 -31
- package/dist/cli/commands/audit-commands.js +64 -473
- package/dist/cli/commands/audit-goal-runners.d.ts +17 -0
- package/dist/cli/commands/audit-goal-runners.js +114 -0
- package/dist/cli/commands/audit-red-lines-runners.d.ts +11 -0
- package/dist/cli/commands/audit-red-lines-runners.js +43 -0
- package/dist/cli/commands/audit-refusal-data.d.ts +23 -0
- package/dist/cli/commands/audit-refusal-data.js +69 -0
- package/dist/cli/commands/audit-static-runners.d.ts +13 -0
- package/dist/cli/commands/audit-static-runners.js +139 -0
- package/dist/cli/commands/await-runners.d.ts +11 -0
- package/dist/cli/commands/await-runners.js +148 -0
- package/dist/cli/commands/code-auto-compact-command.d.ts +3 -0
- package/dist/cli/commands/code-auto-compact-command.js +124 -0
- package/dist/cli/commands/code-auto-compact-envelope.d.ts +22 -0
- package/dist/cli/commands/code-auto-compact-envelope.js +39 -0
- package/dist/cli/commands/code-context-audit-command.d.ts +3 -0
- package/dist/cli/commands/code-context-audit-command.js +68 -0
- package/dist/cli/commands/code-context-now-command.d.ts +3 -0
- package/dist/cli/commands/code-context-now-command.js +124 -0
- package/dist/cli/commands/code-context-now-envelope.d.ts +66 -0
- package/dist/cli/commands/code-context-now-envelope.js +136 -0
- package/dist/cli/commands/code-context-now-mapping.d.ts +27 -0
- package/dist/cli/commands/code-context-now-mapping.js +43 -0
- package/dist/cli/commands/code-emit-handoff-command.d.ts +3 -0
- package/dist/cli/commands/code-emit-handoff-command.js +99 -0
- package/dist/cli/commands/code-gate-step-08-command.d.ts +3 -0
- package/dist/cli/commands/code-gate-step-08-command.js +139 -0
- package/dist/cli/commands/code-post-compact-detect-command.d.ts +3 -0
- package/dist/cli/commands/code-post-compact-detect-command.js +50 -0
- package/dist/cli/commands/code-runtime-commands.d.ts +9 -43
- package/dist/cli/commands/code-runtime-commands.js +20 -672
- package/dist/cli/commands/code-runtime-session.d.ts +1 -0
- package/dist/cli/commands/code-runtime-session.js +15 -0
- package/dist/cli/commands/compact-command.d.ts +6 -2
- package/dist/cli/commands/compact-command.js +12 -559
- package/dist/cli/commands/compact-dry-run-command.d.ts +3 -0
- package/dist/cli/commands/compact-dry-run-command.js +87 -0
- package/dist/cli/commands/compact-force-command.d.ts +3 -0
- package/dist/cli/commands/compact-force-command.js +98 -0
- package/dist/cli/commands/compact-harness-window-command.d.ts +3 -0
- package/dist/cli/commands/compact-harness-window-command.js +174 -0
- package/dist/cli/commands/compact-history-command.d.ts +3 -0
- package/dist/cli/commands/compact-history-command.js +89 -0
- package/dist/cli/commands/compact-read-commands.d.ts +3 -0
- package/dist/cli/commands/compact-read-commands.js +123 -0
- package/dist/cli/commands/compact-settle-command.d.ts +3 -0
- package/dist/cli/commands/compact-settle-command.js +130 -0
- package/dist/cli/commands/compact-shared.d.ts +9 -0
- package/dist/cli/commands/compact-shared.js +26 -0
- package/dist/cli/commands/core/skill-command.d.ts +1 -44
- package/dist/cli/commands/core/skill-command.js +13 -541
- package/dist/cli/commands/core/skill-context-verdict.d.ts +38 -0
- package/dist/cli/commands/core/skill-context-verdict.js +63 -0
- package/dist/cli/commands/core/skill-generated-config-notice.d.ts +41 -0
- package/dist/cli/commands/core/skill-generated-config-notice.js +75 -0
- package/dist/cli/commands/core/skill-heartbeat-commands.d.ts +3 -0
- package/dist/cli/commands/core/skill-heartbeat-commands.js +50 -0
- package/dist/cli/commands/core/skill-presence-commands.d.ts +3 -0
- package/dist/cli/commands/core/skill-presence-commands.js +123 -0
- package/dist/cli/commands/core/skill-presence-housekeeping-commands.d.ts +3 -0
- package/dist/cli/commands/core/skill-presence-housekeeping-commands.js +165 -0
- package/dist/cli/commands/core/skill-registry-commands.d.ts +3 -0
- package/dist/cli/commands/core/skill-registry-commands.js +117 -0
- package/dist/cli/commands/core/skill-runbook-command.d.ts +3 -0
- package/dist/cli/commands/core/skill-runbook-command.js +29 -0
- package/dist/cli/commands/dispatch-command-spec.d.ts +2 -0
- package/dist/cli/commands/dispatch-command-spec.js +62 -0
- package/dist/cli/commands/dispatch-commands.js +159 -775
- package/dist/cli/commands/dispatch-detached-branch.d.ts +3 -0
- package/dist/cli/commands/dispatch-detached-branch.js +58 -0
- package/dist/cli/commands/dispatch-envelope.d.ts +36 -0
- package/dist/cli/commands/dispatch-envelope.js +104 -0
- package/dist/cli/commands/dispatch-isolation-lease.d.ts +17 -0
- package/dist/cli/commands/dispatch-isolation-lease.js +149 -0
- package/dist/cli/commands/dispatch-preflight.d.ts +7 -0
- package/dist/cli/commands/dispatch-preflight.js +105 -0
- package/dist/cli/commands/dispatch-prompt-blocks.d.ts +10 -0
- package/dist/cli/commands/dispatch-prompt-blocks.js +56 -0
- package/dist/cli/commands/dispatch-prompt-composition.d.ts +30 -0
- package/dist/cli/commands/dispatch-prompt-composition.js +171 -0
- package/dist/cli/commands/dispatch-record-write.d.ts +24 -0
- package/dist/cli/commands/dispatch-record-write.js +96 -0
- package/dist/cli/commands/dispatch-tool-call.d.ts +15 -0
- package/dist/cli/commands/dispatch-tool-call.js +128 -0
- package/dist/cli/commands/evolution-command-shared.d.ts +78 -0
- package/dist/cli/commands/evolution-command-shared.js +107 -0
- package/dist/cli/commands/evolution-commands.d.ts +11 -1
- package/dist/cli/commands/evolution-commands.js +19 -350
- package/dist/cli/commands/evolution-evaluate-command.d.ts +24 -0
- package/dist/cli/commands/evolution-evaluate-command.js +138 -0
- package/dist/cli/commands/evolution-propose-command.d.ts +23 -0
- package/dist/cli/commands/evolution-propose-command.js +145 -0
- package/dist/cli/commands/evolution-status-command.d.ts +17 -0
- package/dist/cli/commands/evolution-status-command.js +41 -0
- package/dist/cli/commands/evolution-verdict-commands.d.ts +30 -0
- package/dist/cli/commands/evolution-verdict-commands.js +100 -0
- package/dist/cli/commands/finalize-accumulator.d.ts +44 -0
- package/dist/cli/commands/finalize-accumulator.js +55 -0
- package/dist/cli/commands/finalize-branches.d.ts +34 -0
- package/dist/cli/commands/finalize-branches.js +119 -0
- package/dist/cli/commands/finalize-runners.d.ts +3 -0
- package/dist/cli/commands/finalize-runners.js +92 -0
- package/dist/cli/commands/finalize-selection.d.ts +65 -0
- package/dist/cli/commands/finalize-selection.js +35 -0
- package/dist/cli/commands/gate-commands.js +26 -8
- package/dist/cli/commands/job-checkpoint-commands.d.ts +3 -0
- package/dist/cli/commands/job-checkpoint-commands.js +157 -0
- package/dist/cli/commands/job-command-shared.d.ts +109 -0
- package/dist/cli/commands/job-command-shared.js +72 -0
- package/dist/cli/commands/job-commands.d.ts +4 -64
- package/dist/cli/commands/job-commands.js +42 -552
- package/dist/cli/commands/job-cost-check-command.d.ts +3 -0
- package/dist/cli/commands/job-cost-check-command.js +41 -0
- package/dist/cli/commands/job-init-status-commands.d.ts +3 -0
- package/dist/cli/commands/job-init-status-commands.js +149 -0
- package/dist/cli/commands/job-run-commands.d.ts +3 -0
- package/dist/cli/commands/job-run-commands.js +97 -0
- package/dist/cli/commands/job-state-root.d.ts +35 -0
- package/dist/cli/commands/job-state-root.js +76 -0
- package/dist/cli/commands/loop-eval-capture-index.d.ts +4 -0
- package/dist/cli/commands/loop-eval-capture-index.js +44 -0
- package/dist/cli/commands/loop-eval-commands.d.ts +8 -5
- package/dist/cli/commands/loop-eval-commands.js +12 -626
- package/dist/cli/commands/loop-eval-eval-command.d.ts +3 -0
- package/dist/cli/commands/loop-eval-eval-command.js +168 -0
- package/dist/cli/commands/loop-eval-monotonic-command.d.ts +3 -0
- package/dist/cli/commands/loop-eval-monotonic-command.js +90 -0
- package/dist/cli/commands/loop-eval-parents.d.ts +7 -0
- package/dist/cli/commands/loop-eval-parents.js +20 -0
- package/dist/cli/commands/loop-eval-run-code.d.ts +7 -0
- package/dist/cli/commands/loop-eval-run-code.js +40 -0
- package/dist/cli/commands/loop-eval-run-command.d.ts +3 -0
- package/dist/cli/commands/loop-eval-run-command.js +113 -0
- package/dist/cli/commands/loop-eval-spec-commands.d.ts +3 -0
- package/dist/cli/commands/loop-eval-spec-commands.js +165 -0
- package/dist/cli/commands/loop-eval-spec-lint-command.d.ts +3 -0
- package/dist/cli/commands/loop-eval-spec-lint-command.js +42 -0
- package/dist/cli/commands/loop-eval-workflow-commands.d.ts +3 -0
- package/dist/cli/commands/loop-eval-workflow-commands.js +141 -0
- package/dist/cli/commands/mcp-commands.d.ts +10 -0
- package/dist/cli/commands/mcp-commands.js +157 -0
- package/dist/cli/commands/request-command-options.d.ts +49 -0
- package/dist/cli/commands/request-command-options.js +1 -0
- package/dist/cli/commands/request-commands.d.ts +3 -9
- package/dist/cli/commands/request-commands.js +17 -522
- package/dist/cli/commands/request-init-command.d.ts +3 -0
- package/dist/cli/commands/request-init-command.js +100 -0
- package/dist/cli/commands/request-lint-command.d.ts +3 -0
- package/dist/cli/commands/request-lint-command.js +50 -0
- package/dist/cli/commands/request-list-command.d.ts +10 -0
- package/dist/cli/commands/request-list-command.js +53 -0
- package/dist/cli/commands/request-repair-status-command.d.ts +3 -0
- package/dist/cli/commands/request-repair-status-command.js +61 -0
- package/dist/cli/commands/request-show-command.d.ts +3 -0
- package/dist/cli/commands/request-show-command.js +56 -0
- package/dist/cli/commands/request-transition-command.d.ts +3 -0
- package/dist/cli/commands/request-transition-command.js +122 -0
- package/dist/cli/commands/request-transition-failures.d.ts +8 -0
- package/dist/cli/commands/request-transition-failures.js +90 -0
- package/dist/cli/commands/request-transition-hooks.d.ts +50 -0
- package/dist/cli/commands/request-transition-hooks.js +115 -0
- package/dist/cli/commands/request-transition-preflight.d.ts +10 -0
- package/dist/cli/commands/request-transition-preflight.js +107 -0
- package/dist/cli/commands/scan-command-shared.d.ts +96 -0
- package/dist/cli/commands/scan-command-shared.js +83 -0
- package/dist/cli/commands/scan-commands.d.ts +3 -2
- package/dist/cli/commands/scan-commands.js +23 -463
- package/dist/cli/commands/scan-inventory-commands.d.ts +3 -0
- package/dist/cli/commands/scan-inventory-commands.js +96 -0
- package/dist/cli/commands/scan-project-commands.d.ts +3 -0
- package/dist/cli/commands/scan-project-commands.js +65 -0
- package/dist/cli/commands/scan-scope-commands.d.ts +3 -0
- package/dist/cli/commands/scan-scope-commands.js +149 -0
- package/dist/cli/commands/scan-scope-helpers.d.ts +8 -0
- package/dist/cli/commands/scan-scope-helpers.js +54 -0
- package/dist/cli/commands/scan-structural-commands.d.ts +3 -0
- package/dist/cli/commands/scan-structural-commands.js +113 -0
- package/dist/cli/commands/share-commands.d.ts +12 -68
- package/dist/cli/commands/share-commands.js +47 -556
- package/dist/cli/commands/share-error-hints.d.ts +14 -0
- package/dist/cli/commands/share-error-hints.js +38 -0
- package/dist/cli/commands/share-identity.d.ts +13 -0
- package/dist/cli/commands/share-identity.js +22 -0
- package/dist/cli/commands/share-record-paths.d.ts +37 -0
- package/dist/cli/commands/share-record-paths.js +68 -0
- package/dist/cli/commands/share-runners.d.ts +3 -0
- package/dist/cli/commands/share-runners.js +158 -0
- package/dist/cli/commands/shared-read-runners.d.ts +3 -0
- package/dist/cli/commands/shared-read-runners.js +51 -0
- package/dist/cli/commands/slice-check-command.d.ts +3 -0
- package/dist/cli/commands/slice-check-command.js +54 -0
- package/dist/cli/commands/slice-commands.d.ts +2 -22
- package/dist/cli/commands/slice-commands.js +18 -517
- package/dist/cli/commands/slice-decompose-artifacts.d.ts +18 -0
- package/dist/cli/commands/slice-decompose-artifacts.js +79 -0
- package/dist/cli/commands/slice-decompose-command.d.ts +3 -0
- package/dist/cli/commands/slice-decompose-command.js +123 -0
- package/dist/cli/commands/slice-list-commands.d.ts +3 -0
- package/dist/cli/commands/slice-list-commands.js +182 -0
- package/dist/cli/commands/slice-pick-command.d.ts +3 -0
- package/dist/cli/commands/slice-pick-command.js +60 -0
- package/dist/cli/commands/slice-plan-command.d.ts +24 -0
- package/dist/cli/commands/slice-plan-command.js +111 -0
- package/dist/cli/commands/workflow-commands.d.ts +10 -1
- package/dist/cli/commands/workflow-commands.js +6 -594
- package/dist/cli/commands/workflow-gate-commands.d.ts +3 -0
- package/dist/cli/commands/workflow-gate-commands.js +116 -0
- package/dist/cli/commands/workflow-plan-helpers.d.ts +48 -0
- package/dist/cli/commands/workflow-plan-helpers.js +103 -0
- package/dist/cli/commands/workflow-planning-commands.d.ts +3 -0
- package/dist/cli/commands/workflow-planning-commands.js +56 -0
- package/dist/cli/commands/workflow-swarm-actions.d.ts +7 -0
- package/dist/cli/commands/workflow-swarm-actions.js +109 -0
- package/dist/cli/commands/workflow-swarm-commands.d.ts +3 -0
- package/dist/cli/commands/workflow-swarm-commands.js +138 -0
- package/dist/cli/commands/workflow-tech-actions.d.ts +10 -0
- package/dist/cli/commands/workflow-tech-actions.js +150 -0
- package/dist/cli/commands/workspace/init-actions.d.ts +10 -0
- package/dist/cli/commands/workspace/init-actions.js +199 -0
- package/dist/cli/commands/workspace/init-codegraph-stake.d.ts +10 -0
- package/dist/cli/commands/workspace/init-codegraph-stake.js +54 -0
- package/dist/cli/commands/workspace/init-command.d.ts +8 -124
- package/dist/cli/commands/workspace/init-command.js +59 -623
- package/dist/cli/commands/workspace/init-context.d.ts +58 -0
- package/dist/cli/commands/workspace/init-context.js +121 -0
- package/dist/cli/commands/workspace/init-envelope.d.ts +3 -0
- package/dist/cli/commands/workspace/init-envelope.js +34 -0
- package/dist/cli/commands/workspace/init-failures.d.ts +3 -0
- package/dist/cli/commands/workspace/init-failures.js +84 -0
- package/dist/cli/commands/workspace/init-hooks-decision.d.ts +24 -0
- package/dist/cli/commands/workspace/init-hooks-decision.js +189 -0
- package/dist/cli/commands/workspace/init-options.d.ts +102 -0
- package/dist/cli/commands/workspace/init-options.js +1 -0
- package/dist/cli/commands/worktree-lease-commands.d.ts +10 -6
- package/dist/cli/commands/worktree-lease-commands.js +42 -512
- package/dist/cli/commands/worktree-lease-gc-command.d.ts +12 -0
- package/dist/cli/commands/worktree-lease-gc-command.js +117 -0
- package/dist/cli/commands/worktree-lease-git.d.ts +22 -0
- package/dist/cli/commands/worktree-lease-git.js +48 -0
- package/dist/cli/commands/worktree-lease-list-command.d.ts +12 -0
- package/dist/cli/commands/worktree-lease-list-command.js +100 -0
- package/dist/cli/commands/worktree-lease-load.d.ts +37 -0
- package/dist/cli/commands/worktree-lease-load.js +28 -0
- package/dist/cli/commands/worktree-lease-release-command.d.ts +13 -0
- package/dist/cli/commands/worktree-lease-release-command.js +105 -0
- package/dist/cli/commands/worktree-lease-renew-command.d.ts +11 -0
- package/dist/cli/commands/worktree-lease-renew-command.js +99 -0
- package/dist/cli/commands/worktree-lease-session.d.ts +22 -0
- package/dist/cli/commands/worktree-lease-session.js +29 -0
- package/dist/cli/commands/worktree-lease-spawn-command.d.ts +11 -0
- package/dist/cli/commands/worktree-lease-spawn-command.js +119 -0
- package/dist/cli/commands/worktree-lease-status-command.d.ts +11 -0
- package/dist/cli/commands/worktree-lease-status-command.js +86 -0
- package/dist/cli/commands/worktree-lease-store.d.ts +19 -0
- package/dist/cli/commands/worktree-lease-store.js +24 -0
- package/dist/cli/program.js +5 -0
- package/dist/services/distribution/mcp-install-runner.d.ts +21 -0
- package/dist/services/distribution/mcp-install-runner.js +59 -0
- package/dist/services/distribution/mcp-install.d.ts +95 -0
- package/dist/services/distribution/mcp-install.js +179 -0
- package/dist/services/distribution/plugin-manifest.d.ts +97 -0
- package/dist/services/distribution/plugin-manifest.js +126 -0
- package/dist/services/hooks/mcp-surface-gate.d.ts +19 -0
- package/dist/services/hooks/mcp-surface-gate.js +87 -0
- package/dist/services/ide/adapters/claude-code-adapter.d.ts +4 -35
- package/dist/services/ide/adapters/claude-code-adapter.js +48 -171
- package/dist/services/ide/adapters/claude-code-local-state.d.ts +28 -0
- package/dist/services/ide/adapters/claude-code-local-state.js +112 -0
- package/dist/services/ide/adapters/claude-code-model-window.d.ts +37 -0
- package/dist/services/ide/adapters/claude-code-model-window.js +113 -0
- package/dist/services/ide/ide-mcp-install-types.d.ts +78 -0
- package/dist/services/ide/ide-mcp-install-types.js +104 -0
- package/dist/services/ide/ide-types.d.ts +45 -1
- package/dist/services/ide/mcp-tool-matcher.d.ts +34 -0
- package/dist/services/ide/mcp-tool-matcher.js +84 -0
- package/dist/services/lint/npx-resolver.js +7 -0
- package/dist/services/mcp/cli-executor.d.ts +36 -0
- package/dist/services/mcp/cli-executor.js +97 -0
- package/dist/services/mcp/json-rpc.d.ts +81 -0
- package/dist/services/mcp/json-rpc.js +116 -0
- package/dist/services/mcp/memory-tool.d.ts +3 -0
- package/dist/services/mcp/memory-tool.js +62 -0
- package/dist/services/mcp/server-main.d.ts +1 -0
- package/dist/services/mcp/server-main.js +66 -0
- package/dist/services/mcp/server.d.ts +22 -0
- package/dist/services/mcp/server.js +152 -0
- package/dist/services/mcp/surface.d.ts +62 -0
- package/dist/services/mcp/surface.js +198 -0
- package/dist/services/mcp/tool-core.d.ts +42 -0
- package/dist/services/mcp/tool-core.js +137 -0
- package/dist/services/mcp/tools.d.ts +13 -0
- package/dist/services/mcp/tools.js +58 -0
- package/dist/services/readonly-surface/argv-guard.d.ts +32 -0
- package/dist/services/readonly-surface/argv-guard.js +164 -0
- package/dist/services/readonly-surface/readonly-whitelist.d.ts +147 -0
- package/dist/services/readonly-surface/readonly-whitelist.js +107 -0
- package/dist/services/readonly-surface/whitelist-generator.d.ts +64 -0
- package/dist/services/readonly-surface/whitelist-generator.js +212 -0
- package/dist/services/skills/hooks-codegate-superpowers.d.ts +1 -0
- package/dist/services/skills/hooks-codegate-superpowers.js +26 -0
- package/dist/services/skills/hooks-settings-service.js +10 -2
- package/package.json +17 -6
- package/scripts/install-skills-bundles.mjs +233 -0
- package/scripts/install-skills-fs.mjs +148 -0
- package/scripts/install-skills-ide.mjs +279 -0
- package/scripts/install-skills-output-style-default.mjs +196 -0
- package/scripts/install-skills-output-styles.mjs +121 -0
- package/scripts/install-skills-report.mjs +42 -0
- package/scripts/install-skills-user-config.mjs +198 -0
- package/scripts/install-skills.mjs +36 -1066
- package/scripts/watch-tree.mjs +140 -0
- package/scripts/watch.mjs +4 -126
- package/skills/peaks-status/SKILL.md +31 -13
|
@@ -20,31 +20,21 @@
|
|
|
20
20
|
*
|
|
21
21
|
* Defense in depth: the EvolutionService enforces the ratchet
|
|
22
22
|
* into the service payload.
|
|
23
|
+
*
|
|
24
|
+
* Size-debt split: each verb's registration and action body now lives
|
|
25
|
+
* in its own sibling module — `evolution-propose-command.ts`,
|
|
26
|
+
* `evolution-evaluate-command.ts`, `evolution-verdict-commands.ts`
|
|
27
|
+
* (mark-keep + revert) and `evolution-status-command.ts` — over the
|
|
28
|
+
* shared parse / validate / DB / failure helpers in
|
|
29
|
+
* `evolution-command-shared.ts`. This file keeps the parent and the
|
|
30
|
+
* delegation only; every command name, option, envelope key, error
|
|
31
|
+
* code and exit-code site is unchanged.
|
|
23
32
|
*/
|
|
24
|
-
import {
|
|
25
|
-
import {
|
|
26
|
-
import {
|
|
27
|
-
import {
|
|
28
|
-
import {
|
|
29
|
-
import { findProjectRoot } from '../../services/config/config-safety.js';
|
|
30
|
-
import { runIndependentEvaluator } from '../../services/evolution/independent-evaluator-runner.js';
|
|
31
|
-
import { addJsonOption, getErrorMessage, printResult } from '../cli-helpers.js';
|
|
32
|
-
import { fail, ok } from 'peaks-loop-shared/result';
|
|
33
|
-
/**
|
|
34
|
-
* Parse `--target <kind:id>`. Returns the kind + id, or `null` on
|
|
35
|
-
* failure. Validates `kind` against the EVOLUTION_TARGET_KINDS
|
|
36
|
-
* union.
|
|
37
|
-
*/
|
|
38
|
-
function parseTargetFlag(raw) {
|
|
39
|
-
const idx = raw.indexOf(':');
|
|
40
|
-
if (idx <= 0 || idx === raw.length - 1)
|
|
41
|
-
return null;
|
|
42
|
-
const kind = raw.slice(0, idx);
|
|
43
|
-
const id = raw.slice(idx + 1);
|
|
44
|
-
if (!EVOLUTION_TARGET_KINDS.includes(kind))
|
|
45
|
-
return null;
|
|
46
|
-
return { kind: kind, id };
|
|
47
|
-
}
|
|
33
|
+
import { dirname } from 'node:path';
|
|
34
|
+
import { registerEvaluateCommand } from './evolution-evaluate-command.js';
|
|
35
|
+
import { registerProposeCommand } from './evolution-propose-command.js';
|
|
36
|
+
import { registerStatusCommand } from './evolution-status-command.js';
|
|
37
|
+
import { registerMarkKeepCommand, registerRevertCommand } from './evolution-verdict-commands.js';
|
|
48
38
|
export function registerEvolutionCommands(program, io) {
|
|
49
39
|
// Reuse the existing `evolution` parent if one is registered;
|
|
50
40
|
// otherwise create it. The add-a-new-subcommand-check-for-existing-
|
|
@@ -54,333 +44,12 @@ export function registerEvolutionCommands(program, io) {
|
|
|
54
44
|
program
|
|
55
45
|
.command('evolution')
|
|
56
46
|
.description('Darwin-style ratchet: propose / evaluate / revert / status (spec §6)');
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
.requiredOption('--dimension <name>', "single optimization dimension (e.g. 'clarity')")
|
|
63
|
-
.requiredOption('--before-score <n>', 'score on the 0..10 scale BEFORE the change')
|
|
64
|
-
.requiredOption('--after-score <n>', 'score on the 0..10 scale AFTER the change (LLM-claimed)')
|
|
65
|
-
.option('--delta-min <n>', `minimum score delta for promotion (default: 1.0; spec §6.1 #5)`, '1.0')
|
|
66
|
-
.requiredOption('--author <id>', 'author agent id (the LLM proposing the change)')
|
|
67
|
-
.option('--brief-pointer <ptr>', 'pointer to the evidence brief used in the recommendation (spec §4.7 / §4.4)')
|
|
68
|
-
.option('--project <path>', 'project root (default: cwd)')).action((options) => {
|
|
69
|
-
try {
|
|
70
|
-
const target = parseTargetFlag(options.target);
|
|
71
|
-
if (!target) {
|
|
72
|
-
printResult(io, fail('evolution.propose', 'EVOLUTION_INVALID_TARGET', `--target must be '<kind>:<id>' where kind ∈ {${EVOLUTION_TARGET_KINDS.join(',')}}`, { target: options.target }, ['Pass --target loop:<loop-id> or --target bee:<bee-id>.']), options.json);
|
|
73
|
-
process.exitCode = 1;
|
|
74
|
-
return;
|
|
75
|
-
}
|
|
76
|
-
const before = Number(options.beforeScore);
|
|
77
|
-
const after = Number(options.afterScore);
|
|
78
|
-
const deltaMin = Number(options.deltaMin);
|
|
79
|
-
if (!Number.isFinite(before) || before < 0 || before > 10) {
|
|
80
|
-
printResult(io, fail('evolution.propose', 'EVOLUTION_INVALID_BEFORE_SCORE', `before_score must be a finite number in [0, 10] (got "${options.beforeScore}")`, { beforeScore: options.beforeScore }, ['Pass a numeric --before-score in [0, 10].']), options.json);
|
|
81
|
-
process.exitCode = 1;
|
|
82
|
-
return;
|
|
83
|
-
}
|
|
84
|
-
if (!Number.isFinite(after) || after < 0 || after > 10) {
|
|
85
|
-
printResult(io, fail('evolution.propose', 'EVOLUTION_INVALID_AFTER_SCORE', `after_score must be a finite number in [0, 10] (got "${options.afterScore}")`, { afterScore: options.afterScore }, ['Pass a numeric --after-score in [0, 10].']), options.json);
|
|
86
|
-
process.exitCode = 1;
|
|
87
|
-
return;
|
|
88
|
-
}
|
|
89
|
-
if (!Number.isFinite(deltaMin) || deltaMin < 0) {
|
|
90
|
-
printResult(io, fail('evolution.propose', 'EVOLUTION_INVALID_DELTA_MIN', `delta_min must be a finite number >= 0 (got "${options.deltaMin}")`, { deltaMin: options.deltaMin }, ['Pass a numeric --delta-min >= 0 (default 1.0).']), options.json);
|
|
91
|
-
process.exitCode = 1;
|
|
92
|
-
return;
|
|
93
|
-
}
|
|
94
|
-
const projectRoot = options.project ?? findProjectRoot(process.cwd()) ?? process.cwd();
|
|
95
|
-
if (!existsSync(join(projectRoot, '.peaks'))) {
|
|
96
|
-
// The CLI is allowed to bootstrap an empty .peaks dir so
|
|
97
|
-
// tests do not need a full peaks project.
|
|
98
|
-
mkdirSync(join(projectRoot, '.peaks'), { recursive: true });
|
|
99
|
-
}
|
|
100
|
-
const db = openStateDb(join(projectRoot, '.peaks', 'state.db'));
|
|
101
|
-
try {
|
|
102
|
-
const svc = new EvolutionService(db);
|
|
103
|
-
const input = {
|
|
104
|
-
target_kind: target.kind,
|
|
105
|
-
target_release_id: target.id,
|
|
106
|
-
optimization_dimension: options.dimension,
|
|
107
|
-
before_snapshot: {},
|
|
108
|
-
after_snapshot: { after_score: after },
|
|
109
|
-
diff: {},
|
|
110
|
-
before_score: before,
|
|
111
|
-
after_score: after,
|
|
112
|
-
score_delta_min: deltaMin,
|
|
113
|
-
author_id: options.author,
|
|
114
|
-
single_object: true,
|
|
115
|
-
single_optimization_dimension: true,
|
|
116
|
-
rubric: {},
|
|
117
|
-
red_lines: [],
|
|
118
|
-
source_traces: []
|
|
119
|
-
};
|
|
120
|
-
const proposal = svc.createProposal(input);
|
|
121
|
-
printResult(io, ok('evolution.propose', {
|
|
122
|
-
proposal: {
|
|
123
|
-
id: proposal.id,
|
|
124
|
-
target_kind: proposal.target_kind,
|
|
125
|
-
target_release_id: proposal.target_release_id,
|
|
126
|
-
optimization_dimension: proposal.optimization_dimension,
|
|
127
|
-
before_score: proposal.before_score,
|
|
128
|
-
after_score: proposal.after_score,
|
|
129
|
-
score_delta: proposal.score_delta,
|
|
130
|
-
score_delta_min: proposal.score_delta_min,
|
|
131
|
-
author_id: proposal.author_id,
|
|
132
|
-
verdict: 'needs-user-decision',
|
|
133
|
-
...(options.briefPointer !== undefined
|
|
134
|
-
? { brief_pointer: options.briefPointer }
|
|
135
|
-
: {})
|
|
136
|
-
},
|
|
137
|
-
nextActions: [
|
|
138
|
-
`Run \`peaks evolution evaluate --proposal ${proposal.id} --evaluator <id> --skeptic <id> --evaluator-score <n> --json\` to score the proposal.`
|
|
139
|
-
]
|
|
140
|
-
}, [], []), options.json);
|
|
141
|
-
}
|
|
142
|
-
finally {
|
|
143
|
-
db.close();
|
|
144
|
-
}
|
|
145
|
-
}
|
|
146
|
-
catch (err) {
|
|
147
|
-
if (err instanceof EvolutionIntegrityError) {
|
|
148
|
-
printResult(io, fail('evolution.propose', err.code, err.message, { findings: err.findings }, [
|
|
149
|
-
'Re-shape the proposal per spec §6: single object, single dimension, separate scorer.',
|
|
150
|
-
'If you intended a multi-object change, split it into multiple rounds.'
|
|
151
|
-
]), options.json);
|
|
152
|
-
process.exitCode = 1;
|
|
153
|
-
return;
|
|
154
|
-
}
|
|
155
|
-
printResult(io, fail('evolution.propose', 'EVOLUTION_PROPOSE_FAILED', getErrorMessage(err), {}, [
|
|
156
|
-
'Verify the target flag and dimension.'
|
|
157
|
-
]), options.json);
|
|
158
|
-
process.exitCode = 1;
|
|
159
|
-
}
|
|
160
|
-
});
|
|
161
|
-
// peaks evolution evaluate
|
|
162
|
-
addJsonOption(evolution
|
|
163
|
-
.command('evaluate')
|
|
164
|
-
.description("M4: score a proposal with an independent evaluator (AC-12/AC-13) and a regression skeptic (AC-14). The result is the FINAL verdict: 'keep' (after user confirmation), 'revert' (skeptic blocker or score delta below threshold), or 'needs-user-decision'.")
|
|
165
|
-
.requiredOption('--proposal <id>', 'proposal id returned by `peaks evolution propose`')
|
|
166
|
-
.requiredOption('--evaluator <id>', 'independent scorer id (MUST differ from --author; AC-10)')
|
|
167
|
-
.requiredOption('--skeptic <id>', 'regression skeptic id (MUST differ from --evaluator and --author; AC-12/AC-14)')
|
|
168
|
-
.requiredOption('--evaluator-score <n>', "the independent scorer's score on the 0..10 scale (LLM-derived; NOT the author's after_score)")
|
|
169
|
-
.option('--refute-paragraph <text>', "the independent scorer's one-paragraph refute (LLM-authored)", '')
|
|
170
|
-
.option('--risk-tag <tag>', 'add a risk tag emitted by the evaluator (repeatable)', collectRepeatable, [])
|
|
171
|
-
.option('--brief-pointer <ptr>', 'pointer to the evidence brief (spec §4.7 / §4.4)')
|
|
172
|
-
.option('--project <path>', 'project root (default: cwd)')).action(async (options) => {
|
|
173
|
-
try {
|
|
174
|
-
const score = Number(options.evaluatorScore);
|
|
175
|
-
if (!Number.isFinite(score) || score < 0 || score > 10) {
|
|
176
|
-
printResult(io, fail('evolution.evaluate', 'EVOLUTION_INVALID_EVALUATOR_SCORE', `evaluator-score must be a finite number in [0, 10] (got "${options.evaluatorScore}")`, { evaluatorScore: options.evaluatorScore }, ['Pass a numeric --evaluator-score in [0, 10].']), options.json);
|
|
177
|
-
process.exitCode = 1;
|
|
178
|
-
return;
|
|
179
|
-
}
|
|
180
|
-
const projectRoot = options.project ?? findProjectRoot(process.cwd()) ?? process.cwd();
|
|
181
|
-
if (!existsSync(join(projectRoot, '.peaks'))) {
|
|
182
|
-
mkdirSync(join(projectRoot, '.peaks'), { recursive: true });
|
|
183
|
-
}
|
|
184
|
-
const db = openStateDb(join(projectRoot, '.peaks', 'state.db'));
|
|
185
|
-
try {
|
|
186
|
-
const svc = new EvolutionService(db);
|
|
187
|
-
const proposal = svc.read(options.proposal);
|
|
188
|
-
if (!proposal) {
|
|
189
|
-
printResult(io, fail('evolution.evaluate', 'EVOLUTION_PROPOSAL_NOT_FOUND', `proposal '${options.proposal}' not found`, { proposalId: options.proposal }, ['Verify the proposal id and that you have run `peaks evolution propose` first.']), options.json);
|
|
190
|
-
process.exitCode = 1;
|
|
191
|
-
return;
|
|
192
|
-
}
|
|
193
|
-
// The CLI runs the deterministic LLM stubs (no live LLM in
|
|
194
|
-
// M4). Real LLM wiring lands in M5.
|
|
195
|
-
const evaluatorResult = await runIndependentEvaluator(proposal.proposal);
|
|
196
|
-
// Force the CLI-supplied --evaluator-score to be the
|
|
197
|
-
// final score; the LLM stub's score is informational.
|
|
198
|
-
evaluatorResult.score = score;
|
|
199
|
-
if (options.refuteParagraph && options.refuteParagraph.length > 0) {
|
|
200
|
-
evaluatorResult.refuteParagraph = options.refuteParagraph;
|
|
201
|
-
}
|
|
202
|
-
if (Array.isArray(options.riskTag) && options.riskTag.length > 0) {
|
|
203
|
-
evaluatorResult.riskTags = [...evaluatorResult.riskTags, ...options.riskTag];
|
|
204
|
-
}
|
|
205
|
-
const evaluation = svc.score(options.proposal, {
|
|
206
|
-
evaluator_id: options.evaluator,
|
|
207
|
-
skeptic_id: options.skeptic,
|
|
208
|
-
evaluator_result: evaluatorResult,
|
|
209
|
-
skeptic_result: {
|
|
210
|
-
driftRisks: [],
|
|
211
|
-
overfitRisks: [],
|
|
212
|
-
safetyRegressionRisks: []
|
|
213
|
-
},
|
|
214
|
-
...(options.briefPointer !== undefined ? { brief_pointer: options.briefPointer } : {})
|
|
215
|
-
});
|
|
216
|
-
printResult(io, ok('evolution.evaluate', {
|
|
217
|
-
proposalId: evaluation.id,
|
|
218
|
-
verdict: evaluation.verdict,
|
|
219
|
-
evaluator_id: evaluation.evaluator_id,
|
|
220
|
-
skeptic_id: evaluation.skeptic_id,
|
|
221
|
-
evaluator_result: evaluation.evaluator_result,
|
|
222
|
-
skeptic_result: evaluation.skeptic_result,
|
|
223
|
-
score_delta: evaluation.proposal.score_delta,
|
|
224
|
-
score_delta_min: evaluation.proposal.score_delta_min,
|
|
225
|
-
after_score: evaluation.proposal.after_score,
|
|
226
|
-
nextActions: evaluation.verdict === 'needs-user-decision'
|
|
227
|
-
? [
|
|
228
|
-
`User confirmation required. Run \`peaks evolution mark-keep --proposal ${evaluation.id} --user-confirmation <ptr> --json\` after the user picks "keep", OR \`peaks evolution revert --proposal ${evaluation.id} --json\`.`
|
|
229
|
-
]
|
|
230
|
-
: evaluation.verdict === 'revert'
|
|
231
|
-
? [
|
|
232
|
-
'Proposal reverted. Investigate the skeptic blocker or the score delta below threshold.'
|
|
233
|
-
]
|
|
234
|
-
: [
|
|
235
|
-
'Proposal kept. The target asset remains unchanged on disk; full promotion lands in a later slice.'
|
|
236
|
-
]
|
|
237
|
-
}, [], []), options.json);
|
|
238
|
-
if (evaluation.verdict === 'revert')
|
|
239
|
-
process.exitCode = 1;
|
|
240
|
-
}
|
|
241
|
-
finally {
|
|
242
|
-
db.close();
|
|
243
|
-
}
|
|
244
|
-
}
|
|
245
|
-
catch (err) {
|
|
246
|
-
if (err instanceof EvolutionIntegrityError) {
|
|
247
|
-
printResult(io, fail('evolution.evaluate', err.code, err.message, { findings: err.findings }, [
|
|
248
|
-
'Re-shape per spec §6: evaluator and skeptic MUST be separate from the author; the score delta MUST be >= score_delta_min for keep.'
|
|
249
|
-
]), options.json);
|
|
250
|
-
process.exitCode = 1;
|
|
251
|
-
return;
|
|
252
|
-
}
|
|
253
|
-
printResult(io, fail('evolution.evaluate', 'EVOLUTION_EVALUATE_FAILED', getErrorMessage(err), { proposalId: options.proposal }, ['Verify the proposal id and the evaluator / skeptic ids.']), options.json);
|
|
254
|
-
process.exitCode = 1;
|
|
255
|
-
}
|
|
256
|
-
});
|
|
257
|
-
// peaks evolution mark-keep — explicit user confirmation.
|
|
258
|
-
addJsonOption(evolution
|
|
259
|
-
.command('mark-keep')
|
|
260
|
-
.description('M4: explicit user-confirmed `keep` verdict. Requires --user-confirmation <ptr> and a score_delta >= score_delta_min (AC-11/AC-15).')
|
|
261
|
-
.requiredOption('--proposal <id>', 'proposal id')
|
|
262
|
-
.option('--user-confirmation <ptr>', 'pointer to the user choice record (AC-15) — omit to surface the EVOLUTION_MISSING_USER_CONFIRMATION service-layer error')
|
|
263
|
-
.option('--project <path>', 'project root (default: cwd)')).action((options) => {
|
|
264
|
-
try {
|
|
265
|
-
const projectRoot = options.project ?? findProjectRoot(process.cwd()) ?? process.cwd();
|
|
266
|
-
if (!existsSync(join(projectRoot, '.peaks'))) {
|
|
267
|
-
mkdirSync(join(projectRoot, '.peaks'), { recursive: true });
|
|
268
|
-
}
|
|
269
|
-
const db = openStateDb(join(projectRoot, '.peaks', 'state.db'));
|
|
270
|
-
try {
|
|
271
|
-
const svc = new EvolutionService(db);
|
|
272
|
-
const updated = svc.markVerdict(options.proposal, 'keep', options.userConfirmation);
|
|
273
|
-
if (!updated) {
|
|
274
|
-
printResult(io, fail('evolution.mark-keep', 'EVOLUTION_PROPOSAL_NOT_FOUND', `proposal '${options.proposal}' not found`, { proposalId: options.proposal }, ['Verify the proposal id.']), options.json);
|
|
275
|
-
process.exitCode = 1;
|
|
276
|
-
return;
|
|
277
|
-
}
|
|
278
|
-
printResult(io, ok('evolution.mark-keep', {
|
|
279
|
-
proposalId: updated.id,
|
|
280
|
-
verdict: updated.verdict,
|
|
281
|
-
user_confirmation_pointer: updated.user_confirmation_pointer ?? null,
|
|
282
|
-
score_delta: updated.proposal.score_delta,
|
|
283
|
-
score_delta_min: updated.proposal.score_delta_min
|
|
284
|
-
}, [], []), options.json);
|
|
285
|
-
}
|
|
286
|
-
finally {
|
|
287
|
-
db.close();
|
|
288
|
-
}
|
|
289
|
-
}
|
|
290
|
-
catch (err) {
|
|
291
|
-
if (err instanceof EvolutionIntegrityError) {
|
|
292
|
-
printResult(io, fail('evolution.mark-keep', err.code, err.message, { findings: err.findings }, [
|
|
293
|
-
'Re-shape the proposal or the score so score_delta >= score_delta_min.'
|
|
294
|
-
]), options.json);
|
|
295
|
-
process.exitCode = 1;
|
|
296
|
-
return;
|
|
297
|
-
}
|
|
298
|
-
printResult(io, fail('evolution.mark-keep', 'EVOLUTION_MARK_KEEP_FAILED', getErrorMessage(err), { proposalId: options.proposal }, ['Verify the proposal id.']), options.json);
|
|
299
|
-
process.exitCode = 1;
|
|
300
|
-
}
|
|
301
|
-
});
|
|
302
|
-
// peaks evolution revert
|
|
303
|
-
addJsonOption(evolution
|
|
304
|
-
.command('revert')
|
|
305
|
-
.description('M4: revert a proposal (universal recovery; spec §6.1 #8). Always allowed; the user may supply --user-confirmation for audit.')
|
|
306
|
-
.requiredOption('--proposal <id>', 'proposal id')
|
|
307
|
-
.option('--user-confirmation <ptr>', 'optional pointer to the user choice record')
|
|
308
|
-
.option('--project <path>', 'project root (default: cwd)')).action((options) => {
|
|
309
|
-
try {
|
|
310
|
-
const projectRoot = options.project ?? findProjectRoot(process.cwd()) ?? process.cwd();
|
|
311
|
-
if (!existsSync(join(projectRoot, '.peaks'))) {
|
|
312
|
-
mkdirSync(join(projectRoot, '.peaks'), { recursive: true });
|
|
313
|
-
}
|
|
314
|
-
const db = openStateDb(join(projectRoot, '.peaks', 'state.db'));
|
|
315
|
-
try {
|
|
316
|
-
const svc = new EvolutionService(db);
|
|
317
|
-
const updated = svc.revert(options.proposal, options.userConfirmation);
|
|
318
|
-
if (!updated) {
|
|
319
|
-
printResult(io, fail('evolution.revert', 'EVOLUTION_PROPOSAL_NOT_FOUND', `proposal '${options.proposal}' not found`, { proposalId: options.proposal }, ['Verify the proposal id.']), options.json);
|
|
320
|
-
process.exitCode = 1;
|
|
321
|
-
return;
|
|
322
|
-
}
|
|
323
|
-
printResult(io, ok('evolution.revert', {
|
|
324
|
-
proposalId: updated.id,
|
|
325
|
-
verdict: updated.verdict,
|
|
326
|
-
user_confirmation_pointer: updated.user_confirmation_pointer ?? null
|
|
327
|
-
}, [], []), options.json);
|
|
328
|
-
}
|
|
329
|
-
finally {
|
|
330
|
-
db.close();
|
|
331
|
-
}
|
|
332
|
-
}
|
|
333
|
-
catch (err) {
|
|
334
|
-
printResult(io, fail('evolution.revert', 'EVOLUTION_REVERT_FAILED', getErrorMessage(err), { proposalId: options.proposal }, ['Verify the proposal id.']), options.json);
|
|
335
|
-
process.exitCode = 1;
|
|
336
|
-
}
|
|
337
|
-
});
|
|
338
|
-
// peaks evolution status
|
|
339
|
-
addJsonOption(evolution
|
|
340
|
-
.command('status')
|
|
341
|
-
.description('M4: read the status snapshot for a target (counts of evaluations by verdict + latest evaluation id).')
|
|
342
|
-
.requiredOption('--target <kind:id>', "target asset, e.g. 'loop:loop-onboarding-research'")
|
|
343
|
-
.option('--project <path>', 'project root (default: cwd)')).action((options) => {
|
|
344
|
-
try {
|
|
345
|
-
const target = parseTargetFlag(options.target);
|
|
346
|
-
if (!target) {
|
|
347
|
-
printResult(io, fail('evolution.status', 'EVOLUTION_INVALID_TARGET', `--target must be '<kind>:<id>' where kind ∈ {${EVOLUTION_TARGET_KINDS.join(',')}}`, { target: options.target }, ['Pass --target loop:<loop-id> or --target bee:<bee-id>.']), options.json);
|
|
348
|
-
process.exitCode = 1;
|
|
349
|
-
return;
|
|
350
|
-
}
|
|
351
|
-
const projectRoot = options.project ?? findProjectRoot(process.cwd()) ?? process.cwd();
|
|
352
|
-
if (!existsSync(join(projectRoot, '.peaks'))) {
|
|
353
|
-
mkdirSync(join(projectRoot, '.peaks'), { recursive: true });
|
|
354
|
-
}
|
|
355
|
-
const db = openStateDb(join(projectRoot, '.peaks', 'state.db'));
|
|
356
|
-
try {
|
|
357
|
-
const svc = new EvolutionService(db);
|
|
358
|
-
const status = svc.status({
|
|
359
|
-
target_kind: target.kind,
|
|
360
|
-
target_release_id: target.id
|
|
361
|
-
});
|
|
362
|
-
printResult(io, ok('evolution.status', status, [], []), options.json);
|
|
363
|
-
}
|
|
364
|
-
finally {
|
|
365
|
-
db.close();
|
|
366
|
-
}
|
|
367
|
-
}
|
|
368
|
-
catch (err) {
|
|
369
|
-
printResult(io, fail('evolution.status', 'EVOLUTION_STATUS_FAILED', getErrorMessage(err), { target: options.target }, ['Verify the target flag.']), options.json);
|
|
370
|
-
process.exitCode = 1;
|
|
371
|
-
}
|
|
372
|
-
});
|
|
47
|
+
registerProposeCommand(evolution, io);
|
|
48
|
+
registerEvaluateCommand(evolution, io);
|
|
49
|
+
registerMarkKeepCommand(evolution, io);
|
|
50
|
+
registerRevertCommand(evolution, io);
|
|
51
|
+
registerStatusCommand(evolution, io);
|
|
373
52
|
// Suppress unused-var warnings for the dirname import; it is
|
|
374
53
|
// reserved for the M5 path-pointer materialization.
|
|
375
54
|
void dirname;
|
|
376
55
|
}
|
|
377
|
-
/**
|
|
378
|
-
* Helper: collect repeatable `--risk-tag` values into an array.
|
|
379
|
-
* Commander's `collect` is not always available; we read
|
|
380
|
-
* `previous` from the default value.
|
|
381
|
-
*/
|
|
382
|
-
function collectRepeatable(value, previous) {
|
|
383
|
-
if (Array.isArray(previous))
|
|
384
|
-
return [...previous, value];
|
|
385
|
-
return [value];
|
|
386
|
-
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `peaks evolution evaluate` — M4 / spec §6 / §7.4.
|
|
3
|
+
* Split out of `evolution-commands.ts`: the option surface, the
|
|
4
|
+
* envelope keys, the error codes and the exit-code sites are
|
|
5
|
+
* unchanged.
|
|
6
|
+
*/
|
|
7
|
+
import type { Command } from 'commander';
|
|
8
|
+
import { type ProgramIO } from '../cli-helpers.js';
|
|
9
|
+
/** The `--options` Commander hands to the `evaluate` action. */
|
|
10
|
+
export interface EvaluateOptions {
|
|
11
|
+
proposal: string;
|
|
12
|
+
evaluator: string;
|
|
13
|
+
skeptic: string;
|
|
14
|
+
evaluatorScore: string;
|
|
15
|
+
refuteParagraph?: string;
|
|
16
|
+
riskTag: string[];
|
|
17
|
+
briefPointer?: string;
|
|
18
|
+
project?: string;
|
|
19
|
+
json?: boolean;
|
|
20
|
+
}
|
|
21
|
+
/** The `evaluate` action body. */
|
|
22
|
+
export declare function runEvaluate(options: EvaluateOptions, io: ProgramIO): Promise<void>;
|
|
23
|
+
/** Register `peaks evolution evaluate` on the `evolution` parent. */
|
|
24
|
+
export declare function registerEvaluateCommand(evolution: Command, io: ProgramIO): void;
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
import { EvolutionIntegrityError } from '../../services/evolution/evolution-service.js';
|
|
2
|
+
import { runIndependentEvaluator } from '../../services/evolution/independent-evaluator-runner.js';
|
|
3
|
+
import { addJsonOption, printResult } from '../cli-helpers.js';
|
|
4
|
+
import { ok } from 'peaks-loop-shared/result';
|
|
5
|
+
import { collectRepeatable, isScoreInRange, proposalNotFoundFailure, reportFailure, reportIntegrityFailure, scoreRangeFailure, withEvolutionDbAsync } from './evolution-command-shared.js';
|
|
6
|
+
const EVALUATE_DESCRIPTION = "M4: score a proposal with an independent evaluator (AC-12/AC-13) and a regression skeptic (AC-14). The result is the FINAL verdict: 'keep' (after user confirmation), 'revert' (skeptic blocker or score delta below threshold), or 'needs-user-decision'.";
|
|
7
|
+
/** The `svc.score(...)` argument object, built from the CLI flags. */
|
|
8
|
+
function evaluateScoreArgs(options, evaluatorResult) {
|
|
9
|
+
return {
|
|
10
|
+
evaluator_id: options.evaluator,
|
|
11
|
+
skeptic_id: options.skeptic,
|
|
12
|
+
evaluator_result: evaluatorResult,
|
|
13
|
+
skeptic_result: {
|
|
14
|
+
driftRisks: [],
|
|
15
|
+
overfitRisks: [],
|
|
16
|
+
safetyRegressionRisks: []
|
|
17
|
+
},
|
|
18
|
+
...(options.briefPointer !== undefined ? { brief_pointer: options.briefPointer } : {})
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
/** The `nextActions` the final verdict implies (unchanged wording). */
|
|
22
|
+
function evaluateNextActions(evaluation) {
|
|
23
|
+
if (evaluation.verdict === 'needs-user-decision') {
|
|
24
|
+
return [
|
|
25
|
+
`User confirmation required. Run \`peaks evolution mark-keep --proposal ${evaluation.id} --user-confirmation <ptr> --json\` after the user picks "keep", OR \`peaks evolution revert --proposal ${evaluation.id} --json\`.`
|
|
26
|
+
];
|
|
27
|
+
}
|
|
28
|
+
if (evaluation.verdict === 'revert') {
|
|
29
|
+
return [
|
|
30
|
+
'Proposal reverted. Investigate the skeptic blocker or the score delta below threshold.'
|
|
31
|
+
];
|
|
32
|
+
}
|
|
33
|
+
return [
|
|
34
|
+
'Proposal kept. The target asset remains unchanged on disk; full promotion lands in a later slice.'
|
|
35
|
+
];
|
|
36
|
+
}
|
|
37
|
+
/** The `ok(...)` `data` payload for a completed evaluation. */
|
|
38
|
+
function evaluateEnvelopeData(evaluation) {
|
|
39
|
+
return {
|
|
40
|
+
proposalId: evaluation.id,
|
|
41
|
+
verdict: evaluation.verdict,
|
|
42
|
+
evaluator_id: evaluation.evaluator_id,
|
|
43
|
+
skeptic_id: evaluation.skeptic_id,
|
|
44
|
+
evaluator_result: evaluation.evaluator_result,
|
|
45
|
+
skeptic_result: evaluation.skeptic_result,
|
|
46
|
+
score_delta: evaluation.proposal.score_delta,
|
|
47
|
+
score_delta_min: evaluation.proposal.score_delta_min,
|
|
48
|
+
after_score: evaluation.proposal.after_score,
|
|
49
|
+
nextActions: evaluateNextActions(evaluation)
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
/** Print the evaluate failure envelope for `err` and set exit code 1. */
|
|
53
|
+
function reportEvaluateFailure(io, err, options) {
|
|
54
|
+
if (err instanceof EvolutionIntegrityError) {
|
|
55
|
+
reportIntegrityFailure({
|
|
56
|
+
io,
|
|
57
|
+
command: 'evolution.evaluate',
|
|
58
|
+
error: err,
|
|
59
|
+
nextActions: [
|
|
60
|
+
'Re-shape per spec §6: evaluator and skeptic MUST be separate from the author; the score delta MUST be >= score_delta_min for keep.'
|
|
61
|
+
],
|
|
62
|
+
asJson: options.json
|
|
63
|
+
});
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
reportFailure({
|
|
67
|
+
io,
|
|
68
|
+
command: 'evolution.evaluate',
|
|
69
|
+
code: 'EVOLUTION_EVALUATE_FAILED',
|
|
70
|
+
error: err,
|
|
71
|
+
data: { proposalId: options.proposal },
|
|
72
|
+
nextActions: ['Verify the proposal id and the evaluator / skeptic ids.'],
|
|
73
|
+
asJson: options.json
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
/** The service-side half of the `evaluate` action, inside the open DB scope. */
|
|
77
|
+
async function evaluateWithinService(svc, options, score, io) {
|
|
78
|
+
const evaluation = svc.read(options.proposal);
|
|
79
|
+
if (!evaluation) {
|
|
80
|
+
printResult(io, proposalNotFoundFailure('evolution.evaluate', options.proposal, [
|
|
81
|
+
'Verify the proposal id and that you have run `peaks evolution propose` first.'
|
|
82
|
+
]), options.json);
|
|
83
|
+
process.exitCode = 1;
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
86
|
+
// The CLI runs the deterministic LLM stubs (no live LLM in M4).
|
|
87
|
+
// Real LLM wiring lands in M5.
|
|
88
|
+
const evaluatorResult = await runIndependentEvaluator(evaluation.proposal);
|
|
89
|
+
// Force the CLI-supplied --evaluator-score to be the final score;
|
|
90
|
+
// the LLM stub's score is informational.
|
|
91
|
+
evaluatorResult.score = score;
|
|
92
|
+
if (options.refuteParagraph && options.refuteParagraph.length > 0) {
|
|
93
|
+
evaluatorResult.refuteParagraph = options.refuteParagraph;
|
|
94
|
+
}
|
|
95
|
+
if (Array.isArray(options.riskTag) && options.riskTag.length > 0) {
|
|
96
|
+
evaluatorResult.riskTags = [...evaluatorResult.riskTags, ...options.riskTag];
|
|
97
|
+
}
|
|
98
|
+
const scored = svc.score(options.proposal, evaluateScoreArgs(options, evaluatorResult));
|
|
99
|
+
printResult(io, ok('evolution.evaluate', evaluateEnvelopeData(scored), [], []), options.json);
|
|
100
|
+
if (scored.verdict === 'revert')
|
|
101
|
+
process.exitCode = 1;
|
|
102
|
+
}
|
|
103
|
+
/** The `evaluate` action body. */
|
|
104
|
+
export async function runEvaluate(options, io) {
|
|
105
|
+
try {
|
|
106
|
+
const score = Number(options.evaluatorScore);
|
|
107
|
+
if (!isScoreInRange(score)) {
|
|
108
|
+
printResult(io, scoreRangeFailure({
|
|
109
|
+
command: 'evolution.evaluate',
|
|
110
|
+
code: 'EVOLUTION_INVALID_EVALUATOR_SCORE',
|
|
111
|
+
label: 'evaluator-score',
|
|
112
|
+
flag: '--evaluator-score',
|
|
113
|
+
key: 'evaluatorScore',
|
|
114
|
+
raw: options.evaluatorScore
|
|
115
|
+
}), options.json);
|
|
116
|
+
process.exitCode = 1;
|
|
117
|
+
return;
|
|
118
|
+
}
|
|
119
|
+
await withEvolutionDbAsync(options.project, (svc) => evaluateWithinService(svc, options, score, io));
|
|
120
|
+
}
|
|
121
|
+
catch (err) {
|
|
122
|
+
reportEvaluateFailure(io, err, options);
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
/** Register `peaks evolution evaluate` on the `evolution` parent. */
|
|
126
|
+
export function registerEvaluateCommand(evolution, io) {
|
|
127
|
+
addJsonOption(evolution
|
|
128
|
+
.command('evaluate')
|
|
129
|
+
.description(EVALUATE_DESCRIPTION)
|
|
130
|
+
.requiredOption('--proposal <id>', 'proposal id returned by `peaks evolution propose`')
|
|
131
|
+
.requiredOption('--evaluator <id>', 'independent scorer id (MUST differ from --author; AC-10)')
|
|
132
|
+
.requiredOption('--skeptic <id>', 'regression skeptic id (MUST differ from --evaluator and --author; AC-12/AC-14)')
|
|
133
|
+
.requiredOption('--evaluator-score <n>', "the independent scorer's score on the 0..10 scale (LLM-derived; NOT the author's after_score)")
|
|
134
|
+
.option('--refute-paragraph <text>', "the independent scorer's one-paragraph refute (LLM-authored)", '')
|
|
135
|
+
.option('--risk-tag <tag>', 'add a risk tag emitted by the evaluator (repeatable)', collectRepeatable, [])
|
|
136
|
+
.option('--brief-pointer <ptr>', 'pointer to the evidence brief (spec §4.7 / §4.4)')
|
|
137
|
+
.option('--project <path>', 'project root (default: cwd)')).action((options) => runEvaluate(options, io));
|
|
138
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `peaks evolution propose` — M4 / spec §4.4 / §6.1 #5. Split out of
|
|
3
|
+
* `evolution-commands.ts`: the option surface, the envelope keys and
|
|
4
|
+
* the exit-code sites are unchanged.
|
|
5
|
+
*/
|
|
6
|
+
import type { Command } from 'commander';
|
|
7
|
+
import { type ProgramIO } from '../cli-helpers.js';
|
|
8
|
+
/** The `--options` Commander hands to the `propose` action. */
|
|
9
|
+
export interface ProposeOptions {
|
|
10
|
+
target: string;
|
|
11
|
+
dimension: string;
|
|
12
|
+
beforeScore: string;
|
|
13
|
+
afterScore: string;
|
|
14
|
+
deltaMin: string;
|
|
15
|
+
author: string;
|
|
16
|
+
briefPointer?: string;
|
|
17
|
+
project?: string;
|
|
18
|
+
json?: boolean;
|
|
19
|
+
}
|
|
20
|
+
/** The `propose` action body. */
|
|
21
|
+
export declare function runPropose(options: ProposeOptions, io: ProgramIO): void;
|
|
22
|
+
/** Register `peaks evolution propose` on the `evolution` parent. */
|
|
23
|
+
export declare function registerProposeCommand(evolution: Command, io: ProgramIO): void;
|