peaks-loop 3.1.2 → 4.0.0-beta
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 +62 -12
- package/CHANGELOG.md +50 -36
- package/README-en.md +58 -240
- package/README.md +49 -325
- package/agents/karpathy-reviewer.md +3 -3
- package/dist/src/cli/cli-helpers.d.ts +18 -0
- package/dist/src/cli/cli-helpers.js +8 -0
- package/dist/src/cli/commands/adapter-commands.d.ts +30 -0
- package/dist/src/cli/commands/adapter-commands.js +35 -0
- package/dist/src/cli/commands/context-commands.d.ts +1 -1
- package/dist/src/cli/commands/context-commands.js +1 -1
- package/dist/src/cli/commands/contract-commands.d.ts +1 -1
- package/dist/src/cli/commands/contract-commands.js +1 -1
- package/dist/src/cli/commands/core/session-command.js +12 -0
- package/dist/src/cli/commands/core/skill-command.js +4 -4
- package/dist/src/cli/commands/dispatch-commands.js +2 -2
- package/dist/src/cli/commands/job-commands.js +5 -5
- package/dist/src/cli/commands/observability-commands.js +1 -1
- package/dist/src/cli/commands/perf-audit-commands.js +2 -2
- package/dist/src/cli/commands/security-audit-commands.js +2 -2
- package/dist/src/cli/commands/sediment-commands.d.ts +80 -0
- package/dist/src/cli/commands/sediment-commands.js +640 -0
- package/dist/src/cli/commands/session-migrate-skill-name.d.ts +17 -0
- package/dist/src/cli/commands/session-migrate-skill-name.js +41 -0
- package/dist/src/cli/commands/skill-visibility.d.ts +8 -0
- package/dist/src/cli/commands/skill-visibility.js +63 -0
- package/dist/src/cli/commands/slice-commands.js +2 -2
- package/dist/src/cli/commands/solo-commands.d.ts +2 -2
- package/dist/src/cli/commands/solo-commands.js +8 -8
- package/dist/src/cli/commands/sub-agent-commands.d.ts +1 -1
- package/dist/src/cli/commands/sub-agent-commands.js +1 -1
- package/dist/src/cli/commands/understand-commands.js +1 -1
- package/dist/src/cli/commands/upgrade-commands.d.ts +1 -1
- package/dist/src/cli/commands/upgrade-commands.js +3 -3
- package/dist/src/cli/commands/user-touchpoint-commands.js +1 -1
- package/dist/src/cli/commands/verdict-aggregate-command.d.ts +1 -1
- package/dist/src/cli/commands/verdict-aggregate-command.js +2 -2
- package/dist/src/cli/commands/workflow-commands.js +2 -2
- package/dist/src/cli/commands/workspace/init-command.d.ts +3 -3
- package/dist/src/cli/commands/workspace/init-command.js +7 -7
- package/dist/src/cli/program.js +19 -2
- package/dist/src/services/adapter/adapter.d.ts +27 -0
- package/dist/src/services/adapter/adapter.js +5 -0
- package/dist/src/services/adapter/auto-adapter.d.ts +11 -0
- package/dist/src/services/adapter/auto-adapter.js +15 -0
- package/dist/src/services/adapter/claude-adapter.d.ts +14 -0
- package/dist/src/services/adapter/claude-adapter.js +40 -0
- package/dist/src/services/adapter/codex-adapter.d.ts +14 -0
- package/dist/src/services/adapter/codex-adapter.js +14 -0
- package/dist/src/services/adapter/copilot-adapter.d.ts +14 -0
- package/dist/src/services/adapter/copilot-adapter.js +14 -0
- package/dist/src/services/audit/enforcers/solo-code-ban.d.ts +1 -1
- package/dist/src/services/audit/enforcers/solo-code-ban.js +2 -2
- package/dist/src/services/audit/red-line-catalog.js +1 -1
- package/dist/src/services/audit/scanners/skills-tree-scanner.js +22 -0
- package/dist/src/services/context/auto-compact-dispatcher.d.ts +1 -1
- package/dist/src/services/dispatch/batch-counter.js +1 -1
- package/dist/src/services/dispatch/leak-detector.js +1 -1
- package/dist/src/services/doctor/doctor-service.js +2 -2
- package/dist/src/services/job/job-resource-snapshot.js +29 -1
- package/dist/src/services/memory/project-memory-service.js +1 -1
- package/dist/src/services/migrate-skill-name/migrate.d.ts +17 -0
- package/dist/src/services/migrate-skill-name/migrate.js +152 -0
- package/dist/src/services/migrate-skill-name/schema.d.ts +42 -0
- package/dist/src/services/migrate-skill-name/schema.js +25 -0
- package/dist/src/services/observability/aggregation.d.ts +1 -1
- package/dist/src/services/observability/aggregation.js +1 -1
- package/dist/src/services/perf/perf-baseline-service.d.ts +1 -1
- package/dist/src/services/perf/perf-baseline-service.js +1 -1
- package/dist/src/services/prd/handoff-types.d.ts +1 -1
- package/dist/src/services/prd/handoff-types.js +1 -1
- package/dist/src/services/progress/progress-service.d.ts +1 -1
- package/dist/src/services/progress/progress-service.js +1 -1
- package/dist/src/services/rd/standards-diagnostic.js +1 -1
- package/dist/src/services/recommendations/capability-seed-mappings.js +1 -1
- package/dist/src/services/sc/sc-service.js +1 -1
- package/dist/src/services/sediment/dispose-confirm.d.ts +9 -0
- package/dist/src/services/sediment/dispose-confirm.js +5 -0
- package/dist/src/services/sediment/json-schema.d.ts +247 -0
- package/dist/src/services/sediment/json-schema.js +26 -0
- package/dist/src/services/sediment/manifest-lint.d.ts +13 -0
- package/dist/src/services/sediment/manifest-lint.js +11 -0
- package/dist/src/services/sediment/pool-paths.d.ts +22 -0
- package/dist/src/services/sediment/pool-paths.js +25 -0
- package/dist/src/services/sediment/pool-read.d.ts +20 -0
- package/dist/src/services/sediment/pool-read.js +73 -0
- package/dist/src/services/sediment/pool-rebuild-index.d.ts +15 -0
- package/dist/src/services/sediment/pool-rebuild-index.js +28 -0
- package/dist/src/services/sediment/pool-write.d.ts +14 -0
- package/dist/src/services/sediment/pool-write.js +25 -0
- package/dist/src/services/sediment/promotion-gate.d.ts +12 -0
- package/dist/src/services/sediment/promotion-gate.js +20 -0
- package/dist/src/services/sediment/types.d.ts +52 -0
- package/dist/src/services/sediment/types.js +1 -0
- package/dist/src/services/session/binding-store.d.ts +1 -1
- package/dist/src/services/session/binding-store.js +1 -1
- package/dist/src/services/session/caller-id-types.d.ts +1 -1
- package/dist/src/services/session/session-manager.d.ts +1 -1
- package/dist/src/services/session/session-manager.js +1 -1
- package/dist/src/services/skill/resume-detector.js +1 -1
- package/dist/src/services/skill/skill-scheduler.d.ts +1 -1
- package/dist/src/services/skill/skill-scheduler.js +1 -1
- package/dist/src/services/skillhub/release-diff.d.ts +18 -0
- package/dist/src/services/skillhub/release-diff.js +38 -0
- package/dist/src/services/skillhub/release-export.d.ts +8 -0
- package/dist/src/services/skillhub/release-export.js +31 -0
- package/dist/src/services/skillhub/release-gc-blobs.d.ts +13 -0
- package/dist/src/services/skillhub/release-gc-blobs.js +32 -0
- package/dist/src/services/skillhub/release-import.d.ts +7 -0
- package/dist/src/services/skillhub/release-import.js +59 -0
- package/dist/src/services/skillhub/release-retain.d.ts +23 -0
- package/dist/src/services/skillhub/release-retain.js +89 -0
- package/dist/src/services/skillhub/sqlite-store.d.ts +22 -0
- package/dist/src/services/skillhub/sqlite-store.js +47 -0
- package/dist/src/services/skillhub/tar-runtime.d.ts +21 -0
- package/dist/src/services/skillhub/tar-runtime.js +91 -0
- package/dist/src/services/skillhub/types.d.ts +105 -0
- package/dist/src/services/skillhub/types.js +1 -0
- package/dist/src/services/skills/skill-conformance-service.js +8 -5
- package/dist/src/services/skills/skill-presence-service.d.ts +4 -4
- package/dist/src/services/skills/skill-presence-service.js +2 -2
- package/dist/src/services/skills/skill-registry.js +27 -0
- package/dist/src/services/skills/skill-runbook-service.js +2 -2
- package/dist/src/services/slice/slice-check-service.js +1 -1
- package/dist/src/services/slice/slice-check-types.d.ts +1 -1
- package/dist/src/services/slice/slice-check-types.js +1 -1
- package/dist/src/services/slice/slice-decompose-types.d.ts +1 -1
- package/dist/src/services/slice/slice-decompose-types.js +1 -1
- package/dist/src/services/solo/auto-compact-orchestrator.d.ts +1 -1
- package/dist/src/services/solo/auto-compact-orchestrator.js +2 -2
- package/dist/src/services/solo/dag-orchestrator.d.ts +3 -3
- package/dist/src/services/solo/dag-orchestrator.js +4 -4
- package/dist/src/services/solo/mode-gate.d.ts +2 -2
- package/dist/src/services/solo/post-compact-detector.js +2 -2
- package/dist/src/services/solo/status-line-renderer.d.ts +4 -4
- package/dist/src/services/standards/missing-standards-detector.d.ts +1 -1
- package/dist/src/services/standards/missing-standards-detector.js +1 -1
- package/dist/src/services/standards/project-standards-service.d.ts +1 -1
- package/dist/src/services/standards/project-standards-service.js +4 -4
- package/dist/src/services/understand/understand-types.d.ts +1 -1
- package/dist/src/services/upgrade/1x-detector-service.js +1 -1
- package/dist/src/services/upgrade/upgrade-service.d.ts +34 -0
- package/dist/src/services/upgrade/upgrade-service.js +52 -30
- package/dist/src/services/verdict/verdict-aggregator.d.ts +1 -1
- package/dist/src/services/workflow/workflow-router-service.d.ts +1 -1
- package/dist/src/services/workflow/workflow-router-service.js +3 -3
- package/dist/src/services/workspace/claude-settings-template.d.ts +1 -1
- package/dist/src/services/workspace/claude-settings-template.js +2 -2
- package/dist/src/services/workspace/workspace-claude-settings-materializer.d.ts +1 -1
- package/dist/src/services/workspace/workspace-claude-settings-materializer.js +1 -1
- package/dist/src/services/workspace/workspace-service.d.ts +4 -4
- package/dist/src/services/workspace/workspace-service.js +2 -2
- package/dist/src/shared/paths.d.ts +1 -1
- package/dist/src/shared/paths.js +1 -1
- package/dist/src/shared/version.d.ts +1 -1
- package/dist/src/shared/version.js +1 -1
- package/dist/src/skills/peaks-maker/index.d.ts +5 -0
- package/dist/src/skills/peaks-maker/index.js +32 -0
- package/package.json +8 -3
- package/scripts/install-skills.mjs +29 -4
- package/skills/{peaks-prd → bee/peaks-prd}/SKILL.md +8 -2
- package/skills/{peaks-prd → bee/peaks-prd}/references/workflow.md +1 -1
- package/skills/{peaks-qa → bee/peaks-qa}/SKILL.md +10 -4
- package/skills/{peaks-qa → bee/peaks-qa}/references/browser-validation-contracts.md +2 -2
- package/skills/{peaks-qa → bee/peaks-qa}/references/external-capability-guidance.md +1 -1
- package/skills/{peaks-qa → bee/peaks-qa}/references/qa-fanout-contract.md +3 -3
- package/skills/{peaks-qa → bee/peaks-qa}/references/qa-sub-agent-dispatch.md +1 -1
- package/skills/{peaks-rd → bee/peaks-rd}/SKILL.md +13 -6
- package/skills/{peaks-rd → bee/peaks-rd}/references/browser-self-test-contracts.md +1 -1
- package/skills/{peaks-rd → bee/peaks-rd}/references/mock-data-placement.md +1 -1
- package/skills/{peaks-rd → bee/peaks-rd}/references/parallel-review-fanout.md +1 -1
- package/skills/{peaks-rd → bee/peaks-rd}/references/rd-runbook.md +1 -1
- package/skills/{peaks-rd → bee/peaks-rd}/references/rd-sub-agent-dispatch.md +2 -2
- package/skills/{peaks-rd → bee/peaks-rd}/references/rd-transition-gates.md +1 -1
- package/skills/{peaks-rd → bee/peaks-rd}/references/skill-presence-and-title.md +1 -1
- package/skills/{peaks-reviewer → bee/peaks-reviewer}/SKILL.md +2 -2
- package/skills/{peaks-sc → bee/peaks-sc}/SKILL.md +7 -1
- package/skills/{peaks-txt → bee/peaks-txt}/SKILL.md +9 -3
- package/skills/{peaks-ui → bee/peaks-ui}/SKILL.md +11 -5
- package/skills/peaks-audit/SKILL.md +1 -1
- package/skills/{peaks-solo → peaks-code}/SKILL.md +9 -9
- package/skills/{peaks-solo → peaks-code}/references/a2a-artifact-mapping.md +2 -2
- package/skills/{peaks-solo → peaks-code}/references/anchoring-and-session-info.md +4 -4
- package/skills/{peaks-solo → peaks-code}/references/artifact-contracts.md +2 -2
- package/skills/{peaks-solo → peaks-code}/references/browser-workflow.md +1 -1
- package/skills/peaks-code/references/command-migration.md +3 -0
- package/skills/{peaks-solo → peaks-code}/references/completion-handoff.md +2 -2
- package/skills/{peaks-solo → peaks-code}/references/context-governance.md +2 -2
- package/skills/{peaks-solo → peaks-code}/references/frontend-only-mode.md +1 -1
- package/skills/{peaks-solo → peaks-code}/references/local-artifact-workspace.md +1 -1
- package/skills/{peaks-solo → peaks-code}/references/micro-cycle.md +9 -9
- package/skills/{peaks-solo → peaks-code}/references/mode-selection-with-stale-presence.md +12 -12
- package/skills/{peaks-solo → peaks-code}/references/mode-selection.md +1 -1
- package/skills/{peaks-solo → peaks-code}/references/openspec-workflow.md +1 -1
- package/skills/{peaks-solo → peaks-code}/references/project-scan-checklist.md +1 -1
- package/skills/{peaks-solo → peaks-code}/references/refactor-mode.md +1 -1
- package/skills/{peaks-solo → peaks-code}/references/resume-detection.md +1 -1
- package/skills/{peaks-solo → peaks-code}/references/runbook.md +5 -5
- package/skills/{peaks-solo → peaks-code}/references/skill-presence-and-title.md +3 -3
- package/skills/{peaks-solo → peaks-code}/references/standards-preflight.md +1 -1
- package/skills/{peaks-solo → peaks-code}/references/step-0-55-1x-detection.md +5 -5
- package/skills/{peaks-solo → peaks-code}/references/sub-agent-dispatch.md +10 -10
- package/skills/{peaks-solo → peaks-code}/references/swarm-dispatch-contract.md +7 -7
- package/skills/{peaks-solo → peaks-code}/references/workflow-gates-and-types.md +3 -3
- package/skills/peaks-doctor/SKILL.md +1 -1
- package/skills/peaks-doctor/references/doctor-check-catalog.md +1 -1
- package/skills/peaks-final-review/SKILL.md +3 -3
- package/skills/peaks-final-review/references/4-dimensions.md +1 -1
- package/skills/peaks-ide/SKILL.md +1 -1
- package/skills/{peaks-solo-resume → peaks-resume}/SKILL.md +14 -14
- package/skills/peaks-sop/SKILL.md +1 -1
- package/skills/{peaks-solo-status → peaks-status}/SKILL.md +13 -13
- package/skills/{peaks-solo-test → peaks-test}/SKILL.md +11 -11
- package/skills/peaks-solo/references/command-migration.md +0 -3
- /package/skills/{peaks-perf-audit → bee/peaks-perf-audit}/SKILL.md +0 -0
- /package/skills/{peaks-perf-audit → bee/peaks-perf-audit}/references/audit-protocol.md +0 -0
- /package/skills/{peaks-prd → bee/peaks-prd}/references/artifact-contracts.md +0 -0
- /package/skills/{peaks-prd → bee/peaks-prd}/references/artifact-per-request.md +0 -0
- /package/skills/{peaks-prd → bee/peaks-prd}/references/command-migration.md +0 -0
- /package/skills/{peaks-prd → bee/peaks-prd}/references/prd-for-multi-pass.md +0 -0
- /package/skills/{peaks-qa → bee/peaks-qa}/references/artifact-contracts.md +0 -0
- /package/skills/{peaks-qa → bee/peaks-qa}/references/artifact-per-request.md +0 -0
- /package/skills/{peaks-qa → bee/peaks-qa}/references/codegraph-regression-focus.md +0 -0
- /package/skills/{peaks-qa → bee/peaks-qa}/references/command-migration.md +0 -0
- /package/skills/{peaks-qa → bee/peaks-qa}/references/openspec-validation-gate.md +0 -0
- /package/skills/{peaks-qa → bee/peaks-qa}/references/qa-compact-handoff.md +0 -0
- /package/skills/{peaks-qa → bee/peaks-qa}/references/qa-context-governance.md +0 -0
- /package/skills/{peaks-qa → bee/peaks-qa}/references/qa-gstack-integration.md +0 -0
- /package/skills/{peaks-qa → bee/peaks-qa}/references/qa-local-artifacts.md +0 -0
- /package/skills/{peaks-qa → bee/peaks-qa}/references/qa-matt-pocock-integration.md +0 -0
- /package/skills/{peaks-qa → bee/peaks-qa}/references/qa-perf-test-plan.md +0 -0
- /package/skills/{peaks-qa → bee/peaks-qa}/references/qa-refactor-role.md +0 -0
- /package/skills/{peaks-qa → bee/peaks-qa}/references/qa-runbook.md +0 -0
- /package/skills/{peaks-qa → bee/peaks-qa}/references/qa-security-test-plan.md +0 -0
- /package/skills/{peaks-qa → bee/peaks-qa}/references/qa-skill-presence.md +0 -0
- /package/skills/{peaks-qa → bee/peaks-qa}/references/qa-standards-preflight.md +0 -0
- /package/skills/{peaks-qa → bee/peaks-qa}/references/qa-transition-gates.md +0 -0
- /package/skills/{peaks-qa → bee/peaks-qa}/references/reading-handoff-frontmatter.md +0 -0
- /package/skills/{peaks-qa → bee/peaks-qa}/references/regression-gates.md +0 -0
- /package/skills/{peaks-qa → bee/peaks-qa}/references/requirement-boundary-recheck.md +0 -0
- /package/skills/{peaks-qa → bee/peaks-qa}/references/test-case-generation.md +0 -0
- /package/skills/{peaks-qa → bee/peaks-qa}/references/test-report-output.md +0 -0
- /package/skills/{peaks-rd → bee/peaks-rd}/references/artifact-and-standards-output.md +0 -0
- /package/skills/{peaks-rd → bee/peaks-rd}/references/artifact-contracts.md +0 -0
- /package/skills/{peaks-rd → bee/peaks-rd}/references/artifact-per-request.md +0 -0
- /package/skills/{peaks-rd → bee/peaks-rd}/references/browser-action-wrapper.md +0 -0
- /package/skills/{peaks-rd → bee/peaks-rd}/references/code-reviewer-4dim-hint.md +0 -0
- /package/skills/{peaks-rd → bee/peaks-rd}/references/codegraph-project-analysis.md +0 -0
- /package/skills/{peaks-rd → bee/peaks-rd}/references/command-migration.md +0 -0
- /package/skills/{peaks-rd → bee/peaks-rd}/references/compact-handoff.md +0 -0
- /package/skills/{peaks-rd → bee/peaks-rd}/references/external-references.md +0 -0
- /package/skills/{peaks-rd → bee/peaks-rd}/references/frontend-project-generation.md +0 -0
- /package/skills/{peaks-rd → bee/peaks-rd}/references/karpathy-reviewer-prompt.md +0 -0
- /package/skills/{peaks-rd → bee/peaks-rd}/references/library-version-awareness.md +0 -0
- /package/skills/{peaks-rd → bee/peaks-rd}/references/mandatory-perf-baseline.md +0 -0
- /package/skills/{peaks-rd → bee/peaks-rd}/references/matt-pocock-integration.md +0 -0
- /package/skills/{peaks-rd → bee/peaks-rd}/references/ocr-integration.md +0 -0
- /package/skills/{peaks-rd → bee/peaks-rd}/references/openspec-cli.md +0 -0
- /package/skills/{peaks-rd → bee/peaks-rd}/references/rd-context-governance.md +0 -0
- /package/skills/{peaks-rd → bee/peaks-rd}/references/rd-fanout-contracts.md +0 -0
- /package/skills/{peaks-rd → bee/peaks-rd}/references/rd-gstack-integration.md +0 -0
- /package/skills/{peaks-rd → bee/peaks-rd}/references/rd-standards-preflight.md +0 -0
- /package/skills/{peaks-rd → bee/peaks-rd}/references/reading-v2-slice-results.md +0 -0
- /package/skills/{peaks-rd → bee/peaks-rd}/references/refactor-workflow.md +0 -0
- /package/skills/{peaks-rd → bee/peaks-rd}/references/v2-12-fanout-collapse.md +0 -0
- /package/skills/{peaks-rd → bee/peaks-rd}/references/writing-handoff-frontmatter.md +0 -0
- /package/skills/{peaks-reviewer → bee/peaks-reviewer}/references/reviewer-prompt.md +0 -0
- /package/skills/{peaks-reviewer → bee/peaks-reviewer}/references/reviewer-schema.md +0 -0
- /package/skills/{peaks-sc → bee/peaks-sc}/references/artifact-contracts.md +0 -0
- /package/skills/{peaks-sc → bee/peaks-sc}/references/artifact-retention.md +0 -0
- /package/skills/{peaks-sc → bee/peaks-sc}/references/command-migration.md +0 -0
- /package/skills/{peaks-sc → bee/peaks-sc}/references/openspec-commit-boundaries.md +0 -0
- /package/skills/{peaks-security-audit → bee/peaks-security-audit}/SKILL.md +0 -0
- /package/skills/{peaks-security-audit → bee/peaks-security-audit}/references/audit-protocol.md +0 -0
- /package/skills/{peaks-txt → bee/peaks-txt}/references/artifact-contracts.md +0 -0
- /package/skills/{peaks-txt → bee/peaks-txt}/references/command-migration.md +0 -0
- /package/skills/{peaks-txt → bee/peaks-txt}/references/context-capsule.md +0 -0
- /package/skills/{peaks-ui → bee/peaks-ui}/references/artifact-contracts.md +0 -0
- /package/skills/{peaks-ui → bee/peaks-ui}/references/artifact-per-request.md +0 -0
- /package/skills/{peaks-ui → bee/peaks-ui}/references/command-migration.md +0 -0
- /package/skills/{peaks-ui → bee/peaks-ui}/references/workflow.md +0 -0
- /package/skills/{peaks-solo → peaks-code}/references/boundaries.md +0 -0
- /package/skills/{peaks-solo → peaks-code}/references/checkpoint-resume.md +0 -0
- /package/skills/{peaks-solo → peaks-code}/references/codegraph-orchestration.md +0 -0
- /package/skills/{peaks-solo → peaks-code}/references/cross-date-session-check.md +0 -0
- /package/skills/{peaks-solo → peaks-code}/references/dag-orchestrator.md +0 -0
- /package/skills/{peaks-solo → peaks-code}/references/envelope-contract.md +0 -0
- /package/skills/{peaks-solo → peaks-code}/references/existing-system-extraction.md +0 -0
- /package/skills/{peaks-solo → peaks-code}/references/external-references.md +0 -0
- /package/skills/{peaks-solo → peaks-code}/references/external-skill-invocation.md +0 -0
- /package/skills/{peaks-solo → peaks-code}/references/fanout-mandatory.md +0 -0
- /package/skills/{peaks-solo → peaks-code}/references/fast-mode.md +0 -0
- /package/skills/{peaks-solo → peaks-code}/references/gstack-integration.md +0 -0
- /package/skills/{peaks-solo → peaks-code}/references/headroom-integration.md +0 -0
- /package/skills/{peaks-solo → peaks-code}/references/job-loop.md +0 -0
- /package/skills/{peaks-solo → peaks-code}/references/periodic-checkpoint.md +0 -0
- /package/skills/{peaks-solo → peaks-code}/references/playwright-mcp-multi-terminal.md +0 -0
- /package/skills/{peaks-solo → peaks-code}/references/project-memory-loading.md +0 -0
- /package/skills/{peaks-solo → peaks-code}/references/quality-gate-cheatsheet.md +0 -0
- /package/skills/{peaks-solo → peaks-code}/references/step-0-8-gate.md +0 -0
- /package/skills/{peaks-solo → peaks-code}/references/workflow.md +0 -0
|
@@ -0,0 +1,640 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `peaks skill sediment <verb>` — Sediment pool CLI primitives.
|
|
3
|
+
*
|
|
4
|
+
* Slices 2026-07-04-cli-15a (Task 15a) and 2026-07-04-cli-15b (Task 15b)
|
|
5
|
+
* of the 18-verb plan. This file implements 8 of 18 verbs:
|
|
6
|
+
*
|
|
7
|
+
* Task 15a:
|
|
8
|
+
* add-segment — scaffold ~/.peaks/skills/segments/<name>/SKILL.md
|
|
9
|
+
* add-bee — write ~/.peaks/skills/bees/<name>/manifest.json
|
|
10
|
+
* list — read index.json via readPool
|
|
11
|
+
* rebuild-index — rewrite index.json from filesystem state
|
|
12
|
+
*
|
|
13
|
+
* Task 15b:
|
|
14
|
+
* refine-bee — append a NL-described patch to an existing bee manifest
|
|
15
|
+
* clone-bee — duplicate an existing bee to a new name, status reset
|
|
16
|
+
* promote — flip candidate → stable when PromotionGate passes
|
|
17
|
+
* retire — flip → retired, optionally record a reason
|
|
18
|
+
*
|
|
19
|
+
* Other verbs (dispose / releases / release-show / release-diff / export /
|
|
20
|
+
* import / gc-blobs / search / recent / show) return
|
|
21
|
+
* `{ ok: false, error: "UNKNOWN_VERB: …" }` until Tasks 15c / 15d fill them.
|
|
22
|
+
*
|
|
23
|
+
* The CLI boundary is runSediment(argv, { home }): it returns a
|
|
24
|
+
* `{ ok, error?, data? }` envelope so program.ts can render the result
|
|
25
|
+
* as JSON via peaks-cli's existing printResult primitive.
|
|
26
|
+
*/
|
|
27
|
+
import { writeFileSync, mkdirSync, readFileSync, existsSync, readdirSync, rmSync } from "node:fs";
|
|
28
|
+
import { join, basename } from "node:path";
|
|
29
|
+
import { SYSTEM_PATH_FORBIDDEN, assertNotSystemPath, resolveSegmentsDir, resolveStateDbPath, resolveBlobsDir, resolveUserBeesDir, resolveUserBeeDir, } from "../../services/sediment/pool-paths.js";
|
|
30
|
+
import { writeBeeManifest } from "../../services/sediment/pool-write.js";
|
|
31
|
+
import { readPool } from "../../services/sediment/pool-read.js";
|
|
32
|
+
import { rebuildIndexFromFs } from "../../services/sediment/pool-rebuild-index.js";
|
|
33
|
+
import { evaluateGate } from "../../services/sediment/promotion-gate.js";
|
|
34
|
+
import { printCliEnvelope } from "../cli-helpers.js";
|
|
35
|
+
import { openStateDb } from "../../services/skillhub/sqlite-store.js";
|
|
36
|
+
import { retainRelease } from "../../services/skillhub/release-retain.js";
|
|
37
|
+
import { releaseDiff } from "../../services/skillhub/release-diff.js";
|
|
38
|
+
import { exportRelease } from "../../services/skillhub/release-export.js";
|
|
39
|
+
import { importRelease } from "../../services/skillhub/release-import.js";
|
|
40
|
+
import { gcBlobs } from "../../services/skillhub/release-gc-blobs.js";
|
|
41
|
+
/** Typed accessor over the flag map produced by `parseFlags`.
|
|
42
|
+
*
|
|
43
|
+
* `parseFlags` internally stores every flag with at least one value as a
|
|
44
|
+
* `string[]`. A flag with no following non-flag token (e.g. `--apply`,
|
|
45
|
+
* `--dry-run`) is recorded as `true`. This helper exposes three typed
|
|
46
|
+
* accessors so call-sites don't have to re-narrow `unknown` or
|
|
47
|
+
* `string | boolean | string[]` on every read:
|
|
48
|
+
*
|
|
49
|
+
* - `flags.list(name)` → `string[]` (always an array; a single
|
|
50
|
+
* occurrence is wrapped to a 1-element
|
|
51
|
+
* array at parse time)
|
|
52
|
+
* - `flags.bool(name)` → `boolean` (presence-of flag; missing
|
|
53
|
+
* flag is `false`)
|
|
54
|
+
* - `flags.maybeString(name)` → `string | undefined` (first value,
|
|
55
|
+
* or `undefined` if the flag was given
|
|
56
|
+
* as a bare boolean with no value)
|
|
57
|
+
*
|
|
58
|
+
* The dispatch layer (runSediment) was previously peppered with
|
|
59
|
+
* `typeof flags.x === "string"` / `Array.isArray(flags.x)` narrowing.
|
|
60
|
+
* With this helper the call-sites collapse to one-line reads and the
|
|
61
|
+
* raw flag map stops leaking across the runSediment boundary.
|
|
62
|
+
*/
|
|
63
|
+
export class ParsedFlags {
|
|
64
|
+
raw;
|
|
65
|
+
constructor(raw) {
|
|
66
|
+
this.raw = raw;
|
|
67
|
+
}
|
|
68
|
+
/** Always returns an array. Missing flag → []. Single-occurrence
|
|
69
|
+
* flag → a 1-element array (parseFlags normalizes this). */
|
|
70
|
+
list(name) {
|
|
71
|
+
const v = this.raw[name];
|
|
72
|
+
if (v === undefined)
|
|
73
|
+
return [];
|
|
74
|
+
if (v === true)
|
|
75
|
+
return [];
|
|
76
|
+
return v;
|
|
77
|
+
}
|
|
78
|
+
/** Presence-of a bare boolean flag. Missing → false. */
|
|
79
|
+
bool(name) {
|
|
80
|
+
const v = this.raw[name];
|
|
81
|
+
if (v === undefined)
|
|
82
|
+
return false;
|
|
83
|
+
// A flag given as `--name <value>` is also "present" (it just happens
|
|
84
|
+
// to carry values too). Existing call-sites that want `--dry-run`
|
|
85
|
+
// semantics care about presence, not whether values are attached.
|
|
86
|
+
return true;
|
|
87
|
+
}
|
|
88
|
+
/** First value of a flag, or `undefined` if the flag is absent or
|
|
89
|
+
* was given as a bare boolean. */
|
|
90
|
+
maybeString(name) {
|
|
91
|
+
const v = this.raw[name];
|
|
92
|
+
if (v === undefined)
|
|
93
|
+
return undefined;
|
|
94
|
+
if (v === true)
|
|
95
|
+
return undefined;
|
|
96
|
+
return v[0];
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
/** Parse an argv tail into positional args + flag map.
|
|
100
|
+
*
|
|
101
|
+
* Supports:
|
|
102
|
+
* --flag value → flags[flag] = [value, ...] (advance i by 1)
|
|
103
|
+
* --flag → flags[flag] = true (when next token starts with `--` or is undefined)
|
|
104
|
+
* --flag v1 --flag v2 → repeated `--flag` values are accumulated
|
|
105
|
+
*
|
|
106
|
+
* Internally stores all values as `string[]` (or `true` for a bare
|
|
107
|
+
* boolean flag). Use the `ParsedFlags` helper to read typed accessors.
|
|
108
|
+
*
|
|
109
|
+
* Repeatable flag handling (Task 15b): when the same `--key` appears
|
|
110
|
+
* consecutively (e.g. `--segment a --segment b --segment c`), values
|
|
111
|
+
* are accumulated into a single `string[]`. A single occurrence is
|
|
112
|
+
* normalized to a 1-element array so callers can use `.list(name)`
|
|
113
|
+
* uniformly without shape-narrowing on the call-site.
|
|
114
|
+
*/
|
|
115
|
+
export function parseFlags(argv) {
|
|
116
|
+
const positional = [];
|
|
117
|
+
const rawFlags = {};
|
|
118
|
+
for (let i = 0; i < argv.length; i++) {
|
|
119
|
+
const a = argv[i];
|
|
120
|
+
if (a.startsWith("--")) {
|
|
121
|
+
const k = a.slice(2);
|
|
122
|
+
const v = argv[i + 1];
|
|
123
|
+
if (v === undefined || v.startsWith("--")) {
|
|
124
|
+
rawFlags[k] = true;
|
|
125
|
+
}
|
|
126
|
+
else {
|
|
127
|
+
// Capture first value, then look ahead for `--k <value>` repeats.
|
|
128
|
+
const values = [v];
|
|
129
|
+
i += 2;
|
|
130
|
+
while (i < argv.length &&
|
|
131
|
+
argv[i] === `--${k}` &&
|
|
132
|
+
i + 1 < argv.length &&
|
|
133
|
+
!argv[i + 1].startsWith("--")) {
|
|
134
|
+
values.push(argv[i + 1]);
|
|
135
|
+
i += 2;
|
|
136
|
+
}
|
|
137
|
+
// Back up one — the outer for-loop will i++ past the flag, so the
|
|
138
|
+
// next iteration sees the next real token.
|
|
139
|
+
i--;
|
|
140
|
+
rawFlags[k] = values;
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
else {
|
|
144
|
+
positional.push(a);
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
return { positional, flags: new ParsedFlags(rawFlags) };
|
|
148
|
+
}
|
|
149
|
+
/** Dispatch a sediment verb argv to the matching implementation.
|
|
150
|
+
*
|
|
151
|
+
* Returns { ok: true, data? } on success and { ok: false, error }
|
|
152
|
+
* on validation failure or SYSTEM_PATH_FORBIDDEN. Unknown verbs
|
|
153
|
+
* return `{ ok: false, error: "UNKNOWN_VERB: <v>" }` so callers can
|
|
154
|
+
* distinguish "not yet implemented" from "zod rejected".
|
|
155
|
+
*/
|
|
156
|
+
export async function runSediment(argv, { home }) {
|
|
157
|
+
const { positional, flags } = parseFlags(argv);
|
|
158
|
+
const verb = positional[0];
|
|
159
|
+
try {
|
|
160
|
+
switch (verb) {
|
|
161
|
+
case "add-segment": {
|
|
162
|
+
const name = positional[1];
|
|
163
|
+
if (!name)
|
|
164
|
+
return { ok: false, error: "MISSING_ARG: name" };
|
|
165
|
+
const description = flags.maybeString("describe") ?? "";
|
|
166
|
+
const segDir = join(resolveSegmentsDir({ home }), name);
|
|
167
|
+
// Soft-protection guard: refuse to write under any `.system` path
|
|
168
|
+
// segment. Mirrors the same guard in writeBeeManifest.
|
|
169
|
+
assertNotSystemPath(segDir);
|
|
170
|
+
mkdirSync(segDir, { recursive: true });
|
|
171
|
+
writeFileSync(join(segDir, "SKILL.md"), `---\nname: ${name}\ndescription: ${description}\n---\n`);
|
|
172
|
+
rebuildIndexFromFs({ home });
|
|
173
|
+
return { ok: true };
|
|
174
|
+
}
|
|
175
|
+
case "add-bee": {
|
|
176
|
+
const name = positional[1];
|
|
177
|
+
if (!name)
|
|
178
|
+
return { ok: false, error: "MISSING_ARG: name" };
|
|
179
|
+
// Collect --segment values; the brief uses repeatable --segment
|
|
180
|
+
// flags (one token per segment). parseFlags now returns a
|
|
181
|
+
// 1-element array for a single occurrence and a longer array
|
|
182
|
+
// for repeated keys, so .list() returns a uniform string[].
|
|
183
|
+
const segList = flags.list("segment");
|
|
184
|
+
const description = flags.maybeString("description") ?? "";
|
|
185
|
+
const m = {
|
|
186
|
+
schemaVersion: "peaks.bee/1",
|
|
187
|
+
name,
|
|
188
|
+
source: "user",
|
|
189
|
+
promotion_status: "candidate",
|
|
190
|
+
description,
|
|
191
|
+
segments: segList.map((s) => ({
|
|
192
|
+
name: s,
|
|
193
|
+
inputs: [],
|
|
194
|
+
outputs: [],
|
|
195
|
+
sideEffects: [],
|
|
196
|
+
})),
|
|
197
|
+
entrypoint: { preamble: `## ${name}`, refs: [] },
|
|
198
|
+
promotion: {
|
|
199
|
+
minCycles: 1,
|
|
200
|
+
requiresHumanApproval: true,
|
|
201
|
+
requiresSmokeTest: true,
|
|
202
|
+
},
|
|
203
|
+
createdBy: "llm",
|
|
204
|
+
lastTouchedAt: new Date().toISOString(),
|
|
205
|
+
};
|
|
206
|
+
// writeBeeManifest runs zod validation + SYSTEM_PATH_FORBIDDEN
|
|
207
|
+
// guard internally.
|
|
208
|
+
writeBeeManifest({ home }, m);
|
|
209
|
+
rebuildIndexFromFs({ home });
|
|
210
|
+
return { ok: true };
|
|
211
|
+
}
|
|
212
|
+
case "list": {
|
|
213
|
+
const idx = readPool({ home });
|
|
214
|
+
return { ok: true, data: idx.entries };
|
|
215
|
+
}
|
|
216
|
+
case "rebuild-index": {
|
|
217
|
+
const idx = rebuildIndexFromFs({ home });
|
|
218
|
+
return { ok: true, data: idx };
|
|
219
|
+
}
|
|
220
|
+
// --- Task 15b verbs ---
|
|
221
|
+
case "refine-bee": {
|
|
222
|
+
const name = positional[1];
|
|
223
|
+
if (!name)
|
|
224
|
+
return { ok: false, error: "MISSING_ARG: refine-bee requires <name>" };
|
|
225
|
+
const patch = flags.maybeString("patch") ?? "";
|
|
226
|
+
if (!patch)
|
|
227
|
+
return { ok: false, error: "MISSING_ARG: refine-bee requires --patch" };
|
|
228
|
+
const manifestPath = join(resolveUserBeesDir({ home }), name, "manifest.json");
|
|
229
|
+
if (!existsSync(manifestPath))
|
|
230
|
+
return { ok: false, error: "BEE_NOT_FOUND" };
|
|
231
|
+
const m = JSON.parse(readFileSync(manifestPath, "utf-8"));
|
|
232
|
+
// Append patch note to description, preserving prior content. Cap at
|
|
233
|
+
// 1000 chars to avoid unbounded growth.
|
|
234
|
+
const ts = new Date().toISOString();
|
|
235
|
+
const note = `[refine ${ts}] ${patch}`;
|
|
236
|
+
m.description = (m.description + (m.description ? "\n" : "") + note).slice(0, 1000);
|
|
237
|
+
m.lastTouchedAt = ts;
|
|
238
|
+
// promotion_status is preserved (do not touch it here).
|
|
239
|
+
writeBeeManifest({ home }, m);
|
|
240
|
+
rebuildIndexFromFs({ home });
|
|
241
|
+
return { ok: true };
|
|
242
|
+
}
|
|
243
|
+
case "clone-bee": {
|
|
244
|
+
const name = positional[1];
|
|
245
|
+
if (!name)
|
|
246
|
+
return { ok: false, error: "MISSING_ARG: clone-bee requires <name>" };
|
|
247
|
+
const asName = flags.maybeString("as") ?? "";
|
|
248
|
+
if (!asName)
|
|
249
|
+
return { ok: false, error: "MISSING_ARG: clone-bee requires --as <new-name>" };
|
|
250
|
+
const srcPath = join(resolveUserBeesDir({ home }), name, "manifest.json");
|
|
251
|
+
if (!existsSync(srcPath))
|
|
252
|
+
return { ok: false, error: "BEE_NOT_FOUND" };
|
|
253
|
+
const src = JSON.parse(readFileSync(srcPath, "utf-8"));
|
|
254
|
+
// Fresh id, reset promotion_status to candidate, rename. The source
|
|
255
|
+
// manifest is unchanged on disk.
|
|
256
|
+
const clone = {
|
|
257
|
+
...src,
|
|
258
|
+
name: asName,
|
|
259
|
+
promotion_status: "candidate",
|
|
260
|
+
lastTouchedAt: new Date().toISOString(),
|
|
261
|
+
};
|
|
262
|
+
writeBeeManifest({ home }, clone);
|
|
263
|
+
rebuildIndexFromFs({ home });
|
|
264
|
+
return { ok: true };
|
|
265
|
+
}
|
|
266
|
+
case "promote": {
|
|
267
|
+
const name = positional[1];
|
|
268
|
+
if (!name)
|
|
269
|
+
return { ok: false, error: "MISSING_ARG: promote requires <name>" };
|
|
270
|
+
const manifestPath = join(resolveUserBeesDir({ home }), name, "manifest.json");
|
|
271
|
+
if (!existsSync(manifestPath))
|
|
272
|
+
return { ok: false, error: "BEE_NOT_FOUND" };
|
|
273
|
+
const m = JSON.parse(readFileSync(manifestPath, "utf-8"));
|
|
274
|
+
if (m.source === "system")
|
|
275
|
+
return { ok: false, error: "PROMOTION_SYSTEM_REFUSED" };
|
|
276
|
+
// Evaluate the PromotionGate (Task 5). The CLI is a thin shim; the
|
|
277
|
+
// humanApproved / smokeTestPresent inputs default to "true" here
|
|
278
|
+
// because the LLM-driven peaks-maker workflow has already obtained
|
|
279
|
+
// those approvals before calling promote.
|
|
280
|
+
const gate = evaluateGate({ home }, m, { humanApproved: true, smokeTestPresent: m.promotion.requiresSmokeTest });
|
|
281
|
+
if (!gate.ok) {
|
|
282
|
+
return {
|
|
283
|
+
ok: false,
|
|
284
|
+
error: `PROMOTION_GATE_FAILED: ${gate.failedSubconditions.join(",")}`,
|
|
285
|
+
};
|
|
286
|
+
}
|
|
287
|
+
m.promotion_status = "stable";
|
|
288
|
+
m.lastTouchedAt = new Date().toISOString();
|
|
289
|
+
writeBeeManifest({ home }, m);
|
|
290
|
+
rebuildIndexFromFs({ home });
|
|
291
|
+
return { ok: true };
|
|
292
|
+
}
|
|
293
|
+
case "retire": {
|
|
294
|
+
const name = positional[1];
|
|
295
|
+
if (!name)
|
|
296
|
+
return { ok: false, error: "MISSING_ARG: retire requires <name>" };
|
|
297
|
+
const reason = flags.maybeString("reason") ?? "";
|
|
298
|
+
const manifestPath = join(resolveUserBeesDir({ home }), name, "manifest.json");
|
|
299
|
+
if (!existsSync(manifestPath))
|
|
300
|
+
return { ok: false, error: "BEE_NOT_FOUND" };
|
|
301
|
+
const m = JSON.parse(readFileSync(manifestPath, "utf-8"));
|
|
302
|
+
if (m.source === "system")
|
|
303
|
+
return { ok: false, error: "RETIRE_SYSTEM_REFUSED" };
|
|
304
|
+
m.promotion_status = "retired";
|
|
305
|
+
if (reason) {
|
|
306
|
+
const ts = new Date().toISOString();
|
|
307
|
+
const note = `[retire ${ts}] ${reason}`;
|
|
308
|
+
m.description = (m.description + (m.description ? "\n" : "") + note).slice(0, 1000);
|
|
309
|
+
}
|
|
310
|
+
m.lastTouchedAt = new Date().toISOString();
|
|
311
|
+
writeBeeManifest({ home }, m);
|
|
312
|
+
rebuildIndexFromFs({ home });
|
|
313
|
+
return { ok: true };
|
|
314
|
+
}
|
|
315
|
+
// --- Task 15c verbs ---
|
|
316
|
+
case "dispose": {
|
|
317
|
+
const name = positional[1];
|
|
318
|
+
if (!name)
|
|
319
|
+
return { ok: false, error: "MISSING_ARG: dispose requires <name>" };
|
|
320
|
+
const decision = flags.maybeString("decision") ?? "";
|
|
321
|
+
if (decision !== "destroy" && decision !== "retain") {
|
|
322
|
+
return { ok: false, error: "MISSING_ARG: dispose requires --decision destroy|retain" };
|
|
323
|
+
}
|
|
324
|
+
const manifestPath = join(resolveUserBeesDir({ home }), name, "manifest.json");
|
|
325
|
+
if (!existsSync(manifestPath))
|
|
326
|
+
return { ok: false, error: "BEE_NOT_FOUND" };
|
|
327
|
+
const m = JSON.parse(readFileSync(manifestPath, "utf-8"));
|
|
328
|
+
// System bees: silently destroy; refuse retain (Task 9 contract).
|
|
329
|
+
if (m.source === "system") {
|
|
330
|
+
if (decision === "retain")
|
|
331
|
+
return { ok: false, error: "RETAIN_SYSTEM_REFUSED" };
|
|
332
|
+
return { ok: true, data: { systemDestroyed: true } };
|
|
333
|
+
}
|
|
334
|
+
// User bee destroy: remove the manifest dir from the pool. The
|
|
335
|
+
// scratch materialization is cleaned up by the dispatch flow
|
|
336
|
+
// (its concern), but the pool's bees/<name>/manifest.json entry
|
|
337
|
+
// is removed here so the index reflects reality on next read.
|
|
338
|
+
if (decision === "destroy") {
|
|
339
|
+
const beeDir = resolveUserBeeDir({ home }, name);
|
|
340
|
+
rmSync(beeDir, { recursive: true, force: true });
|
|
341
|
+
rebuildIndexFromFs({ home });
|
|
342
|
+
return { ok: true, data: { userDestroyed: true, path: beeDir } };
|
|
343
|
+
}
|
|
344
|
+
// User bee retain: open state.db, call retainRelease.
|
|
345
|
+
const version = flags.maybeString("version") ?? "0.1.0";
|
|
346
|
+
const scratchDir = flags.maybeString("scratch") ?? join(home, "scratch");
|
|
347
|
+
if (!existsSync(scratchDir))
|
|
348
|
+
return { ok: false, error: "SCRATCH_NOT_FOUND" };
|
|
349
|
+
const stateDbPath = resolveStateDbPath({ home });
|
|
350
|
+
const blobsDir = resolveBlobsDir({ home });
|
|
351
|
+
mkdirSync(blobsDir, { recursive: true });
|
|
352
|
+
const db = openStateDb(stateDbPath);
|
|
353
|
+
try {
|
|
354
|
+
retainRelease({ db, blobsDir, scratchDir, manifest: m, version });
|
|
355
|
+
}
|
|
356
|
+
finally {
|
|
357
|
+
db.close();
|
|
358
|
+
}
|
|
359
|
+
return { ok: true, data: { retained: true, version } };
|
|
360
|
+
}
|
|
361
|
+
case "releases": {
|
|
362
|
+
const beeName = positional[1];
|
|
363
|
+
if (!beeName)
|
|
364
|
+
return { ok: false, error: "MISSING_ARG: releases requires <bee-name>" };
|
|
365
|
+
const stateDbPath = resolveStateDbPath({ home });
|
|
366
|
+
const db = openStateDb(stateDbPath);
|
|
367
|
+
try {
|
|
368
|
+
const rows = db
|
|
369
|
+
.prepare("SELECT id, bee_name, version, source, archived_at, archived_by FROM bee_release WHERE bee_name = ? ORDER BY archived_at DESC")
|
|
370
|
+
.all(beeName);
|
|
371
|
+
return { ok: true, data: rows };
|
|
372
|
+
}
|
|
373
|
+
finally {
|
|
374
|
+
db.close();
|
|
375
|
+
}
|
|
376
|
+
}
|
|
377
|
+
case "release-show": {
|
|
378
|
+
const beeName = positional[1];
|
|
379
|
+
const version = flags.maybeString("version") ?? "";
|
|
380
|
+
if (!beeName || !version) {
|
|
381
|
+
return { ok: false, error: "MISSING_ARG: release-show requires <bee-name> and --version" };
|
|
382
|
+
}
|
|
383
|
+
const stateDbPath = resolveStateDbPath({ home });
|
|
384
|
+
const db = openStateDb(stateDbPath);
|
|
385
|
+
try {
|
|
386
|
+
// Cast the row to the typed interface from skillhub/types.ts so
|
|
387
|
+
// downstream consumers (LLM agents in peaks-maker, CLI JSON
|
|
388
|
+
// renderers) get a structural shape rather than
|
|
389
|
+
// Record<string, unknown>. Minor #12 fix.
|
|
390
|
+
const row = db
|
|
391
|
+
.prepare("SELECT * FROM bee_release WHERE bee_name = ? AND version = ?")
|
|
392
|
+
.get(beeName, version);
|
|
393
|
+
if (!row)
|
|
394
|
+
return { ok: false, error: "VERSION_NOT_FOUND" };
|
|
395
|
+
const id = row.id;
|
|
396
|
+
const manifest = db
|
|
397
|
+
.prepare("SELECT * FROM bee_manifest WHERE release_id = ?")
|
|
398
|
+
.get(id);
|
|
399
|
+
const segments = db
|
|
400
|
+
.prepare("SELECT * FROM bee_segment_ref WHERE release_id = ?")
|
|
401
|
+
.all(id);
|
|
402
|
+
const files = db
|
|
403
|
+
.prepare("SELECT * FROM bee_file WHERE release_id = ?")
|
|
404
|
+
.all(id);
|
|
405
|
+
return { ok: true, data: { release: row, manifest, segments, files } };
|
|
406
|
+
}
|
|
407
|
+
finally {
|
|
408
|
+
db.close();
|
|
409
|
+
}
|
|
410
|
+
}
|
|
411
|
+
case "release-diff": {
|
|
412
|
+
const beeName = positional[1];
|
|
413
|
+
const fromVersion = flags.maybeString("from") ?? "";
|
|
414
|
+
const toVersion = flags.maybeString("to") ?? "";
|
|
415
|
+
if (!beeName || !fromVersion || !toVersion) {
|
|
416
|
+
return { ok: false, error: "MISSING_ARG: release-diff requires <bee-name> and --from and --to" };
|
|
417
|
+
}
|
|
418
|
+
const stateDbPath = resolveStateDbPath({ home });
|
|
419
|
+
const db = openStateDb(stateDbPath);
|
|
420
|
+
try {
|
|
421
|
+
const diff = releaseDiff({ db, beeName, fromVersion, toVersion });
|
|
422
|
+
return { ok: true, data: diff };
|
|
423
|
+
}
|
|
424
|
+
catch (e) {
|
|
425
|
+
const msg = e instanceof Error ? e.message : String(e);
|
|
426
|
+
return { ok: false, error: msg };
|
|
427
|
+
}
|
|
428
|
+
finally {
|
|
429
|
+
db.close();
|
|
430
|
+
}
|
|
431
|
+
}
|
|
432
|
+
// --- Task 15d verbs ---
|
|
433
|
+
case "export": {
|
|
434
|
+
const beeName = positional[1];
|
|
435
|
+
const version = flags.maybeString("version") ?? "";
|
|
436
|
+
const outPath = flags.maybeString("out") ?? "";
|
|
437
|
+
if (!beeName || !version || !outPath) {
|
|
438
|
+
return { ok: false, error: "MISSING_ARG: export requires <bee-name>, --version, --out" };
|
|
439
|
+
}
|
|
440
|
+
const stateDbPath = resolveStateDbPath({ home });
|
|
441
|
+
const blobsDir = resolveBlobsDir({ home });
|
|
442
|
+
const db = openStateDb(stateDbPath);
|
|
443
|
+
try {
|
|
444
|
+
exportRelease({ db, blobsDir, beeName, version, outPath });
|
|
445
|
+
}
|
|
446
|
+
catch (e) {
|
|
447
|
+
const msg = e instanceof Error ? e.message : String(e);
|
|
448
|
+
return { ok: false, error: msg };
|
|
449
|
+
}
|
|
450
|
+
finally {
|
|
451
|
+
db.close();
|
|
452
|
+
}
|
|
453
|
+
return { ok: true, data: { outPath } };
|
|
454
|
+
}
|
|
455
|
+
case "import": {
|
|
456
|
+
const bundlePath = positional[1];
|
|
457
|
+
const asNameRaw = flags.maybeString("as");
|
|
458
|
+
const asName = asNameRaw && asNameRaw.length > 0 ? asNameRaw : undefined;
|
|
459
|
+
if (!bundlePath)
|
|
460
|
+
return { ok: false, error: "MISSING_ARG: import requires <bundle-path>" };
|
|
461
|
+
if (!existsSync(bundlePath))
|
|
462
|
+
return { ok: false, error: "BUNDLE_NOT_FOUND" };
|
|
463
|
+
const stateDbPath = resolveStateDbPath({ home });
|
|
464
|
+
const blobsDir = resolveBlobsDir({ home });
|
|
465
|
+
mkdirSync(blobsDir, { recursive: true });
|
|
466
|
+
const db = openStateDb(stateDbPath);
|
|
467
|
+
try {
|
|
468
|
+
if (asName !== undefined) {
|
|
469
|
+
importRelease({ db, blobsDir, inPath: bundlePath, asName });
|
|
470
|
+
}
|
|
471
|
+
else {
|
|
472
|
+
importRelease({ db, blobsDir, inPath: bundlePath });
|
|
473
|
+
}
|
|
474
|
+
}
|
|
475
|
+
catch (e) {
|
|
476
|
+
const msg = e instanceof Error ? e.message : String(e);
|
|
477
|
+
return { ok: false, error: msg };
|
|
478
|
+
}
|
|
479
|
+
finally {
|
|
480
|
+
db.close();
|
|
481
|
+
}
|
|
482
|
+
return { ok: true, data: { asName: asName ?? basename(bundlePath) } };
|
|
483
|
+
}
|
|
484
|
+
case "gc-blobs": {
|
|
485
|
+
const dryRun = flags.bool("dry-run");
|
|
486
|
+
const stateDbPath = resolveStateDbPath({ home });
|
|
487
|
+
const blobsDir = resolveBlobsDir({ home });
|
|
488
|
+
const db = openStateDb(stateDbPath);
|
|
489
|
+
try {
|
|
490
|
+
const removed = gcBlobs({ db, blobsDir, dryRun });
|
|
491
|
+
return { ok: true, data: { removed } };
|
|
492
|
+
}
|
|
493
|
+
catch (e) {
|
|
494
|
+
const msg = e instanceof Error ? e.message : String(e);
|
|
495
|
+
return { ok: false, error: msg };
|
|
496
|
+
}
|
|
497
|
+
finally {
|
|
498
|
+
db.close();
|
|
499
|
+
}
|
|
500
|
+
}
|
|
501
|
+
case "search": {
|
|
502
|
+
const query = positional[1] ?? flags.maybeString("q") ?? "";
|
|
503
|
+
if (!query)
|
|
504
|
+
return { ok: false, error: "MISSING_ARG: search requires <query>" };
|
|
505
|
+
const beesDir = resolveUserBeesDir({ home });
|
|
506
|
+
const matches = [];
|
|
507
|
+
const warnings = [];
|
|
508
|
+
if (existsSync(beesDir)) {
|
|
509
|
+
const q = query.toLowerCase();
|
|
510
|
+
for (const name of readdirSync(beesDir)) {
|
|
511
|
+
const manifestPath = join(beesDir, name, "manifest.json");
|
|
512
|
+
if (!existsSync(manifestPath))
|
|
513
|
+
continue;
|
|
514
|
+
let m;
|
|
515
|
+
try {
|
|
516
|
+
m = JSON.parse(readFileSync(manifestPath, "utf-8"));
|
|
517
|
+
}
|
|
518
|
+
catch (e) {
|
|
519
|
+
const msg = e instanceof Error ? e.message : String(e);
|
|
520
|
+
warnings.push(`skipped ${name}: ${msg}`);
|
|
521
|
+
continue;
|
|
522
|
+
}
|
|
523
|
+
const haystack = `${m.name ?? ""} ${m.description ?? ""}`.toLowerCase();
|
|
524
|
+
if (haystack.includes(q)) {
|
|
525
|
+
matches.push({
|
|
526
|
+
name: m.name,
|
|
527
|
+
description: m.description,
|
|
528
|
+
source: m.source,
|
|
529
|
+
promotion_status: m.promotion_status,
|
|
530
|
+
});
|
|
531
|
+
}
|
|
532
|
+
}
|
|
533
|
+
}
|
|
534
|
+
return { ok: true, data: { matches, warnings } };
|
|
535
|
+
}
|
|
536
|
+
case "recent": {
|
|
537
|
+
const sinceRaw = flags.maybeString("since") ?? "7d";
|
|
538
|
+
const m = sinceRaw.match(/^(\d+)d$/);
|
|
539
|
+
if (!m)
|
|
540
|
+
return { ok: false, error: "MISSING_ARG: recent requires --since Nd (e.g. 7d)" };
|
|
541
|
+
const sinceDays = parseInt(m[1], 10);
|
|
542
|
+
const cutoff = new Date(Date.now() - sinceDays * 24 * 60 * 60 * 1000).toISOString();
|
|
543
|
+
const beesDir = resolveUserBeesDir({ home });
|
|
544
|
+
const matches = [];
|
|
545
|
+
const warnings = [];
|
|
546
|
+
if (existsSync(beesDir)) {
|
|
547
|
+
for (const name of readdirSync(beesDir)) {
|
|
548
|
+
const manifestPath = join(beesDir, name, "manifest.json");
|
|
549
|
+
if (!existsSync(manifestPath))
|
|
550
|
+
continue;
|
|
551
|
+
let b;
|
|
552
|
+
try {
|
|
553
|
+
b = JSON.parse(readFileSync(manifestPath, "utf-8"));
|
|
554
|
+
}
|
|
555
|
+
catch (e) {
|
|
556
|
+
const msg = e instanceof Error ? e.message : String(e);
|
|
557
|
+
warnings.push(`skipped ${name}: ${msg}`);
|
|
558
|
+
continue;
|
|
559
|
+
}
|
|
560
|
+
if (typeof b.lastTouchedAt === "string" && b.lastTouchedAt >= cutoff) {
|
|
561
|
+
matches.push({
|
|
562
|
+
name: b.name,
|
|
563
|
+
lastTouchedAt: b.lastTouchedAt,
|
|
564
|
+
promotion_status: b.promotion_status,
|
|
565
|
+
});
|
|
566
|
+
}
|
|
567
|
+
}
|
|
568
|
+
}
|
|
569
|
+
return { ok: true, data: { matches, warnings } };
|
|
570
|
+
}
|
|
571
|
+
case "show": {
|
|
572
|
+
const name = positional[1];
|
|
573
|
+
if (!name)
|
|
574
|
+
return { ok: false, error: "MISSING_ARG: show requires <name>" };
|
|
575
|
+
const manifestPath = join(resolveUserBeesDir({ home }), name, "manifest.json");
|
|
576
|
+
if (!existsSync(manifestPath))
|
|
577
|
+
return { ok: false, error: "BEE_NOT_FOUND" };
|
|
578
|
+
try {
|
|
579
|
+
return { ok: true, data: JSON.parse(readFileSync(manifestPath, "utf-8")) };
|
|
580
|
+
}
|
|
581
|
+
catch (e) {
|
|
582
|
+
const msg = e instanceof Error ? e.message : String(e);
|
|
583
|
+
return { ok: false, error: `MANIFEST_CORRUPT: ${msg}` };
|
|
584
|
+
}
|
|
585
|
+
}
|
|
586
|
+
default:
|
|
587
|
+
return { ok: false, error: `UNKNOWN_VERB: ${verb ?? ""}` };
|
|
588
|
+
}
|
|
589
|
+
}
|
|
590
|
+
catch (e) {
|
|
591
|
+
if (e instanceof SYSTEM_PATH_FORBIDDEN) {
|
|
592
|
+
return { ok: false, error: e.message };
|
|
593
|
+
}
|
|
594
|
+
const msg = e instanceof Error ? e.message : typeof e === "string" ? e : String(e);
|
|
595
|
+
return { ok: false, error: msg };
|
|
596
|
+
}
|
|
597
|
+
}
|
|
598
|
+
/** Resolve the `peaks skill` parent command from the program tree,
|
|
599
|
+
* creating it lazily when program.ts hasn't already registered
|
|
600
|
+
* the skill command (matches the pattern in
|
|
601
|
+
* src/cli/commands/workflow-plan-commands.ts:179).
|
|
602
|
+
*
|
|
603
|
+
* Ordering note (T15a.1 future-proofing): `program.command("skill")` lazily
|
|
604
|
+
* registers a Command with description "Manage Peaks skills". If a future
|
|
605
|
+
* slice adds another `peaks skill <sub>` command (e.g. `peaks skill list`),
|
|
606
|
+
* it MUST be registered BEFORE sediment/adapter commands so that the first
|
|
607
|
+
* registration wins and the description is consistent. Today only sediment
|
|
608
|
+
* exists, so the lazy lookup is safe.
|
|
609
|
+
*/
|
|
610
|
+
function getOrCreateSkillCmd(program) {
|
|
611
|
+
const existing = program.commands.find((c) => c.name() === "skill");
|
|
612
|
+
if (existing !== undefined)
|
|
613
|
+
return existing;
|
|
614
|
+
return program.command("skill").description("Manage Peaks skills");
|
|
615
|
+
}
|
|
616
|
+
/** Register the `peaks skill sediment <verb>` subcommand group.
|
|
617
|
+
*
|
|
618
|
+
* Task 15a wired 4 verbs; Task 15b adds 4 more (refine-bee / clone-bee /
|
|
619
|
+
* promote / retire). The subcommand accepts variadic args so caller-side
|
|
620
|
+
* code (peaks-cli action handler) can re-dispatch to `runSediment` for
|
|
621
|
+
* the actual verb routing. Subsequent tasks (15c / 15d) will add the
|
|
622
|
+
* remaining 10 verbs by extending the `runSediment` switch statement.
|
|
623
|
+
*/
|
|
624
|
+
export function registerSedimentCommands(program, io) {
|
|
625
|
+
const skill = getOrCreateSkillCmd(program);
|
|
626
|
+
skill
|
|
627
|
+
.command("sediment <args...>")
|
|
628
|
+
.description("Sediment pool operations (LLM-coordinated; see peaks-maker skill)")
|
|
629
|
+
.action(async (args) => {
|
|
630
|
+
const home = process.env.HOME ?? process.env.USERPROFILE ?? process.cwd();
|
|
631
|
+
const r = await runSediment(args, { home });
|
|
632
|
+
// Delegate the JSON rendering AND the process.exitCode side-effect
|
|
633
|
+
// to the shared CLI shim helper (Critical #1 fix). The library
|
|
634
|
+
// function runSediment itself never mutates process.exitCode —
|
|
635
|
+
// it just returns { ok, error? } — so non-CLI callers (vitest,
|
|
636
|
+
// programmatic dispatch) can re-use it without leaking an exit
|
|
637
|
+
// code into the host process.
|
|
638
|
+
printCliEnvelope(io, r);
|
|
639
|
+
});
|
|
640
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Slice 2 of the peaks-code → peaks-code rename plan.
|
|
3
|
+
*
|
|
4
|
+
* `peaks session migrate-skill-name --from <old> --to <new> [--apply]
|
|
5
|
+
* [--project <path>] [--json]` — idempotent string-rewrite across
|
|
6
|
+
* `.peaks/_runtime/**`. Dry-run by default; pass `--apply` to write
|
|
7
|
+
* through. Skip-paths (`.peaks/memory/**`,
|
|
8
|
+
* `.peaks/skills/.system/bees/<old>/`) are recorded in `skipped`
|
|
9
|
+
* and never opened, so older memory capsules and the bee manifest
|
|
10
|
+
* for the old skill stay untouched.
|
|
11
|
+
*
|
|
12
|
+
* JSON envelope shape is owned by `MigrateResultSchema` in
|
|
13
|
+
* `src/services/migrate-skill-name/schema.ts`. Plain-text mode is
|
|
14
|
+
* a one-screen counter summary; `--json` mode is for tools.
|
|
15
|
+
*/
|
|
16
|
+
import type { Command } from 'commander';
|
|
17
|
+
export declare function registerSessionMigrateSkillNameCommand(session: Command): void;
|