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
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import { execSync } from 'node:child_process';
|
|
2
|
+
import { existsSync, readFileSync } from 'node:fs';
|
|
3
|
+
import { fail, getErrorMessage, ok } from 'peaks-loop-shared/result';
|
|
4
|
+
import { addJsonOption, printResult } from '../cli-helpers.js';
|
|
5
|
+
import { atomicWriteJson } from '../../services/ide/shared/atomic-json.js';
|
|
6
|
+
import { containerLeaseFilePath, deserializeContainerLease, markContainerReleased } from '../../services/container/container-lease.js';
|
|
7
|
+
import { detectContainerRuntime, joinPathSession, resolveContainerTarget } from './container-command-shared.js';
|
|
8
|
+
export function registerContainerReleaseCommand(cmd, io) {
|
|
9
|
+
addJsonOption(cmd
|
|
10
|
+
.command('release')
|
|
11
|
+
.description('Transition a container lease to released and run `docker rm --force`. Idempotent on already-released leases.')
|
|
12
|
+
.requiredOption('--lease-id <id>', 'lease id returned by `peaks container spawn`')
|
|
13
|
+
.option('--session <sid>', 'override session id')
|
|
14
|
+
.option('--project <path>', 'project root (default: findProjectRoot(cwd))')).action((options) => runContainerRelease(io, options));
|
|
15
|
+
}
|
|
16
|
+
/** Read + parse the lease file; `null` once the refusal is emitted. */
|
|
17
|
+
function readLease(io, options, file) {
|
|
18
|
+
if (!existsSync(file)) {
|
|
19
|
+
printResult(io, fail('container.release', 'LEASE_NOT_FOUND', `no lease on disk at ${file}`, {
|
|
20
|
+
leaseId: options.leaseId,
|
|
21
|
+
file
|
|
22
|
+
}, [
|
|
23
|
+
'Run `peaks container list` to inspect active leases.',
|
|
24
|
+
'For a never-spawned lease, this is a no-op — no further action needed.'
|
|
25
|
+
]), options.json);
|
|
26
|
+
process.exitCode = 1;
|
|
27
|
+
return null;
|
|
28
|
+
}
|
|
29
|
+
try {
|
|
30
|
+
return deserializeContainerLease(readFileSync(file, 'utf8'));
|
|
31
|
+
}
|
|
32
|
+
catch (err) {
|
|
33
|
+
printResult(io, fail('container.release', 'LEASE_FILE_INVALID', getErrorMessage(err), {
|
|
34
|
+
leaseId: options.leaseId,
|
|
35
|
+
file
|
|
36
|
+
}, [
|
|
37
|
+
'Delete the malformed lease file manually and re-issue spawn.',
|
|
38
|
+
'For security, release never fails open on a malformed lease.'
|
|
39
|
+
]), options.json);
|
|
40
|
+
process.exitCode = 1;
|
|
41
|
+
return null;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
/** `docker rm --force`, tolerating a container that is already gone. */
|
|
45
|
+
function removeContainer(lease, projectRoot) {
|
|
46
|
+
try {
|
|
47
|
+
const detected = detectContainerRuntime(undefined);
|
|
48
|
+
const runtimeCmd = detected.ok ? detected.runtime : 'docker';
|
|
49
|
+
execSync(`${runtimeCmd} rm --force "${lease.containerId}"`, {
|
|
50
|
+
cwd: projectRoot,
|
|
51
|
+
stdio: 'pipe',
|
|
52
|
+
encoding: 'utf8',
|
|
53
|
+
windowsHide: true
|
|
54
|
+
});
|
|
55
|
+
return false;
|
|
56
|
+
}
|
|
57
|
+
catch {
|
|
58
|
+
return true;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
function runContainerRelease(io, options) {
|
|
62
|
+
const { projectRoot, sessionId } = resolveContainerTarget(options);
|
|
63
|
+
try {
|
|
64
|
+
const file = containerLeaseFilePath(joinPathSession(projectRoot, sessionId), options.leaseId);
|
|
65
|
+
const lease = readLease(io, options, file);
|
|
66
|
+
if (lease === null)
|
|
67
|
+
return;
|
|
68
|
+
if (lease.status === 'released') {
|
|
69
|
+
printResult(io, ok('container.release', { lease, sessionId, projectRoot, alreadyReleased: true }, [], [`Lease ${lease.leaseId} already released; nothing to do.`]), options.json);
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
72
|
+
const outcome = releaseLease({ options, io, projectRoot, sessionId, file, lease });
|
|
73
|
+
printResult(io, ok('container.release', outcome.data, outcome.warnings, outcome.nextActions), options.json);
|
|
74
|
+
}
|
|
75
|
+
catch (err) {
|
|
76
|
+
printResult(io, fail('container.release', 'RELEASE_FAILED', getErrorMessage(err), {
|
|
77
|
+
leaseId: options.leaseId,
|
|
78
|
+
sessionId
|
|
79
|
+
}, ['Verify the lease id and re-run.', 'If the lease was never spawned, no-op.']), options.json);
|
|
80
|
+
process.exitCode = 1;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* `docker rm --force` the container, flip the lease to released and write it
|
|
85
|
+
* back. A failed `docker rm` is reported, not fatal: the lease is the source
|
|
86
|
+
* of truth and it is still marked released.
|
|
87
|
+
*/
|
|
88
|
+
function releaseLease(plan) {
|
|
89
|
+
const { projectRoot, sessionId, file, lease } = plan;
|
|
90
|
+
const dockerRmFailed = removeContainer(lease, projectRoot);
|
|
91
|
+
const released = markContainerReleased(lease);
|
|
92
|
+
atomicWriteJson(file, released);
|
|
93
|
+
return {
|
|
94
|
+
data: { lease: released, sessionId, projectRoot, dockerRmFailed },
|
|
95
|
+
warnings: dockerRmFailed
|
|
96
|
+
? ['docker rm failed (likely the container was already removed); lease marked released.']
|
|
97
|
+
: [],
|
|
98
|
+
nextActions: [
|
|
99
|
+
`Lease ${lease.leaseId} marked released.`,
|
|
100
|
+
dockerRmFailed
|
|
101
|
+
? 'Manual `docker ps -a` + `docker rm` may be needed.'
|
|
102
|
+
: `Container ${lease.containerId} removed.`
|
|
103
|
+
]
|
|
104
|
+
};
|
|
105
|
+
}
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
import { execSync } from 'node:child_process';
|
|
2
|
+
import { readFileSync } from 'node:fs';
|
|
3
|
+
import { fail, getErrorMessage, ok } from 'peaks-loop-shared/result';
|
|
4
|
+
import { addJsonOption, printResult } from '../cli-helpers.js';
|
|
5
|
+
import { atomicWriteJson } from '../../services/ide/shared/atomic-json.js';
|
|
6
|
+
import { normalizePath } from '../../shared/path-utils.js';
|
|
7
|
+
import { containerLeaseFilePath, finalizeContainerLease, generateContainerLeaseId, ttlForContainerRole } from '../../services/container/container-lease.js';
|
|
8
|
+
import { DEFAULT_DOCKER_IMAGE, detectContainerRuntime, joinPathSession, resolveContainerTarget } from './container-command-shared.js';
|
|
9
|
+
export function registerContainerSpawnCommand(cmd, io) {
|
|
10
|
+
addJsonOption(cmd
|
|
11
|
+
.command('spawn')
|
|
12
|
+
.description('Spawn a container via `docker run` and write a container lease. ' +
|
|
13
|
+
'The lease is the source of truth for the L4 PreToolUse gate (Part 12 follow-up). ' +
|
|
14
|
+
'Default TTL is role-aware (rd=30m / qa=15m / ui=1h); pass --ttl <ms> to override. ' +
|
|
15
|
+
'Default image is `node:22-slim`; pass --image <name> to override.')
|
|
16
|
+
.requiredOption('--rid <rid>', 'peaks request id the lease is associated with')
|
|
17
|
+
.requiredOption('--role <role>', 'sub-agent role (rd | qa | ui | sc | prd | general-purpose)')
|
|
18
|
+
.requiredOption('--purpose <text>', 'why this container was spawned (audit log)')
|
|
19
|
+
.option('--image <name>', `container image (default ${DEFAULT_DOCKER_IMAGE})`)
|
|
20
|
+
.option('--ttl <ms>', 'time-to-live in ms (default role-aware; override with positive number)')
|
|
21
|
+
.option('--mount <path>', 'host path to mount as the container working dir (default: <projectRoot>)')
|
|
22
|
+
.option('--session <sid>', 'override session id')
|
|
23
|
+
.option('--project <path>', 'project root (default: findProjectRoot(cwd))')).action((options) => runContainerSpawn(io, options));
|
|
24
|
+
}
|
|
25
|
+
/** The `--runtime` flag, narrowed to the two runtimes the adapter supports. */
|
|
26
|
+
function explicitRuntimeOf(options) {
|
|
27
|
+
if (options.runtime === 'docker')
|
|
28
|
+
return 'docker';
|
|
29
|
+
if (options.runtime === 'podman')
|
|
30
|
+
return 'podman';
|
|
31
|
+
return undefined;
|
|
32
|
+
}
|
|
33
|
+
/** Refuse `--runtime` when neither binary answers; `null` once refused. */
|
|
34
|
+
function requireRuntime(options, io, projectRoot, sessionId) {
|
|
35
|
+
const detected = detectContainerRuntime(explicitRuntimeOf(options));
|
|
36
|
+
if (detected.ok)
|
|
37
|
+
return detected;
|
|
38
|
+
printResult(io, fail('container.spawn', 'CONTAINER_RUNTIME_UNAVAILABLE', `${detected.stderr}: ${detected.hint}`, { rid: options.rid, role: options.role, sessionId }, [
|
|
39
|
+
'Install docker (Docker Desktop on macOS / Windows) or podman (RHEL / Fedora).',
|
|
40
|
+
'On Windows, ensure WSL2 backend is enabled and the daemon is running.',
|
|
41
|
+
'Pass --runtime docker|podman to force a specific runtime.'
|
|
42
|
+
]), options.json);
|
|
43
|
+
process.exitCode = 1;
|
|
44
|
+
return null;
|
|
45
|
+
}
|
|
46
|
+
/** Resolve `--ttl`, refusing a non-positive integer; `null` once refused. */
|
|
47
|
+
function requireTtl(options, io) {
|
|
48
|
+
const ttlMs = options.ttl === undefined
|
|
49
|
+
? ttlForContainerRole(options.role)
|
|
50
|
+
: Number.parseInt(options.ttl, 10);
|
|
51
|
+
if (Number.isInteger(ttlMs) && ttlMs > 0)
|
|
52
|
+
return ttlMs;
|
|
53
|
+
printResult(io, fail('container.spawn', 'INVALID_TTL', '--ttl must be a positive integer (ms)', { ttl: options.ttl }, ['Re-run with --ttl 1800000 (30 min) or omit to use role default.']), options.json);
|
|
54
|
+
process.exitCode = 1;
|
|
55
|
+
return null;
|
|
56
|
+
}
|
|
57
|
+
/** The worker root the cidfile lives in; `normalizePath` keeps Windows paths sane. */
|
|
58
|
+
function cidFileFor(plan) {
|
|
59
|
+
const root = normalizePath(joinPathSession(plan.projectRoot, plan.sessionId));
|
|
60
|
+
return `${root}/.${plan.detected.runtime}-cid-${plan.leaseId}`;
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* `docker run --rm -d` so the container is detached and auto-removed when
|
|
64
|
+
* stopped; `--cidfile` writes the container id to a file we read back. The
|
|
65
|
+
* `--label peaks.leaseId=<id>` lets `peaks container list` / `peaks container gc`
|
|
66
|
+
* find orphans by label when the lease file is missing.
|
|
67
|
+
*
|
|
68
|
+
* Returns the container id, or `null` once DOCKER_RUN_FAILED is emitted.
|
|
69
|
+
*/
|
|
70
|
+
function runDockerSpawn(plan) {
|
|
71
|
+
const { options, io, projectRoot, detected, image, mount } = plan;
|
|
72
|
+
const cidFile = cidFileFor(plan);
|
|
73
|
+
try {
|
|
74
|
+
execSync(`${detected.runtime} run --rm -d --cidfile "${cidFile}" --label "peaks.leaseId=${plan.leaseId}" --label "peaks.rid=${options.rid}" -v "${mount}:/work" -w /work ${image} sleep infinity`, { cwd: projectRoot, stdio: 'pipe', encoding: 'utf8', windowsHide: true });
|
|
75
|
+
}
|
|
76
|
+
catch (err) {
|
|
77
|
+
printResult(io, fail('container.spawn', 'DOCKER_RUN_FAILED', getErrorMessage(err), { rid: options.rid, image, runtime: detected.runtime, sessionId: plan.sessionId }, [
|
|
78
|
+
'Verify the image name is reachable on the configured registry.',
|
|
79
|
+
'Verify the host path is mounted correctly (Windows: the path must be visible to WSL2).',
|
|
80
|
+
`Run \`${detected.runtime} ps -a\` to inspect any leftover containers with the peaks.leaseId label.`
|
|
81
|
+
]), options.json);
|
|
82
|
+
process.exitCode = 1;
|
|
83
|
+
return null;
|
|
84
|
+
}
|
|
85
|
+
return readFileSync(cidFile, 'utf8').trim();
|
|
86
|
+
}
|
|
87
|
+
/** Write the lease and print the success envelope. */
|
|
88
|
+
function finishSpawn(plan, containerId) {
|
|
89
|
+
const { options, io, projectRoot, sessionId, detected, image, mount, leaseId, now, ttlMs } = plan;
|
|
90
|
+
const lease = finalizeContainerLease({
|
|
91
|
+
leaseId,
|
|
92
|
+
rid: options.rid,
|
|
93
|
+
role: options.role,
|
|
94
|
+
path: mount,
|
|
95
|
+
image,
|
|
96
|
+
containerId,
|
|
97
|
+
createdAt: now,
|
|
98
|
+
expiresAt: now + ttlMs,
|
|
99
|
+
purpose: options.purpose
|
|
100
|
+
});
|
|
101
|
+
atomicWriteJson(containerLeaseFilePath(joinPathSession(projectRoot, sessionId), leaseId), lease);
|
|
102
|
+
printResult(io, ok('container.spawn', {
|
|
103
|
+
lease,
|
|
104
|
+
sessionId,
|
|
105
|
+
projectRoot,
|
|
106
|
+
runtime: detected.runtime,
|
|
107
|
+
runtimeVersion: detected.binary,
|
|
108
|
+
nextActions: [
|
|
109
|
+
`Container id: ${containerId}`,
|
|
110
|
+
`Image: ${image}`,
|
|
111
|
+
`Lease expires at: ${new Date(lease.expiresAt).toISOString()}`,
|
|
112
|
+
'Run `peaks container release --lease-id <id>` when done'
|
|
113
|
+
]
|
|
114
|
+
}, [], []), options.json);
|
|
115
|
+
}
|
|
116
|
+
function runContainerSpawn(io, options) {
|
|
117
|
+
const { projectRoot, sessionId } = resolveContainerTarget(options);
|
|
118
|
+
try {
|
|
119
|
+
const detected = requireRuntime(options, io, projectRoot, sessionId);
|
|
120
|
+
if (detected === null)
|
|
121
|
+
return;
|
|
122
|
+
const ttlMs = requireTtl(options, io);
|
|
123
|
+
if (ttlMs === null)
|
|
124
|
+
return;
|
|
125
|
+
const plan = {
|
|
126
|
+
options,
|
|
127
|
+
io,
|
|
128
|
+
projectRoot,
|
|
129
|
+
sessionId,
|
|
130
|
+
detected,
|
|
131
|
+
image: options.image ?? DEFAULT_DOCKER_IMAGE,
|
|
132
|
+
mount: options.mount ?? projectRoot,
|
|
133
|
+
leaseId: generateContainerLeaseId(),
|
|
134
|
+
now: Date.now(),
|
|
135
|
+
ttlMs
|
|
136
|
+
};
|
|
137
|
+
const containerId = runDockerSpawn(plan);
|
|
138
|
+
if (containerId === null)
|
|
139
|
+
return;
|
|
140
|
+
finishSpawn(plan, containerId);
|
|
141
|
+
}
|
|
142
|
+
catch (err) {
|
|
143
|
+
printResult(io, fail('container.spawn', 'SPAWN_FAILED', getErrorMessage(err), { rid: options.rid, sessionId }, [
|
|
144
|
+
'See error message; if the lease was not written, retry after fixing the underlying issue.'
|
|
145
|
+
]), options.json);
|
|
146
|
+
process.exitCode = 1;
|
|
147
|
+
}
|
|
148
|
+
}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { fail, ok } from 'peaks-loop-shared/result';
|
|
2
|
+
import { addJsonOption, getErrorMessage, printResult } from '../cli-helpers.js';
|
|
3
|
+
import { formatMainSessionTriggerLogLine, pickMainSessionTrigger } from '../../services/context/main-session-monitor.js';
|
|
4
|
+
import { emitObservabilityEvent } from '../../services/observability/observability-service.js';
|
|
5
|
+
import { findProjectRoot } from '../../services/config/config-safety.js';
|
|
6
|
+
import { getSessionIdCanonical } from '../../services/session/session-manager.js';
|
|
7
|
+
import { capacityOf, requirePromptSize } from './context-status-command.js';
|
|
8
|
+
/** The `--in-flight-batch` seam: a sub-agent batch defers the trigger (D6.e). */
|
|
9
|
+
function inFlightOf(opts) {
|
|
10
|
+
return opts.inFlightBatch === true
|
|
11
|
+
? { hasInFlightBatch: true, sharedChannelEntries: 1 }
|
|
12
|
+
: undefined;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Observability hook #5/7. Fire-and-forget per PRD Q4; the synchronous emit
|
|
16
|
+
* never throws. Only fires when a session id is resolvable.
|
|
17
|
+
*/
|
|
18
|
+
function emitContextTrigger(trigger, promptSize) {
|
|
19
|
+
const projectRoot = findProjectRoot(process.cwd()) ?? process.cwd();
|
|
20
|
+
const sid = getSessionIdCanonical(projectRoot) ?? '';
|
|
21
|
+
if (sid.length === 0)
|
|
22
|
+
return;
|
|
23
|
+
emitObservabilityEvent({
|
|
24
|
+
schemaVersion: 1,
|
|
25
|
+
ts: new Date().toISOString(),
|
|
26
|
+
sessionId: sid,
|
|
27
|
+
category: 'context-trigger',
|
|
28
|
+
detail: {
|
|
29
|
+
kind: trigger.kind,
|
|
30
|
+
promptSize,
|
|
31
|
+
...(trigger.kind === 'soft-warn' || trigger.kind === 'compact'
|
|
32
|
+
? { ratio: trigger.ratio }
|
|
33
|
+
: {})
|
|
34
|
+
}
|
|
35
|
+
}, { projectRoot });
|
|
36
|
+
}
|
|
37
|
+
/** The single advisory line the tier decides. */
|
|
38
|
+
function triggerAdvice(trigger) {
|
|
39
|
+
if (trigger.kind === 'compact') {
|
|
40
|
+
return `Tier reached → trigger ${trigger.path} on ${trigger.ide} (code=${trigger.code})`;
|
|
41
|
+
}
|
|
42
|
+
if (trigger.kind === 'defer')
|
|
43
|
+
return `Deferred: ${trigger.reason}`;
|
|
44
|
+
if (trigger.kind === 'soft-warn') {
|
|
45
|
+
return `Soft warning at ${(trigger.ratio * 100).toFixed(0)}% (no trigger yet)`;
|
|
46
|
+
}
|
|
47
|
+
return 'Below threshold; no trigger';
|
|
48
|
+
}
|
|
49
|
+
export function registerContextCheckCommand(context, io) {
|
|
50
|
+
addJsonOption(context
|
|
51
|
+
.command('check')
|
|
52
|
+
.description('v2.11.0 D6: threshold check + IDE-aware trigger dispatch. With --auto-trigger, returns the trigger path the LLM should follow; without, returns a dry-run recommendation. The LLM is responsible for actually invoking the trigger (slash command, self-compress, or escalation).')
|
|
53
|
+
.requiredOption('--prompt-size <bytes>', 'estimated prompt size in bytes')
|
|
54
|
+
.option('--capacity <bytes>', 'override the 256K default capacity (test seam)', '262144')
|
|
55
|
+
.option('--in-flight-batch', 'a sub-agent batch is in flight (defer trigger per D6.e)', false)
|
|
56
|
+
.option('--auto-trigger', 'return the trigger path the LLM should follow', false)).action((opts) => {
|
|
57
|
+
try {
|
|
58
|
+
const promptSize = requirePromptSize('context.check', opts, io);
|
|
59
|
+
if (promptSize === null)
|
|
60
|
+
return;
|
|
61
|
+
const trigger = pickMainSessionTrigger({
|
|
62
|
+
promptSize,
|
|
63
|
+
capacityBytes: capacityOf(opts),
|
|
64
|
+
inFlightBatch: inFlightOf(opts)
|
|
65
|
+
});
|
|
66
|
+
emitContextTrigger(trigger, promptSize);
|
|
67
|
+
const payload = {
|
|
68
|
+
...trigger,
|
|
69
|
+
autoTrigger: opts.autoTrigger === true,
|
|
70
|
+
logLine: formatMainSessionTriggerLogLine(trigger, 'main')
|
|
71
|
+
};
|
|
72
|
+
printResult(io, ok('context.check', payload, [], [triggerAdvice(trigger)]), opts.json);
|
|
73
|
+
}
|
|
74
|
+
catch (err) {
|
|
75
|
+
printResult(io, fail('context.check', 'CONTEXT_CHECK_FAILED', getErrorMessage(err), null, [
|
|
76
|
+
'Verify --prompt-size is a non-negative number'
|
|
77
|
+
]), opts.json);
|
|
78
|
+
process.exitCode = 1;
|
|
79
|
+
}
|
|
80
|
+
});
|
|
81
|
+
}
|
|
@@ -1,11 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* peaks context * CLI (Slice #3 L1c) — context 4-layer loader.
|
|
3
3
|
*
|
|
4
|
-
* - L0: full read (every SKILL.md in full)
|
|
5
|
-
* - L1: summary (one paragraph per skill + the skill list)
|
|
6
|
-
* - L2: index (just names + paths)
|
|
7
|
-
* - L3: fuzzy search by query (delegates to peaks memory search)
|
|
8
|
-
*
|
|
9
4
|
* The LLM-side UX layer (peaks-code / peaks-ide) picks the layer based
|
|
10
5
|
* on the L1a task level:
|
|
11
6
|
* - typo: L0 only (a few lines)
|
|
@@ -15,6 +10,6 @@
|
|
|
15
10
|
* - migration: L0 + L1 + L2 + L3 + codegraph
|
|
16
11
|
*/
|
|
17
12
|
import type { Command } from 'commander';
|
|
18
|
-
import {
|
|
19
|
-
export type ContextLayer
|
|
13
|
+
import type { ProgramIO } from '../cli-helpers.js';
|
|
14
|
+
export type { ContextLayer } from './context-layer-fetchers.js';
|
|
20
15
|
export declare function registerContextCommands(program: Command, io: ProgramIO): void;
|
|
@@ -1,281 +1,11 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
* - L0: full read (every SKILL.md in full)
|
|
5
|
-
* - L1: summary (one paragraph per skill + the skill list)
|
|
6
|
-
* - L2: index (just names + paths)
|
|
7
|
-
* - L3: fuzzy search by query (delegates to peaks memory search)
|
|
8
|
-
*
|
|
9
|
-
* The LLM-side UX layer (peaks-code / peaks-ide) picks the layer based
|
|
10
|
-
* on the L1a task level:
|
|
11
|
-
* - typo: L0 only (a few lines)
|
|
12
|
-
* - bug: L0 + L1
|
|
13
|
-
* - feature: L0 + L1 + L2 + L3(按需)
|
|
14
|
-
* - refactor: L0 + L1 + L2 + L3
|
|
15
|
-
* - migration: L0 + L1 + L2 + L3 + codegraph
|
|
16
|
-
*/
|
|
17
|
-
import { existsSync, readFileSync, readdirSync } from 'node:fs';
|
|
18
|
-
import { join } from 'node:path';
|
|
19
|
-
import { searchMemory } from '../../services/memory/memory-search-service.js';
|
|
20
|
-
import { addJsonOption, getErrorMessage, printResult } from '../cli-helpers.js';
|
|
21
|
-
import { fail, ok } from 'peaks-loop-shared/result';
|
|
22
|
-
import { emitObservabilityEvent } from '../../services/observability/observability-service.js';
|
|
23
|
-
import { findProjectRoot } from '../../services/config/config-safety.js';
|
|
24
|
-
import { getSessionIdCanonical } from '../../services/session/session-manager.js';
|
|
25
|
-
import { evaluateMainSessionThreshold, pickMainSessionTrigger, formatMainSessionTriggerLogLine } from '../../services/context/main-session-monitor.js';
|
|
26
|
-
import { detectIdeFromEnv } from '../../services/context/ide-detect.js';
|
|
27
|
-
const SKILLS_DIR = 'skills';
|
|
28
|
-
function readSkillsDir(projectRoot) {
|
|
29
|
-
const skillsRoot = join(projectRoot, SKILLS_DIR);
|
|
30
|
-
if (!existsSync(skillsRoot))
|
|
31
|
-
return [];
|
|
32
|
-
const out = [];
|
|
33
|
-
for (const entry of readdirSync(skillsRoot, { withFileTypes: true })) {
|
|
34
|
-
if (!entry.isDirectory() || entry.name.startsWith('.'))
|
|
35
|
-
continue;
|
|
36
|
-
const skillMd = join(skillsRoot, entry.name, 'SKILL.md');
|
|
37
|
-
if (existsSync(skillMd)) {
|
|
38
|
-
out.push(`skills/${entry.name}/SKILL.md`);
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
return out;
|
|
42
|
-
}
|
|
43
|
-
function readSkillFile(projectRoot, relPath) {
|
|
44
|
-
const abs = join(projectRoot, relPath);
|
|
45
|
-
try {
|
|
46
|
-
return readFileSync(abs, 'utf-8');
|
|
47
|
-
}
|
|
48
|
-
catch {
|
|
49
|
-
return '';
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
async function fetchL0(projectRoot) {
|
|
53
|
-
const files = readSkillsDir(projectRoot);
|
|
54
|
-
const warnings = [];
|
|
55
|
-
let content = '';
|
|
56
|
-
let byteSize = 0;
|
|
57
|
-
const sizes = [];
|
|
58
|
-
for (const rel of files) {
|
|
59
|
-
const body = readSkillFile(projectRoot, rel);
|
|
60
|
-
if (body.length === 0) {
|
|
61
|
-
warnings.push(`failed to read ${rel}`);
|
|
62
|
-
continue;
|
|
63
|
-
}
|
|
64
|
-
content += `## ${rel}\n\n${body}\n\n`;
|
|
65
|
-
sizes.push({ path: rel, bytes: body.length });
|
|
66
|
-
byteSize += body.length;
|
|
67
|
-
}
|
|
68
|
-
return {
|
|
69
|
-
layer: 'L0',
|
|
70
|
-
description: 'full read: every SKILL.md concatenated',
|
|
71
|
-
files: sizes,
|
|
72
|
-
content,
|
|
73
|
-
byteSize,
|
|
74
|
-
warnings
|
|
75
|
-
};
|
|
76
|
-
}
|
|
77
|
-
async function fetchL1(projectRoot) {
|
|
78
|
-
const files = readSkillsDir(projectRoot);
|
|
79
|
-
const warnings = [];
|
|
80
|
-
let content = '';
|
|
81
|
-
let byteSize = 0;
|
|
82
|
-
const sizes = [];
|
|
83
|
-
for (const rel of files) {
|
|
84
|
-
const body = readSkillFile(projectRoot, rel);
|
|
85
|
-
if (body.length === 0) {
|
|
86
|
-
warnings.push(`failed to read ${rel}`);
|
|
87
|
-
continue;
|
|
88
|
-
}
|
|
89
|
-
const firstPara = body.split(/\r?\n\r?\n/, 2)[0] ?? body.slice(0, 400);
|
|
90
|
-
content += `## ${rel}\n\n${firstPara}\n\n`;
|
|
91
|
-
sizes.push({ path: rel, bytes: firstPara.length });
|
|
92
|
-
byteSize += firstPara.length;
|
|
93
|
-
}
|
|
94
|
-
return {
|
|
95
|
-
layer: 'L1',
|
|
96
|
-
description: 'summary: first paragraph per skill',
|
|
97
|
-
files: sizes,
|
|
98
|
-
content,
|
|
99
|
-
byteSize,
|
|
100
|
-
warnings
|
|
101
|
-
};
|
|
102
|
-
}
|
|
103
|
-
async function fetchL2(projectRoot) {
|
|
104
|
-
const files = readSkillsDir(projectRoot);
|
|
105
|
-
const content = files.map((f) => `- ${f}`).join('\n') + '\n';
|
|
106
|
-
const byteSize = content.length;
|
|
107
|
-
return {
|
|
108
|
-
layer: 'L2',
|
|
109
|
-
description: 'index: skill paths only (no body)',
|
|
110
|
-
files: files.map((f) => ({ path: f, bytes: 0 })),
|
|
111
|
-
content,
|
|
112
|
-
byteSize,
|
|
113
|
-
warnings: []
|
|
114
|
-
};
|
|
115
|
-
}
|
|
116
|
-
async function fetchL3(projectRoot, query) {
|
|
117
|
-
const warnings = [];
|
|
118
|
-
if (query.trim().length === 0) {
|
|
119
|
-
warnings.push('empty query; L3 requires a --query string for fuzzy search');
|
|
120
|
-
return {
|
|
121
|
-
layer: 'L3',
|
|
122
|
-
description: 'fuzzy search (empty query)',
|
|
123
|
-
files: [],
|
|
124
|
-
content: '',
|
|
125
|
-
byteSize: 0,
|
|
126
|
-
warnings
|
|
127
|
-
};
|
|
128
|
-
}
|
|
129
|
-
try {
|
|
130
|
-
const hits = searchMemory({ projectRoot, query, limit: 10 });
|
|
131
|
-
const lines = [];
|
|
132
|
-
for (const hit of hits) {
|
|
133
|
-
lines.push(`- [${hit.score.toFixed(2)}] ${hit.sourcePath}: ${hit.description.slice(0, 120)}`);
|
|
134
|
-
}
|
|
135
|
-
const content = lines.join('\n') + '\n';
|
|
136
|
-
return {
|
|
137
|
-
layer: 'L3',
|
|
138
|
-
description: 'fuzzy search: top 10 hits from memory index',
|
|
139
|
-
files: hits.map((h) => ({ path: h.sourcePath, bytes: h.description.length })),
|
|
140
|
-
content,
|
|
141
|
-
byteSize: content.length,
|
|
142
|
-
warnings
|
|
143
|
-
};
|
|
144
|
-
}
|
|
145
|
-
catch (error) {
|
|
146
|
-
return {
|
|
147
|
-
layer: 'L3',
|
|
148
|
-
description: 'fuzzy search (failed)',
|
|
149
|
-
files: [],
|
|
150
|
-
content: '',
|
|
151
|
-
byteSize: 0,
|
|
152
|
-
warnings: [`L3 search failed: ${getErrorMessage(error)}`]
|
|
153
|
-
};
|
|
154
|
-
}
|
|
155
|
-
}
|
|
1
|
+
import { registerContextCheckCommand } from './context-check-command.js';
|
|
2
|
+
import { registerContextLayerCommand } from './context-layer-command.js';
|
|
3
|
+
import { registerContextStatusCommand } from './context-status-command.js';
|
|
156
4
|
export function registerContextCommands(program, io) {
|
|
157
5
|
const context = program
|
|
158
6
|
.command('context')
|
|
159
7
|
.description('Slice L1c: context 4-layer loader (L0 full / L1 summary / L2 index / L3 fuzzy)');
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
.requiredOption('--project <path>', 'target project root')
|
|
164
|
-
.requiredOption('--level <L0|L1|L2|L3>', 'context layer to load')
|
|
165
|
-
.option('--query <text>', 'fuzzy search query (required for L3)')).action(async (options) => {
|
|
166
|
-
try {
|
|
167
|
-
const level = options.level;
|
|
168
|
-
if (level !== 'L0' && level !== 'L1' && level !== 'L2' && level !== 'L3') {
|
|
169
|
-
printResult(io, fail('context.layer', 'INVALID_LEVEL', `level must be one of L0, L1, L2, L3 (got ${level})`, { provided: level }, ['Pass --level L0|L1|L2|L3']), options.json);
|
|
170
|
-
process.exitCode = 1;
|
|
171
|
-
return;
|
|
172
|
-
}
|
|
173
|
-
let payload;
|
|
174
|
-
if (level === 'L0')
|
|
175
|
-
payload = await fetchL0(options.project);
|
|
176
|
-
else if (level === 'L1')
|
|
177
|
-
payload = await fetchL1(options.project);
|
|
178
|
-
else if (level === 'L2')
|
|
179
|
-
payload = await fetchL2(options.project);
|
|
180
|
-
else
|
|
181
|
-
payload = await fetchL3(options.project, options.query ?? '');
|
|
182
|
-
printResult(io, ok('context.layer', payload, [], [
|
|
183
|
-
`${payload.layer} loaded: ${payload.byteSize} bytes across ${payload.files.length} file(s)`,
|
|
184
|
-
payload.warnings.length > 0
|
|
185
|
-
? `${payload.warnings.length} warning(s); see envelope.warnings`
|
|
186
|
-
: null
|
|
187
|
-
].filter((x) => typeof x === 'string')), options.json);
|
|
188
|
-
}
|
|
189
|
-
catch (error) {
|
|
190
|
-
printResult(io, fail('context.layer', 'CONTEXT_LAYER_FAILED', getErrorMessage(error), { projectRoot: options.project }, ['Verify the project path and --level value']), options.json);
|
|
191
|
-
process.exitCode = 1;
|
|
192
|
-
}
|
|
193
|
-
});
|
|
194
|
-
addJsonOption(context
|
|
195
|
-
.command('status')
|
|
196
|
-
.description('v2.11.0 D6: report main-session threshold tier for a given prompt size (no trigger dispatched). Useful for `--json` probes before invoking `peaks context check --auto-trigger`.')
|
|
197
|
-
.requiredOption('--prompt-size <bytes>', 'estimated prompt size in bytes')
|
|
198
|
-
.option('--capacity <bytes>', 'override the 256K default capacity (test seam)', '262144')).action((opts) => {
|
|
199
|
-
try {
|
|
200
|
-
const promptSize = Number(opts.promptSize);
|
|
201
|
-
const capacity = opts.capacity !== undefined ? Number(opts.capacity) : undefined;
|
|
202
|
-
if (!Number.isFinite(promptSize) || promptSize < 0) {
|
|
203
|
-
printResult(io, fail('context.status', 'INVALID_PROMPT_SIZE', `prompt-size must be a non-negative number (got "${opts.promptSize}")`, { provided: opts.promptSize }, ['Pass --prompt-size <bytes>']), opts.json);
|
|
204
|
-
process.exitCode = 1;
|
|
205
|
-
return;
|
|
206
|
-
}
|
|
207
|
-
const evaluation = evaluateMainSessionThreshold(promptSize, capacity);
|
|
208
|
-
printResult(io, ok('context.status', { ...evaluation, ide: detectIdeFromEnv() }, [...evaluation.warnings], [`Main-session tier=${evaluation.tier} (${(evaluation.ratio * 100).toFixed(0)}%)`]), opts.json);
|
|
209
|
-
}
|
|
210
|
-
catch (err) {
|
|
211
|
-
printResult(io, fail('context.status', 'CONTEXT_STATUS_FAILED', getErrorMessage(err), null, [
|
|
212
|
-
'Verify --prompt-size is a non-negative number'
|
|
213
|
-
]), opts.json);
|
|
214
|
-
process.exitCode = 1;
|
|
215
|
-
}
|
|
216
|
-
});
|
|
217
|
-
addJsonOption(context
|
|
218
|
-
.command('check')
|
|
219
|
-
.description('v2.11.0 D6: threshold check + IDE-aware trigger dispatch. With --auto-trigger, returns the trigger path the LLM should follow; without, returns a dry-run recommendation. The LLM is responsible for actually invoking the trigger (slash command, self-compress, or escalation).')
|
|
220
|
-
.requiredOption('--prompt-size <bytes>', 'estimated prompt size in bytes')
|
|
221
|
-
.option('--capacity <bytes>', 'override the 256K default capacity (test seam)', '262144')
|
|
222
|
-
.option('--in-flight-batch', 'a sub-agent batch is in flight (defer trigger per D6.e)', false)
|
|
223
|
-
.option('--auto-trigger', 'return the trigger path the LLM should follow', false)).action((opts) => {
|
|
224
|
-
try {
|
|
225
|
-
const promptSize = Number(opts.promptSize);
|
|
226
|
-
const capacity = opts.capacity !== undefined ? Number(opts.capacity) : undefined;
|
|
227
|
-
if (!Number.isFinite(promptSize) || promptSize < 0) {
|
|
228
|
-
printResult(io, fail('context.check', 'INVALID_PROMPT_SIZE', `prompt-size must be a non-negative number (got "${opts.promptSize}")`, { provided: opts.promptSize }, ['Pass --prompt-size <bytes>']), opts.json);
|
|
229
|
-
process.exitCode = 1;
|
|
230
|
-
return;
|
|
231
|
-
}
|
|
232
|
-
const trigger = pickMainSessionTrigger({
|
|
233
|
-
promptSize,
|
|
234
|
-
capacityBytes: capacity,
|
|
235
|
-
inFlightBatch: opts.inFlightBatch === true
|
|
236
|
-
? { hasInFlightBatch: true, sharedChannelEntries: 1 }
|
|
237
|
-
: undefined
|
|
238
|
-
});
|
|
239
|
-
// Slice C of v2.11.1 — observability hook #5/7. Fire-and-forget
|
|
240
|
-
// per PRD Q4. The synchronous emit never throws.
|
|
241
|
-
const projectRoot = findProjectRoot(process.cwd()) ?? process.cwd();
|
|
242
|
-
const sid = getSessionIdCanonical(projectRoot) ?? '';
|
|
243
|
-
if (sid.length > 0) {
|
|
244
|
-
emitObservabilityEvent({
|
|
245
|
-
schemaVersion: 1,
|
|
246
|
-
ts: new Date().toISOString(),
|
|
247
|
-
sessionId: sid,
|
|
248
|
-
category: 'context-trigger',
|
|
249
|
-
detail: {
|
|
250
|
-
kind: trigger.kind,
|
|
251
|
-
promptSize,
|
|
252
|
-
...(trigger.kind === 'soft-warn' || trigger.kind === 'compact'
|
|
253
|
-
? { ratio: trigger.ratio }
|
|
254
|
-
: {})
|
|
255
|
-
}
|
|
256
|
-
}, { projectRoot });
|
|
257
|
-
}
|
|
258
|
-
const logLine = formatMainSessionTriggerLogLine(trigger, 'main');
|
|
259
|
-
const payload = {
|
|
260
|
-
...trigger,
|
|
261
|
-
autoTrigger: opts.autoTrigger === true,
|
|
262
|
-
logLine
|
|
263
|
-
};
|
|
264
|
-
printResult(io, ok('context.check', payload, [], [
|
|
265
|
-
trigger.kind === 'compact'
|
|
266
|
-
? `Tier reached → trigger ${trigger.path} on ${trigger.ide} (code=${trigger.code})`
|
|
267
|
-
: trigger.kind === 'defer'
|
|
268
|
-
? `Deferred: ${trigger.reason}`
|
|
269
|
-
: trigger.kind === 'soft-warn'
|
|
270
|
-
? `Soft warning at ${(trigger.ratio * 100).toFixed(0)}% (no trigger yet)`
|
|
271
|
-
: 'Below threshold; no trigger'
|
|
272
|
-
]), opts.json);
|
|
273
|
-
}
|
|
274
|
-
catch (err) {
|
|
275
|
-
printResult(io, fail('context.check', 'CONTEXT_CHECK_FAILED', getErrorMessage(err), null, [
|
|
276
|
-
'Verify --prompt-size is a non-negative number'
|
|
277
|
-
]), opts.json);
|
|
278
|
-
process.exitCode = 1;
|
|
279
|
-
}
|
|
280
|
-
});
|
|
8
|
+
registerContextLayerCommand(context, io);
|
|
9
|
+
registerContextStatusCommand(context, io);
|
|
10
|
+
registerContextCheckCommand(context, io);
|
|
281
11
|
}
|