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
|
@@ -399,7 +399,7 @@ export function getSessionId(projectRoot) {
|
|
|
399
399
|
* caller is operating on a user-supplied `--project` flag
|
|
400
400
|
* and the binding may have been written by a CLI invocation
|
|
401
401
|
* that was running from inside the project dir (the common
|
|
402
|
-
* peaks-
|
|
402
|
+
* peaks-code / peaks-sop scenario). Other modules depend
|
|
403
403
|
* on the strict-equality semantics of `getSessionId` (the
|
|
404
404
|
* "no binding" fallback path is part of their contract),
|
|
405
405
|
* so this variant is opt-in.
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* Peaks-Loop Solo Step 0.7 — Resume-mode detector.
|
|
3
3
|
*
|
|
4
4
|
* Mirrors the classification table in
|
|
5
|
-
* `skills/peaks-
|
|
5
|
+
* `skills/peaks-code/SKILL.md` "Peaks-Loop Step 0.7: Detect unfinished work
|
|
6
6
|
* and offer resume". The function is a pure read of session artifacts;
|
|
7
7
|
* it performs no side effects and is safe to call from hooks, scripts,
|
|
8
8
|
* and skills.
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* G6 — skill-level heartbeat scheduler config.
|
|
3
3
|
*
|
|
4
4
|
* Slice 2026-06-07-sub-agent-dispatch-decouple (G6): the SKILL.md front
|
|
5
|
-
* matter for a Dispatcher (peaks-
|
|
5
|
+
* matter for a Dispatcher (peaks-code / peaks-rd / peaks-qa) can opt
|
|
6
6
|
* into a non-default heartbeat interval by including a line like:
|
|
7
7
|
*
|
|
8
8
|
* heartbeatIntervalSec: 15
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* G6 — skill-level heartbeat scheduler config.
|
|
3
3
|
*
|
|
4
4
|
* Slice 2026-06-07-sub-agent-dispatch-decouple (G6): the SKILL.md front
|
|
5
|
-
* matter for a Dispatcher (peaks-
|
|
5
|
+
* matter for a Dispatcher (peaks-code / peaks-rd / peaks-qa) can opt
|
|
6
6
|
* into a non-default heartbeat interval by including a line like:
|
|
7
7
|
*
|
|
8
8
|
* heartbeatIntervalSec: 15
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type Database from "better-sqlite3";
|
|
2
|
+
export interface ReleaseDiff {
|
|
3
|
+
added: string[];
|
|
4
|
+
removed: string[];
|
|
5
|
+
modified: string[];
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* Compare two releases of the same bee and report which file paths were
|
|
9
|
+
* added, removed, or had their content (sha256) changed.
|
|
10
|
+
*
|
|
11
|
+
* Throws `VERSION_NOT_FOUND` if either (bee_name, version) tuple is missing.
|
|
12
|
+
*/
|
|
13
|
+
export declare function releaseDiff({ db, beeName, fromVersion, toVersion, }: {
|
|
14
|
+
db: Database.Database;
|
|
15
|
+
beeName: string;
|
|
16
|
+
fromVersion: string;
|
|
17
|
+
toVersion: string;
|
|
18
|
+
}): ReleaseDiff;
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Compare two releases of the same bee and report which file paths were
|
|
3
|
+
* added, removed, or had their content (sha256) changed.
|
|
4
|
+
*
|
|
5
|
+
* Throws `VERSION_NOT_FOUND` if either (bee_name, version) tuple is missing.
|
|
6
|
+
*/
|
|
7
|
+
export function releaseDiff({ db, beeName, fromVersion, toVersion, }) {
|
|
8
|
+
const aRow = db
|
|
9
|
+
.prepare("SELECT id FROM bee_release WHERE bee_name = ? AND version = ?")
|
|
10
|
+
.get(beeName, fromVersion);
|
|
11
|
+
const bRow = db
|
|
12
|
+
.prepare("SELECT id FROM bee_release WHERE bee_name = ? AND version = ?")
|
|
13
|
+
.get(beeName, toVersion);
|
|
14
|
+
if (!aRow || !bRow)
|
|
15
|
+
throw new Error("VERSION_NOT_FOUND");
|
|
16
|
+
const a = aRow.id;
|
|
17
|
+
const b = bRow.id;
|
|
18
|
+
const aFiles = new Map(db
|
|
19
|
+
.prepare("SELECT path, sha256 FROM bee_file WHERE release_id = ?")
|
|
20
|
+
.all(a).map((r) => [r.path, r.sha256]));
|
|
21
|
+
const bFiles = new Map(db
|
|
22
|
+
.prepare("SELECT path, sha256 FROM bee_file WHERE release_id = ?")
|
|
23
|
+
.all(b).map((r) => [r.path, r.sha256]));
|
|
24
|
+
const added = [];
|
|
25
|
+
const removed = [];
|
|
26
|
+
const modified = [];
|
|
27
|
+
for (const [p, sha] of bFiles) {
|
|
28
|
+
if (!aFiles.has(p))
|
|
29
|
+
added.push(p);
|
|
30
|
+
else if (aFiles.get(p) !== sha)
|
|
31
|
+
modified.push(p);
|
|
32
|
+
}
|
|
33
|
+
for (const [p] of aFiles) {
|
|
34
|
+
if (!bFiles.has(p))
|
|
35
|
+
removed.push(p);
|
|
36
|
+
}
|
|
37
|
+
return { added, removed, modified };
|
|
38
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { mkdirSync, writeFileSync, readFileSync, rmSync } from "node:fs";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
import { runTar } from "./tar-runtime.js";
|
|
4
|
+
export function exportRelease({ db, blobsDir, beeName, version, outPath, }) {
|
|
5
|
+
const id = db
|
|
6
|
+
.prepare("SELECT id FROM bee_release WHERE bee_name = ? AND version = ?")
|
|
7
|
+
.get(beeName, version)?.id;
|
|
8
|
+
if (!id)
|
|
9
|
+
throw new Error("VERSION_NOT_FOUND");
|
|
10
|
+
const manifestRows = db.prepare("SELECT * FROM bee_manifest WHERE release_id = ?").all(id);
|
|
11
|
+
const segRows = db.prepare("SELECT * FROM bee_segment_ref WHERE release_id = ?").all(id);
|
|
12
|
+
const fileRows = db
|
|
13
|
+
.prepare("SELECT * FROM bee_file WHERE release_id = ?")
|
|
14
|
+
.all(id);
|
|
15
|
+
const changeRows = db.prepare("SELECT * FROM bee_change WHERE release_id = ?").all(id);
|
|
16
|
+
const stageDir = join(outPath + ".stage");
|
|
17
|
+
mkdirSync(stageDir, { recursive: true });
|
|
18
|
+
writeFileSync(join(stageDir, "manifest.json"), JSON.stringify({ bee_name: beeName, version, manifestRows, segRows, fileRows, changeRows }, null, 2));
|
|
19
|
+
mkdirSync(join(stageDir, "blobs"), { recursive: true });
|
|
20
|
+
for (const f of fileRows) {
|
|
21
|
+
const src = join(blobsDir, f.sha256.slice(0, 2), f.sha256);
|
|
22
|
+
const dest = join(stageDir, "blobs", f.sha256);
|
|
23
|
+
writeFileSync(dest, readFileSync(src));
|
|
24
|
+
}
|
|
25
|
+
try {
|
|
26
|
+
runTar(["-czf", outPath, "-C", stageDir, "."]);
|
|
27
|
+
}
|
|
28
|
+
finally {
|
|
29
|
+
rmSync(stageDir, { recursive: true, force: true });
|
|
30
|
+
}
|
|
31
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type Database from "better-sqlite3";
|
|
2
|
+
/**
|
|
3
|
+
* Garbage-collect content-addressed blobs under `blobsDir/<aa>/<sha>` that
|
|
4
|
+
* no `bee_file` row currently references.
|
|
5
|
+
*
|
|
6
|
+
* @param dryRun if true, list removed SHAs without deleting files.
|
|
7
|
+
* @returns the list of removed SHA names.
|
|
8
|
+
*/
|
|
9
|
+
export declare function gcBlobs({ db, blobsDir, dryRun, }: {
|
|
10
|
+
db: Database.Database;
|
|
11
|
+
blobsDir: string;
|
|
12
|
+
dryRun: boolean;
|
|
13
|
+
}): string[];
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { readdirSync, rmSync, existsSync, statSync } from "node:fs";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
/**
|
|
4
|
+
* Garbage-collect content-addressed blobs under `blobsDir/<aa>/<sha>` that
|
|
5
|
+
* no `bee_file` row currently references.
|
|
6
|
+
*
|
|
7
|
+
* @param dryRun if true, list removed SHAs without deleting files.
|
|
8
|
+
* @returns the list of removed SHA names.
|
|
9
|
+
*/
|
|
10
|
+
export function gcBlobs({ db, blobsDir, dryRun, }) {
|
|
11
|
+
const refs = new Set(db.prepare("SELECT DISTINCT sha256 FROM bee_file").all().map((r) => r.sha256));
|
|
12
|
+
const removed = [];
|
|
13
|
+
if (!existsSync(blobsDir))
|
|
14
|
+
return removed;
|
|
15
|
+
for (const sub of readdirSync(blobsDir)) {
|
|
16
|
+
const subDir = join(blobsDir, sub);
|
|
17
|
+
if (!statSync(subDir).isDirectory())
|
|
18
|
+
continue;
|
|
19
|
+
for (const sha of readdirSync(subDir)) {
|
|
20
|
+
if (refs.has(sha))
|
|
21
|
+
continue;
|
|
22
|
+
const p = join(subDir, sha);
|
|
23
|
+
if (dryRun) {
|
|
24
|
+
removed.push(sha);
|
|
25
|
+
continue;
|
|
26
|
+
}
|
|
27
|
+
rmSync(p);
|
|
28
|
+
removed.push(sha);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
return removed;
|
|
32
|
+
}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { readFileSync, mkdirSync, writeFileSync, existsSync, rmSync } from "node:fs";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
import { assertNotSystemPath } from "../sediment/pool-paths.js";
|
|
4
|
+
import { runTar } from "./tar-runtime.js";
|
|
5
|
+
export function importRelease({ db, blobsDir, inPath, asName, }) {
|
|
6
|
+
const stageDir = inPath + ".extract";
|
|
7
|
+
if (existsSync(stageDir))
|
|
8
|
+
rmSync(stageDir, { recursive: true, force: true });
|
|
9
|
+
mkdirSync(stageDir, { recursive: true });
|
|
10
|
+
let extractOk = false;
|
|
11
|
+
try {
|
|
12
|
+
runTar(["-xzf", inPath, "-C", stageDir]);
|
|
13
|
+
extractOk = true;
|
|
14
|
+
}
|
|
15
|
+
finally {
|
|
16
|
+
if (!extractOk)
|
|
17
|
+
rmSync(stageDir, { recursive: true, force: true });
|
|
18
|
+
}
|
|
19
|
+
// ExportPayload (defined in ./types.ts) is the structural contract
|
|
20
|
+
// shared with release-export.ts, which writes the same JSON shape
|
|
21
|
+
// into <stageDir>/manifest.json. Minor #13: replace the previous
|
|
22
|
+
// inline anonymous type so producer and consumer stay in lock-step.
|
|
23
|
+
const payload = JSON.parse(readFileSync(join(stageDir, "manifest.json"), "utf-8"));
|
|
24
|
+
const beeName = asName ?? payload.bee_name;
|
|
25
|
+
assertNotSystemPath(beeName);
|
|
26
|
+
// Always check collision (the asName path previously skipped it and
|
|
27
|
+
// fell through to a UNIQUE-constraint mid-INSERT failure). Whether
|
|
28
|
+
// the user gave an explicit asName or relied on payload.bee_name, a
|
|
29
|
+
// pre-existing row must be reported cleanly.
|
|
30
|
+
if (db.prepare("SELECT 1 FROM bee_release WHERE bee_name = ?").get(beeName)) {
|
|
31
|
+
throw new Error("IMPORT_NAME_COLLIDES");
|
|
32
|
+
}
|
|
33
|
+
// Copy blobs
|
|
34
|
+
for (const f of payload.fileRows) {
|
|
35
|
+
const dest = join(blobsDir, f.sha256.slice(0, 2));
|
|
36
|
+
mkdirSync(dest, { recursive: true });
|
|
37
|
+
writeFileSync(join(dest, f.sha256), readFileSync(join(stageDir, "blobs", f.sha256)));
|
|
38
|
+
}
|
|
39
|
+
// Re-insert rows: pick a new release id, mirror payload rows
|
|
40
|
+
const tx = db.transaction(() => {
|
|
41
|
+
const ins = db.prepare(`INSERT INTO bee_release (bee_name, version, source, archived_at, archived_by, user_intent_raw, description, parent_version, changelog) VALUES (?, ?, 'user', ?, 'user', ?, ?, ?, ?)`);
|
|
42
|
+
const id = ins.run(beeName, payload.version, new Date().toISOString(), null, null, null, null).lastInsertRowid;
|
|
43
|
+
db.prepare(`INSERT OR REPLACE INTO bee_release_pointer (bee_name, latest_version, released_at) VALUES (?, ?, ?)`).run(beeName, payload.version, new Date().toISOString());
|
|
44
|
+
for (const m of payload.manifestRows) {
|
|
45
|
+
db.prepare(`INSERT INTO bee_manifest (release_id, schema_version, description, segments_json, entrypoint_preamble, promotion, min_cycles, requires_human, requires_smoke, retire_on_misses) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`).run(id, m.schema_version, m.description, m.segments_json, m.entrypoint_preamble, m.promotion, m.min_cycles, m.requires_human, m.requires_smoke, m.retire_on_misses);
|
|
46
|
+
}
|
|
47
|
+
for (const s of payload.segRows) {
|
|
48
|
+
db.prepare(`INSERT INTO bee_segment_ref (release_id, segment_name, inputs_json, outputs_json, side_effects) VALUES (?, ?, ?, ?, ?)`).run(id, s.segment_name, s.inputs_json, s.outputs_json, s.side_effects);
|
|
49
|
+
}
|
|
50
|
+
for (const f of payload.fileRows) {
|
|
51
|
+
db.prepare(`INSERT INTO bee_file (release_id, owner_kind, owner_name, path, kind, size_bytes, sha256, blob_path) VALUES (?, ?, ?, ?, ?, ?, ?, ?)`).run(id, f.owner_kind, beeName, f.path, f.kind, f.size_bytes, f.sha256, f.blob_path);
|
|
52
|
+
}
|
|
53
|
+
for (const c of payload.changeRows) {
|
|
54
|
+
db.prepare(`INSERT INTO bee_change (release_id, change_kind, target_kind, target_name, detail) VALUES (?, ?, ?, ?, ?)`).run(id, c.change_kind, c.target_kind, c.target_name, c.detail);
|
|
55
|
+
}
|
|
56
|
+
});
|
|
57
|
+
tx();
|
|
58
|
+
rmSync(stageDir, { recursive: true, force: true });
|
|
59
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type Database from "better-sqlite3";
|
|
2
|
+
import type { BeeManifest } from "../sediment/types.js";
|
|
3
|
+
/** Compute the sha256 hash and byte length of a single file. */
|
|
4
|
+
export declare function sha256OfFile(p: string): {
|
|
5
|
+
sha: string;
|
|
6
|
+
bytes: number;
|
|
7
|
+
};
|
|
8
|
+
/** Copy a file into the content-addressed blob store under `blobsDir/<aa>/<sha>`
|
|
9
|
+
* if not already present, and return the relative blob_path used by `bee_file`. */
|
|
10
|
+
export declare function ensureBlob(blobsDir: string, sha: string, srcPath: string): string;
|
|
11
|
+
export declare function walk(root: string, base?: string): Generator<{
|
|
12
|
+
abs: string;
|
|
13
|
+
rel: string;
|
|
14
|
+
}>;
|
|
15
|
+
export declare function retainRelease({ db, blobsDir, scratchDir, manifest, version: explicitVersion, parentVersion, changelog, }: {
|
|
16
|
+
db: Database.Database;
|
|
17
|
+
blobsDir: string;
|
|
18
|
+
scratchDir: string;
|
|
19
|
+
manifest: BeeManifest;
|
|
20
|
+
version?: string;
|
|
21
|
+
parentVersion?: string;
|
|
22
|
+
changelog?: string;
|
|
23
|
+
}): number;
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import { createHash } from "node:crypto";
|
|
2
|
+
import { readFileSync, readdirSync, writeFileSync, mkdirSync, existsSync } from "node:fs";
|
|
3
|
+
import { join, relative } from "node:path";
|
|
4
|
+
/** Compute the sha256 hash and byte length of a single file. */
|
|
5
|
+
export function sha256OfFile(p) {
|
|
6
|
+
const buf = readFileSync(p);
|
|
7
|
+
return { sha: createHash("sha256").update(buf).digest("hex"), bytes: buf.length };
|
|
8
|
+
}
|
|
9
|
+
/** Copy a file into the content-addressed blob store under `blobsDir/<aa>/<sha>`
|
|
10
|
+
* if not already present, and return the relative blob_path used by `bee_file`. */
|
|
11
|
+
export function ensureBlob(blobsDir, sha, srcPath) {
|
|
12
|
+
const dir = join(blobsDir, sha.slice(0, 2));
|
|
13
|
+
const dest = join(dir, sha);
|
|
14
|
+
if (!existsSync(dir))
|
|
15
|
+
mkdirSync(dir, { recursive: true });
|
|
16
|
+
if (!existsSync(dest))
|
|
17
|
+
writeFileSync(dest, readFileSync(srcPath));
|
|
18
|
+
return `blobs/${sha.slice(0, 2)}/${sha}`;
|
|
19
|
+
}
|
|
20
|
+
export function* walk(root, base = root) {
|
|
21
|
+
for (const ent of readdirSync(base, { withFileTypes: true })) {
|
|
22
|
+
const abs = join(base, ent.name);
|
|
23
|
+
if (ent.isDirectory())
|
|
24
|
+
yield* walk(root, abs);
|
|
25
|
+
else {
|
|
26
|
+
const relPosix = relative(root, abs).split(/[\\/]/).join("/");
|
|
27
|
+
yield { abs, rel: relPosix };
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
function warnOverflow(column, length) {
|
|
32
|
+
// Soft warning, no truncation: the spec does not mandate truncation,
|
|
33
|
+
// but a stale over-16KB row would silently break downstream readers
|
|
34
|
+
// that assume <16KB. Surface it for ops review.
|
|
35
|
+
// eslint-disable-next-line no-console
|
|
36
|
+
console.warn(`[release-retain] WARN: column ${column} overflowed 16KB guard (${length} bytes) — review and consider truncation`);
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Defensive 16KB check: if the value would exceed SQLite's
|
|
40
|
+
* recommended 16KB single-column limit, log a warning. Not a hard
|
|
41
|
+
* error — we let SQLite handle overflow. The columns covered are the
|
|
42
|
+
* four TEXT columns previously unchecked: bee_manifest.segments_json,
|
|
43
|
+
* bee_segment_ref.inputs_json, bee_segment_ref.outputs_json,
|
|
44
|
+
* bee_segment_ref.side_effects.
|
|
45
|
+
*/
|
|
46
|
+
function checkOverflow({ table, col }, value) {
|
|
47
|
+
const len = Buffer.byteLength(value, "utf-8");
|
|
48
|
+
if (len > 16 * 1024)
|
|
49
|
+
warnOverflow(`${table}.${col}`, len);
|
|
50
|
+
}
|
|
51
|
+
export function retainRelease({ db, blobsDir, scratchDir, manifest, version: explicitVersion, parentVersion, changelog, }) {
|
|
52
|
+
const version = explicitVersion ?? "0.1.0";
|
|
53
|
+
const tx = db.transaction(() => {
|
|
54
|
+
const ins = db.prepare(`INSERT INTO bee_release (bee_name, version, source, archived_at, archived_by, user_intent_raw, description, parent_version, changelog) VALUES (?, ?, 'user', ?, ?, ?, ?, ?, ?)`);
|
|
55
|
+
const info = ins.run(manifest.name, version, new Date().toISOString(), "llm", null, manifest.description, parentVersion ?? null, changelog ?? null);
|
|
56
|
+
const id = info.lastInsertRowid;
|
|
57
|
+
db.prepare(`INSERT OR REPLACE INTO bee_release_pointer (bee_name, latest_version, released_at) VALUES (?, ?, ?)`).run(manifest.name, version, new Date().toISOString());
|
|
58
|
+
for (const s of manifest.segments) {
|
|
59
|
+
const inputsJson = JSON.stringify(s.inputs);
|
|
60
|
+
const outputsJson = JSON.stringify(s.outputs);
|
|
61
|
+
const sideEffectsStr = s.sideEffects.join(",");
|
|
62
|
+
checkOverflow({ table: "bee_segment_ref", col: "inputs_json" }, inputsJson);
|
|
63
|
+
checkOverflow({ table: "bee_segment_ref", col: "outputs_json" }, outputsJson);
|
|
64
|
+
checkOverflow({ table: "bee_segment_ref", col: "side_effects" }, sideEffectsStr);
|
|
65
|
+
db.prepare(`INSERT INTO bee_segment_ref (release_id, segment_name, inputs_json, outputs_json, side_effects) VALUES (?, ?, ?, ?, ?)`).run(id, s.name, inputsJson, outputsJson, sideEffectsStr);
|
|
66
|
+
}
|
|
67
|
+
// Also guard the manifest-level JSON column that holds the segment
|
|
68
|
+
// name list (can exceed 16KB if a bee advertises thousands of
|
|
69
|
+
// segments).
|
|
70
|
+
const segmentsJson = JSON.stringify(manifest.segments.map((s) => s.name));
|
|
71
|
+
checkOverflow({ table: "bee_manifest", col: "segments_json" }, segmentsJson);
|
|
72
|
+
db.prepare(`INSERT INTO bee_manifest (release_id, schema_version, description, segments_json, entrypoint_preamble, promotion, min_cycles, requires_human, requires_smoke, retire_on_misses) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`).run(id, manifest.schemaVersion, manifest.description, segmentsJson, manifest.entrypoint.preamble, manifest.promotion_status, manifest.promotion.minCycles, manifest.promotion.requiresHumanApproval ? 1 : 0, manifest.promotion.requiresSmokeTest ? 1 : 0, manifest.promotion.retireOnMissesInRow ?? null);
|
|
73
|
+
const insFile = db.prepare(`INSERT INTO bee_file (release_id, owner_kind, owner_name, path, kind, size_bytes, sha256, blob_path) VALUES (?, ?, ?, ?, ?, ?, ?, ?)`);
|
|
74
|
+
for (const f of walk(scratchDir)) {
|
|
75
|
+
const { sha, bytes } = sha256OfFile(f.abs);
|
|
76
|
+
const blobPath = ensureBlob(blobsDir, sha, f.abs);
|
|
77
|
+
const kind = f.rel.endsWith(".md")
|
|
78
|
+
? "markdown"
|
|
79
|
+
: f.rel.startsWith("scripts/")
|
|
80
|
+
? "script"
|
|
81
|
+
: f.rel.startsWith("references/")
|
|
82
|
+
? "reference"
|
|
83
|
+
: "other";
|
|
84
|
+
insFile.run(id, "bee", manifest.name, f.rel, kind, bytes, sha, blobPath);
|
|
85
|
+
}
|
|
86
|
+
return id;
|
|
87
|
+
});
|
|
88
|
+
return tx();
|
|
89
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import Database from "better-sqlite3";
|
|
2
|
+
/**
|
|
3
|
+
* Open (or create) a SkillHub state database at the given path.
|
|
4
|
+
*
|
|
5
|
+
* Behavior:
|
|
6
|
+
* - Creates the parent directory if it does not exist.
|
|
7
|
+
* - Enables WAL journal mode and foreign-key enforcement.
|
|
8
|
+
* - Applies every `migrations/*.sql` file in lexicographic order.
|
|
9
|
+
* Migrations must be idempotent (CREATE TABLE IF NOT EXISTS, etc.).
|
|
10
|
+
*
|
|
11
|
+
* The migrations directory lives next to this source file at build time;
|
|
12
|
+
* we resolve it via `import.meta.url` so the lookup survives vitest ESM
|
|
13
|
+
* (where `__dirname` is undefined). Migration files are discovered by
|
|
14
|
+
* globbing (`*.sql`) and sorted lexicographically so future
|
|
15
|
+
* `002-…`, `003-…` additions are picked up automatically.
|
|
16
|
+
*/
|
|
17
|
+
export declare function openStateDb(path: string): Database.Database;
|
|
18
|
+
/**
|
|
19
|
+
* Return the user-defined table names present in `db` (excluding SQLite
|
|
20
|
+
* system tables such as `sqlite_sequence`).
|
|
21
|
+
*/
|
|
22
|
+
export declare function listTables(db: Database.Database): string[];
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import Database from "better-sqlite3";
|
|
2
|
+
import { readFileSync, readdirSync, existsSync, mkdirSync } from "node:fs";
|
|
3
|
+
import { dirname, join } from "node:path";
|
|
4
|
+
import { fileURLToPath } from "node:url";
|
|
5
|
+
/**
|
|
6
|
+
* Open (or create) a SkillHub state database at the given path.
|
|
7
|
+
*
|
|
8
|
+
* Behavior:
|
|
9
|
+
* - Creates the parent directory if it does not exist.
|
|
10
|
+
* - Enables WAL journal mode and foreign-key enforcement.
|
|
11
|
+
* - Applies every `migrations/*.sql` file in lexicographic order.
|
|
12
|
+
* Migrations must be idempotent (CREATE TABLE IF NOT EXISTS, etc.).
|
|
13
|
+
*
|
|
14
|
+
* The migrations directory lives next to this source file at build time;
|
|
15
|
+
* we resolve it via `import.meta.url` so the lookup survives vitest ESM
|
|
16
|
+
* (where `__dirname` is undefined). Migration files are discovered by
|
|
17
|
+
* globbing (`*.sql`) and sorted lexicographically so future
|
|
18
|
+
* `002-…`, `003-…` additions are picked up automatically.
|
|
19
|
+
*/
|
|
20
|
+
export function openStateDb(path) {
|
|
21
|
+
const parent = dirname(path);
|
|
22
|
+
if (!existsSync(parent))
|
|
23
|
+
mkdirSync(parent, { recursive: true });
|
|
24
|
+
const db = new Database(path);
|
|
25
|
+
db.pragma("journal_mode = WAL");
|
|
26
|
+
db.pragma("foreign_keys = ON");
|
|
27
|
+
const here = dirname(fileURLToPath(import.meta.url));
|
|
28
|
+
const migrationsDir = join(here, "migrations");
|
|
29
|
+
if (existsSync(migrationsDir)) {
|
|
30
|
+
const files = readdirSync(migrationsDir).filter((f) => f.endsWith(".sql")).sort();
|
|
31
|
+
for (const f of files) {
|
|
32
|
+
const sql = readFileSync(join(migrationsDir, f), "utf-8");
|
|
33
|
+
db.exec(sql);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
return db;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Return the user-defined table names present in `db` (excluding SQLite
|
|
40
|
+
* system tables such as `sqlite_sequence`).
|
|
41
|
+
*/
|
|
42
|
+
export function listTables(db) {
|
|
43
|
+
const rows = db
|
|
44
|
+
.prepare("SELECT name FROM sqlite_master WHERE type='table' AND name NOT LIKE 'sqlite_%'")
|
|
45
|
+
.all();
|
|
46
|
+
return rows.map((r) => r.name);
|
|
47
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/** Thrown when no usable tar binary can be located. */
|
|
2
|
+
export declare class TAR_NOT_FOUND extends Error {
|
|
3
|
+
constructor(msg: string);
|
|
4
|
+
}
|
|
5
|
+
/**
|
|
6
|
+
* Run `tar <args...>` in a cross-platform way.
|
|
7
|
+
*
|
|
8
|
+
* Args MUST be `["-czf", outPath, "-C", stageDir, "."]` style (no
|
|
9
|
+
* shell quoting needed because we use execFileSync, not execSync).
|
|
10
|
+
*
|
|
11
|
+
* After the Critical #3 fix:
|
|
12
|
+
* - Honors PEAKS_TAR_BIN / TAR env vars.
|
|
13
|
+
* - On Windows, tries C:\Windows\System32\tar.exe first; falls back
|
|
14
|
+
* to PATH lookup if it's missing.
|
|
15
|
+
* - Accumulates tar's stderr and re-throws it on non-zero exit so
|
|
16
|
+
* operators can see WHY tar failed (path typo, permission, corrupt
|
|
17
|
+
* stage dir, etc.) instead of swallowing it.
|
|
18
|
+
*
|
|
19
|
+
* Throws `TAR_NOT_FOUND` when the binary cannot be located.
|
|
20
|
+
*/
|
|
21
|
+
export declare function runTar(args: string[]): void;
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import { execFileSync } from "node:child_process";
|
|
2
|
+
import { existsSync } from "node:fs";
|
|
3
|
+
/** Thrown when no usable tar binary can be located. */
|
|
4
|
+
export class TAR_NOT_FOUND extends Error {
|
|
5
|
+
constructor(msg) {
|
|
6
|
+
super(`TAR_NOT_FOUND: ${msg}`);
|
|
7
|
+
this.name = "TAR_NOT_FOUND";
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Resolve a tar binary path, in priority order:
|
|
12
|
+
* 1. process.env.PEAKS_TAR_BIN (explicit override; honored unconditionally)
|
|
13
|
+
* 2. process.env.TAR (POSIX convention, honored if set)
|
|
14
|
+
* 3. On Windows: C:\Windows\System32\tar.exe (bsdtar — accepts
|
|
15
|
+
* Windows-style paths verbatim, unlike git-bash GNU tar)
|
|
16
|
+
* 4. PATH lookup: "tar" (delegates to the platform default)
|
|
17
|
+
*
|
|
18
|
+
* Throws `TAR_NOT_FOUND` when none of the candidates exist (Windows
|
|
19
|
+
* file-system check) or no override is set (POSIX). On POSIX we
|
|
20
|
+
* always trust PATH; tar is in base images 99.9% of the time. On
|
|
21
|
+
* Windows we explicitly stat each candidate so a missing
|
|
22
|
+
* C:\Windows\System32\tar.exe falls through to PATH instead of
|
|
23
|
+
* throwing an opaque spawn-ENOENT.
|
|
24
|
+
*/
|
|
25
|
+
function resolveTarBin() {
|
|
26
|
+
const envOverride = process.env.PEAKS_TAR_BIN;
|
|
27
|
+
if (envOverride && envOverride.length > 0)
|
|
28
|
+
return envOverride;
|
|
29
|
+
const envTar = process.env.TAR;
|
|
30
|
+
if (envTar && envTar.length > 0)
|
|
31
|
+
return envTar;
|
|
32
|
+
if (process.platform === "win32") {
|
|
33
|
+
const systemTar = "C:\\Windows\\System32\\tar.exe";
|
|
34
|
+
if (existsSync(systemTar))
|
|
35
|
+
return systemTar;
|
|
36
|
+
// Fall through to PATH lookup below — many dev setups install tar
|
|
37
|
+
// under Git for Windows or WindowsApps rather than System32.
|
|
38
|
+
}
|
|
39
|
+
// PATH lookup. We can't stat `tar` directly (it's a name, not a path),
|
|
40
|
+
// so we trust the resolution to execFileSync and surface a clean
|
|
41
|
+
// TAR_NOT_FOUND error from the caller if it fails.
|
|
42
|
+
return "tar";
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Run `tar <args...>` in a cross-platform way.
|
|
46
|
+
*
|
|
47
|
+
* Args MUST be `["-czf", outPath, "-C", stageDir, "."]` style (no
|
|
48
|
+
* shell quoting needed because we use execFileSync, not execSync).
|
|
49
|
+
*
|
|
50
|
+
* After the Critical #3 fix:
|
|
51
|
+
* - Honors PEAKS_TAR_BIN / TAR env vars.
|
|
52
|
+
* - On Windows, tries C:\Windows\System32\tar.exe first; falls back
|
|
53
|
+
* to PATH lookup if it's missing.
|
|
54
|
+
* - Accumulates tar's stderr and re-throws it on non-zero exit so
|
|
55
|
+
* operators can see WHY tar failed (path typo, permission, corrupt
|
|
56
|
+
* stage dir, etc.) instead of swallowing it.
|
|
57
|
+
*
|
|
58
|
+
* Throws `TAR_NOT_FOUND` when the binary cannot be located.
|
|
59
|
+
*/
|
|
60
|
+
export function runTar(args) {
|
|
61
|
+
const cmd = resolveTarBin();
|
|
62
|
+
try {
|
|
63
|
+
execFileSync(cmd, args, {
|
|
64
|
+
stdio: ["ignore", "ignore", "pipe"],
|
|
65
|
+
// Surface stderr text rather than dumping a Buffer at the caller.
|
|
66
|
+
// execFileSync with stdio: ["ignore","ignore","pipe"] captures the
|
|
67
|
+
// stderr stream into the Error's `.stderr` Buffer when the child
|
|
68
|
+
// exits non-zero.
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
catch (e) {
|
|
72
|
+
// Distinguish "binary not found" from "binary ran but failed".
|
|
73
|
+
if (e && typeof e === "object" && "code" in e) {
|
|
74
|
+
const code = e.code;
|
|
75
|
+
if (code === "ENOENT") {
|
|
76
|
+
throw new TAR_NOT_FOUND(`tar binary not found (cmd="${cmd}"). Set PEAKS_TAR_BIN to override, or install tar (Windows: bsdtar is bundled with Windows 10+).`);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
// Non-zero exit from tar itself — re-throw with stderr text.
|
|
80
|
+
const stderr = e?.stderr;
|
|
81
|
+
const stderrText = stderr instanceof Buffer
|
|
82
|
+
? stderr.toString("utf-8")
|
|
83
|
+
: typeof stderr === "string"
|
|
84
|
+
? stderr
|
|
85
|
+
: "";
|
|
86
|
+
const baseMsg = e instanceof Error ? e.message : typeof e === "string" ? e : String(e);
|
|
87
|
+
const wrapped = new Error(`tar exited non-zero (cmd="${cmd}"): ${baseMsg}${stderrText ? `\ntar stderr:\n${stderrText.trimEnd()}` : ""}`);
|
|
88
|
+
wrapped.cause = e;
|
|
89
|
+
throw wrapped;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
export interface BeeReleaseRow {
|
|
2
|
+
id: number;
|
|
3
|
+
bee_name: string;
|
|
4
|
+
version: string;
|
|
5
|
+
source: "user";
|
|
6
|
+
archived_at: string;
|
|
7
|
+
archived_by: "user" | "llm";
|
|
8
|
+
user_intent_raw: string | null;
|
|
9
|
+
description: string | null;
|
|
10
|
+
parent_version: string | null;
|
|
11
|
+
changelog: string | null;
|
|
12
|
+
}
|
|
13
|
+
export interface BeeReleasePointerRow {
|
|
14
|
+
bee_name: string;
|
|
15
|
+
latest_version: string;
|
|
16
|
+
released_at: string;
|
|
17
|
+
}
|
|
18
|
+
export interface BeeManifestRow {
|
|
19
|
+
release_id: number;
|
|
20
|
+
schema_version: string;
|
|
21
|
+
description: string;
|
|
22
|
+
segments_json: string;
|
|
23
|
+
entrypoint_preamble: string | null;
|
|
24
|
+
promotion: string;
|
|
25
|
+
min_cycles: number | null;
|
|
26
|
+
requires_human: number;
|
|
27
|
+
requires_smoke: number;
|
|
28
|
+
retire_on_misses: number | null;
|
|
29
|
+
}
|
|
30
|
+
export interface BeeSegmentRefRow {
|
|
31
|
+
id: number;
|
|
32
|
+
release_id: number;
|
|
33
|
+
segment_name: string;
|
|
34
|
+
inputs_json: string | null;
|
|
35
|
+
outputs_json: string | null;
|
|
36
|
+
side_effects: string | null;
|
|
37
|
+
}
|
|
38
|
+
export interface BeeFileRow {
|
|
39
|
+
id: number;
|
|
40
|
+
release_id: number;
|
|
41
|
+
owner_kind: "bee" | "segment";
|
|
42
|
+
owner_name: string;
|
|
43
|
+
path: string;
|
|
44
|
+
kind: "markdown" | "script" | "reference" | "binary" | "other";
|
|
45
|
+
size_bytes: number;
|
|
46
|
+
sha256: string;
|
|
47
|
+
blob_path: string;
|
|
48
|
+
}
|
|
49
|
+
export interface BeeChangeRow {
|
|
50
|
+
id: number;
|
|
51
|
+
release_id: number;
|
|
52
|
+
change_kind: string;
|
|
53
|
+
target_kind: string;
|
|
54
|
+
target_name: string;
|
|
55
|
+
detail: string | null;
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Shape of `manifest.json` inside a release export tarball.
|
|
59
|
+
*
|
|
60
|
+
* Producer: `src/services/skillhub/release-export.ts` writes this file via
|
|
61
|
+
* `JSON.stringify({ bee_name, version, manifestRows, segRows, fileRows, changeRows })`.
|
|
62
|
+
* Consumer: `src/services/skillhub/release-import.ts` parses it back with
|
|
63
|
+
* `JSON.parse(readFileSync(join(stageDir, "manifest.json"), "utf-8"))`.
|
|
64
|
+
*
|
|
65
|
+
* Defining it once here (rather than as an inline anonymous type at the
|
|
66
|
+
* call-site) lets both sides share a structural contract. If a future
|
|
67
|
+
* field is added — e.g. an exported schema-version stamp — it lands in
|
|
68
|
+
* one place and TypeScript flags every consumer that needs updating.
|
|
69
|
+
*/
|
|
70
|
+
export interface ExportPayload {
|
|
71
|
+
bee_name: string;
|
|
72
|
+
version: string;
|
|
73
|
+
manifestRows: Array<{
|
|
74
|
+
schema_version: string;
|
|
75
|
+
description: string;
|
|
76
|
+
segments_json: string;
|
|
77
|
+
entrypoint_preamble: string | null;
|
|
78
|
+
promotion: string;
|
|
79
|
+
min_cycles: number | null;
|
|
80
|
+
requires_human: number;
|
|
81
|
+
requires_smoke: number;
|
|
82
|
+
retire_on_misses: number | null;
|
|
83
|
+
}>;
|
|
84
|
+
segRows: Array<{
|
|
85
|
+
segment_name: string;
|
|
86
|
+
inputs_json: string | null;
|
|
87
|
+
outputs_json: string | null;
|
|
88
|
+
side_effects: string | null;
|
|
89
|
+
}>;
|
|
90
|
+
fileRows: Array<{
|
|
91
|
+
owner_kind: string;
|
|
92
|
+
owner_name: string;
|
|
93
|
+
path: string;
|
|
94
|
+
kind: string;
|
|
95
|
+
size_bytes: number;
|
|
96
|
+
sha256: string;
|
|
97
|
+
blob_path: string;
|
|
98
|
+
}>;
|
|
99
|
+
changeRows: Array<{
|
|
100
|
+
change_kind: string;
|
|
101
|
+
target_kind: string;
|
|
102
|
+
target_name: string;
|
|
103
|
+
detail: string | null;
|
|
104
|
+
}>;
|
|
105
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|