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,43 @@
|
|
|
1
|
+
import { type PeaksHookEntry } from './hooks-codegate-superpowers.js';
|
|
2
|
+
import type { HookEntryTarget, HookMatcherEntry, HookTarget } from './hooks-settings-types.js';
|
|
3
|
+
/** True when `target` already holds everything the install would write to it. */
|
|
4
|
+
export declare function targetIsSatisfied(target: HookTarget, allSentinels: ReadonlyArray<string>): boolean;
|
|
5
|
+
/** Flatten the resolved targets into one `{ matcher, sentinel, settingsPath }` row per entry. */
|
|
6
|
+
export declare function describeEntryTargets(targets: ReadonlyArray<HookTarget>): HookEntryTarget[];
|
|
7
|
+
/** Read a settings file as an object, or `{}` when it does not exist yet. */
|
|
8
|
+
export declare function readSettingsFile(settingsPath: string): Record<string, unknown>;
|
|
9
|
+
/** Read the existing hook array entries for the adapter's hookEvent (tolerant of any prior shape). */
|
|
10
|
+
export declare function readHookEventEntries(settings: Record<string, unknown>, eventKey: string): HookMatcherEntry[];
|
|
11
|
+
/** Read the existing hook array entries from a `settings.hooks` object (already extracted). */
|
|
12
|
+
export declare function readHookEntriesFromHooks(hooks: Record<string, unknown>, eventKey: string): HookMatcherEntry[];
|
|
13
|
+
/** True when every command handler in the entry matches a known peaks sentinel for the given IDE. */
|
|
14
|
+
export declare function entryIsPeaksManaged(entry: HookMatcherEntry, sentinels: ReadonlyArray<string>): boolean;
|
|
15
|
+
export declare function isInstalledForEntries(settings: Record<string, unknown>, entries: ReadonlyArray<PeaksHookEntry>): boolean;
|
|
16
|
+
/**
|
|
17
|
+
* Slice #014: detect the "stale progress entry after pre-#014 install"
|
|
18
|
+
* case. The desired shape is gate-enforce-only. If the file currently
|
|
19
|
+
* has a peaks-managed progress-start entry (left behind by a pre-#014
|
|
20
|
+
* install), the install is NOT a no-op — it must strip the stale
|
|
21
|
+
* entry. This helper returns true exactly when the desired shape is
|
|
22
|
+
* fully reflected on disk: gate-enforce present AND no legacy
|
|
23
|
+
* progress-start present.
|
|
24
|
+
*/
|
|
25
|
+
export declare function shapeMatchesDesired(settings: Record<string, unknown>, entries: ReadonlyArray<PeaksHookEntry>, allPeaksSentinels: ReadonlyArray<string>): boolean;
|
|
26
|
+
/**
|
|
27
|
+
* Merge a target's peaks-managed hook entries into `settings`, preserving
|
|
28
|
+
* all other keys and hooks. Entries routed to a DIFFERENT settings file are
|
|
29
|
+
* not part of `entries`, so the legacy-sentinel filter below strips them
|
|
30
|
+
* from this file (that is what migrates a gate-enforce entry that an older
|
|
31
|
+
* peaks release wrote into the shared file).
|
|
32
|
+
*/
|
|
33
|
+
export declare function withHooksInstalled(settings: Record<string, unknown>, entries: ReadonlyArray<PeaksHookEntry>, allSentinels: ReadonlyArray<string>): Record<string, unknown>;
|
|
34
|
+
/**
|
|
35
|
+
* Strip every peaks-managed hook row from one target's settings file, on every
|
|
36
|
+
* event key the file carries — a pre-#014 install could have left the legacy
|
|
37
|
+
* progress-start entry on a different event than the gate-enforce one. Returns
|
|
38
|
+
* the rewritten settings plus whether anything was actually removed.
|
|
39
|
+
*/
|
|
40
|
+
export declare function stripPeaksEntries(target: HookTarget, sentinels: ReadonlyArray<string>): {
|
|
41
|
+
settings: Record<string, unknown>;
|
|
42
|
+
removed: boolean;
|
|
43
|
+
};
|
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Reading and comparing the hook rows a settings file actually holds.
|
|
3
|
+
*
|
|
4
|
+
* Split out of `hooks-settings-service.ts` (file-size cap campaign). The
|
|
5
|
+
* service re-exports every name declared here, so existing importers keep
|
|
6
|
+
* using `./hooks-settings-service.js` unchanged.
|
|
7
|
+
*/
|
|
8
|
+
import { existsSync } from 'node:fs';
|
|
9
|
+
import { readJsonObjectFile } from '../ide/shared/atomic-json.js';
|
|
10
|
+
import { hasExternalGateExemptions } from './hooks-codegate-superpowers.js';
|
|
11
|
+
/** True when `target` already holds everything the install would write to it. */
|
|
12
|
+
export function targetIsSatisfied(target, allSentinels) {
|
|
13
|
+
const settings = readSettingsFile(target.settingsPath);
|
|
14
|
+
if (!shapeMatchesDesired(settings, target.entries, allSentinels))
|
|
15
|
+
return false;
|
|
16
|
+
return target.envExemptions !== true || hasExternalGateExemptions(settings);
|
|
17
|
+
}
|
|
18
|
+
/** Flatten the resolved targets into one `{ matcher, sentinel, settingsPath }` row per entry. */
|
|
19
|
+
export function describeEntryTargets(targets) {
|
|
20
|
+
return targets.flatMap((target) => target.entries.map((entry) => ({
|
|
21
|
+
matcher: entry.matcher,
|
|
22
|
+
sentinel: entry.sentinel,
|
|
23
|
+
settingsPath: target.settingsPath
|
|
24
|
+
})));
|
|
25
|
+
}
|
|
26
|
+
/** Read a settings file as an object, or `{}` when it does not exist yet. */
|
|
27
|
+
export function readSettingsFile(settingsPath) {
|
|
28
|
+
return existsSync(settingsPath) ? readJsonObjectFile(settingsPath) : {};
|
|
29
|
+
}
|
|
30
|
+
/** Read the existing hook array entries for the adapter's hookEvent (tolerant of any prior shape). */
|
|
31
|
+
export function readHookEventEntries(settings, eventKey) {
|
|
32
|
+
const hooks = settings.hooks;
|
|
33
|
+
if (!hooks || typeof hooks !== 'object' || Array.isArray(hooks))
|
|
34
|
+
return [];
|
|
35
|
+
const arr = hooks[eventKey];
|
|
36
|
+
return Array.isArray(arr) ? arr : [];
|
|
37
|
+
}
|
|
38
|
+
/** Read the existing hook array entries from a `settings.hooks` object (already extracted). */
|
|
39
|
+
export function readHookEntriesFromHooks(hooks, eventKey) {
|
|
40
|
+
const arr = hooks[eventKey];
|
|
41
|
+
return Array.isArray(arr) ? arr : [];
|
|
42
|
+
}
|
|
43
|
+
/** True when every command handler in the entry matches a known peaks sentinel for the given IDE. */
|
|
44
|
+
export function entryIsPeaksManaged(entry, sentinels) {
|
|
45
|
+
const handlers = Array.isArray(entry?.hooks) ? entry.hooks : [];
|
|
46
|
+
if (handlers.length === 0)
|
|
47
|
+
return false;
|
|
48
|
+
return handlers.every((h) => {
|
|
49
|
+
if (typeof h?.command !== 'string')
|
|
50
|
+
return false;
|
|
51
|
+
const cmd = h.command;
|
|
52
|
+
return sentinels.some((sentinel) => cmd.includes(sentinel));
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
export function isInstalledForEntries(settings, entries) {
|
|
56
|
+
const sentinels = entries.map((e) => e.sentinel);
|
|
57
|
+
// Check every distinct event key our entries could be on.
|
|
58
|
+
const eventKeys = new Set(entries.map((e) => e.event));
|
|
59
|
+
for (const eventKey of eventKeys) {
|
|
60
|
+
if (readHookEventEntries(settings, eventKey).some((e) => entryIsPeaksManaged(e, sentinels))) {
|
|
61
|
+
return true;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
return false;
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Slice #014: detect the "stale progress entry after pre-#014 install"
|
|
68
|
+
* case. The desired shape is gate-enforce-only. If the file currently
|
|
69
|
+
* has a peaks-managed progress-start entry (left behind by a pre-#014
|
|
70
|
+
* install), the install is NOT a no-op — it must strip the stale
|
|
71
|
+
* entry. This helper returns true exactly when the desired shape is
|
|
72
|
+
* fully reflected on disk: gate-enforce present AND no legacy
|
|
73
|
+
* progress-start present.
|
|
74
|
+
*/
|
|
75
|
+
export function shapeMatchesDesired(settings, entries, allPeaksSentinels) {
|
|
76
|
+
const eventKeys = new Set(entries.map((e) => e.event));
|
|
77
|
+
for (const eventKey of eventKeys) {
|
|
78
|
+
// Only the entries that belong to THIS event key can be expected on it —
|
|
79
|
+
// the desired set must be per-event, or a target whose entries span two
|
|
80
|
+
// event keys (claude-code: SessionStart + PreToolUse) would never look
|
|
81
|
+
// installed and every `peaks hooks install` would rewrite the files.
|
|
82
|
+
const desiredSentinels = new Set(entries.filter((e) => e.event === eventKey).map((e) => e.sentinel));
|
|
83
|
+
const present = readHookEventEntries(settings, eventKey);
|
|
84
|
+
const peaksPresent = present.filter((e) => entryIsPeaksManaged(e, allPeaksSentinels));
|
|
85
|
+
// (a) every peaks-managed entry currently on disk must match the
|
|
86
|
+
// desired sentinel set (no stale entries the caller wants removed).
|
|
87
|
+
for (const entry of peaksPresent) {
|
|
88
|
+
const entrySentinels = (entry.hooks ?? [])
|
|
89
|
+
.map((h) => allPeaksSentinels.find((s) => String(h.command ?? '').includes(s)))
|
|
90
|
+
.filter((s) => Boolean(s));
|
|
91
|
+
if (entrySentinels.some((s) => !desiredSentinels.has(s))) {
|
|
92
|
+
return false;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
// (b) every desired entry must be on disk AND carry the matcher it declares.
|
|
96
|
+
// Presence alone cannot see a WRONG matcher, and a wrong matcher is not
|
|
97
|
+
// cosmetic: `''` and `Bash|Task` route the same command to different
|
|
98
|
+
// tool sets, so the entry is present while the hook never fires on the
|
|
99
|
+
// residual R2): a `PostCompact` entry hand-corrupted to matcher
|
|
100
|
+
// `auto|manual` survived `peaks hooks install` unchanged, and the
|
|
101
|
+
// installer was structurally unable to repair it.
|
|
102
|
+
// An absent matcher reads as `''` — the form Claude Code takes as "every
|
|
103
|
+
// source" — so a file written before matchers were explicit converges
|
|
104
|
+
// once instead of churning on every install.
|
|
105
|
+
for (const desired of entries.filter((e) => e.event === eventKey)) {
|
|
106
|
+
// The identity of a desired entry is the PAIR (sentinel, matcher), not the
|
|
107
|
+
// sentinel alone: one command may legitimately be installed under several
|
|
108
|
+
// matchers (the read-only MCP surface rides `peaks gate enforce` under its
|
|
109
|
+
// own matcher set). Matching on the sentinel first found that first entry
|
|
110
|
+
// every time, so the second one never looked installed and every install
|
|
111
|
+
// rewrote the file. A wrong matcher is still un-repaired — it fails to
|
|
112
|
+
// match and the caller rewrites.
|
|
113
|
+
const onDisk = peaksPresent.find((entry) => (entry.matcher ?? '') === desired.matcher &&
|
|
114
|
+
(entry.hooks ?? []).some((h) => String(h.command ?? '').includes(desired.sentinel)));
|
|
115
|
+
if (onDisk === undefined)
|
|
116
|
+
return false;
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
return true;
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* Merge a target's peaks-managed hook entries into `settings`, preserving
|
|
123
|
+
* all other keys and hooks. Entries routed to a DIFFERENT settings file are
|
|
124
|
+
* not part of `entries`, so the legacy-sentinel filter below strips them
|
|
125
|
+
* from this file (that is what migrates a gate-enforce entry that an older
|
|
126
|
+
* peaks release wrote into the shared file).
|
|
127
|
+
*/
|
|
128
|
+
export function withHooksInstalled(settings, entries, allSentinels) {
|
|
129
|
+
const existingHooks = settings.hooks && typeof settings.hooks === 'object' && !Array.isArray(settings.hooks)
|
|
130
|
+
? settings.hooks
|
|
131
|
+
: {};
|
|
132
|
+
// Our entries may sit on more than one event key. Group by event so each
|
|
133
|
+
// event array is independently merged.
|
|
134
|
+
const ourByEvent = new Map();
|
|
135
|
+
for (const spec of entries) {
|
|
136
|
+
const list = ourByEvent.get(spec.event) ?? [];
|
|
137
|
+
list.push(spec);
|
|
138
|
+
ourByEvent.set(spec.event, list);
|
|
139
|
+
}
|
|
140
|
+
// Slice #014: the legacy sentinel set includes the progress-start
|
|
141
|
+
// sentinel so a pre-#014 install's stale progress-start entry is
|
|
142
|
+
// stripped by the filter (the file converges on the new
|
|
143
|
+
// gate-enforce-only shape, idempotently). The desired set (passed
|
|
144
|
+
// in below) only contains the gate-enforce sentinel.
|
|
145
|
+
const nextHooks = { ...existingHooks };
|
|
146
|
+
// An event key this file used to carry but whose entries all moved to the
|
|
147
|
+
// other file still needs its stale peaks entries stripped.
|
|
148
|
+
const eventKeys = new Set([...ourByEvent.keys(), ...Object.keys(existingHooks)]);
|
|
149
|
+
for (const eventKey of eventKeys) {
|
|
150
|
+
const existing = readHookEntriesFromHooks(nextHooks, eventKey);
|
|
151
|
+
const nonPeaks = existing.filter((entry) => !entryIsPeaksManaged(entry, allSentinels));
|
|
152
|
+
const ourFormatted = (ourByEvent.get(eventKey) ?? []).map((spec) => ({
|
|
153
|
+
matcher: spec.matcher,
|
|
154
|
+
hooks: [
|
|
155
|
+
{
|
|
156
|
+
type: 'command',
|
|
157
|
+
command: spec.command,
|
|
158
|
+
...(spec.shell !== undefined ? { shell: spec.shell } : {})
|
|
159
|
+
}
|
|
160
|
+
]
|
|
161
|
+
}));
|
|
162
|
+
const merged = [...nonPeaks, ...ourFormatted];
|
|
163
|
+
if (merged.length > 0) {
|
|
164
|
+
nextHooks[eventKey] = merged;
|
|
165
|
+
}
|
|
166
|
+
else {
|
|
167
|
+
delete nextHooks[eventKey];
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
return {
|
|
171
|
+
...settings,
|
|
172
|
+
hooks: nextHooks
|
|
173
|
+
};
|
|
174
|
+
}
|
|
175
|
+
/**
|
|
176
|
+
* Strip every peaks-managed hook row from one target's settings file, on every
|
|
177
|
+
* event key the file carries — a pre-#014 install could have left the legacy
|
|
178
|
+
* progress-start entry on a different event than the gate-enforce one. Returns
|
|
179
|
+
* the rewritten settings plus whether anything was actually removed.
|
|
180
|
+
*/
|
|
181
|
+
export function stripPeaksEntries(target, sentinels) {
|
|
182
|
+
const settings = readJsonObjectFile(target.settingsPath);
|
|
183
|
+
const existingHooks = settings.hooks ?? {};
|
|
184
|
+
const eventKeys = new Set([...target.entries.map((e) => e.event), ...Object.keys(existingHooks)]);
|
|
185
|
+
const nextHooks = { ...existingHooks };
|
|
186
|
+
let removed = false;
|
|
187
|
+
for (const eventKey of eventKeys) {
|
|
188
|
+
const entries = readHookEntriesFromHooks(nextHooks, eventKey);
|
|
189
|
+
const kept = entries.filter((entry) => !entryIsPeaksManaged(entry, sentinels));
|
|
190
|
+
if (kept.length !== entries.length)
|
|
191
|
+
removed = true;
|
|
192
|
+
if (kept.length > 0) {
|
|
193
|
+
nextHooks[eventKey] = kept;
|
|
194
|
+
}
|
|
195
|
+
else {
|
|
196
|
+
delete nextHooks[eventKey];
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
const nextSettings = { ...settings };
|
|
200
|
+
if (Object.keys(nextHooks).length > 0) {
|
|
201
|
+
nextSettings.hooks = nextHooks;
|
|
202
|
+
}
|
|
203
|
+
else {
|
|
204
|
+
delete nextSettings.hooks;
|
|
205
|
+
}
|
|
206
|
+
return { settings: nextSettings, removed };
|
|
207
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { type HookScope } from '../ide/shared/safe-path.js';
|
|
2
|
+
import type { IdeId } from '../ide/ide-types.js';
|
|
3
|
+
/** Resolve settings root dir for a scope. */
|
|
4
|
+
export declare function resolveSettingsRoot(scope: HookScope, projectRoot: string | undefined): string;
|
|
5
|
+
export declare function assertSafeSettingsPathCompat(scope: HookScope, ide: IdeId, root: string, settingsPath: string): void;
|
|
6
|
+
/**
|
|
7
|
+
* Resolve the machine-local settings file an IDE may carry (e.g. Claude
|
|
8
|
+
* Code's `.claude/settings.local.json`), or `undefined` when there is none.
|
|
9
|
+
*
|
|
10
|
+
* B3(b) 2026-09-13: the machine-local layer is an adapter-DECLARED capability,
|
|
11
|
+
* not a name list. It used to be two hardcoded facts here — a `Set(['claude-code'])`
|
|
12
|
+
* membership test and the filename literal `'settings.local.json'` — i.e. a
|
|
13
|
+
* module that routes per-IDE was itself naming one IDE and one IDE's file.
|
|
14
|
+
* Both now read off the adapter that owns them
|
|
15
|
+
* (`IdeSettingsLocation.localSettingsFileName`), exactly as
|
|
16
|
+
* `auto-compact-dispatcher.ts` already did for the same field.
|
|
17
|
+
*
|
|
18
|
+
* Behaviour is UNCHANGED, and that was verified rather than assumed: over all
|
|
19
|
+
* nine registered `IdeId`s, `IDES_WITH_LOCAL_SETTINGS.has(id)` was `true` for
|
|
20
|
+
* exactly the ids whose adapter declares `localSettingsFileName` (claude-code
|
|
21
|
+
* alone, `'settings.local.json'`). So the set was an exact duplicate of a
|
|
22
|
+
* declaration the adapters already carried, not an independent policy — and
|
|
23
|
+
* a new adapter that declares the field now gets this path for free instead
|
|
24
|
+
* of being silently denied it.
|
|
25
|
+
*
|
|
26
|
+
* This ALSO removes a live instance of the vendor guard's limit 1 (indirect
|
|
27
|
+
* identity: `SET.has(ide)`), which no AST check over comparisons or literals
|
|
28
|
+
* can see. The guard's header named this exact line as the example.
|
|
29
|
+
*
|
|
30
|
+
* Global scope resolves to `undefined`: the global settings file
|
|
31
|
+
* (`~/.claude/settings.json`) is already machine-local, so nothing needs
|
|
32
|
+
* relocating there.
|
|
33
|
+
*/
|
|
34
|
+
export declare function resolveLocalSettingsPath(scope: HookScope, ide: IdeId, projectRoot: string | undefined): string | undefined;
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The safety checks on an IDE settings path, and the machine-local sibling.
|
|
3
|
+
*
|
|
4
|
+
* Split out of `hooks-settings-service.ts` (file-size cap campaign). The
|
|
5
|
+
* service re-exports every name declared here, so existing importers keep
|
|
6
|
+
* using `./hooks-settings-service.js` unchanged.
|
|
7
|
+
*/
|
|
8
|
+
import { homedir } from 'node:os';
|
|
9
|
+
import { join, resolve } from 'node:path';
|
|
10
|
+
import { assertSafeSettingsFile } from '../ide/shared/safe-path.js';
|
|
11
|
+
import { getAdapter } from '../ide/ide-registry.js';
|
|
12
|
+
/** Resolve settings root dir for a scope. */
|
|
13
|
+
export function resolveSettingsRoot(scope, projectRoot) {
|
|
14
|
+
if (scope === 'global')
|
|
15
|
+
return resolve(homedir());
|
|
16
|
+
if (!projectRoot) {
|
|
17
|
+
throw new Error('Project scope requires a project root');
|
|
18
|
+
}
|
|
19
|
+
return resolve(projectRoot);
|
|
20
|
+
}
|
|
21
|
+
export function assertSafeSettingsPathCompat(scope, ide, root, settingsPath) {
|
|
22
|
+
const adapter = getAdapter(ide);
|
|
23
|
+
assertSafeSettingsFile(scope, root, adapter.settings.dirName, adapter.settings.settingsFileName);
|
|
24
|
+
// The compat path receives the already-computed settingsPath; double-check
|
|
25
|
+
// that the computed path matches what assertSafeSettingsFile would have
|
|
26
|
+
// produced. This guards against drift between the two resolvers.
|
|
27
|
+
const expected = adapter.settings.resolveSettingsFile(scope, scope === 'global' ? homedir() : root);
|
|
28
|
+
if (expected !== settingsPath) {
|
|
29
|
+
throw new Error(`settings path drift: ${expected} vs ${settingsPath}`);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Resolve the machine-local settings file an IDE may carry (e.g. Claude
|
|
34
|
+
* Code's `.claude/settings.local.json`), or `undefined` when there is none.
|
|
35
|
+
*
|
|
36
|
+
* B3(b) 2026-09-13: the machine-local layer is an adapter-DECLARED capability,
|
|
37
|
+
* not a name list. It used to be two hardcoded facts here — a `Set(['claude-code'])`
|
|
38
|
+
* membership test and the filename literal `'settings.local.json'` — i.e. a
|
|
39
|
+
* module that routes per-IDE was itself naming one IDE and one IDE's file.
|
|
40
|
+
* Both now read off the adapter that owns them
|
|
41
|
+
* (`IdeSettingsLocation.localSettingsFileName`), exactly as
|
|
42
|
+
* `auto-compact-dispatcher.ts` already did for the same field.
|
|
43
|
+
*
|
|
44
|
+
* Behaviour is UNCHANGED, and that was verified rather than assumed: over all
|
|
45
|
+
* nine registered `IdeId`s, `IDES_WITH_LOCAL_SETTINGS.has(id)` was `true` for
|
|
46
|
+
* exactly the ids whose adapter declares `localSettingsFileName` (claude-code
|
|
47
|
+
* alone, `'settings.local.json'`). So the set was an exact duplicate of a
|
|
48
|
+
* declaration the adapters already carried, not an independent policy — and
|
|
49
|
+
* a new adapter that declares the field now gets this path for free instead
|
|
50
|
+
* of being silently denied it.
|
|
51
|
+
*
|
|
52
|
+
* This ALSO removes a live instance of the vendor guard's limit 1 (indirect
|
|
53
|
+
* identity: `SET.has(ide)`), which no AST check over comparisons or literals
|
|
54
|
+
* can see. The guard's header named this exact line as the example.
|
|
55
|
+
*
|
|
56
|
+
* Global scope resolves to `undefined`: the global settings file
|
|
57
|
+
* (`~/.claude/settings.json`) is already machine-local, so nothing needs
|
|
58
|
+
* relocating there.
|
|
59
|
+
*/
|
|
60
|
+
export function resolveLocalSettingsPath(scope, ide, projectRoot) {
|
|
61
|
+
if (scope === 'global')
|
|
62
|
+
return undefined;
|
|
63
|
+
const adapter = getAdapter(ide);
|
|
64
|
+
const localFileName = adapter.settings.localSettingsFileName;
|
|
65
|
+
// `undefined` = this IDE has no machine-local layer. Note the order: a
|
|
66
|
+
// caller reaching here with an id the registry does not know still throws
|
|
67
|
+
// from `getAdapter` above, exactly as it did before — every path into this
|
|
68
|
+
// function already called `getAdapter(ide)` via `resolveSettingsPath`, so
|
|
69
|
+
// no new throw path is introduced.
|
|
70
|
+
if (localFileName === undefined)
|
|
71
|
+
return undefined;
|
|
72
|
+
const root = resolveSettingsRoot(scope, projectRoot);
|
|
73
|
+
assertSafeSettingsFile(scope, root, adapter.settings.dirName, localFileName);
|
|
74
|
+
return join(root, adapter.settings.dirName, localFileName);
|
|
75
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* What `peaks hooks status` reports: the peaks-managed rows actually on disk.
|
|
3
|
+
*
|
|
4
|
+
* Split out of `hooks-settings-service.ts` (file-size cap campaign). The
|
|
5
|
+
* service re-exports every name declared here, so existing importers keep
|
|
6
|
+
* using `./hooks-settings-service.js` unchanged.
|
|
7
|
+
*/
|
|
8
|
+
import type { IdeId } from '../ide/ide-types.js';
|
|
9
|
+
/**
|
|
10
|
+
* Slice #014: read the *actually-installed* peaks-managed hook entries
|
|
11
|
+
* from a settings object. Replaces the pre-#014 `listInstalledEntriesForIde`
|
|
12
|
+
* helper in `hooks-commands.ts`, which returned the IDE-EXPECTED list
|
|
13
|
+
* (a hardcoded 2-entry array per adapter) rather than what was on disk.
|
|
14
|
+
* That bug surfaced when slice #013's local cleanup installed
|
|
15
|
+
* `peaks hooks install --no-progress` (gate-enforce only), but the
|
|
16
|
+
* status command still reported `entries: [Bash, Task]` because the
|
|
17
|
+
* helper didn't read the file.
|
|
18
|
+
*
|
|
19
|
+
* The new helper:
|
|
20
|
+
* 1. reads each `hooks.<event>` array,
|
|
21
|
+
* 2. filters to entries that are peaks-managed for the given IDE
|
|
22
|
+
* (matches the legacy sentinel set: gate-enforce + the no-longer-
|
|
23
|
+
* installed progress-start),
|
|
24
|
+
* 3. returns one `{ matcher, sentinel }` row per entry, taking the
|
|
25
|
+
* FIRST matching sentinel per entry (entries have a single command
|
|
26
|
+
* handler in practice, but the loop tolerates multi-handler
|
|
27
|
+
* entries by taking the first match).
|
|
28
|
+
*
|
|
29
|
+
* Pre-#014 settings.json files that have a stale progress-start entry
|
|
30
|
+
* will see it surface in the result. This is intentional: the status
|
|
31
|
+
* command is the user's tool for "what is on disk right now", and
|
|
32
|
+
* surfacing a stale entry is the only way the user can know to run
|
|
33
|
+
* `peaks hooks install` (which now strips it) or `peaks hooks
|
|
34
|
+
* uninstall` (which removes it).
|
|
35
|
+
*/
|
|
36
|
+
export declare function readInstalledEntriesFromSettings(settings: Record<string, unknown>, ide: IdeId): ReadonlyArray<{
|
|
37
|
+
matcher: string;
|
|
38
|
+
sentinel: string;
|
|
39
|
+
}>;
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { resolveLegacySentinels } from './hooks-codegate-superpowers.js';
|
|
2
|
+
import { entryIsPeaksManaged, readHookEntriesFromHooks } from './hooks-settings-file-shape.js';
|
|
3
|
+
/**
|
|
4
|
+
* Slice #014: read the *actually-installed* peaks-managed hook entries
|
|
5
|
+
* from a settings object. Replaces the pre-#014 `listInstalledEntriesForIde`
|
|
6
|
+
* helper in `hooks-commands.ts`, which returned the IDE-EXPECTED list
|
|
7
|
+
* (a hardcoded 2-entry array per adapter) rather than what was on disk.
|
|
8
|
+
* That bug surfaced when slice #013's local cleanup installed
|
|
9
|
+
* `peaks hooks install --no-progress` (gate-enforce only), but the
|
|
10
|
+
* status command still reported `entries: [Bash, Task]` because the
|
|
11
|
+
* helper didn't read the file.
|
|
12
|
+
*
|
|
13
|
+
* The new helper:
|
|
14
|
+
* 1. reads each `hooks.<event>` array,
|
|
15
|
+
* 2. filters to entries that are peaks-managed for the given IDE
|
|
16
|
+
* (matches the legacy sentinel set: gate-enforce + the no-longer-
|
|
17
|
+
* installed progress-start),
|
|
18
|
+
* 3. returns one `{ matcher, sentinel }` row per entry, taking the
|
|
19
|
+
* FIRST matching sentinel per entry (entries have a single command
|
|
20
|
+
* handler in practice, but the loop tolerates multi-handler
|
|
21
|
+
* entries by taking the first match).
|
|
22
|
+
*
|
|
23
|
+
* Pre-#014 settings.json files that have a stale progress-start entry
|
|
24
|
+
* will see it surface in the result. This is intentional: the status
|
|
25
|
+
* command is the user's tool for "what is on disk right now", and
|
|
26
|
+
* surfacing a stale entry is the only way the user can know to run
|
|
27
|
+
* `peaks hooks install` (which now strips it) or `peaks hooks
|
|
28
|
+
* uninstall` (which removes it).
|
|
29
|
+
*/
|
|
30
|
+
export function readInstalledEntriesFromSettings(settings, ide) {
|
|
31
|
+
const sentinels = resolveLegacySentinels(ide);
|
|
32
|
+
// Walk every event key the settings file has, not just the
|
|
33
|
+
// adapter-declared one. A pre-#014 install could have left a
|
|
34
|
+
// progress-start entry on a different event than the gate-enforce
|
|
35
|
+
// entry (Trae: both on beforeToolCall, but a stale install on a
|
|
36
|
+
// future IDE could split them).
|
|
37
|
+
const hooksRoot = settings.hooks;
|
|
38
|
+
if (!hooksRoot || typeof hooksRoot !== 'object' || Array.isArray(hooksRoot))
|
|
39
|
+
return [];
|
|
40
|
+
const result = [];
|
|
41
|
+
for (const eventKey of Object.keys(hooksRoot)) {
|
|
42
|
+
const entries = readHookEntriesFromHooks(hooksRoot, eventKey);
|
|
43
|
+
for (const entry of entries) {
|
|
44
|
+
if (!entryIsPeaksManaged(entry, sentinels))
|
|
45
|
+
continue;
|
|
46
|
+
const matcher = typeof entry.matcher === 'string' ? entry.matcher : '';
|
|
47
|
+
// Find the first matching sentinel inside the entry's command
|
|
48
|
+
// handlers. For each handler, find the first sentinel substring
|
|
49
|
+
// it contains. We pick the first handler's first matching
|
|
50
|
+
// sentinel (entries have a single command in practice).
|
|
51
|
+
const firstHandler = Array.isArray(entry.hooks) ? entry.hooks[0] : undefined;
|
|
52
|
+
const cmd = typeof firstHandler?.command === 'string' ? firstHandler.command : '';
|
|
53
|
+
const sentinel = sentinels.find((s) => cmd.includes(s));
|
|
54
|
+
if (matcher === '' || sentinel === undefined)
|
|
55
|
+
continue;
|
|
56
|
+
result.push({ matcher, sentinel });
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
return result;
|
|
60
|
+
}
|