@cleocode/core 2026.4.9 → 2026.4.11
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/dist/adapters/adapter-registry.js +64 -0
- package/dist/adapters/adapter-registry.js.map +1 -0
- package/dist/adapters/discovery.js +83 -0
- package/dist/adapters/discovery.js.map +1 -0
- package/dist/adapters/index.js +9 -0
- package/dist/adapters/index.js.map +1 -0
- package/dist/adapters/manager.js +260 -0
- package/dist/adapters/manager.js.map +1 -0
- package/dist/admin/export-tasks.js +171 -0
- package/dist/admin/export-tasks.js.map +1 -0
- package/dist/admin/export.js +103 -0
- package/dist/admin/export.js.map +1 -0
- package/dist/admin/help.js +106 -0
- package/dist/admin/help.js.map +1 -0
- package/dist/admin/import-tasks.js +182 -0
- package/dist/admin/import-tasks.js.map +1 -0
- package/dist/admin/import.js +129 -0
- package/dist/admin/import.js.map +1 -0
- package/dist/admin/index.js +13 -0
- package/dist/admin/index.js.map +1 -0
- package/dist/adrs/find.js +134 -0
- package/dist/adrs/find.js.map +1 -0
- package/dist/adrs/index.js +15 -0
- package/dist/adrs/index.js.map +1 -0
- package/dist/adrs/link-pipeline.js +160 -0
- package/dist/adrs/link-pipeline.js.map +1 -0
- package/dist/adrs/list.js +43 -0
- package/dist/adrs/list.js.map +1 -0
- package/dist/adrs/parse.js +51 -0
- package/dist/adrs/parse.js.map +1 -0
- package/dist/adrs/show.js +22 -0
- package/dist/adrs/show.js.map +1 -0
- package/dist/adrs/sync.js +188 -0
- package/dist/adrs/sync.js.map +1 -0
- package/dist/adrs/types.js +9 -0
- package/dist/adrs/types.js.map +1 -0
- package/dist/adrs/validate.js +57 -0
- package/dist/adrs/validate.js.map +1 -0
- package/dist/agents/agent-registry.js +288 -0
- package/dist/agents/agent-registry.js.map +1 -0
- package/dist/agents/agent-schema.d.ts +2 -2
- package/dist/agents/agent-schema.js +82 -0
- package/dist/agents/agent-schema.js.map +1 -0
- package/dist/agents/capacity.js +116 -0
- package/dist/agents/capacity.js.map +1 -0
- package/dist/agents/execution-learning.js +474 -0
- package/dist/agents/execution-learning.js.map +1 -0
- package/dist/agents/health-monitor.js +217 -0
- package/dist/agents/health-monitor.js.map +1 -0
- package/dist/agents/index.js +29 -0
- package/dist/agents/index.js.map +1 -0
- package/dist/agents/registry.js +314 -0
- package/dist/agents/registry.js.map +1 -0
- package/dist/agents/retry.js +215 -0
- package/dist/agents/retry.js.map +1 -0
- package/dist/audit-prune.js +94 -0
- package/dist/audit-prune.js.map +1 -0
- package/dist/audit.js +68 -0
- package/dist/audit.js.map +1 -0
- package/dist/backfill/index.js +229 -0
- package/dist/backfill/index.js.map +1 -0
- package/dist/bootstrap.js +344 -0
- package/dist/bootstrap.js.map +1 -0
- package/dist/caamp/adapter.js +259 -0
- package/dist/caamp/adapter.js.map +1 -0
- package/dist/caamp/capability-check.js +38 -0
- package/dist/caamp/capability-check.js.map +1 -0
- package/dist/caamp/index.js +21 -0
- package/dist/caamp/index.js.map +1 -0
- package/dist/caamp-init.js +16 -0
- package/dist/caamp-init.js.map +1 -0
- package/dist/cleo.js +322 -0
- package/dist/cleo.js.map +1 -0
- package/dist/code/index.js +10 -0
- package/dist/code/index.js.map +1 -0
- package/dist/code/outline.js +165 -0
- package/dist/code/outline.js.map +1 -0
- package/dist/code/parser.js +295 -0
- package/dist/code/parser.js.map +1 -0
- package/dist/code/search.js +135 -0
- package/dist/code/search.js.map +1 -0
- package/dist/code/unfold.js +155 -0
- package/dist/code/unfold.js.map +1 -0
- package/dist/codebase-map/analyzers/architecture.js +130 -0
- package/dist/codebase-map/analyzers/architecture.js.map +1 -0
- package/dist/codebase-map/analyzers/concerns.js +122 -0
- package/dist/codebase-map/analyzers/concerns.js.map +1 -0
- package/dist/codebase-map/analyzers/conventions.js +149 -0
- package/dist/codebase-map/analyzers/conventions.js.map +1 -0
- package/dist/codebase-map/analyzers/integrations.js +108 -0
- package/dist/codebase-map/analyzers/integrations.js.map +1 -0
- package/dist/codebase-map/analyzers/stack.js +117 -0
- package/dist/codebase-map/analyzers/stack.js.map +1 -0
- package/dist/codebase-map/analyzers/structure.js +137 -0
- package/dist/codebase-map/analyzers/structure.js.map +1 -0
- package/dist/codebase-map/analyzers/testing.js +118 -0
- package/dist/codebase-map/analyzers/testing.js.map +1 -0
- package/dist/codebase-map/index.js +57 -0
- package/dist/codebase-map/index.js.map +1 -0
- package/dist/codebase-map/store.js +122 -0
- package/dist/codebase-map/store.js.map +1 -0
- package/dist/codebase-map/summary.js +152 -0
- package/dist/codebase-map/summary.js.map +1 -0
- package/dist/compliance/index.js +288 -0
- package/dist/compliance/index.js.map +1 -0
- package/dist/compliance/protocol-enforcement.js +332 -0
- package/dist/compliance/protocol-enforcement.js.map +1 -0
- package/dist/compliance/protocol-rules.js +786 -0
- package/dist/compliance/protocol-rules.js.map +1 -0
- package/dist/compliance/protocol-types.js +79 -0
- package/dist/compliance/protocol-types.js.map +1 -0
- package/dist/compliance/store.js +53 -0
- package/dist/compliance/store.js.map +1 -0
- package/dist/conduit/conduit-client.js +107 -0
- package/dist/conduit/conduit-client.js.map +1 -0
- package/dist/conduit/factory.js +52 -0
- package/dist/conduit/factory.js.map +1 -0
- package/dist/conduit/http-transport.js +155 -0
- package/dist/conduit/http-transport.js.map +1 -0
- package/dist/conduit/index.js +15 -0
- package/dist/conduit/index.js.map +1 -0
- package/dist/conduit/local-transport.js +245 -0
- package/dist/conduit/local-transport.js.map +1 -0
- package/dist/conduit/sse-transport.js +299 -0
- package/dist/conduit/sse-transport.js.map +1 -0
- package/dist/config/build-config.js +29 -0
- package/dist/config/build-config.js.map +1 -0
- package/dist/config.js +401 -0
- package/dist/config.js.map +1 -0
- package/dist/constants.js +18 -0
- package/dist/constants.js.map +1 -0
- package/dist/context/index.js +137 -0
- package/dist/context/index.js.map +1 -0
- package/dist/crypto/credentials.js +191 -0
- package/dist/crypto/credentials.js.map +1 -0
- package/dist/discovery.js +182 -0
- package/dist/discovery.js.map +1 -0
- package/dist/engine-result.js +12 -0
- package/dist/engine-result.js.map +1 -0
- package/dist/error-catalog.js +404 -0
- package/dist/error-catalog.js.map +1 -0
- package/dist/error-registry.js +393 -0
- package/dist/error-registry.js.map +1 -0
- package/dist/errors.js +167 -0
- package/dist/errors.js.map +1 -0
- package/dist/hooks/handlers/agent-hooks.js +106 -0
- package/dist/hooks/handlers/agent-hooks.js.map +1 -0
- package/dist/hooks/handlers/context-hooks.js +111 -0
- package/dist/hooks/handlers/context-hooks.js.map +1 -0
- package/dist/hooks/handlers/error-hooks.js +52 -0
- package/dist/hooks/handlers/error-hooks.js.map +1 -0
- package/dist/hooks/handlers/file-hooks.js +104 -0
- package/dist/hooks/handlers/file-hooks.js.map +1 -0
- package/dist/hooks/handlers/handler-helpers.js +61 -0
- package/dist/hooks/handlers/handler-helpers.js.map +1 -0
- package/dist/hooks/handlers/index.js +28 -0
- package/dist/hooks/handlers/index.js.map +1 -0
- package/dist/hooks/handlers/memory-bridge-refresh.js +42 -0
- package/dist/hooks/handlers/memory-bridge-refresh.js.map +1 -0
- package/dist/hooks/handlers/notification-hooks.js +62 -0
- package/dist/hooks/handlers/notification-hooks.js.map +1 -0
- package/dist/hooks/handlers/session-hooks.d.ts +21 -0
- package/dist/hooks/handlers/session-hooks.d.ts.map +1 -1
- package/dist/hooks/handlers/session-hooks.js +142 -0
- package/dist/hooks/handlers/session-hooks.js.map +1 -0
- package/dist/hooks/handlers/task-hooks.js +65 -0
- package/dist/hooks/handlers/task-hooks.js.map +1 -0
- package/dist/hooks/handlers/work-capture-hooks.js +165 -0
- package/dist/hooks/handlers/work-capture-hooks.js.map +1 -0
- package/dist/hooks/index.js +13 -0
- package/dist/hooks/index.js.map +1 -0
- package/dist/hooks/payload-schemas.d.ts +2 -2
- package/dist/hooks/payload-schemas.js +220 -0
- package/dist/hooks/payload-schemas.js.map +1 -0
- package/dist/hooks/provider-hooks.js +66 -0
- package/dist/hooks/provider-hooks.js.map +1 -0
- package/dist/hooks/registry.js +229 -0
- package/dist/hooks/registry.js.map +1 -0
- package/dist/hooks/types.js +66 -0
- package/dist/hooks/types.js.map +1 -0
- package/dist/hooks.js +136 -0
- package/dist/hooks.js.map +1 -0
- package/dist/index.js +3361 -3095
- package/dist/index.js.map +4 -4
- package/dist/init.js +852 -0
- package/dist/init.js.map +1 -0
- package/dist/inject/index.js +82 -0
- package/dist/inject/index.js.map +1 -0
- package/dist/injection.js +343 -0
- package/dist/injection.js.map +1 -0
- package/dist/intelligence/adaptive-validation.js +497 -0
- package/dist/intelligence/adaptive-validation.js.map +1 -0
- package/dist/intelligence/impact.js +675 -0
- package/dist/intelligence/impact.js.map +1 -0
- package/dist/intelligence/index.js +22 -0
- package/dist/intelligence/index.js.map +1 -0
- package/dist/intelligence/patterns.js +492 -0
- package/dist/intelligence/patterns.js.map +1 -0
- package/dist/intelligence/prediction.js +499 -0
- package/dist/intelligence/prediction.js.map +1 -0
- package/dist/intelligence/types.js +13 -0
- package/dist/intelligence/types.js.map +1 -0
- package/dist/internal.d.ts +7 -2
- package/dist/internal.d.ts.map +1 -1
- package/dist/internal.js +299 -0
- package/dist/internal.js.map +1 -0
- package/dist/issue/create.js +121 -0
- package/dist/issue/create.js.map +1 -0
- package/dist/issue/diagnostics.js +59 -0
- package/dist/issue/diagnostics.js.map +1 -0
- package/dist/issue/index.js +10 -0
- package/dist/issue/index.js.map +1 -0
- package/dist/issue/template-parser.js +267 -0
- package/dist/issue/template-parser.js.map +1 -0
- package/dist/json-schema-validator.js +76 -0
- package/dist/json-schema-validator.js.map +1 -0
- package/dist/lib/index.js +11 -0
- package/dist/lib/index.js.map +1 -0
- package/dist/lib/retry.js +152 -0
- package/dist/lib/retry.js.map +1 -0
- package/dist/lib/tree-sitter-languages.js +71 -0
- package/dist/lib/tree-sitter-languages.js.map +1 -0
- package/dist/lifecycle/chain-composition.js +152 -0
- package/dist/lifecycle/chain-composition.js.map +1 -0
- package/dist/lifecycle/chain-store.js +246 -0
- package/dist/lifecycle/chain-store.js.map +1 -0
- package/dist/lifecycle/consolidate-rcasd.js +352 -0
- package/dist/lifecycle/consolidate-rcasd.js.map +1 -0
- package/dist/lifecycle/default-chain.js +176 -0
- package/dist/lifecycle/default-chain.js.map +1 -0
- package/dist/lifecycle/evidence.js +180 -0
- package/dist/lifecycle/evidence.js.map +1 -0
- package/dist/lifecycle/frontmatter.js +363 -0
- package/dist/lifecycle/frontmatter.js.map +1 -0
- package/dist/lifecycle/index.js +756 -0
- package/dist/lifecycle/index.js.map +1 -0
- package/dist/lifecycle/pipeline.js +656 -0
- package/dist/lifecycle/pipeline.js.map +1 -0
- package/dist/lifecycle/rcasd-index.js +326 -0
- package/dist/lifecycle/rcasd-index.js.map +1 -0
- package/dist/lifecycle/rcasd-paths.js +220 -0
- package/dist/lifecycle/rcasd-paths.js.map +1 -0
- package/dist/lifecycle/resume.js +864 -0
- package/dist/lifecycle/resume.js.map +1 -0
- package/dist/lifecycle/stage-artifacts.js +94 -0
- package/dist/lifecycle/stage-artifacts.js.map +1 -0
- package/dist/lifecycle/stage-guidance.js +234 -0
- package/dist/lifecycle/stage-guidance.js.map +1 -0
- package/dist/lifecycle/stages.js +534 -0
- package/dist/lifecycle/stages.js.map +1 -0
- package/dist/lifecycle/state-machine.js +516 -0
- package/dist/lifecycle/state-machine.js.map +1 -0
- package/dist/lifecycle/tessera-engine.js +249 -0
- package/dist/lifecycle/tessera-engine.js.map +1 -0
- package/dist/logger.js +140 -0
- package/dist/logger.js.map +1 -0
- package/dist/memory/auto-extract.js +177 -0
- package/dist/memory/auto-extract.js.map +1 -0
- package/dist/memory/brain-embedding.js +66 -0
- package/dist/memory/brain-embedding.js.map +1 -0
- package/dist/memory/brain-lifecycle.js +298 -0
- package/dist/memory/brain-lifecycle.js.map +1 -0
- package/dist/memory/brain-links.js +161 -0
- package/dist/memory/brain-links.js.map +1 -0
- package/dist/memory/brain-maintenance.js +114 -0
- package/dist/memory/brain-maintenance.js.map +1 -0
- package/dist/memory/brain-migration.js +149 -0
- package/dist/memory/brain-migration.js.map +1 -0
- package/dist/memory/brain-reasoning.js +215 -0
- package/dist/memory/brain-reasoning.js.map +1 -0
- package/dist/memory/brain-retrieval.js +542 -0
- package/dist/memory/brain-retrieval.js.map +1 -0
- package/dist/memory/brain-row-types.js +10 -0
- package/dist/memory/brain-row-types.js.map +1 -0
- package/dist/memory/brain-search.js +519 -0
- package/dist/memory/brain-search.js.map +1 -0
- package/dist/memory/brain-similarity.js +145 -0
- package/dist/memory/brain-similarity.js.map +1 -0
- package/dist/memory/claude-mem-migration.js +277 -0
- package/dist/memory/claude-mem-migration.js.map +1 -0
- package/dist/memory/decisions.js +162 -0
- package/dist/memory/decisions.js.map +1 -0
- package/dist/memory/embedding-local.js +97 -0
- package/dist/memory/embedding-local.js.map +1 -0
- package/dist/memory/embedding-queue.js +271 -0
- package/dist/memory/embedding-queue.js.map +1 -0
- package/dist/memory/embedding-worker.js +58 -0
- package/dist/memory/embedding-worker.js.map +1 -0
- package/dist/memory/engine-compat.js +1397 -0
- package/dist/memory/engine-compat.js.map +1 -0
- package/dist/memory/index.js +1140 -0
- package/dist/memory/index.js.map +1 -0
- package/dist/memory/learnings.d.ts +4 -4
- package/dist/memory/learnings.js +121 -0
- package/dist/memory/learnings.js.map +1 -0
- package/dist/memory/memory-bridge.js +370 -0
- package/dist/memory/memory-bridge.js.map +1 -0
- package/dist/memory/patterns.d.ts +6 -6
- package/dist/memory/patterns.js +122 -0
- package/dist/memory/patterns.js.map +1 -0
- package/dist/memory/pipeline-manifest-sqlite.js +975 -0
- package/dist/memory/pipeline-manifest-sqlite.js.map +1 -0
- package/dist/memory/session-memory.js +331 -0
- package/dist/memory/session-memory.js.map +1 -0
- package/dist/metrics/ab-test.js +260 -0
- package/dist/metrics/ab-test.js.map +1 -0
- package/dist/metrics/aggregation.js +363 -0
- package/dist/metrics/aggregation.js.map +1 -0
- package/dist/metrics/common.js +64 -0
- package/dist/metrics/common.js.map +1 -0
- package/dist/metrics/enums.js +78 -0
- package/dist/metrics/enums.js.map +1 -0
- package/dist/metrics/index.js +19 -0
- package/dist/metrics/index.js.map +1 -0
- package/dist/metrics/model-provider-registry.js +88 -0
- package/dist/metrics/model-provider-registry.js.map +1 -0
- package/dist/metrics/otel-integration.js +263 -0
- package/dist/metrics/otel-integration.js.map +1 -0
- package/dist/metrics/provider-detection.js +103 -0
- package/dist/metrics/provider-detection.js.map +1 -0
- package/dist/metrics/token-estimation.js +253 -0
- package/dist/metrics/token-estimation.js.map +1 -0
- package/dist/metrics/token-service.js +450 -0
- package/dist/metrics/token-service.js.map +1 -0
- package/dist/migration/agent-outputs.js +316 -0
- package/dist/migration/agent-outputs.js.map +1 -0
- package/dist/migration/checksum.js +92 -0
- package/dist/migration/checksum.js.map +1 -0
- package/dist/migration/index.js +282 -0
- package/dist/migration/index.js.map +1 -0
- package/dist/migration/logger.js +360 -0
- package/dist/migration/logger.js.map +1 -0
- package/dist/migration/preflight.js +9 -0
- package/dist/migration/preflight.js.map +1 -0
- package/dist/migration/state.js +421 -0
- package/dist/migration/state.js.map +1 -0
- package/dist/migration/validate.js +241 -0
- package/dist/migration/validate.js.map +1 -0
- package/dist/mvi-helpers.js +74 -0
- package/dist/mvi-helpers.js.map +1 -0
- package/dist/nexus/deps.js +375 -0
- package/dist/nexus/deps.js.map +1 -0
- package/dist/nexus/discover.js +288 -0
- package/dist/nexus/discover.js.map +1 -0
- package/dist/nexus/hash.js +10 -0
- package/dist/nexus/hash.js.map +1 -0
- package/dist/nexus/index.js +40 -0
- package/dist/nexus/index.js.map +1 -0
- package/dist/nexus/migrate-json-to-sqlite.js +115 -0
- package/dist/nexus/migrate-json-to-sqlite.js.map +1 -0
- package/dist/nexus/permissions.js +105 -0
- package/dist/nexus/permissions.js.map +1 -0
- package/dist/nexus/query.js +175 -0
- package/dist/nexus/query.js.map +1 -0
- package/dist/nexus/registry.js +584 -0
- package/dist/nexus/registry.js.map +1 -0
- package/dist/nexus/sharing/index.js +288 -0
- package/dist/nexus/sharing/index.js.map +1 -0
- package/dist/nexus/transfer-types.js +8 -0
- package/dist/nexus/transfer-types.js.map +1 -0
- package/dist/nexus/transfer.js +263 -0
- package/dist/nexus/transfer.js.map +1 -0
- package/dist/nexus/workspace.js +355 -0
- package/dist/nexus/workspace.js.map +1 -0
- package/dist/observability/index.js +103 -0
- package/dist/observability/index.js.map +1 -0
- package/dist/observability/log-filter.js +63 -0
- package/dist/observability/log-filter.js.map +1 -0
- package/dist/observability/log-parser.js +99 -0
- package/dist/observability/log-parser.js.map +1 -0
- package/dist/observability/log-reader.js +139 -0
- package/dist/observability/log-reader.js.map +1 -0
- package/dist/observability/types.js +19 -0
- package/dist/observability/types.js.map +1 -0
- package/dist/orchestration/analyze.js +107 -0
- package/dist/orchestration/analyze.js.map +1 -0
- package/dist/orchestration/bootstrap.js +132 -0
- package/dist/orchestration/bootstrap.js.map +1 -0
- package/dist/orchestration/context.js +56 -0
- package/dist/orchestration/context.js.map +1 -0
- package/dist/orchestration/critical-path.js +100 -0
- package/dist/orchestration/critical-path.js.map +1 -0
- package/dist/orchestration/hierarchy.js +183 -0
- package/dist/orchestration/hierarchy.js.map +1 -0
- package/dist/orchestration/index.js +287 -0
- package/dist/orchestration/index.js.map +1 -0
- package/dist/orchestration/parallel.js +89 -0
- package/dist/orchestration/parallel.js.map +1 -0
- package/dist/orchestration/protocol-validators.js +815 -0
- package/dist/orchestration/protocol-validators.js.map +1 -0
- package/dist/orchestration/skill-ops.js +98 -0
- package/dist/orchestration/skill-ops.js.map +1 -0
- package/dist/orchestration/status.js +107 -0
- package/dist/orchestration/status.js.map +1 -0
- package/dist/orchestration/unblock.js +103 -0
- package/dist/orchestration/unblock.js.map +1 -0
- package/dist/orchestration/validate-spawn.js +67 -0
- package/dist/orchestration/validate-spawn.js.map +1 -0
- package/dist/orchestration/waves.js +86 -0
- package/dist/orchestration/waves.js.map +1 -0
- package/dist/otel/index.js +163 -0
- package/dist/otel/index.js.map +1 -0
- package/dist/output.js +164 -0
- package/dist/output.js.map +1 -0
- package/dist/pagination.js +64 -0
- package/dist/pagination.js.map +1 -0
- package/dist/paths.d.ts +39 -9
- package/dist/paths.d.ts.map +1 -1
- package/dist/paths.js +776 -0
- package/dist/paths.js.map +1 -0
- package/dist/phases/deps.js +372 -0
- package/dist/phases/deps.js.map +1 -0
- package/dist/phases/index.js +349 -0
- package/dist/phases/index.js.map +1 -0
- package/dist/pipeline/index.js +10 -0
- package/dist/pipeline/index.js.map +1 -0
- package/dist/pipeline/phase.js +45 -0
- package/dist/pipeline/phase.js.map +1 -0
- package/dist/platform.js +211 -0
- package/dist/platform.js.map +1 -0
- package/dist/project-info.js +84 -0
- package/dist/project-info.js.map +1 -0
- package/dist/reconciliation/index.js +10 -0
- package/dist/reconciliation/index.js.map +1 -0
- package/dist/reconciliation/link-store.js +129 -0
- package/dist/reconciliation/link-store.js.map +1 -0
- package/dist/reconciliation/reconciliation-engine.js +298 -0
- package/dist/reconciliation/reconciliation-engine.js.map +1 -0
- package/dist/release/artifacts.js +427 -0
- package/dist/release/artifacts.js.map +1 -0
- package/dist/release/changelog-writer.js +151 -0
- package/dist/release/changelog-writer.js.map +1 -0
- package/dist/release/channel.js +144 -0
- package/dist/release/channel.js.map +1 -0
- package/dist/release/ci.js +166 -0
- package/dist/release/ci.js.map +1 -0
- package/dist/release/github-pr.js +225 -0
- package/dist/release/github-pr.js.map +1 -0
- package/dist/release/guards.js +116 -0
- package/dist/release/guards.js.map +1 -0
- package/dist/release/index.js +22 -0
- package/dist/release/index.js.map +1 -0
- package/dist/release/release-config.js +158 -0
- package/dist/release/release-config.js.map +1 -0
- package/dist/release/release-manifest.js +1019 -0
- package/dist/release/release-manifest.js.map +1 -0
- package/dist/release/version-bump.js +255 -0
- package/dist/release/version-bump.js.map +1 -0
- package/dist/remote/index.js +257 -0
- package/dist/remote/index.js.map +1 -0
- package/dist/repair.js +130 -0
- package/dist/repair.js.map +1 -0
- package/dist/research/index.js +2 -0
- package/dist/research/index.js.map +1 -0
- package/dist/roadmap/index.js +59 -0
- package/dist/roadmap/index.js.map +1 -0
- package/dist/routing/capability-matrix.js +1556 -0
- package/dist/routing/capability-matrix.js.map +1 -0
- package/dist/routing/index.js +9 -0
- package/dist/routing/index.js.map +1 -0
- package/dist/scaffold.d.ts +15 -2
- package/dist/scaffold.d.ts.map +1 -1
- package/dist/scaffold.js +1759 -0
- package/dist/scaffold.js.map +1 -0
- package/dist/schema-management.js +295 -0
- package/dist/schema-management.js.map +1 -0
- package/dist/security/index.js +9 -0
- package/dist/security/index.js.map +1 -0
- package/dist/security/input-sanitization.js +321 -0
- package/dist/security/input-sanitization.js.map +1 -0
- package/dist/sequence/index.js +295 -0
- package/dist/sequence/index.js.map +1 -0
- package/dist/sessions/assumptions.js +54 -0
- package/dist/sessions/assumptions.js.map +1 -0
- package/dist/sessions/briefing.js +377 -0
- package/dist/sessions/briefing.js.map +1 -0
- package/dist/sessions/context-alert.js +222 -0
- package/dist/sessions/context-alert.js.map +1 -0
- package/dist/sessions/context-inject.js +61 -0
- package/dist/sessions/context-inject.js.map +1 -0
- package/dist/sessions/context-monitor.js +98 -0
- package/dist/sessions/context-monitor.js.map +1 -0
- package/dist/sessions/decisions.js +65 -0
- package/dist/sessions/decisions.js.map +1 -0
- package/dist/sessions/find.js +65 -0
- package/dist/sessions/find.js.map +1 -0
- package/dist/sessions/handoff.js +328 -0
- package/dist/sessions/handoff.js.map +1 -0
- package/dist/sessions/hitl-warnings.js +254 -0
- package/dist/sessions/hitl-warnings.js.map +1 -0
- package/dist/sessions/index.js +327 -0
- package/dist/sessions/index.js.map +1 -0
- package/dist/sessions/session-archive.js +40 -0
- package/dist/sessions/session-archive.js.map +1 -0
- package/dist/sessions/session-cleanup.js +59 -0
- package/dist/sessions/session-cleanup.js.map +1 -0
- package/dist/sessions/session-drift.js +134 -0
- package/dist/sessions/session-drift.js.map +1 -0
- package/dist/sessions/session-enforcement.js +144 -0
- package/dist/sessions/session-enforcement.js.map +1 -0
- package/dist/sessions/session-grade.js +253 -0
- package/dist/sessions/session-grade.js.map +1 -0
- package/dist/sessions/session-history.js +42 -0
- package/dist/sessions/session-history.js.map +1 -0
- package/dist/sessions/session-id.js +81 -0
- package/dist/sessions/session-id.js.map +1 -0
- package/dist/sessions/session-memory-bridge.js +52 -0
- package/dist/sessions/session-memory-bridge.js.map +1 -0
- package/dist/sessions/session-show.js +24 -0
- package/dist/sessions/session-show.js.map +1 -0
- package/dist/sessions/session-stats.js +69 -0
- package/dist/sessions/session-stats.js.map +1 -0
- package/dist/sessions/session-suspend.js +39 -0
- package/dist/sessions/session-suspend.js.map +1 -0
- package/dist/sessions/session-switch.js +51 -0
- package/dist/sessions/session-switch.js.map +1 -0
- package/dist/sessions/session-view.js +76 -0
- package/dist/sessions/session-view.js.map +1 -0
- package/dist/sessions/snapshot.js +213 -0
- package/dist/sessions/snapshot.js.map +1 -0
- package/dist/sessions/statusline-setup.js +85 -0
- package/dist/sessions/statusline-setup.js.map +1 -0
- package/dist/sessions/types.js +8 -0
- package/dist/sessions/types.js.map +1 -0
- package/dist/skills/agents/config.js +94 -0
- package/dist/skills/agents/config.js.map +1 -0
- package/dist/skills/agents/install.js +116 -0
- package/dist/skills/agents/install.js.map +1 -0
- package/dist/skills/agents/registry.js +161 -0
- package/dist/skills/agents/registry.js.map +1 -0
- package/dist/skills/discovery.js +333 -0
- package/dist/skills/discovery.js.map +1 -0
- package/dist/skills/dispatch.js +347 -0
- package/dist/skills/dispatch.js.map +1 -0
- package/dist/skills/dynamic-skill-generator.js +87 -0
- package/dist/skills/dynamic-skill-generator.js.map +1 -0
- package/dist/skills/index.js +44 -0
- package/dist/skills/index.js.map +1 -0
- package/dist/skills/injection/subagent.js +195 -0
- package/dist/skills/injection/subagent.js.map +1 -0
- package/dist/skills/injection/token.js +260 -0
- package/dist/skills/injection/token.js.map +1 -0
- package/dist/skills/install.js +40 -0
- package/dist/skills/install.js.map +1 -0
- package/dist/skills/manifests/contribution.js +175 -0
- package/dist/skills/manifests/contribution.js.map +1 -0
- package/dist/skills/manifests/research.js +281 -0
- package/dist/skills/manifests/research.js.map +1 -0
- package/dist/skills/manifests/resolver.js +146 -0
- package/dist/skills/manifests/resolver.js.map +1 -0
- package/dist/skills/marketplace.js +90 -0
- package/dist/skills/marketplace.js.map +1 -0
- package/dist/skills/orchestrator/spawn.js +178 -0
- package/dist/skills/orchestrator/spawn.js.map +1 -0
- package/dist/skills/orchestrator/startup.js +451 -0
- package/dist/skills/orchestrator/startup.js.map +1 -0
- package/dist/skills/orchestrator/validator.js +301 -0
- package/dist/skills/orchestrator/validator.js.map +1 -0
- package/dist/skills/precedence-integration.js +73 -0
- package/dist/skills/precedence-integration.js.map +1 -0
- package/dist/skills/precedence-types.js +16 -0
- package/dist/skills/precedence-types.js.map +1 -0
- package/dist/skills/routing-table.js +63 -0
- package/dist/skills/routing-table.js.map +1 -0
- package/dist/skills/skill-paths.js +217 -0
- package/dist/skills/skill-paths.js.map +1 -0
- package/dist/skills/test-utility.js +55 -0
- package/dist/skills/test-utility.js.map +1 -0
- package/dist/skills/types.js +118 -0
- package/dist/skills/types.js.map +1 -0
- package/dist/skills/validation.js +183 -0
- package/dist/skills/validation.js.map +1 -0
- package/dist/skills/version.js +57 -0
- package/dist/skills/version.js.map +1 -0
- package/dist/snapshot/index.js +188 -0
- package/dist/snapshot/index.js.map +1 -0
- package/dist/spawn/adapter-registry.js +246 -0
- package/dist/spawn/adapter-registry.js.map +1 -0
- package/dist/spawn/index.js +10 -0
- package/dist/spawn/index.js.map +1 -0
- package/dist/stats/index.js +343 -0
- package/dist/stats/index.js.map +1 -0
- package/dist/stats/workflow-telemetry.js +400 -0
- package/dist/stats/workflow-telemetry.js.map +1 -0
- package/dist/sticky/archive.js +47 -0
- package/dist/sticky/archive.js.map +1 -0
- package/dist/sticky/convert.js +235 -0
- package/dist/sticky/convert.js.map +1 -0
- package/dist/sticky/create.js +48 -0
- package/dist/sticky/create.js.map +1 -0
- package/dist/sticky/id.js +35 -0
- package/dist/sticky/id.js.map +1 -0
- package/dist/sticky/index.js +16 -0
- package/dist/sticky/index.js.map +1 -0
- package/dist/sticky/list.js +44 -0
- package/dist/sticky/list.js.map +1 -0
- package/dist/sticky/purge.js +45 -0
- package/dist/sticky/purge.js.map +1 -0
- package/dist/sticky/show.js +42 -0
- package/dist/sticky/show.js.map +1 -0
- package/dist/sticky/types.js +10 -0
- package/dist/sticky/types.js.map +1 -0
- package/dist/store/agent-registry-accessor.js +265 -0
- package/dist/store/agent-registry-accessor.js.map +1 -0
- package/dist/store/atomic.js +167 -0
- package/dist/store/atomic.js.map +1 -0
- package/dist/store/backup.js +94 -0
- package/dist/store/backup.js.map +1 -0
- package/dist/store/brain-accessor.js +397 -0
- package/dist/store/brain-accessor.js.map +1 -0
- package/dist/store/brain-schema.d.ts +8 -8
- package/dist/store/brain-schema.js +215 -0
- package/dist/store/brain-schema.js.map +1 -0
- package/dist/store/brain-sqlite.js +222 -0
- package/dist/store/brain-sqlite.js.map +1 -0
- package/dist/store/cache.js +168 -0
- package/dist/store/cache.js.map +1 -0
- package/dist/store/chain-schema.js +51 -0
- package/dist/store/chain-schema.js.map +1 -0
- package/dist/store/cleanup-legacy.d.ts +128 -0
- package/dist/store/cleanup-legacy.d.ts.map +1 -0
- package/dist/store/converters.js +124 -0
- package/dist/store/converters.js.map +1 -0
- package/dist/store/cross-db-cleanup.js +319 -0
- package/dist/store/cross-db-cleanup.js.map +1 -0
- package/dist/store/data-accessor.js +26 -0
- package/dist/store/data-accessor.js.map +1 -0
- package/dist/store/data-safety-central.js +269 -0
- package/dist/store/data-safety-central.js.map +1 -0
- package/dist/store/data-safety.js +274 -0
- package/dist/store/data-safety.js.map +1 -0
- package/dist/store/db-helpers.js +224 -0
- package/dist/store/db-helpers.js.map +1 -0
- package/dist/store/export.js +155 -0
- package/dist/store/export.js.map +1 -0
- package/dist/store/file-utils.js +270 -0
- package/dist/store/file-utils.js.map +1 -0
- package/dist/store/git-checkpoint.js +365 -0
- package/dist/store/git-checkpoint.js.map +1 -0
- package/dist/store/import-logging.js +139 -0
- package/dist/store/import-logging.js.map +1 -0
- package/dist/store/import-remap.js +145 -0
- package/dist/store/import-remap.js.map +1 -0
- package/dist/store/import-sort.js +121 -0
- package/dist/store/import-sort.js.map +1 -0
- package/dist/store/index.d.ts +1 -0
- package/dist/store/index.d.ts.map +1 -1
- package/dist/store/index.js +29 -0
- package/dist/store/index.js.map +1 -0
- package/dist/store/json.js +208 -0
- package/dist/store/json.js.map +1 -0
- package/dist/store/lifecycle-store.js +249 -0
- package/dist/store/lifecycle-store.js.map +1 -0
- package/dist/store/lock.js +70 -0
- package/dist/store/lock.js.map +1 -0
- package/dist/store/migration-manager.js +151 -0
- package/dist/store/migration-manager.js.map +1 -0
- package/dist/store/migration-sqlite.js +676 -0
- package/dist/store/migration-sqlite.js.map +1 -0
- package/dist/store/nexus-schema.js +62 -0
- package/dist/store/nexus-schema.js.map +1 -0
- package/dist/store/nexus-sqlite.d.ts +14 -2
- package/dist/store/nexus-sqlite.d.ts.map +1 -1
- package/dist/store/nexus-sqlite.js +217 -0
- package/dist/store/nexus-sqlite.js.map +1 -0
- package/dist/store/nexus-validation-schemas.js +40 -0
- package/dist/store/nexus-validation-schemas.js.map +1 -0
- package/dist/store/parsers.js +37 -0
- package/dist/store/parsers.js.map +1 -0
- package/dist/store/project-detect.js +457 -0
- package/dist/store/project-detect.js.map +1 -0
- package/dist/store/provider.js +101 -0
- package/dist/store/provider.js.map +1 -0
- package/dist/store/safety-data-accessor.js +257 -0
- package/dist/store/safety-data-accessor.js.map +1 -0
- package/dist/store/schema.js +7 -0
- package/dist/store/schema.js.map +1 -0
- package/dist/store/session-store.js +219 -0
- package/dist/store/session-store.js.map +1 -0
- package/dist/store/signaldock-sqlite.js +400 -0
- package/dist/store/signaldock-sqlite.js.map +1 -0
- package/dist/store/sqlite-backup.d.ts +121 -10
- package/dist/store/sqlite-backup.d.ts.map +1 -1
- package/dist/store/sqlite-backup.js +241 -0
- package/dist/store/sqlite-backup.js.map +1 -0
- package/dist/store/sqlite-data-accessor.js +787 -0
- package/dist/store/sqlite-data-accessor.js.map +1 -0
- package/dist/store/sqlite.d.ts.map +1 -1
- package/dist/store/sqlite.js +481 -0
- package/dist/store/sqlite.js.map +1 -0
- package/dist/store/status-registry.js +8 -0
- package/dist/store/status-registry.js.map +1 -0
- package/dist/store/task-store.js +358 -0
- package/dist/store/task-store.js.map +1 -0
- package/dist/store/tasks-schema.d.ts +8 -8
- package/dist/store/tasks-schema.js +610 -0
- package/dist/store/tasks-schema.js.map +1 -0
- package/dist/store/typed-query.js +15 -0
- package/dist/store/typed-query.js.map +1 -0
- package/dist/store/validation-schemas.d.ts +37 -37
- package/dist/store/validation-schemas.js +278 -0
- package/dist/store/validation-schemas.js.map +1 -0
- package/dist/system/archive-analytics.js +277 -0
- package/dist/system/archive-analytics.js.map +1 -0
- package/dist/system/archive-stats.js +64 -0
- package/dist/system/archive-stats.js.map +1 -0
- package/dist/system/audit.js +145 -0
- package/dist/system/audit.js.map +1 -0
- package/dist/system/backup.d.ts +91 -3
- package/dist/system/backup.d.ts.map +1 -1
- package/dist/system/backup.js +280 -0
- package/dist/system/backup.js.map +1 -0
- package/dist/system/cleanup.js +134 -0
- package/dist/system/cleanup.js.map +1 -0
- package/dist/system/health.js +1100 -0
- package/dist/system/health.js.map +1 -0
- package/dist/system/index.js +18 -0
- package/dist/system/index.js.map +1 -0
- package/dist/system/inject-generate.js +122 -0
- package/dist/system/inject-generate.js.map +1 -0
- package/dist/system/labels.js +38 -0
- package/dist/system/labels.js.map +1 -0
- package/dist/system/metrics.js +61 -0
- package/dist/system/metrics.js.map +1 -0
- package/dist/system/migrate.js +43 -0
- package/dist/system/migrate.js.map +1 -0
- package/dist/system/platform-paths.js +80 -0
- package/dist/system/platform-paths.js.map +1 -0
- package/dist/system/runtime.js +161 -0
- package/dist/system/runtime.js.map +1 -0
- package/dist/system/safestop.js +99 -0
- package/dist/system/safestop.js.map +1 -0
- package/dist/system/storage-preflight.js +123 -0
- package/dist/system/storage-preflight.js.map +1 -0
- package/dist/task-work/index.js +159 -0
- package/dist/task-work/index.js.map +1 -0
- package/dist/tasks/add.js +661 -0
- package/dist/tasks/add.js.map +1 -0
- package/dist/tasks/analyze.js +85 -0
- package/dist/tasks/analyze.js.map +1 -0
- package/dist/tasks/archive.js +90 -0
- package/dist/tasks/archive.js.map +1 -0
- package/dist/tasks/atomicity.js +83 -0
- package/dist/tasks/atomicity.js.map +1 -0
- package/dist/tasks/cancel-ops.js +83 -0
- package/dist/tasks/cancel-ops.js.map +1 -0
- package/dist/tasks/complete.js +211 -0
- package/dist/tasks/complete.js.map +1 -0
- package/dist/tasks/crossref-extract.js +73 -0
- package/dist/tasks/crossref-extract.js.map +1 -0
- package/dist/tasks/delete-preview.js +192 -0
- package/dist/tasks/delete-preview.js.map +1 -0
- package/dist/tasks/delete.js +120 -0
- package/dist/tasks/delete.js.map +1 -0
- package/dist/tasks/deletion-strategy.js +200 -0
- package/dist/tasks/deletion-strategy.js.map +1 -0
- package/dist/tasks/dependency-check.js +278 -0
- package/dist/tasks/dependency-check.js.map +1 -0
- package/dist/tasks/deps-ready.js +32 -0
- package/dist/tasks/deps-ready.js.map +1 -0
- package/dist/tasks/enforcement.js +86 -0
- package/dist/tasks/enforcement.js.map +1 -0
- package/dist/tasks/epic-enforcement.js +294 -0
- package/dist/tasks/epic-enforcement.js.map +1 -0
- package/dist/tasks/find.js +154 -0
- package/dist/tasks/find.js.map +1 -0
- package/dist/tasks/graph-cache.js +127 -0
- package/dist/tasks/graph-cache.js.map +1 -0
- package/dist/tasks/graph-ops.js +171 -0
- package/dist/tasks/graph-ops.js.map +1 -0
- package/dist/tasks/graph-rag.js +328 -0
- package/dist/tasks/graph-rag.js.map +1 -0
- package/dist/tasks/hierarchy-policy.js +149 -0
- package/dist/tasks/hierarchy-policy.js.map +1 -0
- package/dist/tasks/hierarchy.js +185 -0
- package/dist/tasks/hierarchy.js.map +1 -0
- package/dist/tasks/id-generator.js +65 -0
- package/dist/tasks/id-generator.js.map +1 -0
- package/dist/tasks/index.js +14 -0
- package/dist/tasks/index.js.map +1 -0
- package/dist/tasks/labels.js +52 -0
- package/dist/tasks/labels.js.map +1 -0
- package/dist/tasks/list.js +75 -0
- package/dist/tasks/list.js.map +1 -0
- package/dist/tasks/phase-tracking.js +133 -0
- package/dist/tasks/phase-tracking.js.map +1 -0
- package/dist/tasks/pipeline-stage.js +248 -0
- package/dist/tasks/pipeline-stage.js.map +1 -0
- package/dist/tasks/plan.js +268 -0
- package/dist/tasks/plan.js.map +1 -0
- package/dist/tasks/relates.js +89 -0
- package/dist/tasks/relates.js.map +1 -0
- package/dist/tasks/show.js +80 -0
- package/dist/tasks/show.js.map +1 -0
- package/dist/tasks/size-weighting.js +86 -0
- package/dist/tasks/size-weighting.js.map +1 -0
- package/dist/tasks/staleness.js +86 -0
- package/dist/tasks/staleness.js.map +1 -0
- package/dist/tasks/task-ops.js +1741 -0
- package/dist/tasks/task-ops.js.map +1 -0
- package/dist/tasks/update.js +277 -0
- package/dist/tasks/update.js.map +1 -0
- package/dist/templates/index.js +10 -0
- package/dist/templates/index.js.map +1 -0
- package/dist/templates/parser.js +254 -0
- package/dist/templates/parser.js.map +1 -0
- package/dist/ui/aliases.js +153 -0
- package/dist/ui/aliases.js.map +1 -0
- package/dist/ui/changelog.js +184 -0
- package/dist/ui/changelog.js.map +1 -0
- package/dist/ui/command-registry.js +168 -0
- package/dist/ui/command-registry.js.map +1 -0
- package/dist/ui/flags.js +94 -0
- package/dist/ui/flags.js.map +1 -0
- package/dist/ui/index.js +24 -0
- package/dist/ui/index.js.map +1 -0
- package/dist/upgrade.js +1148 -0
- package/dist/upgrade.js.map +1 -0
- package/dist/validation/chain-validation.js +146 -0
- package/dist/validation/chain-validation.js.map +1 -0
- package/dist/validation/compliance.js +155 -0
- package/dist/validation/compliance.js.map +1 -0
- package/dist/validation/docs-sync.js +212 -0
- package/dist/validation/docs-sync.js.map +1 -0
- package/dist/validation/doctor/checks.js +1069 -0
- package/dist/validation/doctor/checks.js.map +1 -0
- package/dist/validation/doctor/index.js +9 -0
- package/dist/validation/doctor/index.js.map +1 -0
- package/dist/validation/doctor/project-cache.js +160 -0
- package/dist/validation/doctor/project-cache.js.map +1 -0
- package/dist/validation/doctor/utils.js +155 -0
- package/dist/validation/doctor/utils.js.map +1 -0
- package/dist/validation/engine.js +902 -0
- package/dist/validation/engine.js.map +1 -0
- package/dist/validation/gap-check.js +175 -0
- package/dist/validation/gap-check.js.map +1 -0
- package/dist/validation/index.js +40 -0
- package/dist/validation/index.js.map +1 -0
- package/dist/validation/manifest.js +237 -0
- package/dist/validation/manifest.js.map +1 -0
- package/dist/validation/operation-gate-validators.js +724 -0
- package/dist/validation/operation-gate-validators.js.map +1 -0
- package/dist/validation/operation-verification-gates.js +532 -0
- package/dist/validation/operation-verification-gates.js.map +1 -0
- package/dist/validation/param-utils.js +139 -0
- package/dist/validation/param-utils.js.map +1 -0
- package/dist/validation/protocol-common.js +300 -0
- package/dist/validation/protocol-common.js.map +1 -0
- package/dist/validation/protocols/_shared.js +75 -0
- package/dist/validation/protocols/_shared.js.map +1 -0
- package/dist/validation/protocols/architecture-decision.js +31 -0
- package/dist/validation/protocols/architecture-decision.js.map +1 -0
- package/dist/validation/protocols/artifact-publish.js +28 -0
- package/dist/validation/protocols/artifact-publish.js.map +1 -0
- package/dist/validation/protocols/consensus.js +41 -0
- package/dist/validation/protocols/consensus.js.map +1 -0
- package/dist/validation/protocols/contribution.js +27 -0
- package/dist/validation/protocols/contribution.js.map +1 -0
- package/dist/validation/protocols/decomposition.js +28 -0
- package/dist/validation/protocols/decomposition.js.map +1 -0
- package/dist/validation/protocols/implementation.js +24 -0
- package/dist/validation/protocols/implementation.js.map +1 -0
- package/dist/validation/protocols/provenance.js +29 -0
- package/dist/validation/protocols/provenance.js.map +1 -0
- package/dist/validation/protocols/release.js +29 -0
- package/dist/validation/protocols/release.js.map +1 -0
- package/dist/validation/protocols/research.js +24 -0
- package/dist/validation/protocols/research.js.map +1 -0
- package/dist/validation/protocols/specification.js +27 -0
- package/dist/validation/protocols/specification.js.map +1 -0
- package/dist/validation/protocols/testing.js +30 -0
- package/dist/validation/protocols/testing.js.map +1 -0
- package/dist/validation/protocols/validation.js +30 -0
- package/dist/validation/protocols/validation.js.map +1 -0
- package/dist/validation/schema-integrity.js +170 -0
- package/dist/validation/schema-integrity.js.map +1 -0
- package/dist/validation/schema-validator.js +176 -0
- package/dist/validation/schema-validator.js.map +1 -0
- package/dist/validation/validate-ops.js +937 -0
- package/dist/validation/validate-ops.js.map +1 -0
- package/dist/validation/validation-rules.js +226 -0
- package/dist/validation/validation-rules.js.map +1 -0
- package/dist/validation/verification.js +321 -0
- package/dist/validation/verification.js.map +1 -0
- package/package.json +10 -8
- package/src/__tests__/paths-walkup.test.ts +305 -0
- package/src/__tests__/paths.test.ts +61 -17
- package/src/hooks/handlers/session-hooks.ts +42 -0
- package/src/internal.ts +19 -2
- package/src/paths.ts +91 -14
- package/src/scaffold.ts +22 -3
- package/src/store/__tests__/cleanup-legacy.test.ts +268 -0
- package/src/store/__tests__/database-topology-integration.test.ts +504 -0
- package/src/store/__tests__/sqlite-backup-global.test.ts +281 -0
- package/src/store/__tests__/sqlite-backup.test.ts +118 -10
- package/src/store/cleanup-legacy.ts +208 -0
- package/src/store/index.ts +7 -0
- package/src/store/nexus-sqlite.ts +32 -3
- package/src/store/sqlite-backup.ts +368 -37
- package/src/store/sqlite.ts +19 -3
- package/src/system/__tests__/backup.test.ts +237 -0
- package/src/system/backup.ts +248 -28
- package/templates/cleo-gitignore +19 -3
|
@@ -0,0 +1,281 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tests for global-tier SQLite VACUUM INTO backup (vacuumIntoGlobalBackup,
|
|
3
|
+
* listGlobalSqliteBackups).
|
|
4
|
+
*
|
|
5
|
+
* All tests use a tmp-dir override via `cleoHomeOverride` so they NEVER
|
|
6
|
+
* touch the real user's $XDG_DATA_HOME/cleo/ directory or corrupt actual
|
|
7
|
+
* nexus backups.
|
|
8
|
+
*
|
|
9
|
+
* Coverage:
|
|
10
|
+
* - vacuumIntoGlobalBackup creates a snapshot and increments file count
|
|
11
|
+
* - listGlobalSqliteBackups returns entries sorted newest-first (mtime desc)
|
|
12
|
+
* - Rotation keeps last 10 snapshots, deletes older ones
|
|
13
|
+
* - Snapshot passes PRAGMA integrity_check
|
|
14
|
+
* - Scope filter: listGlobalSqliteBackups with prefix excludes other prefixes
|
|
15
|
+
* - Restore round-trip: snapshot then restore preserves DB content
|
|
16
|
+
* - XDG path: snapshots land under cleoHomeOverride/backups/sqlite/, not hardcoded ~/.cleo/
|
|
17
|
+
*
|
|
18
|
+
* @task T306
|
|
19
|
+
* @epic T299
|
|
20
|
+
*/
|
|
21
|
+
|
|
22
|
+
import { existsSync, mkdirSync, readdirSync, utimesSync, writeFileSync } from 'node:fs';
|
|
23
|
+
import { homedir, tmpdir } from 'node:os';
|
|
24
|
+
import { join } from 'node:path';
|
|
25
|
+
import { DatabaseSync } from 'node:sqlite';
|
|
26
|
+
import { beforeEach, describe, expect, it, vi } from 'vitest';
|
|
27
|
+
|
|
28
|
+
describe('sqlite-backup global tier', () => {
|
|
29
|
+
beforeEach(() => {
|
|
30
|
+
vi.resetModules();
|
|
31
|
+
vi.clearAllMocks();
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Create a minimal, valid SQLite database at `dbPath` with a single table
|
|
36
|
+
* and one row so VACUUM INTO and integrity_check have something to verify.
|
|
37
|
+
*/
|
|
38
|
+
function seedSqliteDb(dbPath: string): void {
|
|
39
|
+
const db = new DatabaseSync(dbPath);
|
|
40
|
+
db.exec(`
|
|
41
|
+
CREATE TABLE IF NOT EXISTS test_data (id INTEGER PRIMARY KEY, value TEXT);
|
|
42
|
+
INSERT INTO test_data (value) VALUES ('hello');
|
|
43
|
+
`);
|
|
44
|
+
db.close();
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
it('vacuumIntoGlobalBackup creates a snapshot file under cleoHomeOverride/backups/sqlite/', async () => {
|
|
48
|
+
vi.resetModules();
|
|
49
|
+
const cleoHome = join(tmpdir(), `cleo-global-test-create-${Date.now()}`);
|
|
50
|
+
const nexusDbPath = join(cleoHome, 'nexus.db');
|
|
51
|
+
mkdirSync(cleoHome, { recursive: true });
|
|
52
|
+
seedSqliteDb(nexusDbPath);
|
|
53
|
+
|
|
54
|
+
// Mock getNexusNativeDb to return a real DatabaseSync handle
|
|
55
|
+
const nexusDb = new DatabaseSync(nexusDbPath);
|
|
56
|
+
vi.doMock('../nexus-sqlite.js', () => ({ getNexusNativeDb: () => nexusDb }));
|
|
57
|
+
vi.doMock('../../paths.js', () => ({ getCleoHome: () => cleoHome }));
|
|
58
|
+
|
|
59
|
+
const { vacuumIntoGlobalBackup } = await import('../sqlite-backup.js');
|
|
60
|
+
const result = await vacuumIntoGlobalBackup('nexus', { cleoHomeOverride: cleoHome });
|
|
61
|
+
|
|
62
|
+
nexusDb.close();
|
|
63
|
+
|
|
64
|
+
expect(result.snapshotPath).toBeTruthy();
|
|
65
|
+
expect(result.snapshotPath).toContain('nexus-');
|
|
66
|
+
expect(result.snapshotPath).toContain(join(cleoHome, 'backups', 'sqlite'));
|
|
67
|
+
expect(existsSync(result.snapshotPath)).toBe(true);
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
it('vacuumIntoGlobalBackup XDG path: uses cleoHomeOverride, not hardcoded ~/.cleo/', async () => {
|
|
71
|
+
vi.resetModules();
|
|
72
|
+
const cleoHome = join(tmpdir(), `cleo-global-xdg-${Date.now()}`);
|
|
73
|
+
const nexusDbPath = join(cleoHome, 'nexus.db');
|
|
74
|
+
mkdirSync(cleoHome, { recursive: true });
|
|
75
|
+
seedSqliteDb(nexusDbPath);
|
|
76
|
+
|
|
77
|
+
const nexusDb = new DatabaseSync(nexusDbPath);
|
|
78
|
+
vi.doMock('../nexus-sqlite.js', () => ({ getNexusNativeDb: () => nexusDb }));
|
|
79
|
+
vi.doMock('../../paths.js', () => ({ getCleoHome: () => cleoHome }));
|
|
80
|
+
|
|
81
|
+
const { vacuumIntoGlobalBackup } = await import('../sqlite-backup.js');
|
|
82
|
+
const result = await vacuumIntoGlobalBackup('nexus', { cleoHomeOverride: cleoHome });
|
|
83
|
+
|
|
84
|
+
nexusDb.close();
|
|
85
|
+
|
|
86
|
+
// Must be under the override dir, not the user's actual cleo home
|
|
87
|
+
expect(result.snapshotPath).toContain(cleoHome);
|
|
88
|
+
expect(result.snapshotPath).not.toContain(join(homedir(), '.local'));
|
|
89
|
+
expect(result.snapshotPath).not.toContain('.cleo');
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
it('vacuumIntoGlobalBackup is non-fatal when getNexusNativeDb() returns null', async () => {
|
|
93
|
+
vi.resetModules();
|
|
94
|
+
vi.doMock('../nexus-sqlite.js', () => ({ getNexusNativeDb: () => null }));
|
|
95
|
+
vi.doMock('../../paths.js', () => ({ getCleoHome: () => tmpdir() }));
|
|
96
|
+
|
|
97
|
+
const { vacuumIntoGlobalBackup } = await import('../sqlite-backup.js');
|
|
98
|
+
const result = await vacuumIntoGlobalBackup('nexus', {
|
|
99
|
+
cleoHomeOverride: join(tmpdir(), `cleo-null-nexus-${Date.now()}`),
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
expect(result.snapshotPath).toBe('');
|
|
103
|
+
expect(result.rotated).toEqual([]);
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
it('vacuumIntoGlobalBackup snapshot passes PRAGMA integrity_check', async () => {
|
|
107
|
+
vi.resetModules();
|
|
108
|
+
const cleoHome = join(tmpdir(), `cleo-global-integrity-${Date.now()}`);
|
|
109
|
+
const nexusDbPath = join(cleoHome, 'nexus.db');
|
|
110
|
+
mkdirSync(cleoHome, { recursive: true });
|
|
111
|
+
seedSqliteDb(nexusDbPath);
|
|
112
|
+
|
|
113
|
+
const nexusDb = new DatabaseSync(nexusDbPath);
|
|
114
|
+
vi.doMock('../nexus-sqlite.js', () => ({ getNexusNativeDb: () => nexusDb }));
|
|
115
|
+
vi.doMock('../../paths.js', () => ({ getCleoHome: () => cleoHome }));
|
|
116
|
+
|
|
117
|
+
const { vacuumIntoGlobalBackup } = await import('../sqlite-backup.js');
|
|
118
|
+
const result = await vacuumIntoGlobalBackup('nexus', { cleoHomeOverride: cleoHome });
|
|
119
|
+
|
|
120
|
+
nexusDb.close();
|
|
121
|
+
|
|
122
|
+
expect(existsSync(result.snapshotPath)).toBe(true);
|
|
123
|
+
|
|
124
|
+
// Open snapshot and verify integrity
|
|
125
|
+
const snapshot = new DatabaseSync(result.snapshotPath, { readonly: true });
|
|
126
|
+
try {
|
|
127
|
+
const row = snapshot.prepare('PRAGMA integrity_check').get() as Record<string, unknown>;
|
|
128
|
+
const ok = row?.['integrity_check'] ?? row?.['integrity check'];
|
|
129
|
+
expect(ok).toBe('ok');
|
|
130
|
+
} finally {
|
|
131
|
+
snapshot.close();
|
|
132
|
+
}
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
it('rotation keeps last 10 snapshots and deletes older ones', async () => {
|
|
136
|
+
vi.resetModules();
|
|
137
|
+
const cleoHome = join(tmpdir(), `cleo-global-rotation-${Date.now()}`);
|
|
138
|
+
const nexusDbPath = join(cleoHome, 'nexus.db');
|
|
139
|
+
const backupDir = join(cleoHome, 'backups', 'sqlite');
|
|
140
|
+
mkdirSync(backupDir, { recursive: true });
|
|
141
|
+
seedSqliteDb(nexusDbPath);
|
|
142
|
+
|
|
143
|
+
// Seed 11 stale snapshots with valid name pattern
|
|
144
|
+
for (let i = 0; i < 11; i++) {
|
|
145
|
+
const day = String(i + 1).padStart(2, '0');
|
|
146
|
+
writeFileSync(join(backupDir, `nexus-202601${day}-120000.db`), 'fake');
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
const nexusDb = new DatabaseSync(nexusDbPath);
|
|
150
|
+
vi.doMock('../nexus-sqlite.js', () => ({ getNexusNativeDb: () => nexusDb }));
|
|
151
|
+
vi.doMock('../../paths.js', () => ({ getCleoHome: () => cleoHome }));
|
|
152
|
+
|
|
153
|
+
const { vacuumIntoGlobalBackup } = await import('../sqlite-backup.js');
|
|
154
|
+
const result = await vacuumIntoGlobalBackup('nexus', { cleoHomeOverride: cleoHome });
|
|
155
|
+
|
|
156
|
+
nexusDb.close();
|
|
157
|
+
|
|
158
|
+
const remaining = readdirSync(backupDir).filter(
|
|
159
|
+
(f) => f.startsWith('nexus-') && f.endsWith('.db'),
|
|
160
|
+
);
|
|
161
|
+
// The new snapshot was written, meaning 11 stale + 1 new. After rotation,
|
|
162
|
+
// MAX_SNAPSHOTS (10) must be respected.
|
|
163
|
+
expect(remaining.length).toBeLessThanOrEqual(10);
|
|
164
|
+
// The result snapshot should exist
|
|
165
|
+
expect(existsSync(result.snapshotPath)).toBe(true);
|
|
166
|
+
// At least 2 files were rotated out (11 + 1 new = 12, keep 10, remove 2)
|
|
167
|
+
expect(result.rotated.length).toBeGreaterThanOrEqual(2);
|
|
168
|
+
});
|
|
169
|
+
|
|
170
|
+
it('listGlobalSqliteBackups returns entries sorted newest-first by mtime', async () => {
|
|
171
|
+
vi.resetModules();
|
|
172
|
+
const cleoHome = join(tmpdir(), `cleo-global-list-${Date.now()}`);
|
|
173
|
+
const backupDir = join(cleoHome, 'backups', 'sqlite');
|
|
174
|
+
mkdirSync(backupDir, { recursive: true });
|
|
175
|
+
vi.doMock('../../paths.js', () => ({ getCleoHome: () => cleoHome }));
|
|
176
|
+
|
|
177
|
+
const f1 = join(backupDir, 'nexus-20260101-120000.db');
|
|
178
|
+
const f2 = join(backupDir, 'nexus-20260102-120000.db');
|
|
179
|
+
const f3 = join(backupDir, 'nexus-20260103-120000.db');
|
|
180
|
+
writeFileSync(f1, 'fake1');
|
|
181
|
+
writeFileSync(f2, 'fake2');
|
|
182
|
+
writeFileSync(f3, 'fake3');
|
|
183
|
+
// Set deterministic mtimes: f1 oldest, f3 newest
|
|
184
|
+
utimesSync(f1, 1_700_000_100, 1_700_000_100);
|
|
185
|
+
utimesSync(f2, 1_700_000_200, 1_700_000_200);
|
|
186
|
+
utimesSync(f3, 1_700_000_300, 1_700_000_300);
|
|
187
|
+
|
|
188
|
+
const { listGlobalSqliteBackups } = await import('../sqlite-backup.js');
|
|
189
|
+
const entries = listGlobalSqliteBackups(undefined, cleoHome);
|
|
190
|
+
|
|
191
|
+
expect(entries.map((e) => e.name)).toEqual([
|
|
192
|
+
'nexus-20260103-120000.db',
|
|
193
|
+
'nexus-20260102-120000.db',
|
|
194
|
+
'nexus-20260101-120000.db',
|
|
195
|
+
]);
|
|
196
|
+
// Each entry has required fields
|
|
197
|
+
for (const e of entries) {
|
|
198
|
+
expect(e.path).toBeTruthy();
|
|
199
|
+
expect(typeof e.size).toBe('number');
|
|
200
|
+
expect(e.mtime).toBeInstanceOf(Date);
|
|
201
|
+
}
|
|
202
|
+
});
|
|
203
|
+
|
|
204
|
+
it('listGlobalSqliteBackups prefix filter excludes other prefixes', async () => {
|
|
205
|
+
vi.resetModules();
|
|
206
|
+
const cleoHome = join(tmpdir(), `cleo-global-filter-${Date.now()}`);
|
|
207
|
+
const backupDir = join(cleoHome, 'backups', 'sqlite');
|
|
208
|
+
mkdirSync(backupDir, { recursive: true });
|
|
209
|
+
vi.doMock('../../paths.js', () => ({ getCleoHome: () => cleoHome }));
|
|
210
|
+
|
|
211
|
+
// Write files for two different prefixes
|
|
212
|
+
writeFileSync(join(backupDir, 'nexus-20260101-120000.db'), 'nexus-data');
|
|
213
|
+
writeFileSync(join(backupDir, 'nexus-20260102-120000.db'), 'nexus-data-2');
|
|
214
|
+
writeFileSync(join(backupDir, 'signaldock-20260101-120000.db'), 'sd-data');
|
|
215
|
+
|
|
216
|
+
const { listGlobalSqliteBackups } = await import('../sqlite-backup.js');
|
|
217
|
+
|
|
218
|
+
const nexusOnly = listGlobalSqliteBackups('nexus', cleoHome);
|
|
219
|
+
const sdOnly = listGlobalSqliteBackups('signaldock', cleoHome);
|
|
220
|
+
const all = listGlobalSqliteBackups(undefined, cleoHome);
|
|
221
|
+
|
|
222
|
+
expect(nexusOnly.every((e) => e.name.startsWith('nexus-'))).toBe(true);
|
|
223
|
+
expect(nexusOnly.length).toBe(2);
|
|
224
|
+
|
|
225
|
+
expect(sdOnly.every((e) => e.name.startsWith('signaldock-'))).toBe(true);
|
|
226
|
+
expect(sdOnly.length).toBe(1);
|
|
227
|
+
|
|
228
|
+
// Unfiltered returns both
|
|
229
|
+
expect(all.length).toBe(3);
|
|
230
|
+
});
|
|
231
|
+
|
|
232
|
+
it('listGlobalSqliteBackups returns empty array when backup dir does not exist', async () => {
|
|
233
|
+
vi.resetModules();
|
|
234
|
+
vi.doMock('../../paths.js', () => ({ getCleoHome: () => tmpdir() }));
|
|
235
|
+
|
|
236
|
+
const { listGlobalSqliteBackups } = await import('../sqlite-backup.js');
|
|
237
|
+
const nonExistentHome = join(tmpdir(), `cleo-no-exist-${Date.now()}`);
|
|
238
|
+
const entries = listGlobalSqliteBackups(undefined, nonExistentHome);
|
|
239
|
+
|
|
240
|
+
expect(entries).toEqual([]);
|
|
241
|
+
});
|
|
242
|
+
|
|
243
|
+
it('restore round-trip: snapshot then restore preserves all rows', async () => {
|
|
244
|
+
vi.resetModules();
|
|
245
|
+
const cleoHome = join(tmpdir(), `cleo-global-roundtrip-${Date.now()}`);
|
|
246
|
+
const nexusDbPath = join(cleoHome, 'nexus.db');
|
|
247
|
+
mkdirSync(cleoHome, { recursive: true });
|
|
248
|
+
|
|
249
|
+
// Seed with known data
|
|
250
|
+
const db = new DatabaseSync(nexusDbPath);
|
|
251
|
+
db.exec(`
|
|
252
|
+
CREATE TABLE IF NOT EXISTS items (id INTEGER PRIMARY KEY, name TEXT);
|
|
253
|
+
INSERT INTO items (name) VALUES ('alpha');
|
|
254
|
+
INSERT INTO items (name) VALUES ('beta');
|
|
255
|
+
`);
|
|
256
|
+
db.close();
|
|
257
|
+
|
|
258
|
+
const nexusDb = new DatabaseSync(nexusDbPath);
|
|
259
|
+
vi.doMock('../nexus-sqlite.js', () => ({ getNexusNativeDb: () => nexusDb }));
|
|
260
|
+
vi.doMock('../../paths.js', () => ({ getCleoHome: () => cleoHome }));
|
|
261
|
+
|
|
262
|
+
const { vacuumIntoGlobalBackup } = await import('../sqlite-backup.js');
|
|
263
|
+
const { snapshotPath } = await vacuumIntoGlobalBackup('nexus', {
|
|
264
|
+
cleoHomeOverride: cleoHome,
|
|
265
|
+
});
|
|
266
|
+
nexusDb.close();
|
|
267
|
+
|
|
268
|
+
expect(existsSync(snapshotPath)).toBe(true);
|
|
269
|
+
|
|
270
|
+
// Verify the snapshot contains all expected rows
|
|
271
|
+
const snapDb = new DatabaseSync(snapshotPath, { readonly: true });
|
|
272
|
+
try {
|
|
273
|
+
const rows = snapDb.prepare('SELECT name FROM items ORDER BY id').all() as Array<{
|
|
274
|
+
name: string;
|
|
275
|
+
}>;
|
|
276
|
+
expect(rows.map((r) => r.name)).toEqual(['alpha', 'beta']);
|
|
277
|
+
} finally {
|
|
278
|
+
snapDb.close();
|
|
279
|
+
}
|
|
280
|
+
});
|
|
281
|
+
});
|
|
@@ -2,16 +2,20 @@
|
|
|
2
2
|
* Tests for SQLite VACUUM INTO backup module.
|
|
3
3
|
*
|
|
4
4
|
* Verifies:
|
|
5
|
-
* - Non-fatal when getNativeDb()
|
|
6
|
-
* - WAL checkpoint runs before VACUUM INTO
|
|
7
|
-
* - Snapshot rotation enforces MAX_SNAPSHOTS limit
|
|
8
|
-
* - Debounce prevents rapid successive backups
|
|
5
|
+
* - Non-fatal when getNativeDb() / getBrainNativeDb() return null
|
|
6
|
+
* - WAL checkpoint runs before VACUUM INTO for each target
|
|
7
|
+
* - Snapshot rotation enforces MAX_SNAPSHOTS limit per prefix
|
|
8
|
+
* - Debounce prevents rapid successive backups per prefix
|
|
9
|
+
* - vacuumIntoBackupAll snapshots both tasks.db and brain.db
|
|
10
|
+
* - listSqliteBackups / listBrainBackups / listSqliteBackupsAll read back
|
|
11
|
+
* the rotated files sorted newest-first
|
|
9
12
|
*
|
|
10
13
|
* @task T4874
|
|
14
|
+
* @task T5158 — extended to cover brain.db + vacuumIntoBackupAll
|
|
11
15
|
* @epic T4867
|
|
12
16
|
*/
|
|
13
17
|
|
|
14
|
-
import { mkdirSync, readdirSync, writeFileSync } from 'node:fs';
|
|
18
|
+
import { mkdirSync, readdirSync, utimesSync, writeFileSync } from 'node:fs';
|
|
15
19
|
import { tmpdir } from 'node:os';
|
|
16
20
|
import { join } from 'node:path';
|
|
17
21
|
import { beforeEach, describe, expect, it, vi } from 'vitest';
|
|
@@ -24,15 +28,26 @@ describe('sqlite-backup', () => {
|
|
|
24
28
|
|
|
25
29
|
it('is non-fatal when getNativeDb() returns null', async () => {
|
|
26
30
|
vi.doMock('../sqlite.js', () => ({ getNativeDb: () => null }));
|
|
31
|
+
vi.doMock('../brain-sqlite.js', () => ({ getBrainNativeDb: () => null }));
|
|
27
32
|
vi.doMock('../../paths.js', () => ({ getCleoDir: () => tmpdir() }));
|
|
28
33
|
|
|
29
34
|
const { vacuumIntoBackup } = await import('../sqlite-backup.js');
|
|
30
35
|
await expect(vacuumIntoBackup({ force: true })).resolves.not.toThrow();
|
|
31
36
|
});
|
|
32
37
|
|
|
33
|
-
it('
|
|
38
|
+
it('is non-fatal when getBrainNativeDb() returns null', async () => {
|
|
39
|
+
vi.doMock('../sqlite.js', () => ({ getNativeDb: () => null }));
|
|
40
|
+
vi.doMock('../brain-sqlite.js', () => ({ getBrainNativeDb: () => null }));
|
|
41
|
+
vi.doMock('../../paths.js', () => ({ getCleoDir: () => tmpdir() }));
|
|
42
|
+
|
|
43
|
+
const { vacuumIntoBackupAll } = await import('../sqlite-backup.js');
|
|
44
|
+
await expect(vacuumIntoBackupAll({ force: true })).resolves.not.toThrow();
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
it('calls PRAGMA wal_checkpoint(TRUNCATE) before VACUUM INTO for tasks.db', async () => {
|
|
34
48
|
const execMock = vi.fn();
|
|
35
49
|
vi.doMock('../sqlite.js', () => ({ getNativeDb: () => ({ exec: execMock }) }));
|
|
50
|
+
vi.doMock('../brain-sqlite.js', () => ({ getBrainNativeDb: () => null }));
|
|
36
51
|
const tempDir = join(tmpdir(), `cleo-test-wal-${Date.now()}`);
|
|
37
52
|
vi.doMock('../../paths.js', () => ({ getCleoDir: () => tempDir }));
|
|
38
53
|
|
|
@@ -46,9 +61,10 @@ describe('sqlite-backup', () => {
|
|
|
46
61
|
expect(walIdx).toBeLessThan(vacuumIdx);
|
|
47
62
|
});
|
|
48
63
|
|
|
49
|
-
it('enforces maximum 10 snapshots via rotation', async () => {
|
|
64
|
+
it('enforces maximum 10 tasks.db snapshots via rotation', async () => {
|
|
50
65
|
const execMock = vi.fn();
|
|
51
66
|
vi.doMock('../sqlite.js', () => ({ getNativeDb: () => ({ exec: execMock }) }));
|
|
67
|
+
vi.doMock('../brain-sqlite.js', () => ({ getBrainNativeDb: () => null }));
|
|
52
68
|
const tempDir = join(tmpdir(), `cleo-test-rot-${Date.now()}`);
|
|
53
69
|
const backupDir = join(tempDir, 'backups', 'sqlite');
|
|
54
70
|
mkdirSync(backupDir, { recursive: true });
|
|
@@ -63,13 +79,64 @@ describe('sqlite-backup', () => {
|
|
|
63
79
|
const { vacuumIntoBackup } = await import('../sqlite-backup.js');
|
|
64
80
|
await vacuumIntoBackup({ force: true });
|
|
65
81
|
|
|
66
|
-
const remaining = readdirSync(backupDir).filter(
|
|
82
|
+
const remaining = readdirSync(backupDir).filter(
|
|
83
|
+
(f) => f.startsWith('tasks-') && f.endsWith('.db'),
|
|
84
|
+
);
|
|
67
85
|
expect(remaining.length).toBeLessThanOrEqual(10);
|
|
68
86
|
});
|
|
69
87
|
|
|
70
|
-
it('
|
|
88
|
+
it('enforces rotation independently per prefix (tasks + brain)', async () => {
|
|
89
|
+
const tasksExec = vi.fn();
|
|
90
|
+
const brainExec = vi.fn();
|
|
91
|
+
vi.doMock('../sqlite.js', () => ({ getNativeDb: () => ({ exec: tasksExec }) }));
|
|
92
|
+
vi.doMock('../brain-sqlite.js', () => ({ getBrainNativeDb: () => ({ exec: brainExec }) }));
|
|
93
|
+
const tempDir = join(tmpdir(), `cleo-test-rot-prefix-${Date.now()}`);
|
|
94
|
+
const backupDir = join(tempDir, 'backups', 'sqlite');
|
|
95
|
+
mkdirSync(backupDir, { recursive: true });
|
|
96
|
+
vi.doMock('../../paths.js', () => ({ getCleoDir: () => tempDir }));
|
|
97
|
+
|
|
98
|
+
// Seed 11 tasks.db and 11 brain.db stale snapshots.
|
|
99
|
+
for (let i = 0; i < 11; i++) {
|
|
100
|
+
const day = String(i + 1).padStart(2, '0');
|
|
101
|
+
writeFileSync(join(backupDir, `tasks-202601${day}-120000.db`), 'fake');
|
|
102
|
+
writeFileSync(join(backupDir, `brain-202601${day}-120000.db`), 'fake');
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
const { vacuumIntoBackupAll } = await import('../sqlite-backup.js');
|
|
106
|
+
await vacuumIntoBackupAll({ force: true });
|
|
107
|
+
|
|
108
|
+
const files = readdirSync(backupDir);
|
|
109
|
+
const tasksFiles = files.filter((f) => f.startsWith('tasks-') && f.endsWith('.db'));
|
|
110
|
+
const brainFiles = files.filter((f) => f.startsWith('brain-') && f.endsWith('.db'));
|
|
111
|
+
expect(tasksFiles.length).toBeLessThanOrEqual(10);
|
|
112
|
+
expect(brainFiles.length).toBeLessThanOrEqual(10);
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
it('vacuumIntoBackupAll snapshots both tasks.db and brain.db', async () => {
|
|
116
|
+
const tasksExec = vi.fn();
|
|
117
|
+
const brainExec = vi.fn();
|
|
118
|
+
vi.doMock('../sqlite.js', () => ({ getNativeDb: () => ({ exec: tasksExec }) }));
|
|
119
|
+
vi.doMock('../brain-sqlite.js', () => ({ getBrainNativeDb: () => ({ exec: brainExec }) }));
|
|
120
|
+
const tempDir = join(tmpdir(), `cleo-test-both-${Date.now()}`);
|
|
121
|
+
vi.doMock('../../paths.js', () => ({ getCleoDir: () => tempDir }));
|
|
122
|
+
|
|
123
|
+
const { vacuumIntoBackupAll } = await import('../sqlite-backup.js');
|
|
124
|
+
await vacuumIntoBackupAll({ force: true });
|
|
125
|
+
|
|
126
|
+
// Each DB should have received a wal_checkpoint and a VACUUM INTO call.
|
|
127
|
+
const assertExec = (mock: ReturnType<typeof vi.fn>) => {
|
|
128
|
+
const calls = mock.mock.calls.map((c) => c[0] as string);
|
|
129
|
+
expect(calls.some((c) => c.includes('wal_checkpoint'))).toBe(true);
|
|
130
|
+
expect(calls.some((c) => c.includes('VACUUM INTO'))).toBe(true);
|
|
131
|
+
};
|
|
132
|
+
assertExec(tasksExec);
|
|
133
|
+
assertExec(brainExec);
|
|
134
|
+
});
|
|
135
|
+
|
|
136
|
+
it('debounce skips second call within debounce window (tasks prefix)', async () => {
|
|
71
137
|
const execMock = vi.fn();
|
|
72
138
|
vi.doMock('../sqlite.js', () => ({ getNativeDb: () => ({ exec: execMock }) }));
|
|
139
|
+
vi.doMock('../brain-sqlite.js', () => ({ getBrainNativeDb: () => null }));
|
|
73
140
|
const tempDir = join(tmpdir(), `cleo-test-debounce-${Date.now()}`);
|
|
74
141
|
vi.doMock('../../paths.js', () => ({ getCleoDir: () => tempDir }));
|
|
75
142
|
|
|
@@ -78,8 +145,49 @@ describe('sqlite-backup', () => {
|
|
|
78
145
|
await vacuumIntoBackup({ force: true });
|
|
79
146
|
const callCountAfterFirst = execMock.mock.calls.length;
|
|
80
147
|
|
|
81
|
-
// Second call without force
|
|
148
|
+
// Second call without force — should be debounced
|
|
82
149
|
await vacuumIntoBackup({ force: false });
|
|
83
150
|
expect(execMock.mock.calls.length).toBe(callCountAfterFirst);
|
|
84
151
|
});
|
|
152
|
+
|
|
153
|
+
it('listSqliteBackups and listBrainBackups return prefix-specific entries newest-first', async () => {
|
|
154
|
+
vi.doMock('../sqlite.js', () => ({ getNativeDb: () => null }));
|
|
155
|
+
vi.doMock('../brain-sqlite.js', () => ({ getBrainNativeDb: () => null }));
|
|
156
|
+
const tempDir = join(tmpdir(), `cleo-test-list-${Date.now()}`);
|
|
157
|
+
const backupDir = join(tempDir, 'backups', 'sqlite');
|
|
158
|
+
mkdirSync(backupDir, { recursive: true });
|
|
159
|
+
vi.doMock('../../paths.js', () => ({ getCleoDir: () => tempDir }));
|
|
160
|
+
|
|
161
|
+
// Write files then explicitly set mtimes so the listing sort (by mtime
|
|
162
|
+
// descending) is deterministic regardless of filesystem timestamp
|
|
163
|
+
// resolution. Without utimesSync, two files written in the same tight
|
|
164
|
+
// loop can share the same mtime and fall back to insertion order.
|
|
165
|
+
const f1 = join(backupDir, 'tasks-20260101-120000.db');
|
|
166
|
+
const f2 = join(backupDir, 'tasks-20260102-120000.db');
|
|
167
|
+
const f3 = join(backupDir, 'brain-20260103-120000.db');
|
|
168
|
+
writeFileSync(f1, 'fake');
|
|
169
|
+
writeFileSync(f2, 'fake');
|
|
170
|
+
writeFileSync(f3, 'fake');
|
|
171
|
+
// Use distinct epoch seconds, increasing with the date in the filename
|
|
172
|
+
// so that tasks-20260102 is strictly newer than tasks-20260101.
|
|
173
|
+
utimesSync(f1, 1_700_000_100, 1_700_000_100);
|
|
174
|
+
utimesSync(f2, 1_700_000_200, 1_700_000_200);
|
|
175
|
+
utimesSync(f3, 1_700_000_300, 1_700_000_300);
|
|
176
|
+
|
|
177
|
+
const { listSqliteBackups, listBrainBackups, listSqliteBackupsAll } = await import(
|
|
178
|
+
'../sqlite-backup.js'
|
|
179
|
+
);
|
|
180
|
+
const tasksList = listSqliteBackups();
|
|
181
|
+
const brainList = listBrainBackups();
|
|
182
|
+
const all = listSqliteBackupsAll();
|
|
183
|
+
|
|
184
|
+
expect(tasksList.map((e) => e.name)).toEqual([
|
|
185
|
+
'tasks-20260102-120000.db',
|
|
186
|
+
'tasks-20260101-120000.db',
|
|
187
|
+
]);
|
|
188
|
+
expect(brainList.map((e) => e.name)).toEqual(['brain-20260103-120000.db']);
|
|
189
|
+
expect(Object.keys(all).sort()).toEqual(['brain', 'tasks']);
|
|
190
|
+
expect(all['tasks']?.length).toBe(2);
|
|
191
|
+
expect(all['brain']?.length).toBe(1);
|
|
192
|
+
});
|
|
85
193
|
});
|
|
@@ -0,0 +1,208 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Idempotent cleanup of legacy and stray CLEO database files.
|
|
3
|
+
*
|
|
4
|
+
* Provides two independent cleanup functions:
|
|
5
|
+
*
|
|
6
|
+
* 1. {@link detectAndRemoveLegacyGlobalFiles} — removes stale files left at
|
|
7
|
+
* the global CLEO home directory (`getCleoHome()`) by pre-v2026.4.11
|
|
8
|
+
* naming migrations. Safe to call on repeat invocations — existence-checks
|
|
9
|
+
* guard every deletion.
|
|
10
|
+
*
|
|
11
|
+
* Files targeted (see ADR-036 §Decision/Global-Tier table):
|
|
12
|
+
* - workspace.db (pre-nexus naming relic)
|
|
13
|
+
* - workspace.db.bak-pre-rename (safety copy from a long-landed rename)
|
|
14
|
+
* - workspace.db-shm (SQLite shared-memory sidecar of workspace.db)
|
|
15
|
+
* - workspace.db-shm-wal (SQLite WAL sidecar of workspace.db)
|
|
16
|
+
* - nexus-pre-cleo.db.bak (pre-CLEO backup of nexus — migration complete)
|
|
17
|
+
*
|
|
18
|
+
* Live files (nexus.db, signaldock.db, machine-key, config.json, etc.) are
|
|
19
|
+
* NEVER touched. The function only acts on the explicit LEGACY_FILES list.
|
|
20
|
+
*
|
|
21
|
+
* 2. {@link detectAndRemoveStrayProjectNexus} — removes a stray
|
|
22
|
+
* `{projectRoot}/.cleo/nexus.db` that violates ADR-036's global-only
|
|
23
|
+
* nexus contract. Some pre-v2026.4.11 code path accidentally created a
|
|
24
|
+
* zero-byte nexus.db at project tier; this cleans it up on first run.
|
|
25
|
+
*
|
|
26
|
+
* @task T304
|
|
27
|
+
* @task T307
|
|
28
|
+
* @epic T299
|
|
29
|
+
* @adr ADR-036
|
|
30
|
+
* @why v2026.4.10 left workspace.db and pre-cleo backups at global tier;
|
|
31
|
+
* ADR-036 mandates their deletion to eliminate diagnostic confusion and
|
|
32
|
+
* false impressions of active legacy databases.
|
|
33
|
+
*/
|
|
34
|
+
|
|
35
|
+
import fs from 'node:fs';
|
|
36
|
+
import path from 'node:path';
|
|
37
|
+
import { getLogger } from '../logger.js';
|
|
38
|
+
import { getCleoHome } from '../paths.js';
|
|
39
|
+
|
|
40
|
+
// ---------------------------------------------------------------------------
|
|
41
|
+
// Constants
|
|
42
|
+
// ---------------------------------------------------------------------------
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Exhaustive list of legacy filenames that MUST be removed from the global
|
|
46
|
+
* CLEO home directory. No other files are touched.
|
|
47
|
+
*
|
|
48
|
+
* @task T304
|
|
49
|
+
*/
|
|
50
|
+
const LEGACY_FILES: readonly string[] = [
|
|
51
|
+
'workspace.db',
|
|
52
|
+
'workspace.db.bak-pre-rename',
|
|
53
|
+
'workspace.db-shm',
|
|
54
|
+
'workspace.db-shm-wal',
|
|
55
|
+
'nexus-pre-cleo.db.bak',
|
|
56
|
+
] as const;
|
|
57
|
+
|
|
58
|
+
// ---------------------------------------------------------------------------
|
|
59
|
+
// Types
|
|
60
|
+
// ---------------------------------------------------------------------------
|
|
61
|
+
|
|
62
|
+
/** Result returned by {@link detectAndRemoveLegacyGlobalFiles}. */
|
|
63
|
+
export interface LegacyCleanupResult {
|
|
64
|
+
/** Filenames (basename only) that were successfully deleted. */
|
|
65
|
+
removed: string[];
|
|
66
|
+
/** Files that could not be deleted, with error messages. */
|
|
67
|
+
errors: Array<{ file: string; error: string }>;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
// ---------------------------------------------------------------------------
|
|
71
|
+
// Implementation
|
|
72
|
+
// ---------------------------------------------------------------------------
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Detect and remove legacy global-tier files from the CLEO home directory.
|
|
76
|
+
*
|
|
77
|
+
* Idempotent: safe to call when some or all files are already absent. Each
|
|
78
|
+
* file is individually existence-checked before attempting deletion. Failures
|
|
79
|
+
* on individual files are captured in `errors` rather than thrown, so the
|
|
80
|
+
* caller receives a complete picture of what was (and was not) cleaned up.
|
|
81
|
+
*
|
|
82
|
+
* Logs each successful deletion at `info` level and each failure at `warn`
|
|
83
|
+
* level via the shared pino logger.
|
|
84
|
+
*
|
|
85
|
+
* @param cleoHomeOverride - Optional directory override for tests. When
|
|
86
|
+
* omitted the canonical `getCleoHome()` path is used. Prefer passing this
|
|
87
|
+
* parameter in test harnesses rather than mutating `CLEO_HOME` environment
|
|
88
|
+
* variables, as it avoids global state contamination between test runs.
|
|
89
|
+
* @returns A {@link LegacyCleanupResult} describing what was removed and any
|
|
90
|
+
* errors encountered.
|
|
91
|
+
*
|
|
92
|
+
* @example
|
|
93
|
+
* ```typescript
|
|
94
|
+
* // Production usage (runs against real global home)
|
|
95
|
+
* const result = detectAndRemoveLegacyGlobalFiles();
|
|
96
|
+
* if (result.removed.length > 0) {
|
|
97
|
+
* // Legacy files were cleaned up
|
|
98
|
+
* }
|
|
99
|
+
*
|
|
100
|
+
* // Test usage (runs against tmp directory)
|
|
101
|
+
* const result = detectAndRemoveLegacyGlobalFiles('/tmp/fake-cleo-home');
|
|
102
|
+
* ```
|
|
103
|
+
*
|
|
104
|
+
* @task T304
|
|
105
|
+
* @epic T299
|
|
106
|
+
*/
|
|
107
|
+
export function detectAndRemoveLegacyGlobalFiles(cleoHomeOverride?: string): LegacyCleanupResult {
|
|
108
|
+
const log = getLogger('cleanup-legacy');
|
|
109
|
+
const cleoHome = cleoHomeOverride ?? getCleoHome();
|
|
110
|
+
const removed: string[] = [];
|
|
111
|
+
const errors: Array<{ file: string; error: string }> = [];
|
|
112
|
+
|
|
113
|
+
for (const fileName of LEGACY_FILES) {
|
|
114
|
+
const fullPath = path.join(cleoHome, fileName);
|
|
115
|
+
try {
|
|
116
|
+
if (fs.existsSync(fullPath)) {
|
|
117
|
+
fs.unlinkSync(fullPath);
|
|
118
|
+
removed.push(fileName);
|
|
119
|
+
log.info({ file: fullPath }, 'Removed legacy global file');
|
|
120
|
+
}
|
|
121
|
+
} catch (err) {
|
|
122
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
123
|
+
errors.push({ file: fileName, error: message });
|
|
124
|
+
log.warn({ file: fullPath, error: message }, 'Failed to remove legacy global file');
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
return { removed, errors };
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
// ---------------------------------------------------------------------------
|
|
132
|
+
// Project-tier stray nexus.db cleanup (T307)
|
|
133
|
+
// ---------------------------------------------------------------------------
|
|
134
|
+
|
|
135
|
+
/** Result returned by {@link detectAndRemoveStrayProjectNexus}. */
|
|
136
|
+
export interface StrayNexusCleanupResult {
|
|
137
|
+
/** Whether a stray nexus.db was found and deleted. */
|
|
138
|
+
removed: boolean;
|
|
139
|
+
/** Absolute path that was checked (and removed if `removed` is true). */
|
|
140
|
+
path: string;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
/**
|
|
144
|
+
* Detect and remove a stray project-tier `.cleo/nexus.db` file.
|
|
145
|
+
*
|
|
146
|
+
* ADR-036 declares nexus.db as **global-only** — it lives exclusively under
|
|
147
|
+
* `getCleoHome()` (e.g. `~/.local/share/cleo/nexus.db` on Linux). A
|
|
148
|
+
* zero-byte stray was discovered at `/mnt/projects/cleocode/.cleo/nexus.db`
|
|
149
|
+
* (created 2026-03-31), likely produced by an early `cleo init` / `cleo
|
|
150
|
+
* nexus init` invocation that ran before the canonical path was fully wired
|
|
151
|
+
* through `getNexusDbPath()`.
|
|
152
|
+
*
|
|
153
|
+
* This function is idempotent: calling it when no stray file exists is a
|
|
154
|
+
* no-op. It is designed to be called once per CLI startup (alongside
|
|
155
|
+
* {@link detectAndRemoveLegacyGlobalFiles}) so that users who upgrade to
|
|
156
|
+
* v2026.4.11 have the stray silently cleaned up on the first `cleo` run.
|
|
157
|
+
*
|
|
158
|
+
* @param projectRoot - Absolute path to the project root directory. When
|
|
159
|
+
* omitted the caller is responsible for supplying the current project
|
|
160
|
+
* root from `getProjectRoot()`. An override parameter is accepted here to
|
|
161
|
+
* keep tests hermetic (avoids reading live `process.cwd()` state).
|
|
162
|
+
* @returns A {@link StrayNexusCleanupResult} indicating whether a file was
|
|
163
|
+
* removed and the absolute path that was checked.
|
|
164
|
+
*
|
|
165
|
+
* @example
|
|
166
|
+
* ```typescript
|
|
167
|
+
* // Production usage
|
|
168
|
+
* import { getProjectRoot } from '../paths.js';
|
|
169
|
+
* const result = detectAndRemoveStrayProjectNexus(getProjectRoot());
|
|
170
|
+
* if (result.removed) {
|
|
171
|
+
* // Stray project-tier nexus.db has been cleaned up
|
|
172
|
+
* }
|
|
173
|
+
*
|
|
174
|
+
* // Test usage (hermetic)
|
|
175
|
+
* const result = detectAndRemoveStrayProjectNexus('/tmp/fake-project-root');
|
|
176
|
+
* ```
|
|
177
|
+
*
|
|
178
|
+
* @task T307
|
|
179
|
+
* @epic T299
|
|
180
|
+
* @adr ADR-036
|
|
181
|
+
* @why ADR-036 §Decision/Global-Tier: nexus.db is global-only. A stray
|
|
182
|
+
* project-tier copy was created by pre-v2026.4.11 code and must be removed
|
|
183
|
+
* to prevent diagnostic confusion and guard against future regressions.
|
|
184
|
+
*/
|
|
185
|
+
export function detectAndRemoveStrayProjectNexus(projectRoot: string): StrayNexusCleanupResult {
|
|
186
|
+
const log = getLogger('cleanup-legacy');
|
|
187
|
+
const strayPath = path.join(projectRoot, '.cleo', 'nexus.db');
|
|
188
|
+
|
|
189
|
+
if (fs.existsSync(strayPath)) {
|
|
190
|
+
try {
|
|
191
|
+
fs.unlinkSync(strayPath);
|
|
192
|
+
log.warn(
|
|
193
|
+
{ path: strayPath },
|
|
194
|
+
'Removed stray project-tier nexus.db (violates ADR-036 global-only contract)',
|
|
195
|
+
);
|
|
196
|
+
return { removed: true, path: strayPath };
|
|
197
|
+
} catch (err) {
|
|
198
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
199
|
+
log.warn(
|
|
200
|
+
{ path: strayPath, error: message },
|
|
201
|
+
'Failed to remove stray project-tier nexus.db — manual deletion may be required',
|
|
202
|
+
);
|
|
203
|
+
return { removed: false, path: strayPath };
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
return { removed: false, path: strayPath };
|
|
208
|
+
}
|
package/src/store/index.ts
CHANGED
|
@@ -61,6 +61,13 @@ export {
|
|
|
61
61
|
SafetyDataAccessor,
|
|
62
62
|
wrapWithSafety,
|
|
63
63
|
} from './safety-data-accessor.js';
|
|
64
|
+
export {
|
|
65
|
+
listBrainBackups,
|
|
66
|
+
listSqliteBackups,
|
|
67
|
+
listSqliteBackupsAll,
|
|
68
|
+
vacuumIntoBackup,
|
|
69
|
+
vacuumIntoBackupAll,
|
|
70
|
+
} from './sqlite-backup.js';
|
|
64
71
|
|
|
65
72
|
/**
|
|
66
73
|
* Get a StoreProvider instance for the given working directory.
|