peaks-loop 4.1.3 → 4.1.4
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 +2 -2
- package/CHANGELOG.md +56 -0
- package/README-en.md +1 -1
- package/README.md +1 -1
- package/dist/cli/commands/asset-command-shared.d.ts +12 -0
- package/dist/cli/commands/asset-command-shared.js +45 -0
- package/dist/cli/commands/asset-commands.d.ts +6 -1
- package/dist/cli/commands/asset-commands.js +11 -372
- package/dist/cli/commands/asset-crystallize-command.d.ts +3 -0
- package/dist/cli/commands/asset-crystallize-command.js +60 -0
- package/dist/cli/commands/asset-crystallize-payload.d.ts +47 -0
- package/dist/cli/commands/asset-crystallize-payload.js +85 -0
- package/dist/cli/commands/asset-crystallize-runner.d.ts +3 -0
- package/dist/cli/commands/asset-crystallize-runner.js +133 -0
- package/dist/cli/commands/asset-dispose-command.d.ts +3 -0
- package/dist/cli/commands/asset-dispose-command.js +99 -0
- package/dist/cli/commands/asset-status-command.d.ts +3 -0
- package/dist/cli/commands/asset-status-command.js +100 -0
- package/dist/cli/commands/baseline-audit-command.d.ts +3 -0
- package/dist/cli/commands/baseline-audit-command.js +64 -0
- package/dist/cli/commands/baseline-command-shared.d.ts +23 -0
- package/dist/cli/commands/baseline-command-shared.js +39 -0
- package/dist/cli/commands/baseline-commands.js +33 -313
- package/dist/cli/commands/baseline-freeze-commands.d.ts +4 -0
- package/dist/cli/commands/baseline-freeze-commands.js +81 -0
- package/dist/cli/commands/baseline-guard-command.d.ts +3 -0
- package/dist/cli/commands/baseline-guard-command.js +52 -0
- package/dist/cli/commands/baseline-read-commands.d.ts +5 -0
- package/dist/cli/commands/baseline-read-commands.js +72 -0
- package/dist/cli/commands/baseline-rollback-commands.d.ts +4 -0
- package/dist/cli/commands/baseline-rollback-commands.js +88 -0
- package/dist/cli/commands/classify-downgrade-command.d.ts +9 -0
- package/dist/cli/commands/classify-downgrade-command.js +21 -0
- package/dist/cli/commands/classify-run-command.d.ts +9 -0
- package/dist/cli/commands/classify-run-command.js +73 -0
- package/dist/cli/commands/classify-signals.d.ts +5 -0
- package/dist/cli/commands/classify-signals.js +104 -0
- package/dist/cli/commands/code-emit-handoff-command.js +40 -3
- package/dist/cli/commands/code-gate-step-08-command.js +25 -9
- package/dist/cli/commands/codegraph-command-options.d.ts +22 -0
- package/dist/cli/commands/codegraph-command-options.js +22 -0
- package/dist/cli/commands/codegraph-commands.d.ts +2 -2
- package/dist/cli/commands/codegraph-commands.js +14 -397
- package/dist/cli/commands/codegraph-config-restore-command.d.ts +3 -0
- package/dist/cli/commands/codegraph-config-restore-command.js +200 -0
- package/dist/cli/commands/codegraph-proxy-commands.d.ts +10 -0
- package/dist/cli/commands/codegraph-proxy-commands.js +159 -0
- package/dist/cli/commands/codegraph-repair-commands.d.ts +3 -0
- package/dist/cli/commands/codegraph-repair-commands.js +94 -0
- package/dist/cli/commands/codegraph-status-command.d.ts +1 -1
- package/dist/cli/commands/codegraph-status-command.js +27 -214
- package/dist/cli/commands/codegraph-status-integrity.d.ts +44 -0
- package/dist/cli/commands/codegraph-status-integrity.js +121 -0
- package/dist/cli/commands/codegraph-status-json.d.ts +5 -0
- package/dist/cli/commands/codegraph-status-json.js +127 -0
- package/dist/cli/commands/container-command-shared.d.ts +60 -0
- package/dist/cli/commands/container-command-shared.js +52 -0
- package/dist/cli/commands/container-commands.d.ts +1 -1
- package/dist/cli/commands/container-commands.js +4 -216
- package/dist/cli/commands/container-release-command.d.ts +3 -0
- package/dist/cli/commands/container-release-command.js +105 -0
- package/dist/cli/commands/container-spawn-command.d.ts +3 -0
- package/dist/cli/commands/container-spawn-command.js +148 -0
- package/dist/cli/commands/context-check-command.d.ts +3 -0
- package/dist/cli/commands/context-check-command.js +81 -0
- package/dist/cli/commands/context-commands.d.ts +2 -7
- package/dist/cli/commands/context-commands.js +6 -276
- package/dist/cli/commands/context-layer-command.d.ts +3 -0
- package/dist/cli/commands/context-layer-command.js +34 -0
- package/dist/cli/commands/context-layer-fetchers.d.ts +15 -0
- package/dist/cli/commands/context-layer-fetchers.js +162 -0
- package/dist/cli/commands/context-status-command.d.ts +17 -0
- package/dist/cli/commands/context-status-command.js +41 -0
- package/dist/cli/commands/contract-write-command.d.ts +3 -0
- package/dist/cli/commands/contract-write-command.js +144 -0
- package/dist/cli/commands/core/doctor-bindings.d.ts +17 -0
- package/dist/cli/commands/core/doctor-bindings.js +30 -0
- package/dist/cli/commands/core/doctor-command.d.ts +4 -18
- package/dist/cli/commands/core/doctor-command.js +2 -323
- package/dist/cli/commands/core/doctor-logs.d.ts +8 -0
- package/dist/cli/commands/core/doctor-logs.js +32 -0
- package/dist/cli/commands/core/doctor-probes.d.ts +3 -0
- package/dist/cli/commands/core/doctor-probes.js +55 -0
- package/dist/cli/commands/core/doctor-run-command.d.ts +12 -0
- package/dist/cli/commands/core/doctor-run-command.js +172 -0
- package/dist/cli/commands/core/doctor-summary.d.ts +7 -0
- package/dist/cli/commands/core/doctor-summary.js +39 -0
- package/dist/cli/commands/core/memory-command-shared.d.ts +25 -0
- package/dist/cli/commands/core/memory-command-shared.js +20 -0
- package/dist/cli/commands/core/memory-command.d.ts +1 -1
- package/dist/cli/commands/core/memory-command.js +6 -227
- package/dist/cli/commands/core/memory-delegated-verbs.d.ts +4 -0
- package/dist/cli/commands/core/memory-delegated-verbs.js +178 -0
- package/dist/cli/commands/core/memory-extract-command.d.ts +3 -0
- package/dist/cli/commands/core/memory-extract-command.js +90 -0
- package/dist/cli/commands/core/memory-sync-command.d.ts +3 -0
- package/dist/cli/commands/core/memory-sync-command.js +38 -0
- package/dist/cli/commands/core/session-command.d.ts +1 -1
- package/dist/cli/commands/core/session-command.js +12 -206
- package/dist/cli/commands/core/session-info-command.d.ts +3 -0
- package/dist/cli/commands/core/session-info-command.js +142 -0
- package/dist/cli/commands/core/session-verb-commands.d.ts +5 -0
- package/dist/cli/commands/core/session-verb-commands.js +58 -0
- package/dist/cli/commands/core/standards-command.d.ts +1 -24
- package/dist/cli/commands/core/standards-command.js +33 -201
- package/dist/cli/commands/core/standards-init-command.d.ts +3 -0
- package/dist/cli/commands/core/standards-init-command.js +87 -0
- package/dist/cli/commands/core/standards-lint.d.ts +24 -0
- package/dist/cli/commands/core/standards-lint.js +57 -0
- package/dist/cli/commands/core/standards-migrate-command.d.ts +3 -0
- package/dist/cli/commands/core/standards-migrate-command.js +57 -0
- package/dist/cli/commands/cron-scheduler-commands.d.ts +5 -1
- package/dist/cli/commands/cron-scheduler-commands.js +36 -206
- package/dist/cli/commands/cron-scheduler-run-once-command.d.ts +7 -0
- package/dist/cli/commands/cron-scheduler-run-once-command.js +35 -0
- package/dist/cli/commands/cron-scheduler-shared.d.ts +6 -0
- package/dist/cli/commands/cron-scheduler-shared.js +48 -0
- package/dist/cli/commands/cron-scheduler-start-command.d.ts +7 -0
- package/dist/cli/commands/cron-scheduler-start-command.js +65 -0
- package/dist/cli/commands/cron-scheduler-status-command.d.ts +7 -0
- package/dist/cli/commands/cron-scheduler-status-command.js +46 -0
- package/dist/cli/commands/cron-scheduler-stop-command.d.ts +7 -0
- package/dist/cli/commands/cron-scheduler-stop-command.js +61 -0
- package/dist/cli/commands/dispatch-dag-envelope.d.ts +41 -0
- package/dist/cli/commands/dispatch-dag-envelope.js +49 -0
- package/dist/cli/commands/dispatch-dag-failure.d.ts +18 -0
- package/dist/cli/commands/dispatch-dag-failure.js +16 -0
- package/dist/cli/commands/dispatch-dag-preflight.d.ts +51 -0
- package/dist/cli/commands/dispatch-dag-preflight.js +105 -0
- package/dist/cli/commands/dispatch-dag-runners.d.ts +48 -0
- package/dist/cli/commands/dispatch-dag-runners.js +73 -0
- package/dist/cli/commands/dispatch-from-dag.d.ts +27 -0
- package/dist/cli/commands/dispatch-from-dag.js +87 -257
- package/dist/cli/commands/final-review-command-envelopes.d.ts +44 -0
- package/dist/cli/commands/final-review-command-envelopes.js +100 -0
- package/dist/cli/commands/final-review-command-shared.d.ts +52 -0
- package/dist/cli/commands/final-review-command-shared.js +35 -0
- package/dist/cli/commands/final-review-commands.d.ts +7 -27
- package/dist/cli/commands/final-review-commands.js +13 -240
- package/dist/cli/commands/final-review-prepare-command.d.ts +3 -0
- package/dist/cli/commands/final-review-prepare-command.js +200 -0
- package/dist/cli/commands/governance-classify-contract-commands.d.ts +23 -9
- package/dist/cli/commands/governance-classify-contract-commands.js +26 -269
- package/dist/cli/commands/hooks-command-shared.d.ts +42 -0
- package/dist/cli/commands/hooks-command-shared.js +32 -0
- package/dist/cli/commands/hooks-commands.d.ts +20 -0
- package/dist/cli/commands/hooks-commands.js +75 -309
- package/dist/cli/commands/hooks-install-envelopes.d.ts +6 -0
- package/dist/cli/commands/hooks-install-envelopes.js +144 -0
- package/dist/cli/commands/hooks-status-command.d.ts +3 -0
- package/dist/cli/commands/hooks-status-command.js +93 -0
- package/dist/cli/commands/hooks-uninstall-command.d.ts +3 -0
- package/dist/cli/commands/hooks-uninstall-command.js +43 -0
- package/dist/cli/commands/loop-command-shared.d.ts +31 -0
- package/dist/cli/commands/loop-command-shared.js +15 -0
- package/dist/cli/commands/loop-commands.d.ts +12 -17
- package/dist/cli/commands/loop-commands.js +56 -238
- package/dist/cli/commands/loop-export-command.d.ts +3 -0
- package/dist/cli/commands/loop-export-command.js +73 -0
- package/dist/cli/commands/loop-goal-compose-command.d.ts +3 -0
- package/dist/cli/commands/loop-goal-compose-command.js +36 -0
- package/dist/cli/commands/loop-import-command.d.ts +3 -0
- package/dist/cli/commands/loop-import-command.js +86 -0
- package/dist/cli/commands/loop-placeholder-commands.d.ts +3 -0
- package/dist/cli/commands/loop-placeholder-commands.js +52 -0
- package/dist/cli/commands/memory-command-shared.d.ts +59 -0
- package/dist/cli/commands/memory-command-shared.js +39 -0
- package/dist/cli/commands/memory-commands.d.ts +6 -79
- package/dist/cli/commands/memory-commands.js +19 -309
- package/dist/cli/commands/memory-ingest-command.d.ts +3 -0
- package/dist/cli/commands/memory-ingest-command.js +50 -0
- package/dist/cli/commands/memory-list-command.d.ts +16 -0
- package/dist/cli/commands/memory-list-command.js +129 -0
- package/dist/cli/commands/memory-reindex-command.d.ts +9 -0
- package/dist/cli/commands/memory-reindex-command.js +78 -0
- package/dist/cli/commands/memory-rotate-command.d.ts +3 -0
- package/dist/cli/commands/memory-rotate-command.js +55 -0
- package/dist/cli/commands/memory-search-command.d.ts +7 -0
- package/dist/cli/commands/memory-search-command.js +46 -0
- package/dist/cli/commands/openspec-archive-command.d.ts +3 -0
- package/dist/cli/commands/openspec-archive-command.js +55 -0
- package/dist/cli/commands/openspec-command-shared.d.ts +62 -0
- package/dist/cli/commands/openspec-command-shared.js +135 -0
- package/dist/cli/commands/openspec-commands.d.ts +1 -1
- package/dist/cli/commands/openspec-commands.js +33 -306
- package/dist/cli/commands/openspec-from-doctor-command.d.ts +3 -0
- package/dist/cli/commands/openspec-from-doctor-command.js +66 -0
- package/dist/cli/commands/openspec-init-command.d.ts +3 -0
- package/dist/cli/commands/openspec-init-command.js +49 -0
- package/dist/cli/commands/openspec-list-command.d.ts +3 -0
- package/dist/cli/commands/openspec-list-command.js +27 -0
- package/dist/cli/commands/openspec-render-command.d.ts +3 -0
- package/dist/cli/commands/openspec-render-command.js +33 -0
- package/dist/cli/commands/openspec-show-command.d.ts +3 -0
- package/dist/cli/commands/openspec-show-command.js +33 -0
- package/dist/cli/commands/openspec-to-rd-command.d.ts +3 -0
- package/dist/cli/commands/openspec-to-rd-command.js +33 -0
- package/dist/cli/commands/openspec-validate-command.d.ts +3 -0
- package/dist/cli/commands/openspec-validate-command.js +45 -0
- package/dist/cli/commands/playwright-browser-command.d.ts +8 -0
- package/dist/cli/commands/playwright-browser-command.js +61 -0
- package/dist/cli/commands/playwright-commands.d.ts +10 -62
- package/dist/cli/commands/playwright-commands.js +77 -400
- package/dist/cli/commands/playwright-envelope.d.ts +8 -0
- package/dist/cli/commands/playwright-envelope.js +29 -0
- package/dist/cli/commands/playwright-ls-stop-commands.d.ts +4 -0
- package/dist/cli/commands/playwright-ls-stop-commands.js +74 -0
- package/dist/cli/commands/playwright-session-store.d.ts +65 -0
- package/dist/cli/commands/playwright-session-store.js +189 -0
- package/dist/cli/commands/project-commands.d.ts +19 -0
- package/dist/cli/commands/project-commands.js +98 -259
- package/dist/cli/commands/project-context-command.d.ts +3 -0
- package/dist/cli/commands/project-context-command.js +44 -0
- package/dist/cli/commands/project-dashboard-command.d.ts +3 -0
- package/dist/cli/commands/project-dashboard-command.js +74 -0
- package/dist/cli/commands/project-knowledge-command.d.ts +3 -0
- package/dist/cli/commands/project-knowledge-command.js +48 -0
- package/dist/cli/commands/project-memories-show-command.d.ts +3 -0
- package/dist/cli/commands/project-memories-show-command.js +87 -0
- package/dist/cli/commands/project-memory-index-command.d.ts +3 -0
- package/dist/cli/commands/project-memory-index-command.js +31 -0
- package/dist/cli/commands/qa-archive-screenshots-command.d.ts +3 -0
- package/dist/cli/commands/qa-archive-screenshots-command.js +53 -0
- package/dist/cli/commands/qa-commands.d.ts +14 -87
- package/dist/cli/commands/qa-commands.js +17 -315
- package/dist/cli/commands/qa-context-prestep.d.ts +1 -0
- package/dist/cli/commands/qa-context-prestep.js +34 -0
- package/dist/cli/commands/qa-run-command.d.ts +3 -0
- package/dist/cli/commands/qa-run-command.js +105 -0
- package/dist/cli/commands/qa-run-options.d.ts +23 -0
- package/dist/cli/commands/qa-run-options.js +31 -0
- package/dist/cli/commands/qa-run-slice.d.ts +41 -0
- package/dist/cli/commands/qa-run-slice.js +145 -0
- package/dist/cli/commands/release-canary-command.d.ts +28 -0
- package/dist/cli/commands/release-canary-command.js +129 -0
- package/dist/cli/commands/release-command-shared.d.ts +13 -0
- package/dist/cli/commands/release-command-shared.js +18 -0
- package/dist/cli/commands/release-commands.d.ts +10 -18
- package/dist/cli/commands/release-commands.js +25 -298
- package/dist/cli/commands/release-done-command.d.ts +3 -0
- package/dist/cli/commands/release-done-command.js +64 -0
- package/dist/cli/commands/release-hotfix-command.d.ts +3 -0
- package/dist/cli/commands/release-hotfix-command.js +50 -0
- package/dist/cli/commands/release-plan-command.d.ts +3 -0
- package/dist/cli/commands/release-plan-command.js +33 -0
- package/dist/cli/commands/release-precheck-command.d.ts +3 -0
- package/dist/cli/commands/release-precheck-command.js +28 -0
- package/dist/cli/commands/release-promote-command.d.ts +3 -0
- package/dist/cli/commands/release-promote-command.js +34 -0
- package/dist/cli/commands/release-rollback-command.d.ts +3 -0
- package/dist/cli/commands/release-rollback-command.js +33 -0
- package/dist/cli/commands/release-watch-command.d.ts +3 -0
- package/dist/cli/commands/release-watch-command.js +44 -0
- package/dist/cli/commands/sediment-argv-flags.d.ts +54 -0
- package/dist/cli/commands/sediment-argv-flags.js +116 -0
- package/dist/cli/commands/sediment-command-shared.d.ts +15 -0
- package/dist/cli/commands/sediment-command-shared.js +5 -0
- package/dist/cli/commands/sediment-commands.d.ts +35 -59
- package/dist/cli/commands/sediment-commands.js +36 -590
- package/dist/cli/commands/sediment-pool-commands.d.ts +9 -0
- package/dist/cli/commands/sediment-pool-commands.js +185 -0
- package/dist/cli/commands/sediment-query-commands.d.ts +4 -0
- package/dist/cli/commands/sediment-query-commands.js +94 -0
- package/dist/cli/commands/sediment-release-commands.d.ts +8 -0
- package/dist/cli/commands/sediment-release-commands.js +232 -0
- package/dist/cli/commands/sop-advance-command.d.ts +3 -0
- package/dist/cli/commands/sop-advance-command.js +160 -0
- package/dist/cli/commands/sop-check-command.d.ts +3 -0
- package/dist/cli/commands/sop-check-command.js +44 -0
- package/dist/cli/commands/sop-command-shared.d.ts +23 -0
- package/dist/cli/commands/sop-command-shared.js +18 -0
- package/dist/cli/commands/sop-commands.d.ts +15 -1
- package/dist/cli/commands/sop-commands.js +26 -240
- package/dist/cli/commands/sop-init-command.d.ts +3 -0
- package/dist/cli/commands/sop-init-command.js +51 -0
- package/dist/cli/commands/sop-lint-command.d.ts +3 -0
- package/dist/cli/commands/sop-lint-command.js +64 -0
- package/dist/cli/commands/sop-register-command.d.ts +3 -0
- package/dist/cli/commands/sop-register-command.js +48 -0
- package/dist/cli/commands/sop-registry-command.d.ts +3 -0
- package/dist/cli/commands/sop-registry-command.js +30 -0
- package/dist/cli/commands/statusline-command-shared.d.ts +73 -0
- package/dist/cli/commands/statusline-command-shared.js +90 -0
- package/dist/cli/commands/statusline-commands.d.ts +1 -19
- package/dist/cli/commands/statusline-commands.js +48 -287
- package/dist/cli/commands/statusline-compact-command.d.ts +4 -0
- package/dist/cli/commands/statusline-compact-command.js +54 -0
- package/dist/cli/commands/statusline-install-command.d.ts +3 -0
- package/dist/cli/commands/statusline-install-command.js +48 -0
- package/dist/cli/commands/statusline-render-command.d.ts +9 -0
- package/dist/cli/commands/statusline-render-command.js +55 -0
- package/dist/cli/commands/statusline-status-command.d.ts +3 -0
- package/dist/cli/commands/statusline-status-command.js +23 -0
- package/dist/cli/commands/statusline-uninstall-command.d.ts +3 -0
- package/dist/cli/commands/statusline-uninstall-command.js +23 -0
- package/dist/cli/commands/test-command-run-helpers.d.ts +27 -0
- package/dist/cli/commands/test-command-run-helpers.js +73 -0
- package/dist/cli/commands/test-command-runner-resolution.d.ts +57 -0
- package/dist/cli/commands/test-command-runner-resolution.js +183 -0
- package/dist/cli/commands/test-commands.d.ts +8 -56
- package/dist/cli/commands/test-commands.js +26 -249
- package/dist/cli/commands/vm-command-shared.d.ts +23 -0
- package/dist/cli/commands/vm-command-shared.js +23 -0
- package/dist/cli/commands/vm-commands.d.ts +1 -28
- package/dist/cli/commands/vm-commands.js +36 -270
- package/dist/cli/commands/vm-hypervisor-runtime.d.ts +15 -0
- package/dist/cli/commands/vm-hypervisor-runtime.js +64 -0
- package/dist/cli/commands/vm-release-command.d.ts +5 -0
- package/dist/cli/commands/vm-release-command.js +101 -0
- package/dist/cli/commands/vm-spawn-command.d.ts +5 -0
- package/dist/cli/commands/vm-spawn-command.js +177 -0
- package/dist/cli/commands/web-command-shared.d.ts +12 -0
- package/dist/cli/commands/web-command-shared.js +30 -0
- package/dist/cli/commands/web-commands.d.ts +7 -14
- package/dist/cli/commands/web-commands.js +6 -314
- package/dist/cli/commands/web-install-command.d.ts +10 -0
- package/dist/cli/commands/web-install-command.js +116 -0
- package/dist/cli/commands/web-lifecycle-commands.d.ts +9 -30
- package/dist/cli/commands/web-lifecycle-commands.js +14 -322
- package/dist/cli/commands/web-login-command.d.ts +14 -0
- package/dist/cli/commands/web-login-command.js +189 -0
- package/dist/cli/commands/web-op-payload.d.ts +22 -0
- package/dist/cli/commands/web-op-payload.js +89 -0
- package/dist/cli/commands/web-op-refusals.d.ts +37 -0
- package/dist/cli/commands/web-op-refusals.js +73 -0
- package/dist/cli/commands/web-op-runner.d.ts +14 -0
- package/dist/cli/commands/web-op-runner.js +166 -0
- package/dist/cli/commands/web-status-command.d.ts +4 -0
- package/dist/cli/commands/web-status-command.js +32 -0
- package/dist/cli/commands/web-stop-command.d.ts +10 -0
- package/dist/cli/commands/web-stop-command.js +59 -0
- package/dist/cli/commands/web-verb-specs.d.ts +18 -0
- package/dist/cli/commands/web-verb-specs.js +66 -0
- package/dist/cli/commands/workflow-command-shared.d.ts +102 -0
- package/dist/cli/commands/workflow-command-shared.js +74 -0
- package/dist/cli/commands/workflow-graph-commands.d.ts +3 -0
- package/dist/cli/commands/workflow-graph-commands.js +73 -0
- package/dist/cli/commands/workflow-init-command.d.ts +3 -0
- package/dist/cli/commands/workflow-init-command.js +68 -0
- package/dist/cli/commands/workflow-lifecycle-commands.d.ts +9 -59
- package/dist/cli/commands/workflow-lifecycle-commands.js +14 -348
- package/dist/cli/commands/workflow-node-commands.d.ts +3 -0
- package/dist/cli/commands/workflow-node-commands.js +154 -0
- package/dist/cli/commands/workflow-terminalize-command.d.ts +3 -0
- package/dist/cli/commands/workflow-terminalize-command.js +56 -0
- package/dist/services/code/auto-compact-artifacts.d.ts +54 -0
- package/dist/services/code/auto-compact-artifacts.js +135 -0
- package/dist/services/code/auto-compact-attempt.d.ts +46 -0
- package/dist/services/code/auto-compact-attempt.js +88 -0
- package/dist/services/code/auto-compact-decision.d.ts +74 -0
- package/dist/services/code/auto-compact-decision.js +149 -0
- package/dist/services/code/auto-compact-dispatch-gate.d.ts +36 -0
- package/dist/services/code/auto-compact-dispatch-gate.js +86 -0
- package/dist/services/code/auto-compact-envelopes.d.ts +33 -0
- package/dist/services/code/auto-compact-envelopes.js +134 -0
- package/dist/services/code/auto-compact-history.d.ts +46 -0
- package/dist/services/code/auto-compact-history.js +17 -0
- package/dist/services/code/auto-compact-orchestrator.d.ts +11 -240
- package/dist/services/code/auto-compact-orchestrator.js +165 -686
- package/dist/services/code/auto-compact-run-types.d.ts +123 -0
- package/dist/services/code/auto-compact-run-types.js +1 -0
- package/dist/services/code/emit-handoff.d.ts +35 -1
- package/dist/services/code/emit-handoff.js +128 -7
- package/dist/services/code/step-08-gate.d.ts +28 -19
- package/dist/services/code/step-08-gate.js +92 -35
- package/dist/services/config/config-coercion.d.ts +7 -0
- package/dist/services/config/config-coercion.js +156 -0
- package/dist/services/config/config-file-io.d.ts +11 -0
- package/dist/services/config/config-file-io.js +61 -0
- package/dist/services/config/config-get.d.ts +2 -0
- package/dist/services/config/config-get.js +36 -0
- package/dist/services/config/config-global-loader.d.ts +15 -0
- package/dist/services/config/config-global-loader.js +111 -0
- package/dist/services/config/config-nested-path.d.ts +3 -0
- package/dist/services/config/config-nested-path.js +53 -0
- package/dist/services/config/config-primitives.d.ts +16 -0
- package/dist/services/config/config-primitives.js +24 -0
- package/dist/services/config/config-service.d.ts +9 -33
- package/dist/services/config/config-service.js +16 -665
- package/dist/services/config/config-validation.d.ts +19 -0
- package/dist/services/config/config-validation.js +152 -0
- package/dist/services/config/config-workspace.d.ts +10 -0
- package/dist/services/config/config-workspace.js +158 -0
- package/dist/services/skills/hooks-settings-deny-list.d.ts +61 -0
- package/dist/services/skills/hooks-settings-deny-list.js +173 -0
- package/dist/services/skills/hooks-settings-envelopes.d.ts +20 -0
- package/dist/services/skills/hooks-settings-envelopes.js +79 -0
- package/dist/services/skills/hooks-settings-file-shape.d.ts +43 -0
- package/dist/services/skills/hooks-settings-file-shape.js +207 -0
- package/dist/services/skills/hooks-settings-paths.d.ts +34 -0
- package/dist/services/skills/hooks-settings-paths.js +75 -0
- package/dist/services/skills/hooks-settings-read-installed.d.ts +39 -0
- package/dist/services/skills/hooks-settings-read-installed.js +60 -0
- package/dist/services/skills/hooks-settings-service.d.ts +12 -212
- package/dist/services/skills/hooks-settings-service.js +71 -657
- package/dist/services/skills/hooks-settings-types.d.ts +139 -0
- package/dist/services/skills/hooks-settings-types.js +1 -0
- package/dist/services/workspace/claude-settings-template-merge.d.ts +89 -0
- package/dist/services/workspace/claude-settings-template-merge.js +243 -0
- package/dist/services/workspace/claude-settings-template.d.ts +29 -87
- package/dist/services/workspace/claude-settings-template.js +81 -236
- package/package.json +5 -5
|
@@ -1,108 +1,38 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
import { getCurrentSessionId } from '../../services/skills/skill-presence-service.js';
|
|
34
|
-
import { atomicWriteJson } from '../../services/ide/shared/atomic-json.js';
|
|
35
|
-
import { DEFAULT_VM_IMAGE, deserializeVmLease, finalizeVmLease, generateVmLeaseId, markVmReleased, ttlForVmRole, vmLeaseFilePath } from '../../services/vm/vm-lease.js';
|
|
36
|
-
import { detectHypervisor } from './vm-hypervisor-probe.js';
|
|
1
|
+
// src/cli/commands/vm-commands.ts
|
|
2
|
+
//
|
|
3
|
+
// L4 VM isolation: the `peaks vm` parent, its status probe, and the
|
|
4
|
+
// spawn/release pair. Split out of the single file this used to be; the parent
|
|
5
|
+
// description, the registration order and every verb's surface are unchanged.
|
|
6
|
+
//
|
|
7
|
+
// Hypervisor dispatch:
|
|
8
|
+
// - `kvm` : `virsh create` + `virsh destroy` (Linux KVM via libvirt)
|
|
9
|
+
// - `hyperkit` : `hvftool create` + `hvftool stop` (macOS HyperKit)
|
|
10
|
+
// - `hyperv` : `hvc create` + `hvftool stop` (Windows Hyper-V via
|
|
11
|
+
// the operator-installed `hvc` shim)
|
|
12
|
+
//
|
|
13
|
+
// The runtime check: which hypervisor binary is on PATH +
|
|
14
|
+
// (for kvm) whether the host kernel exposes /dev/kvm. The
|
|
15
|
+
// spawn is fail-fast: if the requested hypervisor is not
|
|
16
|
+
// available, the CLI returns VM_RUNTIME_UNAVAILABLE with a
|
|
17
|
+
// remediation hint rather than falling through to a different
|
|
18
|
+
// hypervisor (the caller chose a specific mode for a reason).
|
|
19
|
+
//
|
|
20
|
+
// Each spawned VM runs `sleep infinity` as the entrypoint; the
|
|
21
|
+
// VM's working dir is mounted from the host path, and the
|
|
22
|
+
// `peaks.leaseId` / `peaks.rid` labels are propagated via
|
|
23
|
+
// cloud-init metadata. Real workloads are expected to use
|
|
24
|
+
// `peaks vm exec` (a follow-up rid) to run commands inside
|
|
25
|
+
// the VM; Part 35 ships the lease + spawn/release surface
|
|
26
|
+
// only.
|
|
27
|
+
//
|
|
28
|
+
// The verb bodies live beside this file (`vm-spawn-command.ts`,
|
|
29
|
+
// `vm-release-command.ts`), over the shared vocabulary in
|
|
30
|
+
// `vm-command-shared.ts` and the dispatch helpers in
|
|
31
|
+
// `vm-hypervisor-runtime.ts`; `vm-hypervisor-probe.ts` and
|
|
32
|
+
// `vm-status-command.ts` were already siblings.
|
|
37
33
|
import { registerVmStatusCommand } from './vm-status-command.js';
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
}
|
|
41
|
-
function resolveTtlMs(raw, role) {
|
|
42
|
-
if (typeof raw !== 'string' || raw.length === 0)
|
|
43
|
-
return ttlForVmRole(role);
|
|
44
|
-
const parsed = Number.parseInt(raw, 10);
|
|
45
|
-
if (!Number.isInteger(parsed) || parsed <= 0)
|
|
46
|
-
return ttlForVmRole(role);
|
|
47
|
-
return parsed;
|
|
48
|
-
}
|
|
49
|
-
function spawnVmWithHypervisor(args) {
|
|
50
|
-
if (args.hypervisor === 'kvm') {
|
|
51
|
-
// virsh create expects a domain XML file. We emit a minimal
|
|
52
|
-
// XML with the image, mount, and our peaks labels.
|
|
53
|
-
const xml = `<?xml version="1.0"?>
|
|
54
|
-
<domain type="kvm">
|
|
55
|
-
<name>peaks-${args.leaseId}</name>
|
|
56
|
-
<metadata><peaks:label xmlns:peaks="urn:peaks">peaks.leaseId=${args.leaseId};peaks.rid=${args.rid}</peaks:label></metadata>
|
|
57
|
-
<memory>1048576</memory>
|
|
58
|
-
<vcpu>1</vcpu>
|
|
59
|
-
<os><type arch="x86_64">hvm</type></os>
|
|
60
|
-
<devices>
|
|
61
|
-
<disk type="file"><source file="${args.image}"/><target dev="vda"/></disk>
|
|
62
|
-
<filesystem type="mount"><source dir="${args.mount}"/><target dir="/work"/></filesystem>
|
|
63
|
-
</devices>
|
|
64
|
-
</domain>`;
|
|
65
|
-
const xmlPath = `${args.workdir}/.peaks-vm-${args.leaseId}.xml`;
|
|
66
|
-
writeFileSync(xmlPath, xml, 'utf8');
|
|
67
|
-
const out = execSync(`virsh create ${xmlPath}`, {
|
|
68
|
-
cwd: args.workdir,
|
|
69
|
-
stdio: ['ignore', 'pipe', 'pipe'],
|
|
70
|
-
encoding: 'utf8',
|
|
71
|
-
windowsHide: true
|
|
72
|
-
});
|
|
73
|
-
return { vmId: out.trim() };
|
|
74
|
-
}
|
|
75
|
-
if (args.hypervisor === 'hyperkit') {
|
|
76
|
-
const out = execSync(`hvftool create --image ${args.image} --mount ${args.mount}:/work --label peaks.leaseId=${args.leaseId} --label peaks.rid=${args.rid} --entrypoint sleep -- infinity`, { cwd: args.workdir, stdio: ['ignore', 'pipe', 'pipe'], encoding: 'utf8', windowsHide: true });
|
|
77
|
-
return { vmId: out.trim() };
|
|
78
|
-
}
|
|
79
|
-
// hyperv: the hvc shim writes a vhdx + emits the new VM id.
|
|
80
|
-
const out = execSync(`hvc create --image ${args.image} --mount ${args.mount} --label peaks.leaseId=${args.leaseId} --label peaks.rid=${args.rid}`, { cwd: args.workdir, stdio: ['ignore', 'pipe', 'pipe'], encoding: 'utf8', windowsHide: true });
|
|
81
|
-
return { vmId: out.trim() };
|
|
82
|
-
}
|
|
83
|
-
function destroyVmWithHypervisor(args) {
|
|
84
|
-
try {
|
|
85
|
-
if (args.hypervisor === 'kvm') {
|
|
86
|
-
execSync(`virsh destroy ${args.vmId}`, {
|
|
87
|
-
stdio: ['ignore', 'pipe', 'pipe'],
|
|
88
|
-
windowsHide: true
|
|
89
|
-
});
|
|
90
|
-
}
|
|
91
|
-
else if (args.hypervisor === 'hyperkit') {
|
|
92
|
-
execSync(`hvftool stop ${args.vmId}`, {
|
|
93
|
-
stdio: ['ignore', 'pipe', 'pipe'],
|
|
94
|
-
windowsHide: true
|
|
95
|
-
});
|
|
96
|
-
}
|
|
97
|
-
else {
|
|
98
|
-
execSync(`hvc stop ${args.vmId}`, { stdio: ['ignore', 'pipe', 'pipe'], windowsHide: true });
|
|
99
|
-
}
|
|
100
|
-
return true;
|
|
101
|
-
}
|
|
102
|
-
catch {
|
|
103
|
-
return false;
|
|
104
|
-
}
|
|
105
|
-
}
|
|
34
|
+
import { registerVmSpawnCommand } from './vm-spawn-command.js';
|
|
35
|
+
import { registerVmReleaseCommand } from './vm-release-command.js';
|
|
106
36
|
export function registerVmCommand(program, io) {
|
|
107
37
|
const cmd = program
|
|
108
38
|
.command('vm')
|
|
@@ -110,170 +40,6 @@ export function registerVmCommand(program, io) {
|
|
|
110
40
|
// The host probe rides on the same parent, so `peaks vm status`
|
|
111
41
|
// can say which prerequisite is missing before a spawn fails.
|
|
112
42
|
registerVmStatusCommand(cmd, io);
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
.description('Spawn a VM via the requested hypervisor (kvm | hyperkit | hyperv) and write a VM lease. ' +
|
|
116
|
-
'Default TTL is role-aware (rd=30m / qa=15m / ui=1h); pass --ttl <ms> to override. ' +
|
|
117
|
-
'Default image is `peaks-base:22-slim`; pass --image <name> to override.')
|
|
118
|
-
.requiredOption('--rid <rid>', 'peaks request id the lease is associated with')
|
|
119
|
-
.requiredOption('--role <role>', 'sub-agent role (rd | qa | ui | sc | prd | general-purpose)')
|
|
120
|
-
.requiredOption('--purpose <text>', 'why this VM was spawned (audit log)')
|
|
121
|
-
.option('--hypervisor <name>', 'hypervisor to use: kvm | hyperkit | hyperv (default: auto-detect from host)')
|
|
122
|
-
.option('--image <name>', `container image / vhdx to boot (default ${DEFAULT_VM_IMAGE})`)
|
|
123
|
-
.option('--ttl <ms>', 'time-to-live in ms (default role-aware; override with positive number)')
|
|
124
|
-
.option('--mount <path>', 'host path to mount as the VM working dir (default: <projectRoot>)')
|
|
125
|
-
.option('--session <sid>', 'override session id')
|
|
126
|
-
.option('--project <path>', 'project root (default: findProjectRoot(cwd))')).action((options) => {
|
|
127
|
-
try {
|
|
128
|
-
const projectRoot = options.project ?? findProjectRoot(process.cwd()) ?? process.cwd();
|
|
129
|
-
const sessionId = options.session ??
|
|
130
|
-
process.env.PEAKS_SESSION_ID ??
|
|
131
|
-
getCurrentSessionId(projectRoot) ??
|
|
132
|
-
'unknown-sid';
|
|
133
|
-
// Pick hypervisor: explicit > auto-detect.
|
|
134
|
-
const explicit = options.hypervisor;
|
|
135
|
-
const detected = explicit
|
|
136
|
-
? explicit
|
|
137
|
-
: (() => {
|
|
138
|
-
if (existsSync('/dev/kvm'))
|
|
139
|
-
return 'kvm';
|
|
140
|
-
// No platform detector for hyperkit / hyperv — those
|
|
141
|
-
// require explicit --hypervisor.
|
|
142
|
-
return null;
|
|
143
|
-
})();
|
|
144
|
-
if (detected === null) {
|
|
145
|
-
printResult(io, fail('vm.spawn', 'VM_HYPERVISOR_UNSPECIFIED', 'No --hypervisor given and the host does not advertise /dev/kvm. Pass --hypervisor hyperkit|hyperv to force one.', { rid: options.rid, sessionId }, [
|
|
146
|
-
'Linux KVM: ensure /dev/kvm exists and the kvm kernel module is loaded.',
|
|
147
|
-
'macOS HyperKit: install hvftool (brew install hyperkit) and pass --hypervisor hyperkit.',
|
|
148
|
-
'Windows Hyper-V: install the hvc shim and pass --hypervisor hyperv.'
|
|
149
|
-
]), options.json);
|
|
150
|
-
process.exitCode = 1;
|
|
151
|
-
return;
|
|
152
|
-
}
|
|
153
|
-
const probe = detectHypervisor(detected);
|
|
154
|
-
if (!probe.ok) {
|
|
155
|
-
printResult(io, fail('vm.spawn', 'VM_RUNTIME_UNAVAILABLE', `${detected} runtime not available: ${probe.stderr}`, { rid: options.rid, hypervisor: detected, sessionId }, [
|
|
156
|
-
`Install the ${detected} runtime binary on PATH.`,
|
|
157
|
-
'The dispatch fail-fast prevents fallback to a different hypervisor (caller chose this mode for a reason).'
|
|
158
|
-
]), options.json);
|
|
159
|
-
process.exitCode = 1;
|
|
160
|
-
return;
|
|
161
|
-
}
|
|
162
|
-
const leaseId = generateVmLeaseId();
|
|
163
|
-
const now = Date.now();
|
|
164
|
-
const ttlMs = resolveTtlMs(options.ttl, options.role);
|
|
165
|
-
const image = options.image ?? DEFAULT_VM_IMAGE;
|
|
166
|
-
const mount = options.mount ?? projectRoot;
|
|
167
|
-
let spawnResult;
|
|
168
|
-
try {
|
|
169
|
-
spawnResult = spawnVmWithHypervisor({
|
|
170
|
-
hypervisor: detected,
|
|
171
|
-
image,
|
|
172
|
-
mount,
|
|
173
|
-
leaseId,
|
|
174
|
-
rid: options.rid,
|
|
175
|
-
workdir: projectRoot
|
|
176
|
-
});
|
|
177
|
-
}
|
|
178
|
-
catch (err) {
|
|
179
|
-
printResult(io, fail('vm.spawn', 'VM_SPAWN_FAILED', getErrorMessage(err), { rid: options.rid, hypervisor: detected, image, sessionId }, [
|
|
180
|
-
'Verify the image / vhdx is reachable on the host.',
|
|
181
|
-
`For ${detected}: the spawn helper expects domain XML / hvftool args / hvc shim.`
|
|
182
|
-
]), options.json);
|
|
183
|
-
process.exitCode = 1;
|
|
184
|
-
return;
|
|
185
|
-
}
|
|
186
|
-
const lease = finalizeVmLease({
|
|
187
|
-
leaseId,
|
|
188
|
-
rid: options.rid,
|
|
189
|
-
role: options.role,
|
|
190
|
-
path: mount,
|
|
191
|
-
hypervisor: detected,
|
|
192
|
-
image,
|
|
193
|
-
vmId: spawnResult.vmId,
|
|
194
|
-
createdAt: now,
|
|
195
|
-
expiresAt: now + ttlMs,
|
|
196
|
-
purpose: options.purpose
|
|
197
|
-
});
|
|
198
|
-
atomicWriteJson(vmLeaseFilePath(joinPathSession(projectRoot, sessionId), leaseId), lease);
|
|
199
|
-
printResult(io, ok('vm.spawn', {
|
|
200
|
-
lease,
|
|
201
|
-
sessionId,
|
|
202
|
-
projectRoot,
|
|
203
|
-
hypervisor: detected,
|
|
204
|
-
runtime: probe.binary,
|
|
205
|
-
ttlMs,
|
|
206
|
-
nextActions: [
|
|
207
|
-
`VM domain id: ${spawnResult.vmId}`,
|
|
208
|
-
`Image: ${image}`,
|
|
209
|
-
`Lease expires at: ${new Date(lease.expiresAt).toISOString()}`,
|
|
210
|
-
'Run `peaks vm release --lease-id <lease-id>` when done',
|
|
211
|
-
'For inside-the-VM exec, a follow-up rid adds `peaks vm exec` (Part 35 ships lease + spawn/release only).'
|
|
212
|
-
]
|
|
213
|
-
}, [], []), options.json);
|
|
214
|
-
}
|
|
215
|
-
catch (err) {
|
|
216
|
-
printResult(io, fail('vm.spawn', 'SPAWN_FAILED', getErrorMessage(err), {
|
|
217
|
-
rid: options.rid,
|
|
218
|
-
sessionId: options.session ?? process.env.PEAKS_SESSION_ID ?? 'unknown-sid'
|
|
219
|
-
}, [
|
|
220
|
-
'See error message; if the lease was not written, retry after fixing the underlying issue.'
|
|
221
|
-
]), options.json);
|
|
222
|
-
process.exitCode = 1;
|
|
223
|
-
}
|
|
224
|
-
});
|
|
225
|
-
addJsonOption(cmd
|
|
226
|
-
.command('release')
|
|
227
|
-
.description('Transition a VM lease to released and run the hypervisor destroy command. Idempotent on already-released leases.')
|
|
228
|
-
.requiredOption('--lease-id <id>', 'lease id returned by `peaks vm spawn`')
|
|
229
|
-
.option('--session <sid>', 'override session id')
|
|
230
|
-
.option('--project <path>', 'project root (default: findProjectRoot(cwd))')).action((options) => {
|
|
231
|
-
try {
|
|
232
|
-
const projectRoot = options.project ?? findProjectRoot(process.cwd()) ?? process.cwd();
|
|
233
|
-
const sessionId = options.session ??
|
|
234
|
-
process.env.PEAKS_SESSION_ID ??
|
|
235
|
-
getCurrentSessionId(projectRoot) ??
|
|
236
|
-
'unknown-sid';
|
|
237
|
-
const file = vmLeaseFilePath(joinPathSession(projectRoot, sessionId), options.leaseId);
|
|
238
|
-
if (!existsSync(file)) {
|
|
239
|
-
printResult(io, fail('vm.release', 'LEASE_NOT_FOUND', `no VM lease on disk at ${file}`, { leaseId: options.leaseId, file }, [
|
|
240
|
-
'Run `peaks vm list` (follow-up) to inspect active leases.',
|
|
241
|
-
'For a never-spawned lease, this is a no-op.'
|
|
242
|
-
]), options.json);
|
|
243
|
-
process.exitCode = 1;
|
|
244
|
-
return;
|
|
245
|
-
}
|
|
246
|
-
let lease;
|
|
247
|
-
try {
|
|
248
|
-
lease = deserializeVmLease(readFileSync(file, 'utf8'));
|
|
249
|
-
}
|
|
250
|
-
catch (err) {
|
|
251
|
-
printResult(io, fail('vm.release', 'LEASE_FILE_INVALID', getErrorMessage(err), { leaseId: options.leaseId, file }, ['Delete the malformed lease file manually and re-spawn.']), options.json);
|
|
252
|
-
process.exitCode = 1;
|
|
253
|
-
return;
|
|
254
|
-
}
|
|
255
|
-
if (lease.status === 'released') {
|
|
256
|
-
printResult(io, ok('vm.release', { lease, sessionId, projectRoot, alreadyReleased: true }, [], [`Lease ${lease.leaseId} already released; nothing to do.`]), options.json);
|
|
257
|
-
return;
|
|
258
|
-
}
|
|
259
|
-
const destroyed = destroyVmWithHypervisor({ hypervisor: lease.hypervisor, vmId: lease.vmId });
|
|
260
|
-
const released = markVmReleased(lease);
|
|
261
|
-
atomicWriteJson(file, released);
|
|
262
|
-
printResult(io, ok('vm.release', { lease: released, sessionId, projectRoot, vmDestroyed: destroyed }, destroyed
|
|
263
|
-
? []
|
|
264
|
-
: [`${lease.hypervisor} destroy command failed; the lease was marked released anyway.`], [
|
|
265
|
-
`Lease ${lease.leaseId} marked released.`,
|
|
266
|
-
destroyed
|
|
267
|
-
? `${lease.hypervisor} domain ${lease.vmId} stopped.`
|
|
268
|
-
: `Manual \`${lease.hypervisor} stop ${lease.vmId}\` may be needed.`
|
|
269
|
-
]), options.json);
|
|
270
|
-
}
|
|
271
|
-
catch (err) {
|
|
272
|
-
printResult(io, fail('vm.release', 'RELEASE_FAILED', getErrorMessage(err), {
|
|
273
|
-
leaseId: options.leaseId,
|
|
274
|
-
sessionId: options.session ?? process.env.PEAKS_SESSION_ID ?? 'unknown-sid'
|
|
275
|
-
}, ['Verify the lease id and re-run.']), options.json);
|
|
276
|
-
process.exitCode = 1;
|
|
277
|
-
}
|
|
278
|
-
});
|
|
43
|
+
registerVmSpawnCommand(cmd, io);
|
|
44
|
+
registerVmReleaseCommand(cmd, io);
|
|
279
45
|
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { VmHypervisor } from '../../services/vm/vm-lease.js';
|
|
2
|
+
export declare function spawnVmWithHypervisor(args: {
|
|
3
|
+
hypervisor: VmHypervisor;
|
|
4
|
+
image: string;
|
|
5
|
+
mount: string;
|
|
6
|
+
leaseId: string;
|
|
7
|
+
rid: string;
|
|
8
|
+
workdir: string;
|
|
9
|
+
}): {
|
|
10
|
+
vmId: string;
|
|
11
|
+
};
|
|
12
|
+
export declare function destroyVmWithHypervisor(args: {
|
|
13
|
+
hypervisor: VmHypervisor;
|
|
14
|
+
vmId: string;
|
|
15
|
+
}): boolean;
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
// src/cli/commands/vm-hypervisor-runtime.ts
|
|
2
|
+
//
|
|
3
|
+
// The two hypervisor dispatch helpers `peaks vm spawn` / `peaks vm release`
|
|
4
|
+
// call: create a domain and destroy one. Split out of `vm-commands.ts`; every
|
|
5
|
+
// command line, cwd, stdio tuple and `windowsHide` flag is unchanged.
|
|
6
|
+
import { execSync } from 'node:child_process';
|
|
7
|
+
import { writeFileSync } from 'node:fs';
|
|
8
|
+
export function spawnVmWithHypervisor(args) {
|
|
9
|
+
if (args.hypervisor === 'kvm') {
|
|
10
|
+
// virsh create expects a domain XML file. We emit a minimal
|
|
11
|
+
// XML with the image, mount, and our peaks labels.
|
|
12
|
+
const xml = `<?xml version="1.0"?>
|
|
13
|
+
<domain type="kvm">
|
|
14
|
+
<name>peaks-${args.leaseId}</name>
|
|
15
|
+
<metadata><peaks:label xmlns:peaks="urn:peaks">peaks.leaseId=${args.leaseId};peaks.rid=${args.rid}</peaks:label></metadata>
|
|
16
|
+
<memory>1048576</memory>
|
|
17
|
+
<vcpu>1</vcpu>
|
|
18
|
+
<os><type arch="x86_64">hvm</type></os>
|
|
19
|
+
<devices>
|
|
20
|
+
<disk type="file"><source file="${args.image}"/><target dev="vda"/></disk>
|
|
21
|
+
<filesystem type="mount"><source dir="${args.mount}"/><target dir="/work"/></filesystem>
|
|
22
|
+
</devices>
|
|
23
|
+
</domain>`;
|
|
24
|
+
const xmlPath = `${args.workdir}/.peaks-vm-${args.leaseId}.xml`;
|
|
25
|
+
writeFileSync(xmlPath, xml, 'utf8');
|
|
26
|
+
const out = execSync(`virsh create ${xmlPath}`, {
|
|
27
|
+
cwd: args.workdir,
|
|
28
|
+
stdio: ['ignore', 'pipe', 'pipe'],
|
|
29
|
+
encoding: 'utf8',
|
|
30
|
+
windowsHide: true
|
|
31
|
+
});
|
|
32
|
+
return { vmId: out.trim() };
|
|
33
|
+
}
|
|
34
|
+
if (args.hypervisor === 'hyperkit') {
|
|
35
|
+
const out = execSync(`hvftool create --image ${args.image} --mount ${args.mount}:/work --label peaks.leaseId=${args.leaseId} --label peaks.rid=${args.rid} --entrypoint sleep -- infinity`, { cwd: args.workdir, stdio: ['ignore', 'pipe', 'pipe'], encoding: 'utf8', windowsHide: true });
|
|
36
|
+
return { vmId: out.trim() };
|
|
37
|
+
}
|
|
38
|
+
// hyperv: the hvc shim writes a vhdx + emits the new VM id.
|
|
39
|
+
const out = execSync(`hvc create --image ${args.image} --mount ${args.mount} --label peaks.leaseId=${args.leaseId} --label peaks.rid=${args.rid}`, { cwd: args.workdir, stdio: ['ignore', 'pipe', 'pipe'], encoding: 'utf8', windowsHide: true });
|
|
40
|
+
return { vmId: out.trim() };
|
|
41
|
+
}
|
|
42
|
+
export function destroyVmWithHypervisor(args) {
|
|
43
|
+
try {
|
|
44
|
+
if (args.hypervisor === 'kvm') {
|
|
45
|
+
execSync(`virsh destroy ${args.vmId}`, {
|
|
46
|
+
stdio: ['ignore', 'pipe', 'pipe'],
|
|
47
|
+
windowsHide: true
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
else if (args.hypervisor === 'hyperkit') {
|
|
51
|
+
execSync(`hvftool stop ${args.vmId}`, {
|
|
52
|
+
stdio: ['ignore', 'pipe', 'pipe'],
|
|
53
|
+
windowsHide: true
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
else {
|
|
57
|
+
execSync(`hvc stop ${args.vmId}`, { stdio: ['ignore', 'pipe', 'pipe'], windowsHide: true });
|
|
58
|
+
}
|
|
59
|
+
return true;
|
|
60
|
+
}
|
|
61
|
+
catch {
|
|
62
|
+
return false;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { Command } from 'commander';
|
|
2
|
+
import { type ProgramIO } from '../cli-helpers.js';
|
|
3
|
+
import { type ReleaseOptions } from './vm-command-shared.js';
|
|
4
|
+
export declare function runVmRelease(io: ProgramIO, options: ReleaseOptions): void;
|
|
5
|
+
export declare function registerVmReleaseCommand(cmd: Command, io: ProgramIO): void;
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
// src/cli/commands/vm-release-command.ts
|
|
2
|
+
//
|
|
3
|
+
// `peaks vm release` — transition a VM lease to released and run the
|
|
4
|
+
// hypervisor destroy command. Split out of `vm-commands.ts`; every refusal
|
|
5
|
+
// code, message, `data` field, warning and next-action string is unchanged.
|
|
6
|
+
import { existsSync, readFileSync } from 'node:fs';
|
|
7
|
+
import { fail, getErrorMessage, ok } from 'peaks-loop-shared/result';
|
|
8
|
+
import { addJsonOption, printResult } from '../cli-helpers.js';
|
|
9
|
+
import { findProjectRoot } from '../../services/config/config-safety.js';
|
|
10
|
+
import { atomicWriteJson } from '../../services/ide/shared/atomic-json.js';
|
|
11
|
+
import { deserializeVmLease, markVmReleased, vmLeaseFilePath } from '../../services/vm/vm-lease.js';
|
|
12
|
+
import { destroyVmWithHypervisor } from './vm-hypervisor-runtime.js';
|
|
13
|
+
import { joinPathSession, resolveVmSessionId } from './vm-command-shared.js';
|
|
14
|
+
/** Print a `vm.release` refusal; the caller stops. */
|
|
15
|
+
function emitReleaseRefusal(io, options, refusal) {
|
|
16
|
+
printResult(io, fail('vm.release', refusal.code, refusal.message, refusal.data, refusal.nextActions), options.json ?? false);
|
|
17
|
+
process.exitCode = 1;
|
|
18
|
+
}
|
|
19
|
+
/** The lease on disk, or null after the matching refusal envelope was printed. */
|
|
20
|
+
function readLeaseOrRefuse(io, options, file) {
|
|
21
|
+
if (!existsSync(file)) {
|
|
22
|
+
emitReleaseRefusal(io, options, {
|
|
23
|
+
code: 'LEASE_NOT_FOUND',
|
|
24
|
+
message: `no VM lease on disk at ${file}`,
|
|
25
|
+
data: { leaseId: options.leaseId, file },
|
|
26
|
+
nextActions: [
|
|
27
|
+
'Run `peaks vm list` (follow-up) to inspect active leases.',
|
|
28
|
+
'For a never-spawned lease, this is a no-op.'
|
|
29
|
+
]
|
|
30
|
+
});
|
|
31
|
+
return null;
|
|
32
|
+
}
|
|
33
|
+
try {
|
|
34
|
+
return deserializeVmLease(readFileSync(file, 'utf8'));
|
|
35
|
+
}
|
|
36
|
+
catch (err) {
|
|
37
|
+
emitReleaseRefusal(io, options, {
|
|
38
|
+
code: 'LEASE_FILE_INVALID',
|
|
39
|
+
message: getErrorMessage(err),
|
|
40
|
+
data: { leaseId: options.leaseId, file },
|
|
41
|
+
nextActions: ['Delete the malformed lease file manually and re-spawn.']
|
|
42
|
+
});
|
|
43
|
+
return null;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
function emitAlreadyReleased(io, options, target, lease) {
|
|
47
|
+
printResult(io, ok('vm.release', {
|
|
48
|
+
lease,
|
|
49
|
+
sessionId: target.sessionId,
|
|
50
|
+
projectRoot: target.projectRoot,
|
|
51
|
+
alreadyReleased: true
|
|
52
|
+
}, [], [`Lease ${lease.leaseId} already released; nothing to do.`]), options.json ?? false);
|
|
53
|
+
}
|
|
54
|
+
function emitReleaseSuccess(io, options, target, lease) {
|
|
55
|
+
const destroyed = destroyVmWithHypervisor({ hypervisor: lease.hypervisor, vmId: lease.vmId });
|
|
56
|
+
const released = markVmReleased(lease);
|
|
57
|
+
atomicWriteJson(target.file, released);
|
|
58
|
+
printResult(io, ok('vm.release', {
|
|
59
|
+
lease: released,
|
|
60
|
+
sessionId: target.sessionId,
|
|
61
|
+
projectRoot: target.projectRoot,
|
|
62
|
+
vmDestroyed: destroyed
|
|
63
|
+
}, destroyed
|
|
64
|
+
? []
|
|
65
|
+
: [`${lease.hypervisor} destroy command failed; the lease was marked released anyway.`], [
|
|
66
|
+
`Lease ${lease.leaseId} marked released.`,
|
|
67
|
+
destroyed
|
|
68
|
+
? `${lease.hypervisor} domain ${lease.vmId} stopped.`
|
|
69
|
+
: `Manual \`${lease.hypervisor} stop ${lease.vmId}\` may be needed.`
|
|
70
|
+
]), options.json ?? false);
|
|
71
|
+
}
|
|
72
|
+
export function runVmRelease(io, options) {
|
|
73
|
+
try {
|
|
74
|
+
const projectRoot = options.project ?? findProjectRoot(process.cwd()) ?? process.cwd();
|
|
75
|
+
const sessionId = resolveVmSessionId(projectRoot, options.session);
|
|
76
|
+
const file = vmLeaseFilePath(joinPathSession(projectRoot, sessionId), options.leaseId);
|
|
77
|
+
const lease = readLeaseOrRefuse(io, options, file);
|
|
78
|
+
if (lease === null)
|
|
79
|
+
return;
|
|
80
|
+
if (lease.status === 'released') {
|
|
81
|
+
emitAlreadyReleased(io, options, { projectRoot, sessionId, file }, lease);
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
emitReleaseSuccess(io, options, { projectRoot, sessionId, file }, lease);
|
|
85
|
+
}
|
|
86
|
+
catch (err) {
|
|
87
|
+
printResult(io, fail('vm.release', 'RELEASE_FAILED', getErrorMessage(err), {
|
|
88
|
+
leaseId: options.leaseId,
|
|
89
|
+
sessionId: options.session ?? process.env.PEAKS_SESSION_ID ?? 'unknown-sid'
|
|
90
|
+
}, ['Verify the lease id and re-run.']), options.json ?? false);
|
|
91
|
+
process.exitCode = 1;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
export function registerVmReleaseCommand(cmd, io) {
|
|
95
|
+
addJsonOption(cmd
|
|
96
|
+
.command('release')
|
|
97
|
+
.description('Transition a VM lease to released and run the hypervisor destroy command. Idempotent on already-released leases.')
|
|
98
|
+
.requiredOption('--lease-id <id>', 'lease id returned by `peaks vm spawn`')
|
|
99
|
+
.option('--session <sid>', 'override session id')
|
|
100
|
+
.option('--project <path>', 'project root (default: findProjectRoot(cwd))')).action((options) => runVmRelease(io, options));
|
|
101
|
+
}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { Command } from 'commander';
|
|
2
|
+
import { type ProgramIO } from '../cli-helpers.js';
|
|
3
|
+
import { type SpawnOptions } from './vm-command-shared.js';
|
|
4
|
+
export declare function runVmSpawn(io: ProgramIO, options: SpawnOptions): void;
|
|
5
|
+
export declare function registerVmSpawnCommand(cmd: Command, io: ProgramIO): void;
|