@cleocode/core 2026.3.74 → 2026.4.0
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/README.md +1 -1
- package/dist/agents/agent-schema.d.ts.map +1 -1
- package/dist/agents/retry.js +26 -21
- package/dist/agents/retry.js.map +1 -1
- package/dist/cant/approval.d.ts +110 -0
- package/dist/cant/approval.d.ts.map +1 -0
- package/dist/cant/approval.js +185 -0
- package/dist/cant/approval.js.map +1 -0
- package/dist/cant/context-builder.d.ts +79 -0
- package/dist/cant/context-builder.d.ts.map +1 -0
- package/dist/cant/context-builder.js +117 -0
- package/dist/cant/context-builder.js.map +1 -0
- package/dist/cant/discretion.d.ts +95 -0
- package/dist/cant/discretion.d.ts.map +1 -0
- package/dist/cant/discretion.js +116 -0
- package/dist/cant/discretion.js.map +1 -0
- package/dist/cant/index.d.ts +25 -0
- package/dist/cant/index.d.ts.map +1 -0
- package/dist/cant/index.js +23 -0
- package/dist/cant/index.js.map +1 -0
- package/dist/cant/parallel-runner.d.ts +38 -0
- package/dist/cant/parallel-runner.d.ts.map +1 -0
- package/dist/cant/parallel-runner.js +173 -0
- package/dist/cant/parallel-runner.js.map +1 -0
- package/dist/cant/types.d.ts +127 -0
- package/dist/cant/types.d.ts.map +1 -0
- package/dist/cant/types.js +11 -0
- package/dist/cant/types.js.map +1 -0
- package/dist/cant/workflow-executor.d.ts +105 -0
- package/dist/cant/workflow-executor.d.ts.map +1 -0
- package/dist/cant/workflow-executor.js +440 -0
- package/dist/cant/workflow-executor.js.map +1 -0
- package/dist/cleo.js +21 -1
- package/dist/cleo.js.map +1 -1
- package/dist/code/index.d.ts +10 -0
- package/dist/code/index.d.ts.map +1 -0
- package/dist/code/outline.d.ts +51 -0
- package/dist/code/outline.d.ts.map +1 -0
- package/dist/code/parser.d.ts +30 -0
- package/dist/code/parser.d.ts.map +1 -0
- package/dist/code/search.d.ts +42 -0
- package/dist/code/search.d.ts.map +1 -0
- package/dist/code/unfold.d.ts +44 -0
- package/dist/code/unfold.d.ts.map +1 -0
- package/dist/conduit/conduit-client.d.ts +35 -0
- package/dist/conduit/conduit-client.d.ts.map +1 -0
- package/dist/conduit/conduit-client.js +94 -0
- package/dist/conduit/conduit-client.js.map +1 -0
- package/dist/conduit/factory.d.ts +15 -0
- package/dist/conduit/factory.d.ts.map +1 -0
- package/dist/conduit/factory.js +35 -0
- package/dist/conduit/factory.js.map +1 -0
- package/dist/conduit/http-transport.d.ts +44 -0
- package/dist/conduit/http-transport.d.ts.map +1 -0
- package/dist/conduit/http-transport.js +165 -0
- package/dist/conduit/http-transport.js.map +1 -0
- package/dist/conduit/index.d.ts +15 -0
- package/dist/conduit/index.d.ts.map +1 -0
- package/dist/conduit/index.js +12 -0
- package/dist/conduit/index.js.map +1 -0
- package/dist/conduit/local-transport.d.ts +91 -0
- package/dist/conduit/local-transport.d.ts.map +1 -0
- package/dist/conduit/sse-transport.d.ts +68 -0
- package/dist/conduit/sse-transport.d.ts.map +1 -0
- package/dist/config.js +4 -3
- package/dist/config.js.map +1 -1
- package/dist/crypto/credentials.d.ts +40 -0
- package/dist/crypto/credentials.d.ts.map +1 -0
- package/dist/crypto/credentials.js +144 -0
- package/dist/crypto/credentials.js.map +1 -0
- package/dist/engine-result.d.ts +1 -1
- package/dist/engine-result.d.ts.map +1 -1
- package/dist/error-catalog.d.ts +1 -1
- package/dist/error-catalog.d.ts.map +1 -1
- package/dist/error-registry.d.ts +1 -1
- package/dist/error-registry.d.ts.map +1 -1
- package/dist/errors.d.ts +1 -1
- package/dist/errors.d.ts.map +1 -1
- package/dist/hooks/handlers/agent-hooks.d.ts.map +1 -1
- 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.d.ts.map +1 -1
- 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.d.ts +14 -5
- package/dist/hooks/handlers/error-hooks.d.ts.map +1 -1
- package/dist/hooks/handlers/error-hooks.js +15 -6
- package/dist/hooks/handlers/error-hooks.js.map +1 -1
- package/dist/hooks/handlers/file-hooks.d.ts.map +1 -1
- package/dist/hooks/handlers/file-hooks.js +35 -11
- package/dist/hooks/handlers/file-hooks.js.map +1 -1
- package/dist/hooks/handlers/handler-helpers.d.ts +41 -0
- package/dist/hooks/handlers/handler-helpers.d.ts.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 +10 -1
- package/dist/hooks/handlers/index.js.map +1 -1
- package/dist/hooks/handlers/mcp-hooks.d.ts.map +1 -1
- package/dist/hooks/handlers/mcp-hooks.js +88 -21
- package/dist/hooks/handlers/mcp-hooks.js.map +1 -1
- package/dist/hooks/handlers/session-hooks.d.ts.map +1 -1
- package/dist/hooks/handlers/session-hooks.js +5 -10
- package/dist/hooks/handlers/session-hooks.js.map +1 -1
- package/dist/hooks/handlers/task-hooks.d.ts.map +1 -1
- package/dist/hooks/handlers/task-hooks.js +5 -10
- package/dist/hooks/handlers/task-hooks.js.map +1 -1
- package/dist/hooks/handlers/work-capture-hooks.d.ts.map +1 -1
- package/dist/hooks/handlers/work-capture-hooks.js +165 -0
- package/dist/hooks/handlers/work-capture-hooks.js.map +1 -0
- package/dist/hooks/payload-schemas.js +83 -26
- package/dist/hooks/payload-schemas.js.map +1 -1
- package/dist/hooks/provider-hooks.js +37 -5
- package/dist/hooks/provider-hooks.js.map +1 -1
- package/dist/hooks/registry.js +76 -23
- package/dist/hooks/registry.js.map +1 -1
- package/dist/hooks/types.js +17 -13
- package/dist/hooks/types.js.map +1 -1
- package/dist/index.d.ts +4 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +6452 -3371
- package/dist/index.js.map +4 -4
- package/dist/init.d.ts.map +1 -1
- package/dist/init.js +12 -0
- package/dist/init.js.map +1 -1
- package/dist/internal.d.ts +11 -1
- package/dist/internal.d.ts.map +1 -1
- package/dist/internal.js +10 -0
- package/dist/internal.js.map +1 -1
- package/dist/lib/index.d.ts +1 -0
- package/dist/lib/index.d.ts.map +1 -1
- package/dist/lib/tree-sitter-languages.d.ts +29 -0
- package/dist/lib/tree-sitter-languages.d.ts.map +1 -0
- package/dist/memory/brain-links.d.ts.map +1 -1
- package/dist/memory/brain-maintenance.d.ts +13 -0
- package/dist/memory/brain-maintenance.d.ts.map +1 -1
- package/dist/memory/brain-retrieval.d.ts +3 -0
- package/dist/memory/brain-retrieval.d.ts.map +1 -1
- package/dist/memory/brain-retrieval.js +5 -0
- package/dist/memory/brain-retrieval.js.map +1 -1
- package/dist/memory/decisions.d.ts.map +1 -1
- package/dist/mvi-helpers.d.ts +52 -0
- package/dist/mvi-helpers.d.ts.map +1 -0
- package/dist/mvi-helpers.js +74 -0
- package/dist/mvi-helpers.js.map +1 -0
- package/dist/nexus/index.js +2 -0
- package/dist/nexus/index.js.map +1 -1
- package/dist/nexus/workspace.d.ts.map +1 -1
- package/dist/nexus/workspace.js +355 -0
- package/dist/nexus/workspace.js.map +1 -0
- package/dist/orchestration/hierarchy.d.ts +32 -0
- package/dist/orchestration/hierarchy.d.ts.map +1 -0
- package/dist/orchestration/index.d.ts +1 -0
- package/dist/orchestration/index.d.ts.map +1 -1
- package/dist/output.d.ts +2 -2
- package/dist/output.d.ts.map +1 -1
- package/dist/output.js +40 -8
- package/dist/output.js.map +1 -1
- package/dist/pagination.d.ts +1 -1
- package/dist/pagination.d.ts.map +1 -1
- package/dist/sessions/find.d.ts +3 -0
- package/dist/sessions/find.d.ts.map +1 -1
- package/dist/sessions/find.js +3 -1
- package/dist/sessions/find.js.map +1 -1
- package/dist/sessions/index.d.ts.map +1 -1
- package/dist/sessions/index.js +11 -4
- package/dist/sessions/index.js.map +1 -1
- package/dist/sessions/snapshot.js +213 -0
- package/dist/sessions/snapshot.js.map +1 -0
- package/dist/store/agent-registry-accessor.d.ts +31 -0
- package/dist/store/agent-registry-accessor.d.ts.map +1 -0
- package/dist/store/agent-registry-accessor.js +169 -0
- package/dist/store/agent-registry-accessor.js.map +1 -0
- package/dist/store/converters.d.ts.map +1 -1
- package/dist/store/converters.js +2 -0
- package/dist/store/converters.js.map +1 -1
- package/dist/store/cross-db-cleanup.d.ts +34 -0
- package/dist/store/cross-db-cleanup.d.ts.map +1 -1
- package/dist/store/db-helpers.d.ts.map +1 -1
- package/dist/store/db-helpers.js +1 -0
- package/dist/store/db-helpers.js.map +1 -1
- package/dist/store/json.js +2 -2
- package/dist/store/safety-data-accessor.d.ts +7 -0
- package/dist/store/safety-data-accessor.d.ts.map +1 -1
- package/dist/store/safety-data-accessor.js +14 -0
- package/dist/store/safety-data-accessor.js.map +1 -1
- package/dist/store/signaldock-sqlite.d.ts +48 -0
- package/dist/store/signaldock-sqlite.d.ts.map +1 -0
- package/dist/store/signaldock-sqlite.js +178 -0
- package/dist/store/signaldock-sqlite.js.map +1 -0
- package/dist/store/sqlite-data-accessor.d.ts.map +1 -1
- package/dist/store/sqlite-data-accessor.js +50 -0
- package/dist/store/sqlite-data-accessor.js.map +1 -1
- package/dist/store/sqlite.d.ts.map +1 -1
- package/dist/store/sqlite.js +30 -1
- package/dist/store/sqlite.js.map +1 -1
- package/dist/store/task-store.d.ts.map +1 -1
- package/dist/store/task-store.js +2 -0
- package/dist/store/task-store.js.map +1 -1
- package/dist/store/tasks-schema.d.ts +16 -0
- package/dist/store/tasks-schema.d.ts.map +1 -1
- package/dist/store/tasks-schema.js +33 -0
- package/dist/store/tasks-schema.js.map +1 -1
- package/dist/store/validation-schemas.d.ts +32 -0
- package/dist/store/validation-schemas.d.ts.map +1 -1
- package/dist/system/health.d.ts +1 -1
- package/dist/system/health.d.ts.map +1 -1
- package/dist/system/health.js +35 -0
- package/dist/system/health.js.map +1 -1
- package/dist/task-work/index.d.ts.map +1 -1
- package/dist/task-work/index.js +8 -4
- package/dist/task-work/index.js.map +1 -1
- package/dist/tasks/complete.js +5 -2
- package/dist/tasks/complete.js.map +1 -1
- package/dist/tasks/find.d.ts +3 -0
- package/dist/tasks/find.d.ts.map +1 -1
- package/dist/tasks/find.js +7 -1
- package/dist/tasks/find.js.map +1 -1
- package/dist/tasks/list.d.ts +5 -2
- package/dist/tasks/list.d.ts.map +1 -1
- package/dist/tasks/list.js +9 -2
- package/dist/tasks/list.js.map +1 -1
- package/dist/tasks/show.d.ts +3 -0
- package/dist/tasks/show.d.ts.map +1 -1
- package/dist/tasks/show.js +2 -0
- package/dist/tasks/show.js.map +1 -1
- package/dist/upgrade.d.ts.map +1 -1
- package/dist/upgrade.js +15 -0
- package/dist/upgrade.js.map +1 -1
- package/migrations/drizzle-tasks/20260324000000_assignee-column/migration.sql +6 -0
- package/migrations/drizzle-tasks/20260324000000_assignee-column/snapshot.json +9 -0
- package/migrations/drizzle-tasks/20260327000000_agent-credentials/migration.sql +23 -0
- package/package.json +17 -7
- package/src/__tests__/cli-parity.test.js +11 -1
- package/src/__tests__/cli-parity.test.js.map +1 -1
- package/src/__tests__/cli-parity.test.ts +17 -1
- package/src/__tests__/human-output.test.js +11 -1
- package/src/__tests__/human-output.test.js.map +1 -1
- package/src/__tests__/human-output.test.ts +18 -1
- package/src/__tests__/injection-chain.test.js +3 -2
- package/src/__tests__/injection-chain.test.js.map +1 -1
- package/src/__tests__/injection-mvi-tiers.test.d.ts +2 -2
- package/src/__tests__/injection-mvi-tiers.test.js +15 -15
- package/src/__tests__/injection-mvi-tiers.test.js.map +1 -1
- package/src/__tests__/lafs-conformance.test.d.ts +1 -1
- package/src/__tests__/lafs-conformance.test.js +2 -2
- package/src/__tests__/sharing.test.js +19 -0
- package/src/__tests__/sharing.test.js.map +1 -1
- package/src/agents/__tests__/agent-registry.test.d.ts +12 -0
- package/src/agents/__tests__/agent-registry.test.d.ts.map +1 -0
- package/src/agents/__tests__/agent-registry.test.js +262 -0
- package/src/agents/__tests__/agent-registry.test.js.map +1 -0
- package/src/agents/__tests__/execution-learning.test.d.ts +14 -0
- package/src/agents/__tests__/execution-learning.test.d.ts.map +1 -0
- package/src/agents/__tests__/execution-learning.test.js +533 -0
- package/src/agents/__tests__/execution-learning.test.js.map +1 -0
- package/src/agents/__tests__/health-monitor.test.d.ts +10 -0
- package/src/agents/__tests__/health-monitor.test.d.ts.map +1 -0
- package/src/agents/__tests__/health-monitor.test.js +259 -0
- package/src/agents/__tests__/health-monitor.test.js.map +1 -0
- package/src/agents/__tests__/registry.test.js +27 -2
- package/src/agents/__tests__/registry.test.js.map +1 -1
- package/src/agents/agent-schema.ts +2 -5
- package/src/cant/__tests__/cant-agent-parse.test.ts +94 -0
- package/src/cant/approval.ts +218 -0
- package/src/cant/context-builder.ts +135 -0
- package/src/cant/discretion.ts +149 -0
- package/src/cant/index.ts +58 -0
- package/src/cant/parallel-runner.ts +205 -0
- package/src/cant/types.ts +158 -0
- package/src/cant/workflow-executor.ts +618 -0
- package/src/code/index.ts +10 -0
- package/src/code/outline.ts +214 -0
- package/src/code/parser.ts +299 -0
- package/src/code/search.ts +173 -0
- package/src/code/unfold.ts +204 -0
- package/src/conduit/__tests__/dual-api-e2e.test.ts +212 -0
- package/src/conduit/__tests__/local-credential-flow.test.ts +230 -0
- package/src/conduit/__tests__/local-transport.test.ts +320 -0
- package/src/conduit/__tests__/sse-transport.test.ts +344 -0
- package/src/conduit/conduit-client.ts +123 -0
- package/src/conduit/factory.ts +49 -0
- package/src/conduit/http-transport.ts +201 -0
- package/src/conduit/index.ts +15 -0
- package/src/conduit/local-transport.ts +309 -0
- package/src/conduit/sse-transport.ts +382 -0
- package/src/crypto/credentials.ts +166 -0
- package/src/engine-result.ts +1 -1
- package/src/error-catalog.ts +1 -1
- package/src/error-registry.ts +1 -1
- package/src/errors.ts +1 -1
- package/src/hooks/handlers/__tests__/hook-automation-e2e.test.d.ts +13 -0
- package/src/hooks/handlers/__tests__/hook-automation-e2e.test.d.ts.map +1 -0
- package/src/hooks/handlers/__tests__/hook-automation-e2e.test.js +501 -0
- package/src/hooks/handlers/__tests__/hook-automation-e2e.test.js.map +1 -0
- package/src/hooks/handlers/agent-hooks.ts +1 -30
- package/src/hooks/handlers/context-hooks.ts +1 -30
- package/src/hooks/handlers/error-hooks.ts +14 -5
- package/src/hooks/handlers/file-hooks.ts +1 -6
- package/src/hooks/handlers/handler-helpers.ts +62 -0
- package/src/hooks/handlers/mcp-hooks.ts +2 -14
- package/src/hooks/handlers/session-hooks.ts +1 -6
- package/src/hooks/handlers/task-hooks.ts +1 -6
- package/src/hooks/handlers/work-capture-hooks.ts +1 -10
- package/src/index.ts +12 -1
- package/src/init.ts +12 -0
- package/src/intelligence/__tests__/adaptive-validation.test.d.ts +11 -0
- package/src/intelligence/__tests__/adaptive-validation.test.d.ts.map +1 -0
- package/src/intelligence/__tests__/adaptive-validation.test.js +517 -0
- package/src/intelligence/__tests__/adaptive-validation.test.js.map +1 -0
- package/src/intelligence/__tests__/impact.test.d.ts +1 -0
- package/src/intelligence/__tests__/impact.test.d.ts.map +1 -1
- package/src/intelligence/__tests__/impact.test.js +132 -1
- package/src/intelligence/__tests__/impact.test.js.map +1 -1
- package/src/internal.ts +22 -0
- package/src/lib/__tests__/retry.test.d.ts +7 -0
- package/src/lib/__tests__/retry.test.d.ts.map +1 -0
- package/src/lib/__tests__/retry.test.js +225 -0
- package/src/lib/__tests__/retry.test.js.map +1 -0
- package/src/lib/index.ts +8 -0
- package/src/lib/tree-sitter-languages.ts +88 -0
- package/src/lifecycle/__tests__/chain-store.test.js +6 -0
- package/src/lifecycle/__tests__/chain-store.test.js.map +1 -1
- package/src/lifecycle/__tests__/tessera-engine.test.js +52 -0
- package/src/lifecycle/__tests__/tessera-engine.test.js.map +1 -1
- package/src/memory/__tests__/brain-automation.test.d.ts +11 -0
- package/src/memory/__tests__/brain-automation.test.d.ts.map +1 -0
- package/src/memory/__tests__/brain-automation.test.js +730 -0
- package/src/memory/__tests__/brain-automation.test.js.map +1 -0
- package/src/memory/__tests__/brain-links.test.ts +14 -0
- package/src/memory/__tests__/brain-retrieval.test.ts +10 -0
- package/src/memory/__tests__/session-memory.test.ts +17 -0
- package/src/memory/brain-links.ts +17 -0
- package/src/memory/brain-maintenance.ts +33 -1
- package/src/memory/brain-retrieval.ts +27 -2
- package/src/memory/decisions.ts +18 -2
- package/src/mvi-helpers.ts +81 -0
- package/src/nexus/workspace.ts +19 -7
- package/src/orchestration/hierarchy.ts +202 -0
- package/src/orchestration/index.ts +1 -0
- package/src/output.ts +43 -10
- package/src/pagination.ts +1 -1
- package/src/sessions/__tests__/session-edge-cases.test.js +20 -1
- package/src/sessions/__tests__/session-edge-cases.test.js.map +1 -1
- package/src/sessions/__tests__/session-find.test.js +1 -1
- package/src/sessions/__tests__/session-find.test.js.map +1 -1
- package/src/sessions/__tests__/session-find.test.ts +1 -1
- package/src/sessions/find.ts +6 -1
- package/src/sessions/index.ts +9 -0
- package/src/store/__tests__/migration-safety.test.js +3 -0
- package/src/store/__tests__/migration-safety.test.js.map +1 -1
- package/src/store/__tests__/session-store.test.js +128 -1
- package/src/store/__tests__/session-store.test.js.map +1 -1
- package/src/store/__tests__/task-store.test.js +18 -1
- package/src/store/__tests__/task-store.test.js.map +1 -1
- package/src/store/__tests__/test-db-helper.d.ts.map +1 -1
- package/src/store/__tests__/test-db-helper.js +12 -0
- package/src/store/__tests__/test-db-helper.js.map +1 -1
- package/src/store/agent-registry-accessor.ts +375 -0
- package/src/store/converters.ts +2 -0
- package/src/store/cross-db-cleanup.ts +175 -1
- package/src/store/db-helpers.ts +1 -0
- package/src/store/safety-data-accessor.ts +23 -0
- package/src/store/signaldock-sqlite.ts +429 -0
- package/src/store/sqlite-data-accessor.ts +72 -0
- package/src/store/sqlite.ts +4 -1
- package/src/store/task-store.ts +9 -1
- package/src/store/tasks-schema.ts +7 -0
- package/src/system/__tests__/health.test.ts +2 -2
- package/src/system/health.ts +54 -2
- package/src/task-work/index.ts +5 -0
- package/src/tasks/__tests__/add.test.js +19 -1
- package/src/tasks/__tests__/add.test.js.map +1 -1
- package/src/tasks/__tests__/assignee.test.d.ts +14 -0
- package/src/tasks/__tests__/assignee.test.d.ts.map +1 -0
- package/src/tasks/__tests__/assignee.test.js +125 -0
- package/src/tasks/__tests__/assignee.test.js.map +1 -0
- package/src/tasks/__tests__/assignee.test.ts +162 -0
- package/src/tasks/__tests__/complete-unblocks.test.js +13 -1
- package/src/tasks/__tests__/complete-unblocks.test.js.map +1 -1
- package/src/tasks/__tests__/complete.test.js +28 -7
- package/src/tasks/__tests__/complete.test.js.map +1 -1
- package/src/tasks/__tests__/epic-enforcement.test.d.ts +15 -0
- package/src/tasks/__tests__/epic-enforcement.test.d.ts.map +1 -0
- package/src/tasks/__tests__/epic-enforcement.test.js +669 -0
- package/src/tasks/__tests__/epic-enforcement.test.js.map +1 -0
- package/src/tasks/__tests__/hierarchy-policy.test.js +5 -0
- package/src/tasks/__tests__/hierarchy-policy.test.js.map +1 -1
- package/src/tasks/__tests__/minimal-test.test.d.ts +2 -0
- package/src/tasks/__tests__/minimal-test.test.d.ts.map +1 -0
- package/src/tasks/__tests__/minimal-test.test.js +25 -0
- package/src/tasks/__tests__/minimal-test.test.js.map +1 -0
- package/src/tasks/__tests__/pipeline-stage.test.d.ts +14 -0
- package/src/tasks/__tests__/pipeline-stage.test.d.ts.map +1 -0
- package/src/tasks/__tests__/pipeline-stage.test.js +277 -0
- package/src/tasks/__tests__/pipeline-stage.test.js.map +1 -0
- package/src/tasks/__tests__/update.test.js +43 -6
- package/src/tasks/__tests__/update.test.js.map +1 -1
- package/src/tasks/find.ts +11 -1
- package/src/tasks/list.ts +14 -3
- package/src/tasks/show.ts +6 -0
- package/src/upgrade.ts +16 -0
- package/dist/tasks/reparent.d.ts +0 -38
- package/dist/tasks/reparent.d.ts.map +0 -1
- package/dist/ui/injection-legacy.d.ts +0 -26
- package/dist/ui/injection-legacy.d.ts.map +0 -1
- package/dist/ui/injection-legacy.js +0 -42
- package/dist/ui/injection-legacy.js.map +0 -1
- package/src/signaldock/__tests__/claude-code-transport.test.d.ts +0 -7
- package/src/signaldock/__tests__/claude-code-transport.test.d.ts.map +0 -1
- package/src/signaldock/__tests__/claude-code-transport.test.js +0 -147
- package/src/signaldock/__tests__/claude-code-transport.test.js.map +0 -1
- package/src/signaldock/__tests__/claude-code-transport.test.ts +0 -180
- package/src/signaldock/__tests__/factory.test.d.ts +0 -7
- package/src/signaldock/__tests__/factory.test.d.ts.map +0 -1
- package/src/signaldock/__tests__/factory.test.js +0 -55
- package/src/signaldock/__tests__/factory.test.js.map +0 -1
- package/src/signaldock/__tests__/factory.test.ts +0 -61
- package/src/signaldock/__tests__/signaldock-transport.test.d.ts +0 -9
- package/src/signaldock/__tests__/signaldock-transport.test.d.ts.map +0 -1
- package/src/signaldock/__tests__/signaldock-transport.test.js +0 -321
- package/src/signaldock/__tests__/signaldock-transport.test.js.map +0 -1
- package/src/signaldock/__tests__/signaldock-transport.test.ts +0 -421
- package/src/signaldock/claude-code-transport.ts +0 -137
- package/src/signaldock/factory.ts +0 -39
- package/src/signaldock/index.ts +0 -28
- package/src/signaldock/signaldock-transport.ts +0 -194
- package/src/signaldock/transport.ts +0 -78
- package/src/signaldock/types.ts +0 -100
|
@@ -0,0 +1,429 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SQLite store for signaldock.db — local agent messaging database.
|
|
3
|
+
*
|
|
4
|
+
* Creates and manages .cleo/signaldock.db using node:sqlite directly.
|
|
5
|
+
* Runs the consolidated Diesel migration SQL (from signaldock-storage crate)
|
|
6
|
+
* to bootstrap all 22 tables for local agent infrastructure.
|
|
7
|
+
*
|
|
8
|
+
* This is the Node.js bootstrap path. In production cloud, the Rust
|
|
9
|
+
* signaldock-storage crate manages this DB via Diesel ORM directly.
|
|
10
|
+
* Locally, we create the DB here so that cleo init scaffolds the full
|
|
11
|
+
* .cleo/ directory with all databases ready.
|
|
12
|
+
*
|
|
13
|
+
* @task T223
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
import { existsSync, mkdirSync } from 'node:fs';
|
|
17
|
+
import { createRequire } from 'node:module';
|
|
18
|
+
import { dirname, join } from 'node:path';
|
|
19
|
+
import type { DatabaseSync } from 'node:sqlite';
|
|
20
|
+
import { getCleoDirAbsolute } from '../paths.js';
|
|
21
|
+
|
|
22
|
+
const _require = createRequire(import.meta.url);
|
|
23
|
+
const { DatabaseSync: DatabaseSyncClass } = _require('node:sqlite') as {
|
|
24
|
+
DatabaseSync: new (...args: ConstructorParameters<typeof DatabaseSync>) => DatabaseSync;
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
/** Database file name within .cleo/ directory. */
|
|
28
|
+
const DB_FILENAME = 'signaldock.db';
|
|
29
|
+
|
|
30
|
+
/** Schema version for signaldock databases. */
|
|
31
|
+
export const SIGNALDOCK_SCHEMA_VERSION = '2026.3.76';
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Get the path to the signaldock.db SQLite database file.
|
|
35
|
+
*/
|
|
36
|
+
export function getSignaldockDbPath(cwd?: string): string {
|
|
37
|
+
const cleoDir = cwd ? join(cwd, '.cleo') : getCleoDirAbsolute();
|
|
38
|
+
return join(cleoDir, DB_FILENAME);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// ---------------------------------------------------------------------------
|
|
42
|
+
// Embedded migration SQL — bundled so signaldock.db works in ANY project,
|
|
43
|
+
// not just the monorepo where crates/signaldock-storage/ exists.
|
|
44
|
+
// Source: crates/signaldock-storage/migrations/
|
|
45
|
+
// ---------------------------------------------------------------------------
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Ordered migration entries. Each has a name (for tracking) and SQL.
|
|
49
|
+
* Add new migrations to the END of this array.
|
|
50
|
+
*/
|
|
51
|
+
const EMBEDDED_MIGRATIONS: Array<{ name: string; sql: string }> = [
|
|
52
|
+
{
|
|
53
|
+
name: '2026-03-28-000000_initial',
|
|
54
|
+
sql: `-- Consolidated initial migration for SignalDock storage (19 sqlx migrations merged).
|
|
55
|
+
CREATE TABLE IF NOT EXISTS users (
|
|
56
|
+
id TEXT PRIMARY KEY, email TEXT NOT NULL UNIQUE, password_hash TEXT NOT NULL,
|
|
57
|
+
name TEXT, slug TEXT, default_agent_id TEXT, username TEXT, display_username TEXT,
|
|
58
|
+
email_verified INTEGER NOT NULL DEFAULT 0, image TEXT, role TEXT NOT NULL DEFAULT 'user',
|
|
59
|
+
banned INTEGER NOT NULL DEFAULT 0, ban_reason TEXT, ban_expires TEXT,
|
|
60
|
+
two_factor_enabled INTEGER NOT NULL DEFAULT 0, metadata TEXT,
|
|
61
|
+
created_at INTEGER NOT NULL, updated_at INTEGER NOT NULL
|
|
62
|
+
);
|
|
63
|
+
CREATE UNIQUE INDEX IF NOT EXISTS idx_users_slug ON users(slug);
|
|
64
|
+
|
|
65
|
+
CREATE TABLE IF NOT EXISTS organization (
|
|
66
|
+
id TEXT PRIMARY KEY NOT NULL, name TEXT NOT NULL, slug TEXT, logo TEXT, metadata TEXT,
|
|
67
|
+
owner_id TEXT, created_at INTEGER NOT NULL DEFAULT (strftime('%s','now')),
|
|
68
|
+
updated_at INTEGER NOT NULL DEFAULT (strftime('%s','now'))
|
|
69
|
+
);
|
|
70
|
+
CREATE UNIQUE INDEX IF NOT EXISTS idx_organization_slug ON organization(slug);
|
|
71
|
+
|
|
72
|
+
CREATE TABLE IF NOT EXISTS agents (
|
|
73
|
+
id TEXT PRIMARY KEY, agent_id TEXT NOT NULL UNIQUE, name TEXT NOT NULL,
|
|
74
|
+
description TEXT, class TEXT NOT NULL DEFAULT 'custom',
|
|
75
|
+
privacy_tier TEXT NOT NULL DEFAULT 'public', owner_id TEXT REFERENCES users(id),
|
|
76
|
+
endpoint TEXT, webhook_secret TEXT, capabilities TEXT NOT NULL DEFAULT '[]',
|
|
77
|
+
skills TEXT NOT NULL DEFAULT '[]', avatar TEXT, messages_sent INTEGER NOT NULL DEFAULT 0,
|
|
78
|
+
messages_received INTEGER NOT NULL DEFAULT 0, conversation_count INTEGER NOT NULL DEFAULT 0,
|
|
79
|
+
friend_count INTEGER NOT NULL DEFAULT 0, status TEXT NOT NULL DEFAULT 'online',
|
|
80
|
+
last_seen INTEGER, payment_config TEXT, api_key_hash TEXT,
|
|
81
|
+
organization_id TEXT REFERENCES organization(id) ON DELETE SET NULL,
|
|
82
|
+
created_at INTEGER NOT NULL, updated_at INTEGER NOT NULL
|
|
83
|
+
);
|
|
84
|
+
CREATE UNIQUE INDEX IF NOT EXISTS agents_agent_id_idx ON agents(agent_id);
|
|
85
|
+
CREATE INDEX IF NOT EXISTS agents_owner_idx ON agents(owner_id);
|
|
86
|
+
CREATE INDEX IF NOT EXISTS agents_class_idx ON agents(class);
|
|
87
|
+
CREATE INDEX IF NOT EXISTS agents_privacy_idx ON agents(privacy_tier);
|
|
88
|
+
CREATE INDEX IF NOT EXISTS agents_org_idx ON agents(organization_id);
|
|
89
|
+
|
|
90
|
+
CREATE TABLE IF NOT EXISTS conversations (
|
|
91
|
+
id TEXT PRIMARY KEY, participants TEXT NOT NULL,
|
|
92
|
+
visibility TEXT NOT NULL DEFAULT 'private', message_count INTEGER NOT NULL DEFAULT 0,
|
|
93
|
+
last_message_at INTEGER, created_at INTEGER NOT NULL, updated_at INTEGER NOT NULL
|
|
94
|
+
);
|
|
95
|
+
|
|
96
|
+
CREATE TABLE IF NOT EXISTS messages (
|
|
97
|
+
id TEXT PRIMARY KEY, conversation_id TEXT NOT NULL REFERENCES conversations(id),
|
|
98
|
+
from_agent_id TEXT NOT NULL, to_agent_id TEXT NOT NULL, content TEXT NOT NULL,
|
|
99
|
+
content_type TEXT NOT NULL DEFAULT 'text', status TEXT NOT NULL DEFAULT 'pending',
|
|
100
|
+
attachments TEXT NOT NULL DEFAULT '[]', group_id TEXT, metadata TEXT DEFAULT '{}',
|
|
101
|
+
reply_to TEXT, created_at INTEGER NOT NULL, delivered_at INTEGER, read_at INTEGER
|
|
102
|
+
);
|
|
103
|
+
CREATE INDEX IF NOT EXISTS messages_conversation_idx ON messages(conversation_id);
|
|
104
|
+
CREATE INDEX IF NOT EXISTS messages_from_agent_idx ON messages(from_agent_id);
|
|
105
|
+
CREATE INDEX IF NOT EXISTS messages_to_agent_idx ON messages(to_agent_id);
|
|
106
|
+
CREATE INDEX IF NOT EXISTS messages_created_at_idx ON messages(created_at);
|
|
107
|
+
CREATE INDEX IF NOT EXISTS idx_messages_group_id ON messages(group_id) WHERE group_id IS NOT NULL;
|
|
108
|
+
CREATE INDEX IF NOT EXISTS idx_messages_reply_to ON messages(reply_to) WHERE reply_to IS NOT NULL;
|
|
109
|
+
|
|
110
|
+
CREATE TABLE IF NOT EXISTS claim_codes (
|
|
111
|
+
id TEXT PRIMARY KEY, agent_id TEXT NOT NULL REFERENCES agents(id),
|
|
112
|
+
code TEXT NOT NULL UNIQUE, expires_at INTEGER NOT NULL, used_at INTEGER,
|
|
113
|
+
used_by TEXT REFERENCES users(id), created_at INTEGER NOT NULL
|
|
114
|
+
);
|
|
115
|
+
CREATE UNIQUE INDEX IF NOT EXISTS claim_codes_code_idx ON claim_codes(code);
|
|
116
|
+
CREATE INDEX IF NOT EXISTS claim_codes_agent_idx ON claim_codes(agent_id);
|
|
117
|
+
|
|
118
|
+
CREATE TABLE IF NOT EXISTS connections (
|
|
119
|
+
id TEXT PRIMARY KEY, agent_a TEXT NOT NULL REFERENCES agents(id),
|
|
120
|
+
agent_b TEXT NOT NULL REFERENCES agents(id), status TEXT NOT NULL DEFAULT 'pending',
|
|
121
|
+
initiated_by TEXT NOT NULL, created_at INTEGER NOT NULL, updated_at INTEGER NOT NULL
|
|
122
|
+
);
|
|
123
|
+
CREATE INDEX IF NOT EXISTS connections_agent_a_idx ON connections(agent_a);
|
|
124
|
+
CREATE INDEX IF NOT EXISTS connections_agent_b_idx ON connections(agent_b);
|
|
125
|
+
|
|
126
|
+
CREATE TABLE IF NOT EXISTS delivery_jobs (
|
|
127
|
+
id TEXT PRIMARY KEY, message_id TEXT NOT NULL, payload TEXT NOT NULL,
|
|
128
|
+
status TEXT NOT NULL DEFAULT 'pending', attempts INTEGER NOT NULL DEFAULT 0,
|
|
129
|
+
max_attempts INTEGER NOT NULL DEFAULT 6, next_attempt_at INTEGER NOT NULL,
|
|
130
|
+
last_error TEXT, created_at INTEGER NOT NULL, updated_at INTEGER NOT NULL
|
|
131
|
+
);
|
|
132
|
+
CREATE INDEX IF NOT EXISTS idx_delivery_jobs_status ON delivery_jobs(status, next_attempt_at);
|
|
133
|
+
|
|
134
|
+
CREATE TABLE IF NOT EXISTS dead_letters (
|
|
135
|
+
id TEXT PRIMARY KEY, message_id TEXT NOT NULL, job_id TEXT NOT NULL,
|
|
136
|
+
reason TEXT NOT NULL, attempts INTEGER NOT NULL, created_at INTEGER NOT NULL
|
|
137
|
+
);
|
|
138
|
+
CREATE INDEX IF NOT EXISTS idx_dead_letters_message ON dead_letters(message_id);
|
|
139
|
+
|
|
140
|
+
CREATE VIRTUAL TABLE IF NOT EXISTS messages_fts USING fts5(content, from_agent_id, content='messages', content_rowid='rowid');
|
|
141
|
+
INSERT INTO messages_fts(messages_fts) VALUES('rebuild');
|
|
142
|
+
CREATE TRIGGER IF NOT EXISTS messages_ai AFTER INSERT ON messages BEGIN
|
|
143
|
+
INSERT INTO messages_fts(rowid, content, from_agent_id) VALUES (new.rowid, new.content, new.from_agent_id);
|
|
144
|
+
END;
|
|
145
|
+
CREATE TRIGGER IF NOT EXISTS messages_ad AFTER DELETE ON messages BEGIN
|
|
146
|
+
INSERT INTO messages_fts(messages_fts, rowid, content, from_agent_id) VALUES('delete', old.rowid, old.content, old.from_agent_id);
|
|
147
|
+
END;
|
|
148
|
+
CREATE TRIGGER IF NOT EXISTS messages_au AFTER UPDATE ON messages BEGIN
|
|
149
|
+
INSERT INTO messages_fts(messages_fts, rowid, content, from_agent_id) VALUES('delete', old.rowid, old.content, old.from_agent_id);
|
|
150
|
+
INSERT INTO messages_fts(rowid, content, from_agent_id) VALUES (new.rowid, new.content, new.from_agent_id);
|
|
151
|
+
END;
|
|
152
|
+
|
|
153
|
+
CREATE TABLE IF NOT EXISTS message_pins (
|
|
154
|
+
id TEXT PRIMARY KEY, message_id TEXT NOT NULL, conversation_id TEXT NOT NULL,
|
|
155
|
+
pinned_by TEXT NOT NULL, note TEXT, created_at INTEGER NOT NULL, UNIQUE(message_id, pinned_by)
|
|
156
|
+
);
|
|
157
|
+
CREATE INDEX IF NOT EXISTS idx_pins_conversation ON message_pins(conversation_id);
|
|
158
|
+
CREATE INDEX IF NOT EXISTS idx_pins_agent ON message_pins(pinned_by);
|
|
159
|
+
|
|
160
|
+
CREATE TABLE IF NOT EXISTS attachments (
|
|
161
|
+
slug TEXT PRIMARY KEY, conversation_id TEXT NOT NULL, from_agent_id TEXT NOT NULL,
|
|
162
|
+
content BLOB NOT NULL, original_size INTEGER NOT NULL, compressed_size INTEGER NOT NULL,
|
|
163
|
+
content_hash TEXT NOT NULL, format TEXT NOT NULL DEFAULT 'text', title TEXT,
|
|
164
|
+
tokens INTEGER NOT NULL DEFAULT 0, expires_at INTEGER NOT NULL DEFAULT 0,
|
|
165
|
+
storage_key TEXT, mode TEXT NOT NULL DEFAULT 'draft',
|
|
166
|
+
version_count INTEGER NOT NULL DEFAULT 1, current_version INTEGER NOT NULL DEFAULT 1,
|
|
167
|
+
created_at INTEGER NOT NULL
|
|
168
|
+
);
|
|
169
|
+
CREATE INDEX IF NOT EXISTS attachments_conversation_idx ON attachments(conversation_id);
|
|
170
|
+
CREATE INDEX IF NOT EXISTS attachments_agent_idx ON attachments(from_agent_id);
|
|
171
|
+
|
|
172
|
+
CREATE TABLE IF NOT EXISTS capabilities (
|
|
173
|
+
id TEXT PRIMARY KEY, slug TEXT NOT NULL UNIQUE, name TEXT NOT NULL,
|
|
174
|
+
description TEXT NOT NULL, category TEXT NOT NULL, created_at INTEGER NOT NULL
|
|
175
|
+
);
|
|
176
|
+
CREATE TABLE IF NOT EXISTS skills (
|
|
177
|
+
id TEXT PRIMARY KEY, slug TEXT NOT NULL UNIQUE, name TEXT NOT NULL,
|
|
178
|
+
description TEXT NOT NULL, category TEXT NOT NULL, created_at INTEGER NOT NULL
|
|
179
|
+
);
|
|
180
|
+
CREATE TABLE IF NOT EXISTS agent_capabilities (
|
|
181
|
+
agent_id TEXT NOT NULL REFERENCES agents(id), capability_id TEXT NOT NULL REFERENCES capabilities(id),
|
|
182
|
+
PRIMARY KEY (agent_id, capability_id)
|
|
183
|
+
);
|
|
184
|
+
CREATE TABLE IF NOT EXISTS agent_skills (
|
|
185
|
+
agent_id TEXT NOT NULL REFERENCES agents(id), skill_id TEXT NOT NULL REFERENCES skills(id),
|
|
186
|
+
PRIMARY KEY (agent_id, skill_id)
|
|
187
|
+
);
|
|
188
|
+
|
|
189
|
+
CREATE TABLE IF NOT EXISTS accounts (
|
|
190
|
+
id TEXT PRIMARY KEY NOT NULL, user_id TEXT NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
|
191
|
+
account_id TEXT NOT NULL, provider_id TEXT NOT NULL, access_token TEXT, refresh_token TEXT,
|
|
192
|
+
id_token TEXT, access_token_expires_at TEXT, refresh_token_expires_at TEXT, scope TEXT,
|
|
193
|
+
password TEXT, created_at TEXT NOT NULL, updated_at TEXT NOT NULL
|
|
194
|
+
);
|
|
195
|
+
CREATE INDEX IF NOT EXISTS idx_accounts_user_id ON accounts(user_id);
|
|
196
|
+
CREATE UNIQUE INDEX IF NOT EXISTS idx_accounts_provider ON accounts(provider_id, account_id);
|
|
197
|
+
|
|
198
|
+
CREATE TABLE IF NOT EXISTS sessions (
|
|
199
|
+
id TEXT PRIMARY KEY NOT NULL, user_id TEXT NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
|
200
|
+
token TEXT NOT NULL UNIQUE, ip_address TEXT, user_agent TEXT, expires_at TEXT NOT NULL,
|
|
201
|
+
active_organization_id TEXT, impersonated_by TEXT, active INTEGER NOT NULL DEFAULT 1,
|
|
202
|
+
created_at TEXT NOT NULL, updated_at TEXT NOT NULL
|
|
203
|
+
);
|
|
204
|
+
CREATE UNIQUE INDEX IF NOT EXISTS idx_sessions_token ON sessions(token);
|
|
205
|
+
CREATE INDEX IF NOT EXISTS idx_sessions_user_id ON sessions(user_id);
|
|
206
|
+
|
|
207
|
+
CREATE TABLE IF NOT EXISTS verifications (
|
|
208
|
+
id TEXT PRIMARY KEY NOT NULL, identifier TEXT NOT NULL, value TEXT NOT NULL,
|
|
209
|
+
expires_at TEXT NOT NULL, created_at TEXT NOT NULL, updated_at TEXT NOT NULL
|
|
210
|
+
);
|
|
211
|
+
CREATE INDEX IF NOT EXISTS idx_verifications_identifier ON verifications(identifier);
|
|
212
|
+
|
|
213
|
+
CREATE TABLE IF NOT EXISTS org_agent_keys (
|
|
214
|
+
id TEXT PRIMARY KEY NOT NULL, organization_id TEXT NOT NULL REFERENCES organization(id) ON DELETE CASCADE,
|
|
215
|
+
agent_id TEXT NOT NULL REFERENCES agents(id) ON DELETE CASCADE,
|
|
216
|
+
created_by TEXT NOT NULL, created_at INTEGER NOT NULL
|
|
217
|
+
);
|
|
218
|
+
CREATE INDEX IF NOT EXISTS org_agent_keys_org_idx ON org_agent_keys(organization_id);
|
|
219
|
+
CREATE INDEX IF NOT EXISTS org_agent_keys_agent_idx ON org_agent_keys(agent_id);
|
|
220
|
+
|
|
221
|
+
CREATE TABLE IF NOT EXISTS attachment_versions (
|
|
222
|
+
id TEXT PRIMARY KEY, slug TEXT NOT NULL REFERENCES attachments(slug) ON DELETE CASCADE,
|
|
223
|
+
version_number INTEGER NOT NULL, author_agent_id TEXT NOT NULL,
|
|
224
|
+
change_type TEXT NOT NULL DEFAULT 'patch', patch_text TEXT, storage_key TEXT NOT NULL,
|
|
225
|
+
content_hash TEXT NOT NULL, original_size INTEGER NOT NULL, compressed_size INTEGER NOT NULL,
|
|
226
|
+
tokens INTEGER NOT NULL, change_summary TEXT, sections_modified TEXT NOT NULL DEFAULT '[]',
|
|
227
|
+
tokens_added INTEGER NOT NULL DEFAULT 0, tokens_removed INTEGER NOT NULL DEFAULT 0,
|
|
228
|
+
created_at INTEGER NOT NULL, UNIQUE(slug, version_number)
|
|
229
|
+
);
|
|
230
|
+
CREATE INDEX IF NOT EXISTS idx_attachment_versions_slug ON attachment_versions(slug);
|
|
231
|
+
CREATE INDEX IF NOT EXISTS idx_attachment_versions_author ON attachment_versions(author_agent_id);
|
|
232
|
+
|
|
233
|
+
CREATE TABLE IF NOT EXISTS attachment_approvals (
|
|
234
|
+
id TEXT PRIMARY KEY, slug TEXT NOT NULL REFERENCES attachments(slug) ON DELETE CASCADE,
|
|
235
|
+
reviewer_agent_id TEXT NOT NULL, status TEXT NOT NULL DEFAULT 'pending', comment TEXT,
|
|
236
|
+
version_reviewed INTEGER NOT NULL, created_at INTEGER NOT NULL, updated_at INTEGER NOT NULL,
|
|
237
|
+
UNIQUE(slug, reviewer_agent_id)
|
|
238
|
+
);
|
|
239
|
+
CREATE INDEX IF NOT EXISTS idx_attachment_approvals_slug ON attachment_approvals(slug);
|
|
240
|
+
|
|
241
|
+
CREATE TABLE IF NOT EXISTS attachment_contributors (
|
|
242
|
+
slug TEXT NOT NULL REFERENCES attachments(slug) ON DELETE CASCADE,
|
|
243
|
+
agent_id TEXT NOT NULL, version_count INTEGER NOT NULL DEFAULT 0,
|
|
244
|
+
total_tokens_added INTEGER NOT NULL DEFAULT 0, total_tokens_removed INTEGER NOT NULL DEFAULT 0,
|
|
245
|
+
first_contribution_at INTEGER NOT NULL, last_contribution_at INTEGER NOT NULL,
|
|
246
|
+
PRIMARY KEY (slug, agent_id)
|
|
247
|
+
);`,
|
|
248
|
+
},
|
|
249
|
+
{
|
|
250
|
+
name: '2026-03-30-000001_agent_connections',
|
|
251
|
+
sql: `-- Add transport_type to agents table for connection mode classification.
|
|
252
|
+
ALTER TABLE agents ADD COLUMN transport_type TEXT NOT NULL DEFAULT 'http';
|
|
253
|
+
CREATE INDEX idx_agents_transport_type ON agents(transport_type);
|
|
254
|
+
|
|
255
|
+
CREATE TABLE agent_connections (
|
|
256
|
+
id TEXT PRIMARY KEY NOT NULL, agent_id TEXT NOT NULL,
|
|
257
|
+
transport_type TEXT NOT NULL DEFAULT 'http', connection_id TEXT,
|
|
258
|
+
connected_at BIGINT NOT NULL, last_heartbeat BIGINT NOT NULL,
|
|
259
|
+
connection_metadata TEXT, created_at BIGINT NOT NULL,
|
|
260
|
+
FOREIGN KEY (agent_id) REFERENCES agents(agent_id) ON DELETE CASCADE,
|
|
261
|
+
UNIQUE(agent_id, connection_id)
|
|
262
|
+
);
|
|
263
|
+
CREATE INDEX idx_agent_connections_agent ON agent_connections(agent_id);
|
|
264
|
+
CREATE INDEX idx_agent_connections_transport ON agent_connections(transport_type);
|
|
265
|
+
CREATE INDEX idx_agent_connections_heartbeat ON agent_connections(last_heartbeat);`,
|
|
266
|
+
},
|
|
267
|
+
{
|
|
268
|
+
name: '2026-03-31-000001_agent_credentials',
|
|
269
|
+
sql: `-- Move agent credentials into signaldock.db agents table (T234 clean-cut).
|
|
270
|
+
ALTER TABLE agents ADD COLUMN api_key_encrypted TEXT;
|
|
271
|
+
ALTER TABLE agents ADD COLUMN api_base_url TEXT NOT NULL DEFAULT 'https://api.signaldock.io';
|
|
272
|
+
ALTER TABLE agents ADD COLUMN classification TEXT;
|
|
273
|
+
ALTER TABLE agents ADD COLUMN transport_config TEXT NOT NULL DEFAULT '{}';
|
|
274
|
+
ALTER TABLE agents ADD COLUMN is_active INTEGER NOT NULL DEFAULT 1;
|
|
275
|
+
ALTER TABLE agents ADD COLUMN last_used_at INTEGER;
|
|
276
|
+
CREATE INDEX IF NOT EXISTS idx_agents_is_active ON agents(is_active);
|
|
277
|
+
CREATE INDEX IF NOT EXISTS idx_agents_last_used ON agents(last_used_at);`,
|
|
278
|
+
},
|
|
279
|
+
];
|
|
280
|
+
|
|
281
|
+
/**
|
|
282
|
+
* Ensure signaldock.db exists and has the full schema applied.
|
|
283
|
+
*
|
|
284
|
+
* Idempotent — safe to call multiple times. Uses `CREATE TABLE IF NOT EXISTS`
|
|
285
|
+
* and `CREATE INDEX IF NOT EXISTS` throughout.
|
|
286
|
+
*
|
|
287
|
+
* @returns Object with action ('created' | 'exists') and the database path.
|
|
288
|
+
*/
|
|
289
|
+
export async function ensureSignaldockDb(
|
|
290
|
+
cwd?: string,
|
|
291
|
+
): Promise<{ action: 'created' | 'exists'; path: string }> {
|
|
292
|
+
const dbPath = getSignaldockDbPath(cwd);
|
|
293
|
+
const alreadyExists = existsSync(dbPath);
|
|
294
|
+
|
|
295
|
+
// Ensure parent directory exists
|
|
296
|
+
mkdirSync(dirname(dbPath), { recursive: true });
|
|
297
|
+
|
|
298
|
+
// Open or create the database
|
|
299
|
+
const db = new DatabaseSyncClass(dbPath);
|
|
300
|
+
|
|
301
|
+
try {
|
|
302
|
+
// Set pragmas for optimal performance
|
|
303
|
+
db.exec('PRAGMA journal_mode = WAL');
|
|
304
|
+
db.exec('PRAGMA busy_timeout = 5000');
|
|
305
|
+
db.exec('PRAGMA synchronous = NORMAL');
|
|
306
|
+
db.exec('PRAGMA foreign_keys = ON');
|
|
307
|
+
db.exec('PRAGMA cache_size = -64000'); // 64MB
|
|
308
|
+
|
|
309
|
+
// Check if schema already applied (agents table as sentinel)
|
|
310
|
+
const hasSchema = (() => {
|
|
311
|
+
try {
|
|
312
|
+
const result = db
|
|
313
|
+
.prepare("SELECT name FROM sqlite_master WHERE type='table' AND name='agents'")
|
|
314
|
+
.get() as { name: string } | undefined;
|
|
315
|
+
return !!result;
|
|
316
|
+
} catch {
|
|
317
|
+
return false;
|
|
318
|
+
}
|
|
319
|
+
})();
|
|
320
|
+
|
|
321
|
+
// Ensure migration tracking tables exist
|
|
322
|
+
db.exec(`
|
|
323
|
+
CREATE TABLE IF NOT EXISTS _signaldock_meta (
|
|
324
|
+
key TEXT PRIMARY KEY,
|
|
325
|
+
value TEXT NOT NULL,
|
|
326
|
+
updated_at INTEGER NOT NULL DEFAULT (strftime('%s', 'now'))
|
|
327
|
+
)
|
|
328
|
+
`);
|
|
329
|
+
db.exec(`
|
|
330
|
+
CREATE TABLE IF NOT EXISTS _signaldock_migrations (
|
|
331
|
+
name TEXT PRIMARY KEY,
|
|
332
|
+
applied_at INTEGER NOT NULL DEFAULT (strftime('%s', 'now'))
|
|
333
|
+
)
|
|
334
|
+
`);
|
|
335
|
+
|
|
336
|
+
// Apply embedded migrations (works in ANY project, not just monorepo)
|
|
337
|
+
for (const migration of EMBEDDED_MIGRATIONS) {
|
|
338
|
+
// Skip already-applied migrations
|
|
339
|
+
const applied = db
|
|
340
|
+
.prepare('SELECT name FROM _signaldock_migrations WHERE name = ?')
|
|
341
|
+
.get(migration.name) as { name: string } | undefined;
|
|
342
|
+
if (applied) continue;
|
|
343
|
+
|
|
344
|
+
db.exec('BEGIN TRANSACTION');
|
|
345
|
+
try {
|
|
346
|
+
db.exec(migration.sql);
|
|
347
|
+
db.prepare('INSERT INTO _signaldock_migrations (name) VALUES (?)').run(migration.name);
|
|
348
|
+
db.exec('COMMIT');
|
|
349
|
+
} catch (err) {
|
|
350
|
+
db.exec('ROLLBACK');
|
|
351
|
+
throw err;
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
// Record schema version
|
|
356
|
+
db.exec(`
|
|
357
|
+
INSERT OR REPLACE INTO _signaldock_meta (key, value, updated_at)
|
|
358
|
+
VALUES ('schema_version', '${SIGNALDOCK_SCHEMA_VERSION}', strftime('%s', 'now'))
|
|
359
|
+
`);
|
|
360
|
+
|
|
361
|
+
return {
|
|
362
|
+
action: alreadyExists && hasSchema ? 'exists' : 'created',
|
|
363
|
+
path: dbPath,
|
|
364
|
+
};
|
|
365
|
+
} finally {
|
|
366
|
+
db.close();
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
/**
|
|
371
|
+
* Check signaldock.db health — table count, WAL mode, schema version.
|
|
372
|
+
*
|
|
373
|
+
* Used by `cleo doctor` to verify signaldock.db integrity.
|
|
374
|
+
*
|
|
375
|
+
* @returns Health report object or null if DB doesn't exist.
|
|
376
|
+
*/
|
|
377
|
+
export async function checkSignaldockDbHealth(cwd?: string): Promise<{
|
|
378
|
+
exists: boolean;
|
|
379
|
+
path: string;
|
|
380
|
+
tableCount: number;
|
|
381
|
+
walMode: boolean;
|
|
382
|
+
schemaVersion: string | null;
|
|
383
|
+
foreignKeysEnabled: boolean;
|
|
384
|
+
} | null> {
|
|
385
|
+
const dbPath = getSignaldockDbPath(cwd);
|
|
386
|
+
if (!existsSync(dbPath)) {
|
|
387
|
+
return {
|
|
388
|
+
exists: false,
|
|
389
|
+
path: dbPath,
|
|
390
|
+
tableCount: 0,
|
|
391
|
+
walMode: false,
|
|
392
|
+
schemaVersion: null,
|
|
393
|
+
foreignKeysEnabled: false,
|
|
394
|
+
};
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
const db = new DatabaseSyncClass(dbPath);
|
|
398
|
+
try {
|
|
399
|
+
const tables = db
|
|
400
|
+
.prepare(
|
|
401
|
+
"SELECT COUNT(*) as count FROM sqlite_master WHERE type='table' AND name NOT LIKE 'sqlite_%'",
|
|
402
|
+
)
|
|
403
|
+
.get() as { count: number };
|
|
404
|
+
|
|
405
|
+
const journalMode = db.prepare('PRAGMA journal_mode').get() as { journal_mode: string };
|
|
406
|
+
const fkEnabled = db.prepare('PRAGMA foreign_keys').get() as { foreign_keys: number };
|
|
407
|
+
|
|
408
|
+
let schemaVersion: string | null = null;
|
|
409
|
+
try {
|
|
410
|
+
const meta = db
|
|
411
|
+
.prepare("SELECT value FROM _signaldock_meta WHERE key = 'schema_version'")
|
|
412
|
+
.get() as { value: string } | undefined;
|
|
413
|
+
schemaVersion = meta?.value ?? null;
|
|
414
|
+
} catch {
|
|
415
|
+
// Meta table may not exist
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
return {
|
|
419
|
+
exists: true,
|
|
420
|
+
path: dbPath,
|
|
421
|
+
tableCount: tables.count,
|
|
422
|
+
walMode: journalMode.journal_mode === 'wal',
|
|
423
|
+
schemaVersion,
|
|
424
|
+
foreignKeysEnabled: fkEnabled.foreign_keys === 1,
|
|
425
|
+
};
|
|
426
|
+
} finally {
|
|
427
|
+
db.close();
|
|
428
|
+
}
|
|
429
|
+
}
|
|
@@ -14,6 +14,7 @@
|
|
|
14
14
|
import type { Session, Task, TaskStatus } from '@cleocode/contracts';
|
|
15
15
|
import { and, eq, inArray, isNull, like, ne, notInArray, or, sql } from 'drizzle-orm';
|
|
16
16
|
import { archivedTaskToRow, rowToSession, rowToTask, taskToRow } from './converters.js';
|
|
17
|
+
import { cleanupBrainRefsOnSessionDelete } from './cross-db-cleanup.js';
|
|
17
18
|
import type {
|
|
18
19
|
ArchiveFile,
|
|
19
20
|
DataAccessor,
|
|
@@ -380,6 +381,8 @@ export async function createSqliteDataAccessor(cwd?: string): Promise<DataAccess
|
|
|
380
381
|
async removeSingleSession(sessionId: string): Promise<void> {
|
|
381
382
|
const db = await getDb(cwd);
|
|
382
383
|
await db.delete(schema.sessions).where(eq(schema.sessions.id, sessionId)).run();
|
|
384
|
+
// Best-effort cross-db cleanup: nullify brain.db references to this session
|
|
385
|
+
void cleanupBrainRefsOnSessionDelete(sessionId, cwd);
|
|
383
386
|
},
|
|
384
387
|
|
|
385
388
|
// ---- Targeted query methods (Phase 2 modernization) ----
|
|
@@ -783,6 +786,7 @@ export async function createSqliteDataAccessor(cwd?: string): Promise<DataAccess
|
|
|
783
786
|
['createdBy', 'createdBy'],
|
|
784
787
|
['modifiedBy', 'modifiedBy'],
|
|
785
788
|
['sessionId', 'sessionId'],
|
|
789
|
+
['assignee', 'assignee'],
|
|
786
790
|
];
|
|
787
791
|
|
|
788
792
|
for (const [key, col] of fieldMap) {
|
|
@@ -874,6 +878,74 @@ export async function createSqliteDataAccessor(cwd?: string): Promise<DataAccess
|
|
|
874
878
|
const meta = await getMetaValue<{ schemaVersion?: string }>(cwd, 'file_meta');
|
|
875
879
|
return meta?.schemaVersion ?? null;
|
|
876
880
|
},
|
|
881
|
+
|
|
882
|
+
// ---- Agent instances ----
|
|
883
|
+
|
|
884
|
+
async listAgentInstances(filters) {
|
|
885
|
+
const { listAgentInstances: listAgents } = await import('../agents/registry.js');
|
|
886
|
+
// Cast generic string filters to the specific union types expected by the agents module
|
|
887
|
+
return listAgents(filters as Parameters<typeof listAgents>[0], cwd);
|
|
888
|
+
},
|
|
889
|
+
|
|
890
|
+
async getAgentInstance(agentId) {
|
|
891
|
+
const { getAgentInstance: getAgent } = await import('../agents/registry.js');
|
|
892
|
+
return getAgent(agentId, cwd);
|
|
893
|
+
},
|
|
894
|
+
|
|
895
|
+
// ---- Agent task claiming ----
|
|
896
|
+
|
|
897
|
+
async claimTask(taskId: string, agentId: string): Promise<void> {
|
|
898
|
+
const nativeDb = getNativeTasksDb();
|
|
899
|
+
if (!nativeDb) {
|
|
900
|
+
throw new Error('Native database not initialized');
|
|
901
|
+
}
|
|
902
|
+
|
|
903
|
+
// Verify the task exists first
|
|
904
|
+
const existsRow = nativeDb.prepare('SELECT assignee FROM tasks WHERE id = ?').get(taskId) as
|
|
905
|
+
| { assignee: string | null }
|
|
906
|
+
| undefined;
|
|
907
|
+
if (!existsRow) {
|
|
908
|
+
throw new Error(`Task not found: ${taskId}`);
|
|
909
|
+
}
|
|
910
|
+
|
|
911
|
+
// Atomic claim: only succeeds if assignee IS NULL or already claimed by this agent.
|
|
912
|
+
// This prevents race conditions between concurrent agents.
|
|
913
|
+
const result = nativeDb
|
|
914
|
+
.prepare(
|
|
915
|
+
'UPDATE tasks SET assignee = ?, updated_at = ? WHERE id = ? AND (assignee IS NULL OR assignee = ?)',
|
|
916
|
+
)
|
|
917
|
+
.run(agentId, new Date().toISOString(), taskId, agentId) as { changes: number };
|
|
918
|
+
|
|
919
|
+
if (result.changes === 0) {
|
|
920
|
+
// Row was not updated — task is claimed by a different agent
|
|
921
|
+
const currentRow = nativeDb
|
|
922
|
+
.prepare('SELECT assignee FROM tasks WHERE id = ?')
|
|
923
|
+
.get(taskId) as { assignee: string | null } | undefined;
|
|
924
|
+
throw new Error(
|
|
925
|
+
`Task ${taskId} is already claimed by agent: ${currentRow?.assignee ?? 'unknown'}`,
|
|
926
|
+
);
|
|
927
|
+
}
|
|
928
|
+
},
|
|
929
|
+
|
|
930
|
+
async unclaimTask(taskId: string): Promise<void> {
|
|
931
|
+
const nativeDb = getNativeTasksDb();
|
|
932
|
+
if (!nativeDb) {
|
|
933
|
+
throw new Error('Native database not initialized');
|
|
934
|
+
}
|
|
935
|
+
|
|
936
|
+
// Verify the task exists
|
|
937
|
+
const existsRow = nativeDb.prepare('SELECT id FROM tasks WHERE id = ?').get(taskId) as
|
|
938
|
+
| { id: string }
|
|
939
|
+
| undefined;
|
|
940
|
+
if (!existsRow) {
|
|
941
|
+
throw new Error(`Task not found: ${taskId}`);
|
|
942
|
+
}
|
|
943
|
+
|
|
944
|
+
// Clear the assignee — no-op if already null
|
|
945
|
+
nativeDb
|
|
946
|
+
.prepare('UPDATE tasks SET assignee = NULL, updated_at = ? WHERE id = ?')
|
|
947
|
+
.run(new Date().toISOString(), taskId);
|
|
948
|
+
},
|
|
877
949
|
};
|
|
878
950
|
|
|
879
951
|
return accessor;
|
package/src/store/sqlite.ts
CHANGED
|
@@ -403,7 +403,10 @@ export { isSqliteBusy } from './migration-manager.js';
|
|
|
403
403
|
*/
|
|
404
404
|
import type { RequiredColumn } from './migration-manager.js';
|
|
405
405
|
|
|
406
|
-
const REQUIRED_TASK_COLUMNS: RequiredColumn[] = [
|
|
406
|
+
const REQUIRED_TASK_COLUMNS: RequiredColumn[] = [
|
|
407
|
+
{ name: 'pipeline_stage', ddl: 'text' },
|
|
408
|
+
{ name: 'assignee', ddl: 'text' },
|
|
409
|
+
];
|
|
407
410
|
|
|
408
411
|
/**
|
|
409
412
|
* Required columns that MUST exist on the sessions table before the
|
package/src/store/task-store.ts
CHANGED
|
@@ -78,7 +78,14 @@ export async function updateTask(
|
|
|
78
78
|
|
|
79
79
|
if (updates.title !== undefined) updateRow.title = updates.title;
|
|
80
80
|
if (updates.description !== undefined) updateRow.description = updates.description;
|
|
81
|
-
if (updates.status !== undefined)
|
|
81
|
+
if (updates.status !== undefined) {
|
|
82
|
+
updateRow.status = updates.status;
|
|
83
|
+
// Clear stale timestamps when status resets to non-terminal state
|
|
84
|
+
if (updates.status === 'pending' || updates.status === 'active') {
|
|
85
|
+
if (updates.cancelledAt === undefined) updateRow.cancelledAt = null;
|
|
86
|
+
if (updates.completedAt === undefined) updateRow.completedAt = null;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
82
89
|
if (updates.priority !== undefined) updateRow.priority = updates.priority;
|
|
83
90
|
if (updates.type !== undefined) updateRow.type = updates.type;
|
|
84
91
|
if (updates.parentId !== undefined) updateRow.parentId = updates.parentId;
|
|
@@ -99,6 +106,7 @@ export async function updateTask(
|
|
|
99
106
|
updateRow.cancellationReason = updates.cancellationReason;
|
|
100
107
|
if (updates.verification !== undefined)
|
|
101
108
|
updateRow.verificationJson = JSON.stringify(updates.verification);
|
|
109
|
+
if (updates.assignee !== undefined) updateRow.assignee = updates.assignee;
|
|
102
110
|
|
|
103
111
|
db.update(schema.tasks).set(updateRow).where(eq(schema.tasks.id, taskId)).run();
|
|
104
112
|
|
|
@@ -196,6 +196,8 @@ export const tasks = sqliteTable(
|
|
|
196
196
|
// Not referencing lifecycle_stages.id so that stage binding works without
|
|
197
197
|
// requiring a lifecycle pipeline record for every task.
|
|
198
198
|
pipelineStage: text('pipeline_stage'),
|
|
199
|
+
/** Agent ID that has claimed/is assigned to this task. */
|
|
200
|
+
assignee: text('assignee'),
|
|
199
201
|
},
|
|
200
202
|
(table) => [
|
|
201
203
|
index('idx_tasks_status').on(table.status),
|
|
@@ -205,6 +207,7 @@ export const tasks = sqliteTable(
|
|
|
205
207
|
index('idx_tasks_priority').on(table.priority),
|
|
206
208
|
index('idx_tasks_session_id').on(table.sessionId),
|
|
207
209
|
index('idx_tasks_pipeline_stage').on(table.pipelineStage),
|
|
210
|
+
index('idx_tasks_assignee').on(table.assignee),
|
|
208
211
|
// T033 composite indexes
|
|
209
212
|
index('idx_tasks_parent_status').on(table.parentId, table.status),
|
|
210
213
|
index('idx_tasks_status_priority').on(table.status, table.priority),
|
|
@@ -850,3 +853,7 @@ export type ReleaseManifestRow = typeof releaseManifests.$inferSelect;
|
|
|
850
853
|
export type NewReleaseManifestRow = typeof releaseManifests.$inferInsert;
|
|
851
854
|
export type ExternalTaskLinkRow = typeof externalTaskLinks.$inferSelect;
|
|
852
855
|
export type NewExternalTaskLinkRow = typeof externalTaskLinks.$inferInsert;
|
|
856
|
+
|
|
857
|
+
// agent_credentials REMOVED from tasks.db — T234 clean-cut.
|
|
858
|
+
// Agent data (identity, credentials, capabilities, skills) now lives
|
|
859
|
+
// exclusively in signaldock.db. See AgentRegistryAccessor.
|
|
@@ -27,7 +27,7 @@ describe('system health audit_log checks', () => {
|
|
|
27
27
|
await getDb(projectRoot);
|
|
28
28
|
closeDb();
|
|
29
29
|
|
|
30
|
-
const result = getSystemHealth(projectRoot);
|
|
30
|
+
const result = await getSystemHealth(projectRoot);
|
|
31
31
|
const auditLog = result.checks.find((c) => c.name === 'audit_log');
|
|
32
32
|
|
|
33
33
|
expect(auditLog).toBeDefined();
|
|
@@ -45,7 +45,7 @@ describe('system health audit_log checks', () => {
|
|
|
45
45
|
db.close();
|
|
46
46
|
expect(existsSync(dbPath)).toBe(true);
|
|
47
47
|
|
|
48
|
-
const result = getSystemHealth(projectRoot);
|
|
48
|
+
const result = await getSystemHealth(projectRoot);
|
|
49
49
|
const auditLog = result.checks.find((c) => c.name === 'audit_log');
|
|
50
50
|
|
|
51
51
|
expect(auditLog).toBeDefined();
|
package/src/system/health.ts
CHANGED
|
@@ -145,7 +145,7 @@ export interface DiagnosticsResult {
|
|
|
145
145
|
}
|
|
146
146
|
|
|
147
147
|
/** Run system health checks (SQLite-first per ADR-006). */
|
|
148
|
-
export function getSystemHealth(projectRoot: string, opts?: { detailed?: boolean }): HealthResult {
|
|
148
|
+
export async function getSystemHealth(projectRoot: string, opts?: { detailed?: boolean }): Promise<HealthResult> {
|
|
149
149
|
const cleoDir = join(projectRoot, '.cleo');
|
|
150
150
|
const checks: HealthCheck[] = [];
|
|
151
151
|
|
|
@@ -181,6 +181,58 @@ export function getSystemHealth(projectRoot: string, opts?: { detailed?: boolean
|
|
|
181
181
|
checks.push(checkAuditLogAvailability(dbPath));
|
|
182
182
|
}
|
|
183
183
|
|
|
184
|
+
// Check signaldock.db with schema health (local agent messaging per T225)
|
|
185
|
+
const sdDbPath = join(cleoDir, 'signaldock.db');
|
|
186
|
+
if (existsSync(sdDbPath)) {
|
|
187
|
+
try {
|
|
188
|
+
const { DatabaseSync: SdDb } = _require('node:sqlite') as {
|
|
189
|
+
DatabaseSync: new (path: string) => {
|
|
190
|
+
prepare(sql: string): { get(...args: unknown[]): unknown };
|
|
191
|
+
close(): void;
|
|
192
|
+
};
|
|
193
|
+
};
|
|
194
|
+
const sdDb = new SdDb(sdDbPath);
|
|
195
|
+
try {
|
|
196
|
+
const tables = sdDb
|
|
197
|
+
.prepare(
|
|
198
|
+
"SELECT COUNT(*) as count FROM sqlite_master WHERE type='table' AND name NOT LIKE 'sqlite_%' AND name NOT LIKE '_signaldock%'",
|
|
199
|
+
)
|
|
200
|
+
.get() as { count: number };
|
|
201
|
+
const journalMode = sdDb.prepare('PRAGMA journal_mode').get() as {
|
|
202
|
+
journal_mode: string;
|
|
203
|
+
};
|
|
204
|
+
let schemaVersion = 'unknown';
|
|
205
|
+
try {
|
|
206
|
+
const meta = sdDb
|
|
207
|
+
.prepare("SELECT value FROM _signaldock_meta WHERE key = 'schema_version'")
|
|
208
|
+
.get() as { value: string } | undefined;
|
|
209
|
+
schemaVersion = meta?.value ?? 'unknown';
|
|
210
|
+
} catch {
|
|
211
|
+
/* meta table may not exist */
|
|
212
|
+
}
|
|
213
|
+
checks.push({
|
|
214
|
+
name: 'signaldock_db',
|
|
215
|
+
status: tables.count >= 20 ? 'pass' : 'warn',
|
|
216
|
+
message: `signaldock.db: ${tables.count} tables, ${journalMode.journal_mode}, v${schemaVersion}`,
|
|
217
|
+
});
|
|
218
|
+
} finally {
|
|
219
|
+
sdDb.close();
|
|
220
|
+
}
|
|
221
|
+
} catch {
|
|
222
|
+
checks.push({
|
|
223
|
+
name: 'signaldock_db',
|
|
224
|
+
status: 'pass',
|
|
225
|
+
message: `signaldock.db: ${statSync(sdDbPath).size} bytes`,
|
|
226
|
+
});
|
|
227
|
+
}
|
|
228
|
+
} else {
|
|
229
|
+
checks.push({
|
|
230
|
+
name: 'signaldock_db',
|
|
231
|
+
status: 'warn',
|
|
232
|
+
message: 'signaldock.db not found. Run: cleo init',
|
|
233
|
+
});
|
|
234
|
+
}
|
|
235
|
+
|
|
184
236
|
// Check config.json (config remains JSON per ADR-006)
|
|
185
237
|
const configPath = join(cleoDir, 'config.json');
|
|
186
238
|
if (existsSync(configPath)) {
|
|
@@ -264,7 +316,7 @@ export async function getSystemDiagnostics(
|
|
|
264
316
|
projectRoot: string,
|
|
265
317
|
opts?: { checks?: string[] },
|
|
266
318
|
): Promise<DiagnosticsResult> {
|
|
267
|
-
const healthResult = getSystemHealth(projectRoot, { detailed: true });
|
|
319
|
+
const healthResult = await getSystemHealth(projectRoot, { detailed: true });
|
|
268
320
|
|
|
269
321
|
const diagChecks: DiagnosticsCheck[] = healthResult.checks.map((c) => ({
|
|
270
322
|
name: c.name,
|