peaks-loop 4.1.2 → 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 +136 -47
- package/CHANGELOG.md +112 -0
- package/README-en.md +1 -1
- package/README.md +1 -1
- package/contracts/readonly-argv-whitelist.json +211 -0
- 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/audit-artifact-runners.d.ts +16 -0
- package/dist/cli/commands/audit-artifact-runners.js +170 -0
- package/dist/cli/commands/audit-command-shared.d.ts +97 -0
- package/dist/cli/commands/audit-command-shared.js +60 -0
- package/dist/cli/commands/audit-commands.d.ts +7 -31
- package/dist/cli/commands/audit-commands.js +64 -473
- package/dist/cli/commands/audit-goal-runners.d.ts +17 -0
- package/dist/cli/commands/audit-goal-runners.js +114 -0
- package/dist/cli/commands/audit-red-lines-runners.d.ts +11 -0
- package/dist/cli/commands/audit-red-lines-runners.js +43 -0
- package/dist/cli/commands/audit-refusal-data.d.ts +23 -0
- package/dist/cli/commands/audit-refusal-data.js +69 -0
- package/dist/cli/commands/audit-static-runners.d.ts +13 -0
- package/dist/cli/commands/audit-static-runners.js +139 -0
- package/dist/cli/commands/await-runners.d.ts +11 -0
- package/dist/cli/commands/await-runners.js +148 -0
- package/dist/cli/commands/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-auto-compact-command.d.ts +3 -0
- package/dist/cli/commands/code-auto-compact-command.js +124 -0
- package/dist/cli/commands/code-auto-compact-envelope.d.ts +22 -0
- package/dist/cli/commands/code-auto-compact-envelope.js +39 -0
- package/dist/cli/commands/code-context-audit-command.d.ts +3 -0
- package/dist/cli/commands/code-context-audit-command.js +68 -0
- package/dist/cli/commands/code-context-now-command.d.ts +3 -0
- package/dist/cli/commands/code-context-now-command.js +124 -0
- package/dist/cli/commands/code-context-now-envelope.d.ts +66 -0
- package/dist/cli/commands/code-context-now-envelope.js +136 -0
- package/dist/cli/commands/code-context-now-mapping.d.ts +27 -0
- package/dist/cli/commands/code-context-now-mapping.js +43 -0
- package/dist/cli/commands/code-emit-handoff-command.d.ts +3 -0
- package/dist/cli/commands/code-emit-handoff-command.js +136 -0
- package/dist/cli/commands/code-gate-step-08-command.d.ts +3 -0
- package/dist/cli/commands/code-gate-step-08-command.js +155 -0
- package/dist/cli/commands/code-post-compact-detect-command.d.ts +3 -0
- package/dist/cli/commands/code-post-compact-detect-command.js +50 -0
- package/dist/cli/commands/code-runtime-commands.d.ts +9 -43
- package/dist/cli/commands/code-runtime-commands.js +20 -672
- package/dist/cli/commands/code-runtime-session.d.ts +1 -0
- package/dist/cli/commands/code-runtime-session.js +15 -0
- package/dist/cli/commands/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/compact-command.d.ts +6 -2
- package/dist/cli/commands/compact-command.js +12 -559
- package/dist/cli/commands/compact-dry-run-command.d.ts +3 -0
- package/dist/cli/commands/compact-dry-run-command.js +87 -0
- package/dist/cli/commands/compact-force-command.d.ts +3 -0
- package/dist/cli/commands/compact-force-command.js +98 -0
- package/dist/cli/commands/compact-harness-window-command.d.ts +3 -0
- package/dist/cli/commands/compact-harness-window-command.js +174 -0
- package/dist/cli/commands/compact-history-command.d.ts +3 -0
- package/dist/cli/commands/compact-history-command.js +89 -0
- package/dist/cli/commands/compact-read-commands.d.ts +3 -0
- package/dist/cli/commands/compact-read-commands.js +123 -0
- package/dist/cli/commands/compact-settle-command.d.ts +3 -0
- package/dist/cli/commands/compact-settle-command.js +130 -0
- package/dist/cli/commands/compact-shared.d.ts +9 -0
- package/dist/cli/commands/compact-shared.js +26 -0
- package/dist/cli/commands/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/skill-command.d.ts +1 -44
- package/dist/cli/commands/core/skill-command.js +13 -541
- package/dist/cli/commands/core/skill-context-verdict.d.ts +38 -0
- package/dist/cli/commands/core/skill-context-verdict.js +63 -0
- package/dist/cli/commands/core/skill-generated-config-notice.d.ts +41 -0
- package/dist/cli/commands/core/skill-generated-config-notice.js +75 -0
- package/dist/cli/commands/core/skill-heartbeat-commands.d.ts +3 -0
- package/dist/cli/commands/core/skill-heartbeat-commands.js +50 -0
- package/dist/cli/commands/core/skill-presence-commands.d.ts +3 -0
- package/dist/cli/commands/core/skill-presence-commands.js +123 -0
- package/dist/cli/commands/core/skill-presence-housekeeping-commands.d.ts +3 -0
- package/dist/cli/commands/core/skill-presence-housekeeping-commands.js +165 -0
- package/dist/cli/commands/core/skill-registry-commands.d.ts +3 -0
- package/dist/cli/commands/core/skill-registry-commands.js +117 -0
- package/dist/cli/commands/core/skill-runbook-command.d.ts +3 -0
- package/dist/cli/commands/core/skill-runbook-command.js +29 -0
- package/dist/cli/commands/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-command-spec.d.ts +2 -0
- package/dist/cli/commands/dispatch-command-spec.js +62 -0
- package/dist/cli/commands/dispatch-commands.js +159 -775
- package/dist/cli/commands/dispatch-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-detached-branch.d.ts +3 -0
- package/dist/cli/commands/dispatch-detached-branch.js +58 -0
- package/dist/cli/commands/dispatch-envelope.d.ts +36 -0
- package/dist/cli/commands/dispatch-envelope.js +104 -0
- package/dist/cli/commands/dispatch-from-dag.d.ts +27 -0
- package/dist/cli/commands/dispatch-from-dag.js +87 -257
- package/dist/cli/commands/dispatch-isolation-lease.d.ts +17 -0
- package/dist/cli/commands/dispatch-isolation-lease.js +149 -0
- package/dist/cli/commands/dispatch-preflight.d.ts +7 -0
- package/dist/cli/commands/dispatch-preflight.js +105 -0
- package/dist/cli/commands/dispatch-prompt-blocks.d.ts +10 -0
- package/dist/cli/commands/dispatch-prompt-blocks.js +56 -0
- package/dist/cli/commands/dispatch-prompt-composition.d.ts +30 -0
- package/dist/cli/commands/dispatch-prompt-composition.js +171 -0
- package/dist/cli/commands/dispatch-record-write.d.ts +24 -0
- package/dist/cli/commands/dispatch-record-write.js +96 -0
- package/dist/cli/commands/dispatch-tool-call.d.ts +15 -0
- package/dist/cli/commands/dispatch-tool-call.js +128 -0
- package/dist/cli/commands/evolution-command-shared.d.ts +78 -0
- package/dist/cli/commands/evolution-command-shared.js +107 -0
- package/dist/cli/commands/evolution-commands.d.ts +11 -1
- package/dist/cli/commands/evolution-commands.js +19 -350
- package/dist/cli/commands/evolution-evaluate-command.d.ts +24 -0
- package/dist/cli/commands/evolution-evaluate-command.js +138 -0
- package/dist/cli/commands/evolution-propose-command.d.ts +23 -0
- package/dist/cli/commands/evolution-propose-command.js +145 -0
- package/dist/cli/commands/evolution-status-command.d.ts +17 -0
- package/dist/cli/commands/evolution-status-command.js +41 -0
- package/dist/cli/commands/evolution-verdict-commands.d.ts +30 -0
- package/dist/cli/commands/evolution-verdict-commands.js +100 -0
- package/dist/cli/commands/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/finalize-accumulator.d.ts +44 -0
- package/dist/cli/commands/finalize-accumulator.js +55 -0
- package/dist/cli/commands/finalize-branches.d.ts +34 -0
- package/dist/cli/commands/finalize-branches.js +119 -0
- package/dist/cli/commands/finalize-runners.d.ts +3 -0
- package/dist/cli/commands/finalize-runners.js +92 -0
- package/dist/cli/commands/finalize-selection.d.ts +65 -0
- package/dist/cli/commands/finalize-selection.js +35 -0
- package/dist/cli/commands/gate-commands.js +26 -8
- package/dist/cli/commands/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/job-checkpoint-commands.d.ts +3 -0
- package/dist/cli/commands/job-checkpoint-commands.js +157 -0
- package/dist/cli/commands/job-command-shared.d.ts +109 -0
- package/dist/cli/commands/job-command-shared.js +72 -0
- package/dist/cli/commands/job-commands.d.ts +4 -64
- package/dist/cli/commands/job-commands.js +42 -552
- package/dist/cli/commands/job-cost-check-command.d.ts +3 -0
- package/dist/cli/commands/job-cost-check-command.js +41 -0
- package/dist/cli/commands/job-init-status-commands.d.ts +3 -0
- package/dist/cli/commands/job-init-status-commands.js +149 -0
- package/dist/cli/commands/job-run-commands.d.ts +3 -0
- package/dist/cli/commands/job-run-commands.js +97 -0
- package/dist/cli/commands/job-state-root.d.ts +35 -0
- package/dist/cli/commands/job-state-root.js +76 -0
- package/dist/cli/commands/loop-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-eval-capture-index.d.ts +4 -0
- package/dist/cli/commands/loop-eval-capture-index.js +44 -0
- package/dist/cli/commands/loop-eval-commands.d.ts +8 -5
- package/dist/cli/commands/loop-eval-commands.js +12 -626
- package/dist/cli/commands/loop-eval-eval-command.d.ts +3 -0
- package/dist/cli/commands/loop-eval-eval-command.js +168 -0
- package/dist/cli/commands/loop-eval-monotonic-command.d.ts +3 -0
- package/dist/cli/commands/loop-eval-monotonic-command.js +90 -0
- package/dist/cli/commands/loop-eval-parents.d.ts +7 -0
- package/dist/cli/commands/loop-eval-parents.js +20 -0
- package/dist/cli/commands/loop-eval-run-code.d.ts +7 -0
- package/dist/cli/commands/loop-eval-run-code.js +40 -0
- package/dist/cli/commands/loop-eval-run-command.d.ts +3 -0
- package/dist/cli/commands/loop-eval-run-command.js +113 -0
- package/dist/cli/commands/loop-eval-spec-commands.d.ts +3 -0
- package/dist/cli/commands/loop-eval-spec-commands.js +165 -0
- package/dist/cli/commands/loop-eval-spec-lint-command.d.ts +3 -0
- package/dist/cli/commands/loop-eval-spec-lint-command.js +42 -0
- package/dist/cli/commands/loop-eval-workflow-commands.d.ts +3 -0
- package/dist/cli/commands/loop-eval-workflow-commands.js +141 -0
- package/dist/cli/commands/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/mcp-commands.d.ts +10 -0
- package/dist/cli/commands/mcp-commands.js +157 -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/request-command-options.d.ts +49 -0
- package/dist/cli/commands/request-command-options.js +1 -0
- package/dist/cli/commands/request-commands.d.ts +3 -9
- package/dist/cli/commands/request-commands.js +17 -522
- package/dist/cli/commands/request-init-command.d.ts +3 -0
- package/dist/cli/commands/request-init-command.js +100 -0
- package/dist/cli/commands/request-lint-command.d.ts +3 -0
- package/dist/cli/commands/request-lint-command.js +50 -0
- package/dist/cli/commands/request-list-command.d.ts +10 -0
- package/dist/cli/commands/request-list-command.js +53 -0
- package/dist/cli/commands/request-repair-status-command.d.ts +3 -0
- package/dist/cli/commands/request-repair-status-command.js +61 -0
- package/dist/cli/commands/request-show-command.d.ts +3 -0
- package/dist/cli/commands/request-show-command.js +56 -0
- package/dist/cli/commands/request-transition-command.d.ts +3 -0
- package/dist/cli/commands/request-transition-command.js +122 -0
- package/dist/cli/commands/request-transition-failures.d.ts +8 -0
- package/dist/cli/commands/request-transition-failures.js +90 -0
- package/dist/cli/commands/request-transition-hooks.d.ts +50 -0
- package/dist/cli/commands/request-transition-hooks.js +115 -0
- package/dist/cli/commands/request-transition-preflight.d.ts +10 -0
- package/dist/cli/commands/request-transition-preflight.js +107 -0
- package/dist/cli/commands/scan-command-shared.d.ts +96 -0
- package/dist/cli/commands/scan-command-shared.js +83 -0
- package/dist/cli/commands/scan-commands.d.ts +3 -2
- package/dist/cli/commands/scan-commands.js +23 -463
- package/dist/cli/commands/scan-inventory-commands.d.ts +3 -0
- package/dist/cli/commands/scan-inventory-commands.js +96 -0
- package/dist/cli/commands/scan-project-commands.d.ts +3 -0
- package/dist/cli/commands/scan-project-commands.js +65 -0
- package/dist/cli/commands/scan-scope-commands.d.ts +3 -0
- package/dist/cli/commands/scan-scope-commands.js +149 -0
- package/dist/cli/commands/scan-scope-helpers.d.ts +8 -0
- package/dist/cli/commands/scan-scope-helpers.js +54 -0
- package/dist/cli/commands/scan-structural-commands.d.ts +3 -0
- package/dist/cli/commands/scan-structural-commands.js +113 -0
- package/dist/cli/commands/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/share-commands.d.ts +12 -68
- package/dist/cli/commands/share-commands.js +47 -556
- package/dist/cli/commands/share-error-hints.d.ts +14 -0
- package/dist/cli/commands/share-error-hints.js +38 -0
- package/dist/cli/commands/share-identity.d.ts +13 -0
- package/dist/cli/commands/share-identity.js +22 -0
- package/dist/cli/commands/share-record-paths.d.ts +37 -0
- package/dist/cli/commands/share-record-paths.js +68 -0
- package/dist/cli/commands/share-runners.d.ts +3 -0
- package/dist/cli/commands/share-runners.js +158 -0
- package/dist/cli/commands/shared-read-runners.d.ts +3 -0
- package/dist/cli/commands/shared-read-runners.js +51 -0
- package/dist/cli/commands/slice-check-command.d.ts +3 -0
- package/dist/cli/commands/slice-check-command.js +54 -0
- package/dist/cli/commands/slice-commands.d.ts +2 -22
- package/dist/cli/commands/slice-commands.js +18 -517
- package/dist/cli/commands/slice-decompose-artifacts.d.ts +18 -0
- package/dist/cli/commands/slice-decompose-artifacts.js +79 -0
- package/dist/cli/commands/slice-decompose-command.d.ts +3 -0
- package/dist/cli/commands/slice-decompose-command.js +123 -0
- package/dist/cli/commands/slice-list-commands.d.ts +3 -0
- package/dist/cli/commands/slice-list-commands.js +182 -0
- package/dist/cli/commands/slice-pick-command.d.ts +3 -0
- package/dist/cli/commands/slice-pick-command.js +60 -0
- package/dist/cli/commands/slice-plan-command.d.ts +24 -0
- package/dist/cli/commands/slice-plan-command.js +111 -0
- package/dist/cli/commands/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-commands.d.ts +10 -1
- package/dist/cli/commands/workflow-commands.js +6 -594
- package/dist/cli/commands/workflow-gate-commands.d.ts +3 -0
- package/dist/cli/commands/workflow-gate-commands.js +116 -0
- package/dist/cli/commands/workflow-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-plan-helpers.d.ts +48 -0
- package/dist/cli/commands/workflow-plan-helpers.js +103 -0
- package/dist/cli/commands/workflow-planning-commands.d.ts +3 -0
- package/dist/cli/commands/workflow-planning-commands.js +56 -0
- package/dist/cli/commands/workflow-swarm-actions.d.ts +7 -0
- package/dist/cli/commands/workflow-swarm-actions.js +109 -0
- package/dist/cli/commands/workflow-swarm-commands.d.ts +3 -0
- package/dist/cli/commands/workflow-swarm-commands.js +138 -0
- package/dist/cli/commands/workflow-tech-actions.d.ts +10 -0
- package/dist/cli/commands/workflow-tech-actions.js +150 -0
- package/dist/cli/commands/workflow-terminalize-command.d.ts +3 -0
- package/dist/cli/commands/workflow-terminalize-command.js +56 -0
- package/dist/cli/commands/workspace/init-actions.d.ts +10 -0
- package/dist/cli/commands/workspace/init-actions.js +199 -0
- package/dist/cli/commands/workspace/init-codegraph-stake.d.ts +10 -0
- package/dist/cli/commands/workspace/init-codegraph-stake.js +54 -0
- package/dist/cli/commands/workspace/init-command.d.ts +8 -124
- package/dist/cli/commands/workspace/init-command.js +59 -623
- package/dist/cli/commands/workspace/init-context.d.ts +58 -0
- package/dist/cli/commands/workspace/init-context.js +121 -0
- package/dist/cli/commands/workspace/init-envelope.d.ts +3 -0
- package/dist/cli/commands/workspace/init-envelope.js +34 -0
- package/dist/cli/commands/workspace/init-failures.d.ts +3 -0
- package/dist/cli/commands/workspace/init-failures.js +84 -0
- package/dist/cli/commands/workspace/init-hooks-decision.d.ts +24 -0
- package/dist/cli/commands/workspace/init-hooks-decision.js +189 -0
- package/dist/cli/commands/workspace/init-options.d.ts +102 -0
- package/dist/cli/commands/workspace/init-options.js +1 -0
- package/dist/cli/commands/worktree-lease-commands.d.ts +10 -6
- package/dist/cli/commands/worktree-lease-commands.js +42 -512
- package/dist/cli/commands/worktree-lease-gc-command.d.ts +12 -0
- package/dist/cli/commands/worktree-lease-gc-command.js +117 -0
- package/dist/cli/commands/worktree-lease-git.d.ts +22 -0
- package/dist/cli/commands/worktree-lease-git.js +48 -0
- package/dist/cli/commands/worktree-lease-list-command.d.ts +12 -0
- package/dist/cli/commands/worktree-lease-list-command.js +100 -0
- package/dist/cli/commands/worktree-lease-load.d.ts +37 -0
- package/dist/cli/commands/worktree-lease-load.js +28 -0
- package/dist/cli/commands/worktree-lease-release-command.d.ts +13 -0
- package/dist/cli/commands/worktree-lease-release-command.js +105 -0
- package/dist/cli/commands/worktree-lease-renew-command.d.ts +11 -0
- package/dist/cli/commands/worktree-lease-renew-command.js +99 -0
- package/dist/cli/commands/worktree-lease-session.d.ts +22 -0
- package/dist/cli/commands/worktree-lease-session.js +29 -0
- package/dist/cli/commands/worktree-lease-spawn-command.d.ts +11 -0
- package/dist/cli/commands/worktree-lease-spawn-command.js +119 -0
- package/dist/cli/commands/worktree-lease-status-command.d.ts +11 -0
- package/dist/cli/commands/worktree-lease-status-command.js +86 -0
- package/dist/cli/commands/worktree-lease-store.d.ts +19 -0
- package/dist/cli/commands/worktree-lease-store.js +24 -0
- package/dist/cli/program.js +5 -0
- package/dist/services/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/distribution/mcp-install-runner.d.ts +21 -0
- package/dist/services/distribution/mcp-install-runner.js +59 -0
- package/dist/services/distribution/mcp-install.d.ts +95 -0
- package/dist/services/distribution/mcp-install.js +179 -0
- package/dist/services/distribution/plugin-manifest.d.ts +97 -0
- package/dist/services/distribution/plugin-manifest.js +126 -0
- package/dist/services/hooks/mcp-surface-gate.d.ts +19 -0
- package/dist/services/hooks/mcp-surface-gate.js +87 -0
- package/dist/services/ide/adapters/claude-code-adapter.d.ts +4 -35
- package/dist/services/ide/adapters/claude-code-adapter.js +48 -171
- package/dist/services/ide/adapters/claude-code-local-state.d.ts +28 -0
- package/dist/services/ide/adapters/claude-code-local-state.js +112 -0
- package/dist/services/ide/adapters/claude-code-model-window.d.ts +37 -0
- package/dist/services/ide/adapters/claude-code-model-window.js +113 -0
- package/dist/services/ide/ide-mcp-install-types.d.ts +78 -0
- package/dist/services/ide/ide-mcp-install-types.js +104 -0
- package/dist/services/ide/ide-types.d.ts +45 -1
- package/dist/services/ide/mcp-tool-matcher.d.ts +34 -0
- package/dist/services/ide/mcp-tool-matcher.js +84 -0
- package/dist/services/lint/npx-resolver.js +7 -0
- package/dist/services/mcp/cli-executor.d.ts +36 -0
- package/dist/services/mcp/cli-executor.js +97 -0
- package/dist/services/mcp/json-rpc.d.ts +81 -0
- package/dist/services/mcp/json-rpc.js +116 -0
- package/dist/services/mcp/memory-tool.d.ts +3 -0
- package/dist/services/mcp/memory-tool.js +62 -0
- package/dist/services/mcp/server-main.d.ts +1 -0
- package/dist/services/mcp/server-main.js +66 -0
- package/dist/services/mcp/server.d.ts +22 -0
- package/dist/services/mcp/server.js +152 -0
- package/dist/services/mcp/surface.d.ts +62 -0
- package/dist/services/mcp/surface.js +198 -0
- package/dist/services/mcp/tool-core.d.ts +42 -0
- package/dist/services/mcp/tool-core.js +137 -0
- package/dist/services/mcp/tools.d.ts +13 -0
- package/dist/services/mcp/tools.js +58 -0
- package/dist/services/readonly-surface/argv-guard.d.ts +32 -0
- package/dist/services/readonly-surface/argv-guard.js +164 -0
- package/dist/services/readonly-surface/readonly-whitelist.d.ts +147 -0
- package/dist/services/readonly-surface/readonly-whitelist.js +107 -0
- package/dist/services/readonly-surface/whitelist-generator.d.ts +64 -0
- package/dist/services/readonly-surface/whitelist-generator.js +212 -0
- package/dist/services/skills/hooks-codegate-superpowers.d.ts +1 -0
- package/dist/services/skills/hooks-codegate-superpowers.js +26 -0
- package/dist/services/skills/hooks-settings-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 -649
- 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 +17 -6
- package/scripts/install-skills-bundles.mjs +233 -0
- package/scripts/install-skills-fs.mjs +148 -0
- package/scripts/install-skills-ide.mjs +279 -0
- package/scripts/install-skills-output-style-default.mjs +196 -0
- package/scripts/install-skills-output-styles.mjs +121 -0
- package/scripts/install-skills-report.mjs +42 -0
- package/scripts/install-skills-user-config.mjs +198 -0
- package/scripts/install-skills.mjs +36 -1066
- package/scripts/watch-tree.mjs +140 -0
- package/scripts/watch.mjs +4 -126
- package/skills/peaks-status/SKILL.md +31 -13
|
@@ -1,1071 +1,41 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
} from 'node:fs';
|
|
18
|
-
import { randomUUID } from 'node:crypto';
|
|
1
|
+
// scripts/install-skills.mjs
|
|
2
|
+
//
|
|
3
|
+
// The npm postinstall entry. What stays HERE, and why it cannot move:
|
|
4
|
+
//
|
|
5
|
+
// 1. The two per-platform fan-outs. Their `ideId === 'claude-code'` branches are the
|
|
6
|
+
// env-var override the 1.x-compat contract is written on, and they are pinned BY
|
|
7
|
+
// FILE NAME by `tests/unit/runtime/vendor-neutral-identity-guard.test.ts` — moving
|
|
8
|
+
// them would either drop a pinned decision or add one to a file the ratchet does
|
|
9
|
+
// not know about. Their bodies are unchanged.
|
|
10
|
+
// 2. The CLI entry block. It identifies its own path (`import.meta.url` against
|
|
11
|
+
// `process.argv[1]`), which is exactly what the module's own location means, so it
|
|
12
|
+
// cannot live anywhere else.
|
|
13
|
+
//
|
|
14
|
+
// Everything else moved to a sibling by responsibility; the public surface below is a
|
|
15
|
+
// re-export, so no importer changes.
|
|
16
|
+
//
|
|
19
17
|
import { homedir } from 'node:os';
|
|
20
|
-
import {
|
|
21
|
-
import {
|
|
22
|
-
|
|
23
|
-
// The canonical store — `~/.peaks/{skills,agents,output-styles}`. Skills are
|
|
24
|
-
// linked to it instead of to `<packageRoot>/skills/<name>`; see the loop in
|
|
25
|
-
// `installBundledSkills` for why the target moved and why repair is now
|
|
26
|
-
// unconditional. `canonical-store-link.mjs` is the same contract for the two
|
|
27
|
-
// families whose entry is a single FILE rather than a tree, and it is where the
|
|
28
|
-
// "the symlink was refused, here is the report" fallback lives. MUST both stay in
|
|
29
|
-
// `package.json#files`: this file IS the npm postinstall, and an unpublished
|
|
30
|
-
// sibling import breaks every user's install.
|
|
31
|
-
import { reconcileCanonicalEntry } from './canonical-store.mjs';
|
|
32
|
-
import { reconcileCanonicalFileEntry } from './canonical-store-link.mjs';
|
|
33
|
-
import { pruneBundledEntries } from './canonical-store-prune.mjs';
|
|
34
|
-
|
|
35
|
-
function getPathStats(path) {
|
|
36
|
-
try {
|
|
37
|
-
return lstatSync(path);
|
|
38
|
-
} catch {
|
|
39
|
-
return null;
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
function validateOpenFile(fd, path, errorMessage) {
|
|
44
|
-
const fdStats = fstatSync(fd);
|
|
45
|
-
const pathStats = lstatSync(path);
|
|
46
|
-
if (
|
|
47
|
-
!fdStats.isFile() ||
|
|
48
|
-
!pathStats.isFile() ||
|
|
49
|
-
fdStats.dev !== pathStats.dev ||
|
|
50
|
-
fdStats.ino !== pathStats.ino
|
|
51
|
-
) {
|
|
52
|
-
throw new Error(errorMessage);
|
|
53
|
-
}
|
|
54
|
-
if (fdStats.nlink !== 1 || pathStats.nlink !== 1) {
|
|
55
|
-
throw new Error(`${errorMessage}: hardlinked file`);
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
function getSafeReadOpenFlags() {
|
|
60
|
-
return typeof constants.O_NOFOLLOW === 'number'
|
|
61
|
-
? constants.O_RDONLY | constants.O_NOFOLLOW
|
|
62
|
-
: constants.O_RDONLY;
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
function readFileSafely(path, errorMessage) {
|
|
66
|
-
const fd = openSync(path, getSafeReadOpenFlags());
|
|
67
|
-
try {
|
|
68
|
-
validateOpenFile(fd, path, errorMessage);
|
|
69
|
-
return readFileSync(fd, 'utf8');
|
|
70
|
-
} finally {
|
|
71
|
-
closeSync(fd);
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
function validateInstallRoot(targetRoot, label) {
|
|
76
|
-
const rootStats = lstatSync(targetRoot);
|
|
77
|
-
if (rootStats.isSymbolicLink()) {
|
|
78
|
-
throw new Error(`${label} install root must not be a symlink`);
|
|
79
|
-
}
|
|
80
|
-
if (!rootStats.isDirectory()) {
|
|
81
|
-
throw new Error(`${label} install root must be a directory`);
|
|
82
|
-
}
|
|
83
|
-
return rootStats;
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
function createInstallRootValidator(targetRoot, label) {
|
|
87
|
-
const expectedStats = validateInstallRoot(targetRoot, label);
|
|
88
|
-
return () => {
|
|
89
|
-
const rootStats = validateInstallRoot(targetRoot, label);
|
|
90
|
-
if (rootStats.dev !== expectedStats.dev || rootStats.ino !== expectedStats.ino) {
|
|
91
|
-
throw new Error(`${label} install root changed during write`);
|
|
92
|
-
}
|
|
93
|
-
};
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
function createInstallResult() {
|
|
97
|
-
return { installed: [], skipped: [], pruned: [], fallbacks: [] };
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
function resolvePackageRoot(options = {}) {
|
|
101
|
-
return resolve(options.packageRoot ?? join(dirname(fileURLToPath(import.meta.url)), '..'));
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
function readPackageVersion(packageRoot = resolvePackageRoot()) {
|
|
105
|
-
const packageJson = JSON.parse(readFileSync(join(packageRoot, 'package.json'), 'utf8'));
|
|
106
|
-
if (typeof packageJson.version !== 'string' || packageJson.version.length === 0) {
|
|
107
|
-
throw new Error('package.json version must be a non-empty string');
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
return packageJson.version;
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
function createConfigDefaults(packageRoot) {
|
|
114
|
-
return {
|
|
115
|
-
version: readPackageVersion(packageRoot),
|
|
116
|
-
currentWorkspace: null,
|
|
117
|
-
workspaces: [],
|
|
118
|
-
language: 'en',
|
|
119
|
-
economyMode: true,
|
|
120
|
-
swarmMode: true,
|
|
121
|
-
tokens: {},
|
|
122
|
-
proxy: {}
|
|
123
|
-
};
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
function createConfigResult(overrides = {}) {
|
|
127
|
-
return { created: false, updated: false, skipped: false, ...overrides };
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
function isInsidePath(childPath, parentPath) {
|
|
131
|
-
const relativePath = relative(parentPath, childPath);
|
|
132
|
-
return relativePath === '' || (!relativePath.startsWith('..') && !isAbsolute(relativePath));
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
function isPlainObject(value) {
|
|
136
|
-
return value !== null && typeof value === 'object' && !Array.isArray(value);
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
function mergeMissingConfigValues(existing, defaults) {
|
|
140
|
-
return Object.entries(defaults).reduce(
|
|
141
|
-
(next, [key, defaultValue]) => {
|
|
142
|
-
if (!(key in next)) {
|
|
143
|
-
return { ...next, [key]: defaultValue };
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
const existingValue = next[key];
|
|
147
|
-
if (isPlainObject(existingValue) && isPlainObject(defaultValue)) {
|
|
148
|
-
return { ...next, [key]: mergeMissingConfigValues(existingValue, defaultValue) };
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
return next;
|
|
152
|
-
},
|
|
153
|
-
{ ...existing }
|
|
154
|
-
);
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
function readConfigFile(configPath, label) {
|
|
158
|
-
if (!existsSync(configPath)) {
|
|
159
|
-
return null;
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
try {
|
|
163
|
-
const parsed = JSON.parse(
|
|
164
|
-
readFileSafely(configPath, `${label} config path changed during read`)
|
|
165
|
-
);
|
|
166
|
-
if (!isPlainObject(parsed)) {
|
|
167
|
-
throw new Error(`${label} config must contain a JSON object`);
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
return parsed;
|
|
171
|
-
} catch (error) {
|
|
172
|
-
const message =
|
|
173
|
-
error instanceof SyntaxError
|
|
174
|
-
? `${label} config must contain valid JSON`
|
|
175
|
-
: error instanceof Error
|
|
176
|
-
? error.message
|
|
177
|
-
: String(error);
|
|
178
|
-
throw new Error(message);
|
|
179
|
-
}
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
function validateConfigPath(root, peaksRoot, configPath, label) {
|
|
183
|
-
const rootReal = realpathSync(root);
|
|
184
|
-
const peaksStats = lstatSync(peaksRoot);
|
|
185
|
-
const peaksReal = realpathSync(peaksRoot);
|
|
186
|
-
if (
|
|
187
|
-
!peaksStats.isDirectory() ||
|
|
188
|
-
peaksStats.isSymbolicLink() ||
|
|
189
|
-
peaksReal !== resolve(rootReal, '.peaks')
|
|
190
|
-
) {
|
|
191
|
-
throw new Error(`${label} config path must stay inside the ${label.toLowerCase()} root`);
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
const configStats = getPathStats(configPath);
|
|
195
|
-
if (configStats?.isSymbolicLink()) {
|
|
196
|
-
throw new Error(`${label} config path must not be a symlink`);
|
|
197
|
-
}
|
|
198
|
-
if (configStats && !configStats.isFile()) {
|
|
199
|
-
throw new Error(`${label} config path must be a file`);
|
|
200
|
-
}
|
|
201
|
-
if (configStats) {
|
|
202
|
-
if (configStats.nlink !== 1) {
|
|
203
|
-
throw new Error(`${label} config path must not be hardlinked`);
|
|
204
|
-
}
|
|
205
|
-
const configReal = realpathSync(configPath);
|
|
206
|
-
if (!isInsidePath(configReal, rootReal) || !isInsidePath(configReal, peaksReal)) {
|
|
207
|
-
throw new Error(`${label} config path must stay inside the ${label.toLowerCase()} root`);
|
|
208
|
-
}
|
|
209
|
-
}
|
|
210
|
-
}
|
|
211
|
-
|
|
212
|
-
function validateUserConfigPaths(userRoot, peaksRoot, configPath) {
|
|
213
|
-
validateConfigPath(userRoot, peaksRoot, configPath, 'User');
|
|
214
|
-
}
|
|
215
|
-
|
|
216
|
-
function getSafeTempOpenFlags() {
|
|
217
|
-
const baseFlags = constants.O_WRONLY | constants.O_CREAT | constants.O_EXCL;
|
|
218
|
-
return typeof constants.O_NOFOLLOW === 'number' ? baseFlags | constants.O_NOFOLLOW : baseFlags;
|
|
219
|
-
}
|
|
220
|
-
|
|
221
|
-
function writeFileAtomically(configPath, content, errorMessage, validateBeforeWrite) {
|
|
222
|
-
validateBeforeWrite();
|
|
223
|
-
|
|
224
|
-
const tempPath = `${configPath}.${process.pid}.${randomUUID()}.tmp`;
|
|
225
|
-
let fd = openSync(tempPath, getSafeTempOpenFlags(), 0o600);
|
|
226
|
-
let renamed = false;
|
|
227
|
-
let closeError = null;
|
|
228
|
-
try {
|
|
229
|
-
validateOpenFile(fd, tempPath, errorMessage);
|
|
230
|
-
fchmodSync(fd, 0o600);
|
|
231
|
-
writeFileSync(fd, content, 'utf8');
|
|
232
|
-
const writeFd = fd;
|
|
233
|
-
fd = null;
|
|
234
|
-
closeSync(writeFd);
|
|
235
|
-
validateBeforeWrite();
|
|
236
|
-
const readFd = openSync(tempPath, getSafeReadOpenFlags());
|
|
237
|
-
try {
|
|
238
|
-
validateOpenFile(readFd, tempPath, errorMessage);
|
|
239
|
-
} finally {
|
|
240
|
-
closeSync(readFd);
|
|
241
|
-
}
|
|
242
|
-
renameSync(tempPath, configPath);
|
|
243
|
-
renamed = true;
|
|
244
|
-
} finally {
|
|
245
|
-
if (fd !== null) {
|
|
246
|
-
try {
|
|
247
|
-
closeSync(fd);
|
|
248
|
-
} catch (error) {
|
|
249
|
-
closeError = error;
|
|
250
|
-
}
|
|
251
|
-
}
|
|
252
|
-
try {
|
|
253
|
-
if (!renamed && existsSync(tempPath)) {
|
|
254
|
-
unlinkSync(tempPath);
|
|
255
|
-
}
|
|
256
|
-
} finally {
|
|
257
|
-
if (closeError) {
|
|
258
|
-
throw closeError;
|
|
259
|
-
}
|
|
260
|
-
}
|
|
261
|
-
}
|
|
262
|
-
}
|
|
263
|
-
|
|
264
|
-
function writeUserConfig(userRoot, peaksRoot, configPath, content) {
|
|
265
|
-
writeFileAtomically(configPath, content, 'User config path changed during write', () =>
|
|
266
|
-
validateUserConfigPaths(userRoot, peaksRoot, configPath)
|
|
267
|
-
);
|
|
268
|
-
}
|
|
269
|
-
|
|
270
|
-
function resolveProjectRoot(options) {
|
|
271
|
-
const projectRoot = options.projectRoot ?? process.env.PEAKS_PROJECT_ROOT ?? process.env.INIT_CWD;
|
|
272
|
-
return projectRoot ? resolve(projectRoot) : null;
|
|
273
|
-
}
|
|
274
|
-
|
|
275
|
-
/**
|
|
276
|
-
* Slice #011: Detect the installed IDE for the postinstall dispatch layer.
|
|
277
|
-
*
|
|
278
|
-
* Mirrors `src/services/ide/ide-detector.ts:detectInstalledIde` (cwd heuristic)
|
|
279
|
-
* but inlined here because `install-skills.mjs` is a plain `.mjs` script and
|
|
280
|
-
* cannot import the TS service at runtime. The dispatch:
|
|
281
|
-
* - Look for `.claude`, `.trae`, `.codex`, `.cursor`, `.qoder`,
|
|
282
|
-
* `.tongyi-lingma` in the project root in that insertion order
|
|
283
|
-
* (matches the registry's adapter order in `src/services/ide/ide-registry.ts`).
|
|
284
|
-
* - Returns the first match, or `null` if no adapter's directory is present.
|
|
285
|
-
*
|
|
286
|
-
* If the resolved IDE has no `skillInstall` declared (Trae in slice 1.3.2),
|
|
287
|
-
* the caller falls back to the legacy `~/.claude/{skills,output-styles}` path
|
|
288
|
-
* + emits a stderr warning. The dispatch is conservative: the env-var
|
|
289
|
-
* overrides `PEAKS_CLAUDE_SKILLS_DIR` / `PEAKS_CLAUDE_OUTPUT_STYLES_DIR`
|
|
290
|
-
* continue to work, and the legacy default is preserved.
|
|
291
|
-
*
|
|
292
|
-
* 2026-09-15 (D12 fix): `hermes` and `openclaw` have install profiles in
|
|
293
|
-
* `IDE_SKILL_INSTALL_PROFILES` but were absent from this table. A profile
|
|
294
|
-
* that no detector can ever return is reachable only through the
|
|
295
|
-
* every-platform fan-out — i.e. it is installed for users who do NOT have
|
|
296
|
-
* the tool and skipped for nobody. Both are listed here now, so detection
|
|
297
|
-
* and installation answer the same question with the same table.
|
|
298
|
-
*
|
|
299
|
-
* This table is ALSO the presence oracle for `isPlatformPresent` below: a
|
|
300
|
-
* directory here in the project root means the user has that tool.
|
|
301
|
-
*/
|
|
302
|
-
export const IDE_DETECTION_DIRS = [
|
|
303
|
-
{ id: 'claude-code', dir: '.claude' },
|
|
304
|
-
{ id: 'trae', dir: '.trae' },
|
|
305
|
-
{ id: 'trae-cn', dir: '.trae-cn' },
|
|
306
|
-
{ id: 'codex', dir: '.codex' },
|
|
307
|
-
{ id: 'cursor', dir: '.cursor' },
|
|
308
|
-
{ id: 'qoder', dir: '.qoder' },
|
|
309
|
-
{ id: 'tongyi-lingma', dir: '.tongyi-lingma' },
|
|
310
|
-
{ id: 'zcode', dir: '.zcode' },
|
|
311
|
-
{ id: 'hermes', dir: '.hermes' },
|
|
312
|
-
{ id: 'openclaw', dir: '.openclaw' }
|
|
313
|
-
];
|
|
314
|
-
|
|
315
|
-
/**
|
|
316
|
-
* Per-IDE skill install paths. Per peaks-loop tenet
|
|
317
|
-
* "minimal-user-operation" (2026-06-11), the user should
|
|
318
|
-
* never have to run a per-platform install command — the
|
|
319
|
-
* `npm i -g peaks-loop` postinstall iterates the platforms
|
|
320
|
-
* the user HAS and symlinks the peaks-* skill family into each
|
|
321
|
-
* (see `isPlatformPresent`; D9/2026-09-15 made "has" load-bearing).
|
|
322
|
-
*
|
|
323
|
-
* 1.x had only `claude-code` (the other 5 entries were
|
|
324
|
-
* `null`); real Trae users reported the Trae skill
|
|
325
|
-
* directory was never populated. 2.0 fixes this by giving
|
|
326
|
-
* every platform a canonical install path.
|
|
327
|
-
*/
|
|
328
|
-
export const IDE_SKILL_INSTALL_PROFILES = {
|
|
329
|
-
'claude-code': {
|
|
330
|
-
// `alwaysPresent` — see `isPlatformPresent`. Declared HERE, in the
|
|
331
|
-
// vendor's own row, rather than as an `ideId === 'claude-code'` branch in
|
|
332
|
-
// the consumer: the guard at
|
|
333
|
-
// `tests/unit/runtime/vendor-neutral-identity-guard.test.ts` pins identity
|
|
334
|
-
// DECISIONS to the vendor declarations, and a comparison in the consumer
|
|
335
|
-
// is exactly the re-injection shape it exists to catch. A future vendor
|
|
336
|
-
// opts into the same policy by setting this field.
|
|
337
|
-
alwaysPresent: true,
|
|
338
|
-
skillsDir: join(homedir(), '.claude', 'skills'),
|
|
339
|
-
outputStylesDir: join(homedir(), '.claude', 'output-styles'),
|
|
340
|
-
agentsDir: join(homedir(), '.claude', 'agents'),
|
|
341
|
-
envVar: 'PEAKS_CLAUDE_SKILLS_DIR',
|
|
342
|
-
outputStylesEnvVar: 'PEAKS_CLAUDE_OUTPUT_STYLES_DIR',
|
|
343
|
-
agentsEnvVar: 'PEAKS_CLAUDE_AGENTS_DIR'
|
|
344
|
-
},
|
|
345
|
-
trae: {
|
|
346
|
-
skillsDir: join(homedir(), '.trae', 'skills'),
|
|
347
|
-
outputStylesDir: join(homedir(), '.trae', 'output-styles'),
|
|
348
|
-
agentsDir: join(homedir(), '.trae', 'agents'),
|
|
349
|
-
envVar: 'PEAKS_TRAE_SKILLS_DIR',
|
|
350
|
-
outputStylesEnvVar: 'PEAKS_TRAE_OUTPUT_STYLES_DIR',
|
|
351
|
-
agentsEnvVar: 'PEAKS_TRAE_AGENTS_DIR'
|
|
352
|
-
},
|
|
353
|
-
'trae-cn': {
|
|
354
|
-
skillsDir: join(homedir(), '.trae-cn', 'skills'),
|
|
355
|
-
outputStylesDir: join(homedir(), '.trae-cn', 'output-styles'),
|
|
356
|
-
agentsDir: join(homedir(), '.trae-cn', 'agents'),
|
|
357
|
-
envVar: 'PEAKS_TRAE_CN_SKILLS_DIR',
|
|
358
|
-
outputStylesEnvVar: 'PEAKS_TRAE_CN_OUTPUT_STYLES_DIR',
|
|
359
|
-
agentsEnvVar: 'PEAKS_TRAE_CN_AGENTS_DIR'
|
|
360
|
-
},
|
|
361
|
-
codex: {
|
|
362
|
-
skillsDir: join(homedir(), '.codex', 'skills'),
|
|
363
|
-
outputStylesDir: join(homedir(), '.codex', 'output-styles'),
|
|
364
|
-
agentsDir: join(homedir(), '.codex', 'agents'),
|
|
365
|
-
envVar: 'PEAKS_CODEX_SKILLS_DIR',
|
|
366
|
-
outputStylesEnvVar: 'PEAKS_CODEX_OUTPUT_STYLES_DIR',
|
|
367
|
-
agentsEnvVar: 'PEAKS_CODEX_AGENTS_DIR'
|
|
368
|
-
},
|
|
369
|
-
cursor: {
|
|
370
|
-
skillsDir: join(homedir(), '.cursor', 'skills'),
|
|
371
|
-
outputStylesDir: join(homedir(), '.cursor', 'output-styles'),
|
|
372
|
-
agentsDir: join(homedir(), '.cursor', 'agents'),
|
|
373
|
-
envVar: 'PEAKS_CURSOR_SKILLS_DIR',
|
|
374
|
-
outputStylesEnvVar: 'PEAKS_CURSOR_OUTPUT_STYLES_DIR',
|
|
375
|
-
agentsEnvVar: 'PEAKS_CURSOR_AGENTS_DIR'
|
|
376
|
-
},
|
|
377
|
-
qoder: {
|
|
378
|
-
skillsDir: join(homedir(), '.qoder', 'skills'),
|
|
379
|
-
outputStylesDir: join(homedir(), '.qoder', 'output-styles'),
|
|
380
|
-
envVar: 'PEAKS_QODER_SKILLS_DIR',
|
|
381
|
-
outputStylesEnvVar: 'PEAKS_QODER_OUTPUT_STYLES_DIR'
|
|
382
|
-
},
|
|
383
|
-
'tongyi-lingma': {
|
|
384
|
-
skillsDir: join(homedir(), '.tongyi-lingma', 'skills'),
|
|
385
|
-
outputStylesDir: join(homedir(), '.tongyi-lingma', 'output-styles'),
|
|
386
|
-
envVar: 'PEAKS_TONGYI_SKILLS_DIR',
|
|
387
|
-
outputStylesEnvVar: 'PEAKS_TONGYI_OUTPUT_STYLES_DIR'
|
|
388
|
-
},
|
|
389
|
-
hermes: {
|
|
390
|
-
skillsDir: join(homedir(), '.hermes', 'skills'),
|
|
391
|
-
outputStylesDir: join(homedir(), '.hermes', 'output-styles'),
|
|
392
|
-
envVar: 'PEAKS_HERMES_SKILLS_DIR',
|
|
393
|
-
outputStylesEnvVar: 'PEAKS_HERMES_OUTPUT_STYLES_DIR'
|
|
394
|
-
},
|
|
395
|
-
openclaw: {
|
|
396
|
-
skillsDir: join(homedir(), '.openclaw', 'skills'),
|
|
397
|
-
outputStylesDir: join(homedir(), '.openclaw', 'output-styles'),
|
|
398
|
-
envVar: 'PEAKS_OPENCLAW_SKILLS_DIR',
|
|
399
|
-
outputStylesEnvVar: 'PEAKS_OPENCLAW_OUTPUT_STYLES_DIR'
|
|
400
|
-
},
|
|
401
|
-
zcode: {
|
|
402
|
-
skillsDir: join(homedir(), '.zcode', 'skills'),
|
|
403
|
-
outputStylesDir: join(homedir(), '.zcode', 'output-styles'),
|
|
404
|
-
agentsDir: join(homedir(), '.zcode', 'agents'),
|
|
405
|
-
envVar: 'PEAKS_ZCODE_SKILLS_DIR',
|
|
406
|
-
outputStylesEnvVar: 'PEAKS_ZCODE_OUTPUT_STYLES_DIR',
|
|
407
|
-
agentsEnvVar: 'PEAKS_ZCODE_AGENTS_DIR'
|
|
408
|
-
}
|
|
409
|
-
};
|
|
410
|
-
|
|
411
|
-
function detectInstalledIdeId(projectRoot) {
|
|
412
|
-
if (!projectRoot) return null;
|
|
413
|
-
for (const { id, dir } of IDE_DETECTION_DIRS) {
|
|
414
|
-
if (existsSync(join(projectRoot, dir))) {
|
|
415
|
-
return id;
|
|
416
|
-
}
|
|
417
|
-
}
|
|
418
|
-
return null;
|
|
419
|
-
}
|
|
420
|
-
|
|
421
|
-
function resolveIdeSkillInstallProfile(ideId) {
|
|
422
|
-
if (ideId === null) return null;
|
|
423
|
-
return IDE_SKILL_INSTALL_PROFILES[ideId] ?? null;
|
|
424
|
-
}
|
|
425
|
-
|
|
426
|
-
/**
|
|
427
|
-
* Is this platform actually installed FOR? (D9 fix, 2026-09-15.)
|
|
428
|
-
*
|
|
429
|
-
* Before this gate, the postinstall ran `mkdirSync(targetRoot, {recursive:
|
|
430
|
-
* true})` for ALL 10 profiles unconditionally, so `npm i -g peaks-loop` created
|
|
431
|
-
* `~/.hermes`, `~/.openclaw`, `~/.qoder`, `~/.tongyi-lingma` and `~/.zcode` in
|
|
432
|
-
* the home of a user who has never installed those tools. The peaks-loop tenet
|
|
433
|
-
* is "the user never has to run a per-platform install command" — it is NOT
|
|
434
|
-
* "peaks-loop guesses which tools you have". Creating a directory for a tool
|
|
435
|
-
* the user does not own is the tenet misread, and it is visible on disk.
|
|
436
|
-
*
|
|
437
|
-
* Present means EITHER:
|
|
438
|
-
* - the tool's marker directory exists in the project root (the same
|
|
439
|
-
* directory `detectInstalledIdeId` consults above), OR
|
|
440
|
-
* - the tool's own home directory (`~/.<tool>`, derived from its profile)
|
|
441
|
-
* already exists on this machine.
|
|
442
|
-
*
|
|
443
|
-
* `claude-code` is unconditionally present: it is peaks-loop's primary runtime
|
|
444
|
-
* and the documented legacy install target, so a machine with no `~/.claude`
|
|
445
|
-
* yet still gets the trees the user is installing peaks-loop for. That fact is
|
|
446
|
-
* declared as `alwaysPresent: true` IN THE VENDOR'S OWN PROFILE ROW — not as an
|
|
447
|
-
* `ideId === 'claude-code'` branch here. This file sits outside the adapter
|
|
448
|
-
* layer, so an identity comparison in it is the re-injection shape
|
|
449
|
-
* `tests/unit/runtime/vendor-neutral-identity-guard.test.ts` pins; reading the
|
|
450
|
-
* vendor's declaration keeps the policy in one place and vendor-neutral.
|
|
451
|
-
*
|
|
452
|
-
* A named target bypasses this gate entirely — `options.targetRoot`,
|
|
453
|
-
* `options.ideId`, and the `PEAKS_<TOOL>_SKILLS_DIR` env vars are callers who
|
|
454
|
-
* have already said which platform they mean; guessing a second time there
|
|
455
|
-
* would break the 1.x back-compat contract that slice 2026-06-12 restored.
|
|
456
|
-
*/
|
|
457
|
-
function isPlatformPresent(ideId, profile, projectRoot) {
|
|
458
|
-
if (profile.alwaysPresent === true) return true;
|
|
459
|
-
const detection = IDE_DETECTION_DIRS.find((entry) => entry.id === ideId);
|
|
460
|
-
if (
|
|
461
|
-
detection !== undefined &&
|
|
462
|
-
projectRoot !== null &&
|
|
463
|
-
existsSync(join(projectRoot, detection.dir))
|
|
464
|
-
) {
|
|
465
|
-
return true;
|
|
466
|
-
}
|
|
467
|
-
return existsSync(dirname(profile.skillsDir));
|
|
468
|
-
}
|
|
469
|
-
|
|
470
|
-
function warnUnverifiedIde(ideId, projectRoot) {
|
|
471
|
-
process.stderr.write(
|
|
472
|
-
`peaks install-skills: IDE '${ideId}' has no skillInstall profile declared; ` +
|
|
473
|
-
`falling back to the legacy Claude Code path (~/.claude/skills + ~/.claude/output-styles) ` +
|
|
474
|
-
`for project '${projectRoot}'. This is a slice #011 follow-up gap; ` +
|
|
475
|
-
`see .peaks/memory/ide-adapter-resource-profile-framework.md.\n`
|
|
476
|
-
);
|
|
477
|
-
}
|
|
478
|
-
|
|
479
|
-
function warnNoIdeDetected(projectRoot) {
|
|
480
|
-
process.stderr.write(
|
|
481
|
-
`peaks install-skills: no IDE detected in '${projectRoot ?? '(project root unknown)'}'; ` +
|
|
482
|
-
`installing to the legacy Claude Code path (~/.claude/skills + ~/.claude/output-styles). ` +
|
|
483
|
-
`Set PEAKS_CLAUDE_SKILLS_DIR / PEAKS_CLAUDE_OUTPUT_STYLES_DIR to override.\n`
|
|
484
|
-
);
|
|
485
|
-
}
|
|
486
|
-
|
|
487
|
-
function writeMergedConfig(configPath, label, defaults, writeConfig) {
|
|
488
|
-
const existing = readConfigFile(configPath, label);
|
|
489
|
-
const next = {
|
|
490
|
-
...(existing === null ? defaults : mergeMissingConfigValues(existing, defaults)),
|
|
491
|
-
version: defaults.version
|
|
492
|
-
};
|
|
493
|
-
const currentJson = existing === null ? null : `${JSON.stringify(existing, null, 2)}\n`;
|
|
494
|
-
const nextJson = `${JSON.stringify(next, null, 2)}\n`;
|
|
495
|
-
|
|
496
|
-
if (currentJson === nextJson) {
|
|
497
|
-
return createConfigResult();
|
|
498
|
-
}
|
|
499
|
-
|
|
500
|
-
writeConfig(nextJson);
|
|
501
|
-
return createConfigResult(existing === null ? { created: true } : { updated: true });
|
|
502
|
-
}
|
|
503
|
-
|
|
504
|
-
export function installUserConfig(options = {}) {
|
|
505
|
-
if (
|
|
506
|
-
process.env.PEAKS_SKIP_SKILL_INSTALL === '1' ||
|
|
507
|
-
process.env.PEAKS_SKIP_USER_CONFIG_INSTALL === '1'
|
|
508
|
-
) {
|
|
509
|
-
return createConfigResult({ skipped: true });
|
|
510
|
-
}
|
|
511
|
-
|
|
512
|
-
const userRoot = resolve(options.userRoot ?? homedir());
|
|
513
|
-
const peaksRoot = resolve(userRoot, '.peaks');
|
|
514
|
-
const configPath = resolve(peaksRoot, 'config.json');
|
|
515
|
-
if (!isInsidePath(configPath, userRoot)) {
|
|
516
|
-
throw new Error('User config path must stay inside the user root');
|
|
517
|
-
}
|
|
518
|
-
|
|
519
|
-
if (!existsSync(peaksRoot)) {
|
|
520
|
-
mkdirSync(peaksRoot, { recursive: true });
|
|
521
|
-
}
|
|
522
|
-
validateUserConfigPaths(userRoot, peaksRoot, configPath);
|
|
18
|
+
import { join, resolve } from 'node:path';
|
|
19
|
+
import { pathToFileURL } from 'node:url';
|
|
523
20
|
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
}
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
* `npm i -g peaks-loop` executed from inside a user's repo would write
|
|
543
|
-
* `<project>/.peaks/config.json` as a side effect of a GLOBAL install. The
|
|
544
|
-
* project-level config is owned by `peaks workspace init` and the config
|
|
545
|
-
* service at runtime; a postinstall reaching into the current working
|
|
546
|
-
* directory to create project state is the opposite of the "minimal user
|
|
547
|
-
* operation" tenet — an operation the user never asked for.
|
|
548
|
-
*
|
|
549
|
-
* The user-config sibling (`installUserConfig`, below) is live and is what
|
|
550
|
-
* the postinstall actually calls.
|
|
551
|
-
*/
|
|
552
|
-
|
|
553
|
-
export function installBundledSkills(options = {}) {
|
|
554
|
-
const packageRoot = resolvePackageRoot(options);
|
|
555
|
-
const skillsRoot = join(packageRoot, 'skills');
|
|
556
|
-
|
|
557
|
-
if (process.env.PEAKS_SKIP_SKILL_INSTALL === '1' || !existsSync(skillsRoot)) {
|
|
558
|
-
return createInstallResult();
|
|
559
|
-
}
|
|
560
|
-
|
|
561
|
-
// Slice #011: IDE-aware dispatch. Precedence (highest first):
|
|
562
|
-
// 1. explicit options.targetRoot (test / hook override)
|
|
563
|
-
// 2. options.ideId skillInstall.skillsDir (per-IDE dispatch)
|
|
564
|
-
// 3. PEAKS_CLAUDE_SKILLS_DIR env var (legacy back-compat)
|
|
565
|
-
// 4. detected IDE's skillInstall.skillsDir (auto-detect from projectRoot)
|
|
566
|
-
// 5. legacy default (~/.claude/skills) (no-IDE fallback)
|
|
567
|
-
const projectRoot = resolveProjectRoot(options);
|
|
568
|
-
const detectedIdeId = detectInstalledIdeId(projectRoot);
|
|
569
|
-
const detectedProfile = resolveIdeSkillInstallProfile(detectedIdeId);
|
|
570
|
-
|
|
571
|
-
if (
|
|
572
|
-
options.targetRoot === undefined &&
|
|
573
|
-
options.ideId === undefined &&
|
|
574
|
-
detectedProfile === null &&
|
|
575
|
-
detectedIdeId !== null
|
|
576
|
-
) {
|
|
577
|
-
warnUnverifiedIde(detectedIdeId, projectRoot ?? '(project root unknown)');
|
|
578
|
-
}
|
|
579
|
-
if (
|
|
580
|
-
options.targetRoot === undefined &&
|
|
581
|
-
options.ideId === undefined &&
|
|
582
|
-
detectedIdeId === null &&
|
|
583
|
-
projectRoot !== null
|
|
584
|
-
) {
|
|
585
|
-
warnNoIdeDetected(projectRoot);
|
|
586
|
-
}
|
|
587
|
-
|
|
588
|
-
const profileSkillsDir = detectedProfile?.skillsDir ?? null;
|
|
589
|
-
const targetRoot = resolve(
|
|
590
|
-
options.targetRoot ??
|
|
591
|
-
(options.ideId !== undefined
|
|
592
|
-
? (resolveIdeSkillInstallProfile(options.ideId)?.skillsDir ?? null)
|
|
593
|
-
: null) ??
|
|
594
|
-
process.env.PEAKS_CLAUDE_SKILLS_DIR ??
|
|
595
|
-
profileSkillsDir ??
|
|
596
|
-
join(homedir(), '.claude', 'skills')
|
|
597
|
-
);
|
|
598
|
-
|
|
599
|
-
const installed = [];
|
|
600
|
-
const skipped = [];
|
|
601
|
-
mkdirSync(targetRoot, { recursive: true });
|
|
602
|
-
const validateSkillsRoot = createInstallRootValidator(targetRoot, 'Peaks skills');
|
|
603
|
-
|
|
604
|
-
// After the v2.13.0 bee-demote (commit de0872b), the role skills
|
|
605
|
-
// (peaks-prd, peaks-rd, peaks-qa, peaks-ui, peaks-sc, peaks-txt)
|
|
606
|
-
// moved under `skills/bee/<role>/` while user-facing helpers stayed
|
|
607
|
-
// at `skills/<name>/`. Build the install candidate list by walking
|
|
608
|
-
// top-level entries (user-facing helpers) AND `skills/bee/<role>`
|
|
609
|
-
// (demoted role skills). Each candidate is installed under its
|
|
610
|
-
// basename so the postinstall links `~/.claude/skills/peaks-rd`
|
|
611
|
-
// to `skills/bee/peaks-rd` (rather than `skills/bee`).
|
|
612
|
-
const beeRoot = join(skillsRoot, 'bee');
|
|
613
|
-
/** @type {Array<{ skillName: string, sourcePath: string }>} */
|
|
614
|
-
const candidates = [];
|
|
615
|
-
for (const skillName of readdirSync(skillsRoot)) {
|
|
616
|
-
if (skillName === 'bee') continue;
|
|
617
|
-
const sourcePath = join(skillsRoot, skillName);
|
|
618
|
-
const skillFile = join(sourcePath, 'SKILL.md');
|
|
619
|
-
if (!lstatSync(sourcePath).isDirectory() || !existsSync(skillFile)) continue;
|
|
620
|
-
candidates.push({ skillName, sourcePath });
|
|
621
|
-
}
|
|
622
|
-
if (existsSync(beeRoot) && lstatSync(beeRoot).isDirectory()) {
|
|
623
|
-
for (const skillName of readdirSync(beeRoot)) {
|
|
624
|
-
const sourcePath = join(beeRoot, skillName);
|
|
625
|
-
const skillFile = join(sourcePath, 'SKILL.md');
|
|
626
|
-
if (!lstatSync(sourcePath).isDirectory() || !existsSync(skillFile)) continue;
|
|
627
|
-
// De-dupe: a top-level helper with the same name wins (preserves
|
|
628
|
-
// the existing install contract for any helper that shares a name
|
|
629
|
-
// with a demoted role skill, e.g. legacy overlap).
|
|
630
|
-
if (candidates.some((c) => c.skillName === skillName)) continue;
|
|
631
|
-
candidates.push({ skillName, sourcePath });
|
|
632
|
-
}
|
|
633
|
-
}
|
|
634
|
-
|
|
635
|
-
for (const { skillName, sourcePath } of candidates) {
|
|
636
|
-
const targetPath = join(targetRoot, skillName);
|
|
637
|
-
|
|
638
|
-
// Slice 2 (`agents-canonical-store`) — the entry points at the CANONICAL
|
|
639
|
-
// STORE (`~/.peaks/skills/<name>`), not at `<packageRoot>/skills/<name>`,
|
|
640
|
-
// because `<packageRoot>` changes on every `npm i -g peaks-loop@latest` and
|
|
641
|
-
// the links must bind to a PATH peaks-loop owns, not to a VERSION. Repair is
|
|
642
|
-
// the only behaviour: an entry peaks-loop owns (sidecar matches, or the link
|
|
643
|
-
// dangles) is relinked onto the store; only a real directory the user authored
|
|
644
|
-
// is left alone and reported `skipped`. `options.reconcileJunctions` is
|
|
645
|
-
// therefore READ NOWHERE here — still accepted (`sync-service.ts` forwards it)
|
|
646
|
-
// so passing it changes nothing, and removing it is a CLI-surface change this
|
|
647
|
-
// slice does not own.
|
|
648
|
-
validateSkillsRoot();
|
|
649
|
-
const reconciled = reconcileCanonicalEntry({
|
|
650
|
-
kind: 'skills',
|
|
651
|
-
name: skillName,
|
|
652
|
-
sourcePath,
|
|
653
|
-
linkPath: targetPath
|
|
654
|
-
});
|
|
655
|
-
validateSkillsRoot();
|
|
656
|
-
|
|
657
|
-
if (reconciled.linkAction === 'skipped') {
|
|
658
|
-
skipped.push(skillName);
|
|
659
|
-
continue;
|
|
660
|
-
}
|
|
661
|
-
installed.push(skillName);
|
|
662
|
-
}
|
|
663
|
-
|
|
664
|
-
// Slice 3 — PRUNE. The loop above only ever ADDS. A skill removed from the
|
|
665
|
-
// package left its canonical copy, every IDE link and every sidecar on the
|
|
666
|
-
// user's machine forever, because nothing walked the DESTINATIONS. This does,
|
|
667
|
-
// and deletes only what `isManagedEntry` proves is ours.
|
|
668
|
-
const { pruned } = pruneBundledEntries({
|
|
669
|
-
kind: 'skills',
|
|
670
|
-
keepNames: candidates.map((candidate) => candidate.skillName),
|
|
671
|
-
linkDirs: [targetRoot]
|
|
672
|
-
});
|
|
673
|
-
|
|
674
|
-
return { installed, skipped, pruned };
|
|
675
|
-
}
|
|
676
|
-
|
|
677
|
-
/**
|
|
678
|
-
* DISPATCH STRATEGY — the three paths in this file, and why they differ
|
|
679
|
-
* (D10, written down 2026-09-15).
|
|
680
|
-
*
|
|
681
|
-
* This script installs three kinds of asset, and each one resolves its target
|
|
682
|
-
* by a different rule. That was undocumented and untested; it is now
|
|
683
|
-
* documented here and each rule is stated with its reason.
|
|
684
|
-
*
|
|
685
|
-
* 1. SKILLS (`installBundledSkillsForAllPlatforms`)
|
|
686
|
-
* Fan out to every platform the user HAS (`isPlatformPresent`).
|
|
687
|
-
* Reason: a skill directory is per-tool; the same skill is legitimately
|
|
688
|
-
* wanted in several tools at once, and peaks cannot know which tool the
|
|
689
|
-
* user will open next. Fan-out is the tenet; presence is the licence.
|
|
690
|
-
*
|
|
691
|
-
* 2. AGENTS (`installBundledAgentsForAllPlatforms`)
|
|
692
|
-
* Fan out to present platforms, INTERSECTED with the profiles that
|
|
693
|
-
* declare `agentsDir`. Reason: sub-agent loaders are not a universal
|
|
694
|
-
* concept — only 6 of 10 profiles have one. The intersection is the fan
|
|
695
|
-
* of (1) with a capability filter, not a third rule.
|
|
696
|
-
*
|
|
697
|
-
* 3. OUTPUT STYLES (`installBundledOutputStyles`, this function)
|
|
698
|
-
* ONE target: the IDE detected in the project root, else the legacy
|
|
699
|
-
* `~/.claude/output-styles`. Reason: an output style is not a
|
|
700
|
-
* per-tool asset — it is registered as THE active style for the
|
|
701
|
-
* session by writing a single `outputStyle` key into
|
|
702
|
-
* `~/.claude/settings.json` (`installBundledOutputStyleDefault`). A
|
|
703
|
-
* second copy in `~/.trae/output-styles` would be a file nothing reads
|
|
704
|
-
* and a setting no one consults; fanning it out would be storing the
|
|
705
|
-
* same answer in ten places and reading it from one.
|
|
706
|
-
*
|
|
707
|
-
* So: (1) and (2) share one predicate and differ only by capability; (3) is
|
|
708
|
-
* deliberately single-target, and this comment is the reason the brief asked
|
|
709
|
-
* for. If a future platform needs a different rule, state it here.
|
|
710
|
-
*/
|
|
711
|
-
export function installBundledOutputStyles(options = {}) {
|
|
712
|
-
const packageRoot = resolvePackageRoot(options);
|
|
713
|
-
const outputStylesRoot = join(packageRoot, 'output-styles');
|
|
714
|
-
|
|
715
|
-
if (process.env.PEAKS_SKIP_SKILL_INSTALL === '1' || !existsSync(outputStylesRoot)) {
|
|
716
|
-
return createInstallResult();
|
|
717
|
-
}
|
|
718
|
-
|
|
719
|
-
// Slice #011: IDE-aware dispatch. Same precedence as installBundledSkills.
|
|
720
|
-
const projectRoot = resolveProjectRoot(options);
|
|
721
|
-
const detectedIdeId = detectInstalledIdeId(projectRoot);
|
|
722
|
-
const detectedProfile = resolveIdeSkillInstallProfile(detectedIdeId);
|
|
723
|
-
|
|
724
|
-
const profileOutputStylesDir = detectedProfile?.outputStylesDir ?? null;
|
|
725
|
-
const targetRoot = resolve(
|
|
726
|
-
options.targetRoot ??
|
|
727
|
-
(options.ideId !== undefined
|
|
728
|
-
? (resolveIdeSkillInstallProfile(options.ideId)?.outputStylesDir ?? null)
|
|
729
|
-
: null) ??
|
|
730
|
-
process.env.PEAKS_CLAUDE_OUTPUT_STYLES_DIR ??
|
|
731
|
-
profileOutputStylesDir ??
|
|
732
|
-
join(homedir(), '.claude', 'output-styles')
|
|
733
|
-
);
|
|
734
|
-
|
|
735
|
-
const installed = [];
|
|
736
|
-
const skipped = [];
|
|
737
|
-
const fallbacks = [];
|
|
738
|
-
mkdirSync(targetRoot, { recursive: true });
|
|
739
|
-
const validateOutputStylesRoot = createInstallRootValidator(targetRoot, 'Peaks output styles');
|
|
740
|
-
|
|
741
|
-
// Slice 4 (`agents-canonical-store`) — same move slice 2 made for skills, with the
|
|
742
|
-
// one difference the brief calls out: a style is a FILE, so the link is a file
|
|
743
|
-
// symlink, which Windows only grants with developer mode or Administrator.
|
|
744
|
-
// `reconcileCanonicalFileEntry` is the whole policy — canonical copy, link, and the
|
|
745
|
-
// reported fallback to a real copy when the host refuses the link. The loop below
|
|
746
|
-
// no longer decides ownership, and that is deliberate: the decision it used to make
|
|
747
|
-
// was `resolve(marker.sourcePath) === resolve(sourcePath)`, a string comparison
|
|
748
|
-
// against a version-scoped package path that went false forever on the first
|
|
749
|
-
// upgrade and silently froze the style.
|
|
750
|
-
const bundledStyleNames = [];
|
|
751
|
-
for (const outputStyleName of readdirSync(outputStylesRoot)) {
|
|
752
|
-
const sourcePath = join(outputStylesRoot, outputStyleName);
|
|
753
|
-
if (!lstatSync(sourcePath).isFile() || !outputStyleName.endsWith('.md')) continue;
|
|
754
|
-
bundledStyleNames.push(outputStyleName);
|
|
755
|
-
|
|
756
|
-
validateOutputStylesRoot();
|
|
757
|
-
const reconciled = reconcileCanonicalFileEntry({
|
|
758
|
-
kind: 'output-styles',
|
|
759
|
-
name: outputStyleName,
|
|
760
|
-
sourcePath,
|
|
761
|
-
linkPath: join(targetRoot, outputStyleName),
|
|
762
|
-
createFileLink: options.createFileLink
|
|
763
|
-
});
|
|
764
|
-
validateOutputStylesRoot();
|
|
765
|
-
|
|
766
|
-
if (reconciled.linkAction === 'skipped') {
|
|
767
|
-
skipped.push(outputStyleName);
|
|
768
|
-
continue;
|
|
769
|
-
}
|
|
770
|
-
installed.push(outputStyleName);
|
|
771
|
-
if (reconciled.fallback !== null) {
|
|
772
|
-
fallbacks.push({ name: outputStyleName, ...reconciled.fallback });
|
|
773
|
-
}
|
|
774
|
-
}
|
|
775
|
-
|
|
776
|
-
// The delete half, for the same reason skills have one: the loop above only ever
|
|
777
|
-
// adds. A style removed from the package used to leave its canonical copy, its IDE
|
|
778
|
-
// link and both sidecars behind forever.
|
|
779
|
-
const { pruned } = pruneBundledEntries({
|
|
780
|
-
kind: 'output-styles',
|
|
781
|
-
keepNames: bundledStyleNames,
|
|
782
|
-
linkDirs: [targetRoot]
|
|
783
|
-
});
|
|
784
|
-
|
|
785
|
-
return { installed, skipped, pruned, fallbacks };
|
|
786
|
-
}
|
|
787
|
-
|
|
788
|
-
/**
|
|
789
|
-
* Slice 2026-08-02 — auto-register bundled output style.
|
|
790
|
-
*
|
|
791
|
-
* Real user feedback (2026-08-02): `npm i -g peaks-loop@latest` on a
|
|
792
|
-
* fresh 0-1 project copied `peaks-skill-swarm.md` into
|
|
793
|
-
* `~/.claude/output-styles/` but never wrote
|
|
794
|
-
* `outputStyle: 'peaks-skill-swarm'` into `~/.claude/settings.json`.
|
|
795
|
-
* Result: Claude Code loaded no Peaks output style in new sessions.
|
|
796
|
-
*
|
|
797
|
-
* The fix: when `peaks-skill-swarm.md` is present in the bundled output
|
|
798
|
-
* styles directory AND `~/.claude/settings.json` does NOT yet declare
|
|
799
|
-
* `outputStyle`, merge in `outputStyle: 'peaks-skill-swarm'` while
|
|
800
|
-
* preserving every other key. If the user already set `outputStyle`,
|
|
801
|
-
* leave it alone — the user is the source of truth.
|
|
802
|
-
*
|
|
803
|
-
* Resolution precedence:
|
|
804
|
-
* 1. options.settingsFile (explicit override / test hook)
|
|
805
|
-
* 2. PEAKS_CLAUDE_SETTINGS_FILE env var (CI override)
|
|
806
|
-
* 3. homedir-relative `<homedir>/.claude/settings.json` (default)
|
|
807
|
-
*
|
|
808
|
-
* Soft-fail contract: every error path (missing file, malformed JSON,
|
|
809
|
-
* missing bundled style file, permission denied) is logged to stderr
|
|
810
|
-
* and returns `{ skipped: true, ... }` instead of throwing. The
|
|
811
|
-
* postinstall must never fail on this step because the bundled file
|
|
812
|
-
* itself was already written successfully.
|
|
813
|
-
*/
|
|
814
|
-
function resolveSettingsFilePath(options = {}) {
|
|
815
|
-
if (typeof options.settingsFile === 'string' && options.settingsFile.length > 0) {
|
|
816
|
-
return resolve(options.settingsFile);
|
|
817
|
-
}
|
|
818
|
-
const envOverride = process.env.PEAKS_CLAUDE_SETTINGS_FILE;
|
|
819
|
-
if (typeof envOverride === 'string' && envOverride.length > 0) {
|
|
820
|
-
return resolve(envOverride);
|
|
821
|
-
}
|
|
822
|
-
return resolve(homedir(), '.claude', 'settings.json');
|
|
823
|
-
}
|
|
824
|
-
|
|
825
|
-
export function installBundledOutputStyleDefault(options = {}) {
|
|
826
|
-
if (
|
|
827
|
-
process.env.PEAKS_SKIP_SKILL_INSTALL === '1' ||
|
|
828
|
-
process.env.PEAKS_SKIP_OUTPUT_STYLE_DEFAULT === '1'
|
|
829
|
-
) {
|
|
830
|
-
return { skipped: true, reason: 'PEAKS_SKIP_OUTPUT_STYLE_DEFAULT=1' };
|
|
831
|
-
}
|
|
832
|
-
|
|
833
|
-
const bundledStylesDir = resolve(
|
|
834
|
-
options.targetRoot ??
|
|
835
|
-
process.env.PEAKS_CLAUDE_OUTPUT_STYLES_DIR ??
|
|
836
|
-
join(homedir(), '.claude', 'output-styles')
|
|
837
|
-
);
|
|
838
|
-
const settingsPath = resolveSettingsFilePath(options);
|
|
839
|
-
const bundledStyleName = 'peaks-skill-swarm.md';
|
|
840
|
-
const bundledStylePath = join(bundledStylesDir, bundledStyleName);
|
|
841
|
-
|
|
842
|
-
// Read the existing settings.json (if any) FIRST so a malformed file
|
|
843
|
-
// surfaces as a parse error (more actionable to the user than the
|
|
844
|
-
// generic "bundled style not present" message). Malformed JSON is a
|
|
845
|
-
// user-authored file we MUST NOT clobber — log and skip.
|
|
846
|
-
let existing = null;
|
|
847
|
-
if (existsSync(settingsPath)) {
|
|
848
|
-
const stats = getPathStats(settingsPath);
|
|
849
|
-
if (!stats || !stats.isFile() || stats.isSymbolicLink() || stats.nlink !== 1) {
|
|
850
|
-
process.stderr.write(
|
|
851
|
-
`peaks install-skills: refusing to overwrite non-regular settings.json at ${settingsPath}\n`
|
|
852
|
-
);
|
|
853
|
-
return { skipped: true, reason: 'settings.json is not a regular file' };
|
|
854
|
-
}
|
|
855
|
-
try {
|
|
856
|
-
const raw = readFileSafely(settingsPath, 'Claude settings.json path changed during read');
|
|
857
|
-
const parsed = JSON.parse(raw);
|
|
858
|
-
if (!isPlainObject(parsed)) {
|
|
859
|
-
process.stderr.write(
|
|
860
|
-
`peaks install-skills: refusing to overwrite settings.json that is not a JSON object at ${settingsPath}\n`
|
|
861
|
-
);
|
|
862
|
-
return { skipped: true, reason: 'settings.json is not a JSON object' };
|
|
863
|
-
}
|
|
864
|
-
existing = parsed;
|
|
865
|
-
} catch (error) {
|
|
866
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
867
|
-
process.stderr.write(
|
|
868
|
-
`peaks install-skills: failed to parse settings.json at ${settingsPath}: ${message}; leaving untouched\n`
|
|
869
|
-
);
|
|
870
|
-
return { skipped: true, reason: 'settings.json parse error' };
|
|
871
|
-
}
|
|
872
|
-
}
|
|
873
|
-
|
|
874
|
-
// Pre-condition: the bundled style file must be present in the
|
|
875
|
-
// dispatched target. If it's not, we MUST NOT inject
|
|
876
|
-
// `outputStyle: 'peaks-skill-swarm'` — Claude Code would then fail
|
|
877
|
-
// to load the style and fall back to default anyway, leaving the
|
|
878
|
-
// user with broken state. Skipping is the safe default.
|
|
879
|
-
if (!existsSync(bundledStylePath)) {
|
|
880
|
-
return { skipped: true, reason: `bundled output style not present at ${bundledStylePath}` };
|
|
881
|
-
}
|
|
882
|
-
|
|
883
|
-
// User-authored outputStyle wins — never overwrite.
|
|
884
|
-
if (
|
|
885
|
-
existing !== null &&
|
|
886
|
-
typeof existing.outputStyle === 'string' &&
|
|
887
|
-
existing.outputStyle.length > 0
|
|
888
|
-
) {
|
|
889
|
-
return {
|
|
890
|
-
skipped: true,
|
|
891
|
-
reason: `user-defined outputStyle already set: ${existing.outputStyle}`
|
|
892
|
-
};
|
|
893
|
-
}
|
|
894
|
-
|
|
895
|
-
const next =
|
|
896
|
-
existing === null
|
|
897
|
-
? { outputStyle: 'peaks-skill-swarm' }
|
|
898
|
-
: { ...existing, outputStyle: 'peaks-skill-swarm' };
|
|
899
|
-
|
|
900
|
-
const existingJson = existing === null ? null : `${JSON.stringify(existing, null, 2)}\n`;
|
|
901
|
-
const nextJson = `${JSON.stringify(next, null, 2)}\n`;
|
|
902
|
-
if (existingJson === nextJson) {
|
|
903
|
-
return { skipped: true, reason: 'no change' };
|
|
904
|
-
}
|
|
905
|
-
|
|
906
|
-
try {
|
|
907
|
-
writeFileAtomically(
|
|
908
|
-
settingsPath,
|
|
909
|
-
nextJson,
|
|
910
|
-
'Claude settings.json path changed during write',
|
|
911
|
-
() => {
|
|
912
|
-
if (!existsSync(settingsPath)) return;
|
|
913
|
-
const stats = getPathStats(settingsPath);
|
|
914
|
-
if (!stats || !stats.isFile() || stats.isSymbolicLink() || stats.nlink !== 1) {
|
|
915
|
-
throw new Error('Claude settings.json path is not a regular file');
|
|
916
|
-
}
|
|
917
|
-
}
|
|
918
|
-
);
|
|
919
|
-
} catch (error) {
|
|
920
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
921
|
-
process.stderr.write(
|
|
922
|
-
`peaks install-skills: failed to write settings.json at ${settingsPath}: ${message}\n`
|
|
923
|
-
);
|
|
924
|
-
return { skipped: true, reason: 'write error', error: message };
|
|
925
|
-
}
|
|
926
|
-
|
|
927
|
-
return {
|
|
928
|
-
installed: true,
|
|
929
|
-
created: existing === null,
|
|
930
|
-
updated: existing !== null,
|
|
931
|
-
settingsPath,
|
|
932
|
-
outputStyle: 'peaks-skill-swarm'
|
|
933
|
-
};
|
|
934
|
-
}
|
|
935
|
-
|
|
936
|
-
/**
|
|
937
|
-
* Slice 7/7 — bundled agents (Claude Code sub-agent prompts).
|
|
938
|
-
*
|
|
939
|
-
* Writes into the IDE's sub-agent loader directory (`~/.claude/agents/` for Claude
|
|
940
|
-
* Code, and whatever `agentsDir` the detected profile declares). The bytes live in
|
|
941
|
-
* the canonical store (`~/.peaks/agents/<name>`) and the IDE entry is a link to it.
|
|
942
|
-
*
|
|
943
|
-
* Ownership policy — ONE predicate, in `canonical-store-link.mjs::isOwnedFileEntry`,
|
|
944
|
-
* and it is deliberately not a string comparison:
|
|
945
|
-
* - entry resolves to the canonical copy → leave it (idempotent run)
|
|
946
|
-
* - entry is a link we wrote (sidecar agrees, dangles) → relink onto the store
|
|
947
|
-
* - entry is a real file with OUR sidecar beside it → re-point it at the store
|
|
948
|
-
* - entry is a real file with a LEGACY sidecar whose
|
|
949
|
-
* recorded package path no longer resolves → same: repair it
|
|
950
|
-
* - entry is a real file we never wrote (no sidecar) → skip (user-authored)
|
|
951
|
-
* - entry is a real file whose sidecar names a path
|
|
952
|
-
* that STILL resolves → skip (a second live install)
|
|
953
|
-
*
|
|
954
|
-
* The two "skip" arms above are the ones the old code got wrong in opposite
|
|
955
|
-
* directions: it skipped whenever the package path merely DIFFERED, which froze
|
|
956
|
-
* every entry on the first upgrade, silently and permanently. See
|
|
957
|
-
* `isOwnedFileEntry` for why a vanished package path is proof of an earlier install.
|
|
958
|
-
*/
|
|
959
|
-
export function installBundledAgents(options = {}) {
|
|
960
|
-
const packageRoot = resolvePackageRoot(options);
|
|
961
|
-
const agentsRoot = join(packageRoot, 'agents');
|
|
962
|
-
|
|
963
|
-
// Per-IDE env-var override (claude-code only today): PEAKS_CLAUDE_AGENTS_DIR.
|
|
964
|
-
// Universal escape hatch: PEAKS_SKIP_AGENT_INSTALL=1 (parallel to
|
|
965
|
-
// PEAKS_SKIP_SKILL_INSTALL).
|
|
966
|
-
if (
|
|
967
|
-
process.env.PEAKS_SKIP_SKILL_INSTALL === '1' ||
|
|
968
|
-
process.env.PEAKS_SKIP_AGENT_INSTALL === '1' ||
|
|
969
|
-
!existsSync(agentsRoot)
|
|
970
|
-
) {
|
|
971
|
-
return createInstallResult();
|
|
972
|
-
}
|
|
973
|
-
|
|
974
|
-
// Slice #011: IDE-aware dispatch. Same precedence as installBundledOutputStyles.
|
|
975
|
-
const projectRoot = resolveProjectRoot(options);
|
|
976
|
-
const detectedIdeId = detectInstalledIdeId(projectRoot);
|
|
977
|
-
const detectedProfile = resolveIdeSkillInstallProfile(detectedIdeId);
|
|
978
|
-
|
|
979
|
-
const profileAgentsDir = detectedProfile?.agentsDir ?? null;
|
|
980
|
-
const targetRoot = resolve(
|
|
981
|
-
options.targetRoot ??
|
|
982
|
-
(options.ideId !== undefined
|
|
983
|
-
? (resolveIdeSkillInstallProfile(options.ideId)?.agentsDir ?? null)
|
|
984
|
-
: null) ??
|
|
985
|
-
process.env.PEAKS_CLAUDE_AGENTS_DIR ??
|
|
986
|
-
profileAgentsDir ??
|
|
987
|
-
join(homedir(), '.claude', 'agents')
|
|
988
|
-
);
|
|
989
|
-
|
|
990
|
-
const installed = [];
|
|
991
|
-
const skipped = [];
|
|
992
|
-
const fallbacks = [];
|
|
993
|
-
mkdirSync(targetRoot, { recursive: true });
|
|
994
|
-
const validateAgentsRoot = createInstallRootValidator(targetRoot, 'Peaks agents');
|
|
995
|
-
|
|
996
|
-
// Slice 4 (`agents-canonical-store`) — the canonical store owns the bytes and the
|
|
997
|
-
// IDE entry points at it. Everything this loop used to decide about ownership is
|
|
998
|
-
// now `reconcileCanonicalFileEntry`'s, and the reason is the defect the brief
|
|
999
|
-
// names as this slice's core: the old test was
|
|
1000
|
-
// `resolve(marker.sourcePath) === resolve(sourcePath)`, a STRING comparison against
|
|
1001
|
-
// the package path of the installing version — a path with a node version inside it
|
|
1002
|
-
// (`…\nvm\v24.21.0\node_modules\peaks-loop\agents\…`). It went false the first time
|
|
1003
|
-
// the package moved and stayed false, so the agent silently never updated again.
|
|
1004
|
-
const bundledAgentNames = [];
|
|
1005
|
-
for (const agentFileName of readdirSync(agentsRoot)) {
|
|
1006
|
-
const sourcePath = join(agentsRoot, agentFileName);
|
|
1007
|
-
if (!lstatSync(sourcePath).isFile() || !agentFileName.endsWith('.md')) continue;
|
|
1008
|
-
bundledAgentNames.push(agentFileName);
|
|
1009
|
-
|
|
1010
|
-
validateAgentsRoot();
|
|
1011
|
-
const reconciled = reconcileCanonicalFileEntry({
|
|
1012
|
-
kind: 'agents',
|
|
1013
|
-
name: agentFileName,
|
|
1014
|
-
sourcePath,
|
|
1015
|
-
linkPath: join(targetRoot, agentFileName),
|
|
1016
|
-
createFileLink: options.createFileLink
|
|
1017
|
-
});
|
|
1018
|
-
validateAgentsRoot();
|
|
1019
|
-
|
|
1020
|
-
if (reconciled.linkAction === 'skipped') {
|
|
1021
|
-
skipped.push(agentFileName);
|
|
1022
|
-
continue;
|
|
1023
|
-
}
|
|
1024
|
-
installed.push(agentFileName);
|
|
1025
|
-
if (reconciled.fallback !== null) {
|
|
1026
|
-
fallbacks.push({ name: agentFileName, ...reconciled.fallback });
|
|
1027
|
-
}
|
|
1028
|
-
}
|
|
1029
|
-
|
|
1030
|
-
// The delete half: an agent the package stops shipping used to leave its canonical
|
|
1031
|
-
// copy, its IDE entry and both sidecars on the machine forever.
|
|
1032
|
-
const { pruned } = pruneBundledEntries({
|
|
1033
|
-
kind: 'agents',
|
|
1034
|
-
keepNames: bundledAgentNames,
|
|
1035
|
-
linkDirs: [targetRoot]
|
|
1036
|
-
});
|
|
1037
|
-
|
|
1038
|
-
return { installed, skipped, pruned, fallbacks };
|
|
1039
|
-
}
|
|
1040
|
-
|
|
1041
|
-
/**
|
|
1042
|
-
* A fallback is not a failure — but it must never LOOK like a plain success. The
|
|
1043
|
-
* entry is a real copy instead of a link, and the postinstall says so, naming each
|
|
1044
|
-
* one. Silence here would be the same shape as the defect this slice fixes: an
|
|
1045
|
-
* outcome nobody can observe from the outside.
|
|
1046
|
-
*/
|
|
1047
|
-
function reportCopyFallbacks(label, fallbacks) {
|
|
1048
|
-
if (fallbacks.length === 0) return;
|
|
1049
|
-
process.stderr.write(
|
|
1050
|
-
`Peaks ${label}: ${fallbacks.map((entry) => entry.name).join(', ')} ` +
|
|
1051
|
-
'installed as REAL COPIES because this host refused a symlink ' +
|
|
1052
|
-
`(${fallbacks[0].code ?? 'no code returned'})\n`
|
|
1053
|
-
);
|
|
1054
|
-
}
|
|
1055
|
-
|
|
1056
|
-
/**
|
|
1057
|
-
* The other half of the same rule, for the other bucket. A `skipped` entry means the
|
|
1058
|
-
* canonical copy WAS written and the IDE entry was NOT — a half migration. Whatever the
|
|
1059
|
-
* cause (a file the user authored, or an entry whose sidecar names a second live
|
|
1060
|
-
* installation), it must not be invisible: the whole defect this slice fixes was an
|
|
1061
|
-
* outcome nobody could observe from outside.
|
|
1062
|
-
*/
|
|
1063
|
-
function reportLeftAlone(label, skipped) {
|
|
1064
|
-
if (skipped.length === 0) return;
|
|
1065
|
-
process.stderr.write(
|
|
1066
|
-
`Peaks ${label}: left alone, not peaks-loop's to replace: ${skipped.join(', ')}\n`
|
|
1067
|
-
);
|
|
1068
|
-
}
|
|
21
|
+
import { installBundledAgents, installBundledSkills } from './install-skills-bundles.mjs';
|
|
22
|
+
import {
|
|
23
|
+
IDE_SKILL_INSTALL_PROFILES,
|
|
24
|
+
isPlatformPresent,
|
|
25
|
+
resolveProjectRoot
|
|
26
|
+
} from './install-skills-ide.mjs';
|
|
27
|
+
import { installBundledOutputStyles } from './install-skills-output-styles.mjs';
|
|
28
|
+
import { installBundledOutputStyleDefault } from './install-skills-output-style-default.mjs';
|
|
29
|
+
import { reportCopyFallbacks, reportLeftAlone } from './install-skills-report.mjs';
|
|
30
|
+
import { createConfigResult, installUserConfig } from './install-skills-user-config.mjs';
|
|
31
|
+
|
|
32
|
+
// THE PUBLIC SURFACE, re-exported so no importer changes. IDE_DETECTION_DIRS is
|
|
33
|
+
// not read here, so it is re-exported without a local binding.
|
|
34
|
+
export { IDE_DETECTION_DIRS } from './install-skills-ide.mjs';
|
|
35
|
+
export { IDE_SKILL_INSTALL_PROFILES };
|
|
36
|
+
export { installBundledSkills, installBundledAgents };
|
|
37
|
+
export { installUserConfig };
|
|
38
|
+
export { installBundledOutputStyles, installBundledOutputStyleDefault };
|
|
1069
39
|
|
|
1070
40
|
/**
|
|
1071
41
|
* Per-platform fan-out — iterate the platforms the user HAS and call
|