@cleocode/core 2026.3.76 → 2026.4.2
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/agents/agent-schema.d.ts.map +1 -1
- package/dist/audit.d.ts +1 -1
- package/dist/audit.d.ts.map +1 -1
- package/dist/bootstrap.d.ts +2 -2
- package/dist/bootstrap.d.ts.map +1 -1
- package/dist/caamp/adapter.d.ts +6 -49
- package/dist/caamp/adapter.d.ts.map +1 -1
- package/dist/caamp/index.d.ts +2 -2
- package/dist/caamp/index.d.ts.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 +32 -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/compliance/protocol-enforcement.d.ts +1 -1
- package/dist/compliance/protocol-rules.d.ts +1 -1
- package/dist/compliance/protocol-types.d.ts +2 -3
- package/dist/compliance/protocol-types.d.ts.map +1 -1
- package/dist/conduit/conduit-client.d.ts +14 -0
- package/dist/conduit/conduit-client.d.ts.map +1 -1
- package/dist/conduit/factory.d.ts +11 -1
- package/dist/conduit/factory.d.ts.map +1 -1
- package/dist/conduit/http-transport.d.ts +17 -5
- package/dist/conduit/http-transport.d.ts.map +1 -1
- package/dist/conduit/index.d.ts +5 -2
- package/dist/conduit/index.d.ts.map +1 -1
- 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/crypto/credentials.d.ts.map +1 -1
- package/dist/error-catalog.d.ts +3 -3
- package/dist/error-catalog.d.ts.map +1 -1
- package/dist/errors.d.ts +1 -1
- package/dist/hooks/handlers/index.d.ts +2 -2
- package/dist/hooks/handlers/index.d.ts.map +1 -1
- package/dist/hooks/handlers/notification-hooks.d.ts +31 -0
- package/dist/hooks/handlers/notification-hooks.d.ts.map +1 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4646 -3476
- package/dist/index.js.map +4 -4
- package/dist/init.d.ts +6 -6
- package/dist/init.d.ts.map +1 -1
- package/dist/injection.d.ts.map +1 -1
- package/dist/internal.d.ts +7 -5
- package/dist/internal.d.ts.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/logger.d.ts +3 -3
- 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 +1 -1
- package/dist/memory/brain-retrieval.d.ts.map +1 -1
- package/dist/memory/decisions.d.ts.map +1 -1
- package/dist/memory/engine-compat.d.ts +392 -25
- package/dist/memory/engine-compat.d.ts.map +1 -1
- package/dist/memory/index.d.ts +416 -3
- package/dist/memory/index.d.ts.map +1 -1
- package/dist/metrics/token-service.d.ts +3 -3
- package/dist/metrics/token-service.d.ts.map +1 -1
- 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/paths.d.ts +335 -2
- package/dist/paths.d.ts.map +1 -1
- package/dist/routing/capability-matrix.d.ts +3 -3
- package/dist/routing/capability-matrix.d.ts.map +1 -1
- package/dist/scaffold.d.ts +422 -11
- package/dist/scaffold.d.ts.map +1 -1
- package/dist/security/input-sanitization.d.ts +2 -2
- package/dist/skills/dynamic-skill-generator.d.ts +3 -2
- package/dist/skills/dynamic-skill-generator.d.ts.map +1 -1
- package/dist/skills/routing-table.d.ts +4 -4
- package/dist/skills/routing-table.d.ts.map +1 -1
- package/dist/store/agent-registry-accessor.d.ts +10 -433
- package/dist/store/agent-registry-accessor.d.ts.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/provider.d.ts +1 -1
- package/dist/store/signaldock-sqlite.d.ts.map +1 -1
- package/dist/store/sqlite-data-accessor.d.ts.map +1 -1
- package/dist/store/sqlite.d.ts +1 -1
- package/dist/store/task-store.d.ts.map +1 -1
- package/dist/store/tasks-schema.d.ts +4 -228
- package/dist/store/tasks-schema.d.ts.map +1 -1
- package/dist/store/validation-schemas.d.ts +4 -5
- package/dist/store/validation-schemas.d.ts.map +1 -1
- package/dist/system/archive-analytics.d.ts +1 -1
- package/dist/system/health.d.ts +2 -2
- package/dist/system/health.d.ts.map +1 -1
- package/dist/system/runtime.d.ts +2 -1
- package/dist/system/runtime.d.ts.map +1 -1
- package/dist/tasks/list.d.ts +1 -1
- package/dist/tasks/list.d.ts.map +1 -1
- package/dist/tasks/task-ops.d.ts +415 -3
- package/dist/tasks/task-ops.d.ts.map +1 -1
- package/dist/templates/parser.d.ts +1 -1
- package/dist/ui/index.d.ts +1 -1
- package/dist/upgrade.d.ts +1 -1
- package/dist/upgrade.d.ts.map +1 -1
- package/dist/validation/operation-gate-validators.d.ts +1 -1
- package/dist/validation/operation-verification-gates.d.ts +3 -3
- package/dist/validation/param-utils.d.ts +6 -5
- package/dist/validation/param-utils.d.ts.map +1 -1
- package/dist/validation/validate-ops.d.ts +1 -1
- package/dist/validation/validate-ops.d.ts.map +1 -1
- package/package.json +19 -7
- package/src/__tests__/caamp-skill-install.test.js +0 -15
- package/src/__tests__/caamp-skill-install.test.js.map +1 -1
- package/src/__tests__/caamp-skill-install.test.ts +0 -16
- package/src/__tests__/injection-mvi-tiers.test.js +7 -7
- package/src/__tests__/injection-mvi-tiers.test.js.map +1 -1
- package/src/__tests__/injection-mvi-tiers.test.ts +55 -103
- package/src/agents/agent-schema.ts +2 -5
- package/src/audit.ts +2 -2
- package/src/bootstrap.ts +5 -39
- package/src/caamp/adapter.ts +3 -219
- package/src/caamp/index.ts +1 -13
- package/src/cant/__tests__/cant-agent-parse.test.d.ts.map +1 -0
- package/src/cant/__tests__/cant-agent-parse.test.js +77 -0
- package/src/cant/__tests__/cant-agent-parse.test.js.map +1 -0
- package/src/code/index.ts +10 -0
- package/src/code/outline.ts +214 -0
- package/src/code/parser.ts +331 -0
- package/src/code/search.ts +173 -0
- package/src/code/unfold.ts +204 -0
- package/src/codebase-map/analyzers/architecture.ts +2 -2
- package/src/compliance/protocol-enforcement.ts +1 -1
- package/src/compliance/protocol-rules.ts +1 -1
- package/src/compliance/protocol-types.ts +2 -3
- package/src/conduit/__tests__/dual-api-e2e.test.d.ts.map +1 -0
- package/src/conduit/__tests__/dual-api-e2e.test.js +178 -0
- package/src/conduit/__tests__/dual-api-e2e.test.js.map +1 -0
- package/src/conduit/__tests__/dual-api-e2e.test.ts +212 -0
- package/src/conduit/__tests__/local-credential-flow.test.d.ts.map +1 -0
- package/src/conduit/__tests__/local-credential-flow.test.js +185 -0
- package/src/conduit/__tests__/local-credential-flow.test.js.map +1 -0
- package/src/conduit/__tests__/local-credential-flow.test.ts +230 -0
- package/src/conduit/__tests__/local-transport.test.d.ts.map +1 -0
- package/src/conduit/__tests__/local-transport.test.js +404 -0
- package/src/conduit/__tests__/local-transport.test.js.map +1 -0
- package/src/conduit/__tests__/local-transport.test.ts +509 -0
- package/src/conduit/__tests__/sse-transport.test.d.ts.map +1 -0
- package/src/conduit/__tests__/sse-transport.test.js +291 -0
- package/src/conduit/__tests__/sse-transport.test.js.map +1 -0
- package/src/conduit/__tests__/sse-transport.test.ts +344 -0
- package/src/conduit/conduit-client.ts +14 -0
- package/src/conduit/factory.ts +29 -8
- package/src/conduit/http-transport.ts +78 -16
- package/src/conduit/index.ts +5 -2
- package/src/conduit/local-transport.ts +309 -0
- package/src/conduit/sse-transport.ts +382 -0
- package/src/crypto/credentials.ts +59 -13
- package/src/error-catalog.ts +3 -3
- package/src/errors.ts +1 -1
- package/src/hooks/__tests__/provider-hooks.test.js +4 -4
- package/src/hooks/__tests__/provider-hooks.test.js.map +1 -1
- package/src/hooks/__tests__/provider-hooks.test.ts +4 -4
- package/src/hooks/handlers/__tests__/hook-automation-e2e.test.js +2 -2
- package/src/hooks/handlers/__tests__/hook-automation-e2e.test.js.map +1 -1
- package/src/hooks/handlers/__tests__/hook-automation-e2e.test.ts +6 -4
- package/src/hooks/handlers/index.ts +2 -6
- package/src/hooks/handlers/notification-hooks.ts +65 -0
- package/src/index.ts +2 -1
- package/src/init.ts +14 -54
- package/src/injection.ts +4 -3
- package/src/internal.ts +7 -5
- package/src/lib/index.ts +8 -0
- package/src/lib/tree-sitter-languages.ts +88 -0
- package/src/logger.ts +5 -5
- package/src/memory/__tests__/brain-links.test.js +13 -0
- package/src/memory/__tests__/brain-links.test.js.map +1 -1
- package/src/memory/__tests__/brain-links.test.ts +14 -0
- package/src/memory/__tests__/brain-retrieval.test.js +9 -0
- package/src/memory/__tests__/brain-retrieval.test.js.map +1 -1
- package/src/memory/__tests__/brain-retrieval.test.ts +10 -0
- package/src/memory/__tests__/session-memory.test.js +16 -0
- package/src/memory/__tests__/session-memory.test.js.map +1 -1
- 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 +19 -3
- package/src/memory/decisions.ts +18 -2
- package/src/memory/engine-compat.ts +392 -25
- package/src/memory/index.ts +417 -4
- package/src/metrics/token-service.ts +4 -4
- package/src/migration/index.ts +1 -1
- package/src/orchestration/hierarchy.ts +202 -0
- package/src/orchestration/index.ts +1 -0
- package/src/paths.ts +340 -5
- package/src/routing/capability-matrix.ts +49 -49
- package/src/scaffold.ts +428 -70
- package/src/security/input-sanitization.ts +4 -4
- package/src/sessions/__tests__/session-grade.integration.test.js +9 -9
- package/src/sessions/__tests__/session-grade.integration.test.ts +9 -9
- package/src/sessions/__tests__/session-grade.test.js +10 -10
- package/src/sessions/__tests__/session-grade.test.js.map +1 -1
- package/src/sessions/__tests__/session-grade.test.ts +10 -10
- package/src/sessions/session-grade.ts +4 -4
- package/src/skills/__tests__/dynamic-skill-generator.test.js +24 -26
- package/src/skills/__tests__/dynamic-skill-generator.test.js.map +1 -1
- package/src/skills/__tests__/dynamic-skill-generator.test.ts +24 -26
- package/src/skills/__tests__/routing-table.test.js +22 -22
- package/src/skills/__tests__/routing-table.test.js.map +1 -1
- package/src/skills/__tests__/routing-table.test.ts +23 -23
- package/src/skills/dynamic-skill-generator.ts +13 -24
- package/src/skills/routing-table.ts +4 -4
- package/src/store/__tests__/data-safety-central.test.js +8 -0
- package/src/store/__tests__/data-safety-central.test.js.map +1 -1
- package/src/store/__tests__/data-safety-central.test.ts +8 -0
- package/src/store/__tests__/safety-accessor.test.js +8 -0
- package/src/store/__tests__/safety-accessor.test.js.map +1 -1
- package/src/store/__tests__/safety-accessor.test.ts +8 -0
- package/src/store/agent-registry-accessor.ts +284 -108
- package/src/store/cross-db-cleanup.ts +175 -1
- package/src/store/provider.ts +2 -2
- package/src/store/signaldock-sqlite.ts +262 -60
- package/src/store/sqlite-data-accessor.ts +3 -0
- package/src/store/sqlite.ts +2 -2
- package/src/store/task-store.ts +8 -1
- package/src/store/tasks-schema.ts +5 -40
- package/src/system/__tests__/health.test.js +2 -2
- package/src/system/__tests__/health.test.js.map +1 -1
- package/src/system/__tests__/health.test.ts +2 -2
- package/src/system/archive-analytics.ts +1 -1
- package/src/system/health.ts +43 -19
- package/src/system/inject-generate.ts +20 -20
- package/src/system/runtime.ts +5 -4
- package/src/tasks/atomicity.ts +1 -1
- package/src/tasks/list.ts +1 -1
- package/src/tasks/task-ops.ts +415 -3
- package/src/templates/parser.ts +1 -1
- package/src/ui/index.ts +4 -4
- package/src/upgrade.ts +3 -14
- package/src/validation/operation-gate-validators.ts +1 -1
- package/src/validation/operation-verification-gates.ts +3 -3
- package/src/validation/param-utils.ts +11 -10
- package/src/validation/validate-ops.ts +6 -6
- package/templates/CLEO-INJECTION.md +38 -110
- package/dist/hooks/handlers/mcp-hooks.d.ts +0 -48
- package/dist/hooks/handlers/mcp-hooks.d.ts.map +0 -1
- package/dist/mcp/index.d.ts +0 -42
- package/dist/mcp/index.d.ts.map +0 -1
- package/src/__tests__/audit-prune.test.d.ts +0 -2
- package/src/__tests__/caamp-skill-install.test.d.ts +0 -14
- package/src/__tests__/cli-mcp-parity.integration.test.d.ts +0 -34
- package/src/__tests__/cli-mcp-parity.integration.test.d.ts.map +0 -1
- package/src/__tests__/cli-mcp-parity.integration.test.js +0 -898
- package/src/__tests__/cli-mcp-parity.integration.test.js.map +0 -1
- package/src/__tests__/cli-parity.test.d.ts +0 -9
- package/src/__tests__/config.test.d.ts +0 -7
- package/src/__tests__/core-parity.test.d.ts +0 -17
- package/src/__tests__/error-catalog.test.d.ts +0 -2
- package/src/__tests__/golden-parity.test.d.ts +0 -12
- package/src/__tests__/hooks.test.d.ts +0 -5
- package/src/__tests__/human-output.test.d.ts +0 -12
- package/src/__tests__/index-api-compat.test.d.ts +0 -2
- package/src/__tests__/init-e2e.test.d.ts +0 -12
- package/src/__tests__/injection-chain.test.d.ts +0 -18
- package/src/__tests__/injection-mvi-tiers.test.d.ts +0 -14
- package/src/__tests__/injection-shared.test.d.ts +0 -10
- package/src/__tests__/lafs-conformance.test.d.ts +0 -18
- package/src/__tests__/logger.test.d.ts +0 -2
- package/src/__tests__/mcp-install-verify.test.d.ts +0 -13
- package/src/__tests__/mcp-install-verify.test.d.ts.map +0 -1
- package/src/__tests__/mcp-install-verify.test.js +0 -177
- package/src/__tests__/mcp-install-verify.test.js.map +0 -1
- package/src/__tests__/mcp-install-verify.test.ts +0 -217
- package/src/__tests__/paths.test.d.ts +0 -7
- package/src/__tests__/project-info.test.d.ts +0 -2
- package/src/__tests__/rcsd-pipeline-e2e.test.d.ts +0 -14
- package/src/__tests__/remote.test.d.ts +0 -6
- package/src/__tests__/scaffold.test.d.ts +0 -6
- package/src/__tests__/schema-management.test.d.ts +0 -5
- package/src/__tests__/schema.test.d.ts +0 -2
- package/src/__tests__/sharing.test.d.ts +0 -6
- package/src/__tests__/snapshot.test.d.ts +0 -6
- package/src/__tests__/upgrade.test.d.ts +0 -7
- package/src/adapters/__tests__/discovery.test.d.ts +0 -6
- package/src/adapters/__tests__/manager.test.d.ts +0 -6
- package/src/agents/__tests__/agent-registry.test.d.ts +0 -12
- package/src/agents/__tests__/capacity.test.d.ts +0 -7
- package/src/agents/__tests__/execution-learning.test.d.ts +0 -14
- package/src/agents/__tests__/health-monitor.test.d.ts +0 -10
- package/src/agents/__tests__/registry.test.d.ts +0 -8
- package/src/agents/__tests__/retry.test.d.ts +0 -7
- package/src/compliance/__tests__/sync.test.d.ts +0 -5
- package/src/hooks/__tests__/provider-hooks.test.d.ts +0 -2
- package/src/hooks/__tests__/registry.test.d.ts +0 -2
- package/src/hooks/handlers/__tests__/error-hooks.test.d.ts +0 -2
- package/src/hooks/handlers/__tests__/file-hooks.test.d.ts +0 -2
- package/src/hooks/handlers/__tests__/hook-automation-e2e.test.d.ts +0 -13
- package/src/hooks/handlers/__tests__/mcp-hooks.test.d.ts +0 -2
- package/src/hooks/handlers/__tests__/mcp-hooks.test.d.ts.map +0 -1
- package/src/hooks/handlers/__tests__/mcp-hooks.test.js +0 -119
- package/src/hooks/handlers/__tests__/mcp-hooks.test.js.map +0 -1
- package/src/hooks/handlers/__tests__/mcp-hooks.test.ts +0 -150
- package/src/hooks/handlers/__tests__/session-hooks.test.d.ts +0 -2
- package/src/hooks/handlers/__tests__/task-hooks.test.d.ts +0 -2
- package/src/hooks/handlers/mcp-hooks.ts +0 -162
- package/src/intelligence/__tests__/adaptive-validation.test.d.ts +0 -11
- package/src/intelligence/__tests__/impact.test.d.ts +0 -16
- package/src/intelligence/__tests__/patterns.test.d.ts +0 -8
- package/src/intelligence/__tests__/prediction.test.d.ts +0 -8
- package/src/lib/__tests__/retry.test.d.ts +0 -7
- package/src/lifecycle/__tests__/chain-store.test.d.ts +0 -10
- package/src/lifecycle/__tests__/consolidate-rcasd.test.d.ts +0 -7
- package/src/lifecycle/__tests__/default-chain.test.d.ts +0 -7
- package/src/lifecycle/__tests__/frontmatter.test.d.ts +0 -7
- package/src/lifecycle/__tests__/lifecycle.test.d.ts +0 -7
- package/src/lifecycle/__tests__/pipeline.integration.test.d.ts +0 -19
- package/src/lifecycle/__tests__/rcasd-paths.test.d.ts +0 -7
- package/src/lifecycle/__tests__/resume-schema-contract.test.d.ts +0 -16
- package/src/lifecycle/__tests__/stage-record-provenance.integration.test.d.ts +0 -7
- package/src/lifecycle/__tests__/tessera-engine.test.d.ts +0 -10
- package/src/mcp/index.ts +0 -163
- package/src/memory/__tests__/auto-extract.test.d.ts +0 -7
- package/src/memory/__tests__/brain-automation.test.d.ts +0 -11
- package/src/memory/__tests__/brain-embedding.test.d.ts +0 -2
- package/src/memory/__tests__/brain-links.test.d.ts +0 -8
- package/src/memory/__tests__/brain-migration.test.d.ts +0 -8
- package/src/memory/__tests__/brain-retrieval.test.d.ts +0 -10
- package/src/memory/__tests__/brain-search.test.d.ts +0 -8
- package/src/memory/__tests__/claude-mem-migration.test.d.ts +0 -12
- package/src/memory/__tests__/decisions.test.d.ts +0 -8
- package/src/memory/__tests__/engine-compat.test.d.ts +0 -12
- package/src/memory/__tests__/memory-bridge.test.d.ts +0 -10
- package/src/memory/__tests__/pipeline-manifest-sqlite.test.d.ts +0 -13
- package/src/memory/__tests__/session-memory.test.d.ts +0 -9
- package/src/metrics/__tests__/model-provider-registry.test.d.ts +0 -2
- package/src/metrics/__tests__/provider-detection.test.d.ts +0 -2
- package/src/migration/__tests__/checksum.test.d.ts +0 -8
- package/src/migration/__tests__/logger.test.d.ts +0 -5
- package/src/migration/__tests__/migration-failure.integration.test.d.ts +0 -15
- package/src/migration/__tests__/migration.test.d.ts +0 -13
- package/src/migration/__tests__/state.test.d.ts +0 -8
- package/src/migration/__tests__/validate.test.d.ts +0 -8
- package/src/nexus/__tests__/deps.test.d.ts +0 -7
- package/src/nexus/__tests__/nexus-e2e.test.d.ts +0 -12
- package/src/nexus/__tests__/permissions.test.d.ts +0 -7
- package/src/nexus/__tests__/query.test.d.ts +0 -7
- package/src/nexus/__tests__/reconcile.test.d.ts +0 -7
- package/src/nexus/__tests__/registry.test.d.ts +0 -7
- package/src/nexus/__tests__/transfer.test.d.ts +0 -8
- package/src/observability/__tests__/index.test.d.ts +0 -7
- package/src/observability/__tests__/log-filter.test.d.ts +0 -7
- package/src/observability/__tests__/log-parser.test.d.ts +0 -7
- package/src/observability/__tests__/log-reader.test.d.ts +0 -7
- package/src/orchestration/__tests__/autonomous-spec.test.d.ts +0 -9
- package/src/orchestration/__tests__/orchestration.test.d.ts +0 -7
- package/src/orchestration/__tests__/protocol-validators.test.d.ts +0 -9
- package/src/phases/__tests__/deps.test.d.ts +0 -7
- package/src/phases/__tests__/phases.test.d.ts +0 -7
- package/src/release/__tests__/artifacts.test.d.ts +0 -7
- package/src/release/__tests__/cancel-release.test.d.ts +0 -10
- package/src/release/__tests__/changelog-writer.test.d.ts +0 -6
- package/src/release/__tests__/push-policy.test.d.ts +0 -14
- package/src/release/__tests__/release.test.d.ts +0 -11
- package/src/sequence/__tests__/allocate.test.d.ts +0 -6
- package/src/sessions/__tests__/briefing-blocked.test.d.ts +0 -6
- package/src/sessions/__tests__/briefing.test.d.ts +0 -11
- package/src/sessions/__tests__/handoff-integration.test.d.ts +0 -8
- package/src/sessions/__tests__/handoff.test.d.ts +0 -11
- package/src/sessions/__tests__/index.test.d.ts +0 -2
- package/src/sessions/__tests__/session-cleanup.test.d.ts +0 -7
- package/src/sessions/__tests__/session-edge-cases.test.d.ts +0 -9
- package/src/sessions/__tests__/session-find.test.d.ts +0 -9
- package/src/sessions/__tests__/session-grade.integration.test.d.ts +0 -11
- package/src/sessions/__tests__/session-grade.test.d.ts +0 -6
- package/src/sessions/__tests__/session-memory-bridge.test.d.ts +0 -2
- package/src/sessions/__tests__/sessions.test.d.ts +0 -7
- package/src/skills/__tests__/discovery.test.d.ts +0 -6
- package/src/skills/__tests__/dispatch.test.d.ts +0 -6
- package/src/skills/__tests__/dynamic-skill-generator.test.d.ts +0 -2
- package/src/skills/__tests__/manifests.test.d.ts +0 -6
- package/src/skills/__tests__/precedence.test.d.ts +0 -6
- package/src/skills/__tests__/routing-table.test.d.ts +0 -2
- package/src/skills/__tests__/skill-paths.test.d.ts +0 -7
- package/src/skills/__tests__/test-utility.test.d.ts +0 -7
- package/src/skills/__tests__/token.test.d.ts +0 -6
- package/src/skills/__tests__/validation.test.d.ts +0 -6
- package/src/skills/__tests__/version.test.d.ts +0 -5
- package/src/skills/injection/__tests__/subagent.test.d.ts +0 -2
- package/src/skills/orchestrator/__tests__/spawn-tier.test.d.ts +0 -2
- package/src/spawn/__tests__/adapter-registry.test.d.ts +0 -2
- package/src/stats/__tests__/stats.test.d.ts +0 -7
- package/src/sticky/__tests__/purge.test.d.ts +0 -9
- package/src/store/__tests__/atomic.test.d.ts +0 -7
- package/src/store/__tests__/backup.test.d.ts +0 -7
- package/src/store/__tests__/brain-accessor-pageindex.test.d.ts +0 -12
- package/src/store/__tests__/brain-accessor.test.d.ts +0 -10
- package/src/store/__tests__/brain-pageindex.test.d.ts +0 -11
- package/src/store/__tests__/brain-schema.test.d.ts +0 -11
- package/src/store/__tests__/brain-vec.test.d.ts +0 -11
- package/src/store/__tests__/collision-detection.test.d.ts +0 -11
- package/src/store/__tests__/data-safety-central.test.d.ts +0 -20
- package/src/store/__tests__/db-helpers.test.d.ts +0 -7
- package/src/store/__tests__/e2e-safety-integration.test.d.ts +0 -13
- package/src/store/__tests__/git-checkpoint.test.d.ts +0 -7
- package/src/store/__tests__/idempotent-migration.test.d.ts +0 -5
- package/src/store/__tests__/import-logging.test.d.ts +0 -7
- package/src/store/__tests__/import-sort.test.d.ts +0 -7
- package/src/store/__tests__/json.test.d.ts +0 -7
- package/src/store/__tests__/lifecycle-schema-parity.test.d.ts +0 -2
- package/src/store/__tests__/migration-integration.test.d.ts +0 -15
- package/src/store/__tests__/migration-retry.test.d.ts +0 -10
- package/src/store/__tests__/migration-safety.test.d.ts +0 -21
- package/src/store/__tests__/migration-sqlite.test.d.ts +0 -11
- package/src/store/__tests__/performance-safety.test.d.ts +0 -17
- package/src/store/__tests__/project-detect.test.d.ts +0 -6
- package/src/store/__tests__/project-registry.test.d.ts +0 -7
- package/src/store/__tests__/provider.test.d.ts +0 -9
- package/src/store/__tests__/relations.test.d.ts +0 -9
- package/src/store/__tests__/safety-accessor.test.d.ts +0 -18
- package/src/store/__tests__/sequence-validation.test.d.ts +0 -11
- package/src/store/__tests__/session-store.test.d.ts +0 -11
- package/src/store/__tests__/sqlite-backup.test.d.ts +0 -14
- package/src/store/__tests__/sqlite.test.d.ts +0 -11
- package/src/store/__tests__/task-store.test.d.ts +0 -11
- package/src/store/__tests__/test-db-helper.d.ts +0 -61
- package/src/store/__tests__/write-verification.test.d.ts +0 -11
- package/src/system/__tests__/cleanup.test.d.ts +0 -2
- package/src/system/__tests__/health.test.d.ts +0 -2
- package/src/task-work/__tests__/start-deps.test.d.ts +0 -6
- package/src/tasks/__tests__/add.test.d.ts +0 -7
- package/src/tasks/__tests__/archive.test.d.ts +0 -7
- package/src/tasks/__tests__/assignee.test.d.ts +0 -14
- package/src/tasks/__tests__/atomicity.test.d.ts +0 -6
- package/src/tasks/__tests__/cancel-ops.test.d.ts +0 -7
- package/src/tasks/__tests__/complete-unblocks.test.d.ts +0 -6
- package/src/tasks/__tests__/complete.test.d.ts +0 -7
- package/src/tasks/__tests__/delete.test.d.ts +0 -7
- package/src/tasks/__tests__/dependency-check.test.d.ts +0 -7
- package/src/tasks/__tests__/deps-ready.test.d.ts +0 -6
- package/src/tasks/__tests__/epic-enforcement.test.d.ts +0 -15
- package/src/tasks/__tests__/find.test.d.ts +0 -7
- package/src/tasks/__tests__/graph-ops.test.d.ts +0 -7
- package/src/tasks/__tests__/hierarchy-policy.test.d.ts +0 -6
- package/src/tasks/__tests__/hierarchy.test.d.ts +0 -7
- package/src/tasks/__tests__/id-generator.test.d.ts +0 -2
- package/src/tasks/__tests__/labels.test.d.ts +0 -7
- package/src/tasks/__tests__/list.test.d.ts +0 -7
- package/src/tasks/__tests__/minimal-test.test.d.ts +0 -2
- package/src/tasks/__tests__/phase-tracking.test.d.ts +0 -7
- package/src/tasks/__tests__/pipeline-stage.test.d.ts +0 -14
- package/src/tasks/__tests__/plan-priority.test.d.ts +0 -10
- package/src/tasks/__tests__/priority-normalization.test.d.ts +0 -7
- package/src/tasks/__tests__/relates.test.d.ts +0 -9
- package/src/tasks/__tests__/show-deps.test.d.ts +0 -6
- package/src/tasks/__tests__/show.test.d.ts +0 -7
- package/src/tasks/__tests__/staleness.test.d.ts +0 -7
- package/src/tasks/__tests__/task-ops-depends.test.d.ts +0 -6
- package/src/tasks/__tests__/update.test.d.ts +0 -7
- package/src/validation/__tests__/chain-validation.test.d.ts +0 -7
- package/src/validation/__tests__/compliance.test.d.ts +0 -7
- package/src/validation/__tests__/docs-sync.test.d.ts +0 -7
- package/src/validation/__tests__/doctor-gitignore.test.d.ts +0 -7
- package/src/validation/__tests__/doctor-injection.test.d.ts +0 -11
- package/src/validation/__tests__/doctor.test.d.ts +0 -7
- package/src/validation/__tests__/engine.test.d.ts +0 -7
- package/src/validation/__tests__/manifest.test.d.ts +0 -7
- package/src/validation/__tests__/protocol-common.test.d.ts +0 -7
- package/src/validation/__tests__/verification.test.d.ts +0 -7
|
@@ -1,85 +1,194 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Agent Registry Accessor — CRUD operations for agent
|
|
2
|
+
* Agent Registry Accessor — CRUD operations for agent data in signaldock.db.
|
|
3
|
+
*
|
|
4
|
+
* signaldock.db is the SSoT for ALL agent data: identity, credentials,
|
|
5
|
+
* capabilities, skills, transport config. No agent data lives in tasks.db.
|
|
3
6
|
*
|
|
4
|
-
* Implements the `AgentRegistryAPI` contract from `@cleocode/contracts`.
|
|
5
7
|
* API keys are encrypted at rest using the crypto/credentials module.
|
|
6
8
|
*
|
|
7
|
-
* @see docs/specs/
|
|
8
|
-
* @task
|
|
9
|
+
* @see docs/specs/DATABASE-ARCHITECTURE.md
|
|
10
|
+
* @task T234
|
|
9
11
|
*/
|
|
10
12
|
|
|
13
|
+
import { createRequire } from 'node:module';
|
|
14
|
+
import type { DatabaseSync } from 'node:sqlite';
|
|
11
15
|
import type {
|
|
12
16
|
AgentCredential,
|
|
13
17
|
AgentListFilter,
|
|
14
18
|
AgentRegistryAPI,
|
|
15
19
|
TransportConfig,
|
|
16
20
|
} from '@cleocode/contracts';
|
|
17
|
-
import { desc, eq } from 'drizzle-orm';
|
|
18
|
-
import type { NodeSQLiteDatabase } from 'drizzle-orm/node-sqlite';
|
|
19
|
-
import { createInsertSchema, createSelectSchema } from 'drizzle-orm/zod';
|
|
20
21
|
import { decrypt, encrypt } from '../crypto/credentials.js';
|
|
21
|
-
import
|
|
22
|
-
|
|
23
|
-
const { agentCredentials } = schema;
|
|
22
|
+
import { ensureSignaldockDb, getSignaldockDbPath } from './signaldock-sqlite.js';
|
|
24
23
|
|
|
25
|
-
|
|
26
|
-
|
|
24
|
+
const _require = createRequire(import.meta.url);
|
|
25
|
+
const { DatabaseSync: DatabaseSyncClass } = _require('node:sqlite') as {
|
|
26
|
+
DatabaseSync: new (...args: ConstructorParameters<typeof DatabaseSync>) => DatabaseSync;
|
|
27
|
+
};
|
|
27
28
|
|
|
28
|
-
/**
|
|
29
|
-
|
|
30
|
-
|
|
29
|
+
/** Raw row shape from signaldock.db agents table. */
|
|
30
|
+
interface AgentDbRow {
|
|
31
|
+
id: string;
|
|
32
|
+
agent_id: string;
|
|
33
|
+
name: string;
|
|
34
|
+
description: string | null;
|
|
35
|
+
class: string;
|
|
36
|
+
privacy_tier: string;
|
|
37
|
+
capabilities: string;
|
|
38
|
+
skills: string;
|
|
39
|
+
transport_type: string;
|
|
40
|
+
api_key_encrypted: string | null;
|
|
41
|
+
api_base_url: string;
|
|
42
|
+
classification: string | null;
|
|
43
|
+
transport_config: string;
|
|
44
|
+
is_active: number;
|
|
45
|
+
last_used_at: number | null;
|
|
46
|
+
created_at: number;
|
|
47
|
+
updated_at: number;
|
|
48
|
+
}
|
|
31
49
|
|
|
32
|
-
/** Convert a
|
|
33
|
-
async function rowToCredential(
|
|
34
|
-
row
|
|
35
|
-
projectPath: string,
|
|
36
|
-
): Promise<AgentCredential> {
|
|
37
|
-
const apiKey = await decrypt(row.apiKeyEncrypted, projectPath);
|
|
50
|
+
/** Convert a signaldock.db row to an AgentCredential, decrypting the API key. */
|
|
51
|
+
async function rowToCredential(row: AgentDbRow, projectPath: string): Promise<AgentCredential> {
|
|
52
|
+
const apiKey = row.api_key_encrypted ? await decrypt(row.api_key_encrypted, projectPath) : '';
|
|
38
53
|
return {
|
|
39
|
-
agentId: row.
|
|
40
|
-
displayName: row.
|
|
54
|
+
agentId: row.agent_id,
|
|
55
|
+
displayName: row.name,
|
|
41
56
|
apiKey,
|
|
42
|
-
apiBaseUrl: row.
|
|
57
|
+
apiBaseUrl: row.api_base_url,
|
|
43
58
|
classification: row.classification ?? undefined,
|
|
44
|
-
privacyTier: row.
|
|
59
|
+
privacyTier: row.privacy_tier as AgentCredential['privacyTier'],
|
|
45
60
|
capabilities: JSON.parse(row.capabilities) as string[],
|
|
46
61
|
skills: JSON.parse(row.skills) as string[],
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
62
|
+
transportType: (row.transport_type ?? 'http') as AgentCredential['transportType'],
|
|
63
|
+
transportConfig: JSON.parse(row.transport_config) as TransportConfig,
|
|
64
|
+
isActive: row.is_active === 1,
|
|
65
|
+
lastUsedAt: row.last_used_at ? new Date(row.last_used_at * 1000).toISOString() : undefined,
|
|
66
|
+
createdAt: new Date(row.created_at * 1000).toISOString(),
|
|
67
|
+
updatedAt: new Date(row.updated_at * 1000).toISOString(),
|
|
52
68
|
};
|
|
53
69
|
}
|
|
54
70
|
|
|
55
|
-
/**
|
|
71
|
+
/** Open signaldock.db for read/write operations. Caller must close. */
|
|
72
|
+
function openDb(projectPath: string): DatabaseSync {
|
|
73
|
+
const dbPath = getSignaldockDbPath(projectPath);
|
|
74
|
+
const db = new DatabaseSyncClass(dbPath);
|
|
75
|
+
db.exec('PRAGMA foreign_keys = ON');
|
|
76
|
+
db.exec('PRAGMA journal_mode = WAL');
|
|
77
|
+
return db;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Sync capabilities/skills to junction tables in signaldock.db.
|
|
82
|
+
* Junction tables are the SSoT — JSON columns are materialized cache.
|
|
83
|
+
*/
|
|
84
|
+
function syncJunctionTables(
|
|
85
|
+
db: DatabaseSync,
|
|
86
|
+
agentUuid: string,
|
|
87
|
+
capabilities: string[],
|
|
88
|
+
skills: string[],
|
|
89
|
+
): void {
|
|
90
|
+
db.prepare('DELETE FROM agent_capabilities WHERE agent_id = ?').run(agentUuid);
|
|
91
|
+
db.prepare('DELETE FROM agent_skills WHERE agent_id = ?').run(agentUuid);
|
|
92
|
+
for (const cap of capabilities) {
|
|
93
|
+
const capRow = db.prepare('SELECT id FROM capabilities WHERE slug = ?').get(cap) as
|
|
94
|
+
| { id: string }
|
|
95
|
+
| undefined;
|
|
96
|
+
if (capRow) {
|
|
97
|
+
db.prepare(
|
|
98
|
+
'INSERT OR IGNORE INTO agent_capabilities (agent_id, capability_id) VALUES (?, ?)',
|
|
99
|
+
).run(agentUuid, capRow.id);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
for (const skill of skills) {
|
|
103
|
+
const skillRow = db.prepare('SELECT id FROM skills WHERE slug = ?').get(skill) as
|
|
104
|
+
| { id: string }
|
|
105
|
+
| undefined;
|
|
106
|
+
if (skillRow) {
|
|
107
|
+
db.prepare('INSERT OR IGNORE INTO agent_skills (agent_id, skill_id) VALUES (?, ?)').run(
|
|
108
|
+
agentUuid,
|
|
109
|
+
skillRow.id,
|
|
110
|
+
);
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
/** signaldock.db implementation of the AgentRegistryAPI. */
|
|
56
116
|
export class AgentRegistryAccessor implements AgentRegistryAPI {
|
|
57
|
-
constructor(
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
) {
|
|
117
|
+
constructor(private projectPath: string) {}
|
|
118
|
+
|
|
119
|
+
/** Ensure signaldock.db exists with full schema before any operation. */
|
|
120
|
+
private async ensureDb(): Promise<void> {
|
|
121
|
+
await ensureSignaldockDb(this.projectPath);
|
|
122
|
+
}
|
|
61
123
|
|
|
62
124
|
async register(
|
|
63
125
|
credential: Omit<AgentCredential, 'createdAt' | 'updatedAt'>,
|
|
64
126
|
): Promise<AgentCredential> {
|
|
65
|
-
|
|
66
|
-
const
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
127
|
+
await this.ensureDb();
|
|
128
|
+
const nowTs = Math.floor(Date.now() / 1000);
|
|
129
|
+
const apiKeyEncrypted = credential.apiKey
|
|
130
|
+
? await encrypt(credential.apiKey, this.projectPath)
|
|
131
|
+
: null;
|
|
132
|
+
|
|
133
|
+
const db = openDb(this.projectPath);
|
|
134
|
+
try {
|
|
135
|
+
const existing = db
|
|
136
|
+
.prepare('SELECT id FROM agents WHERE agent_id = ?')
|
|
137
|
+
.get(credential.agentId) as { id: string } | undefined;
|
|
138
|
+
|
|
139
|
+
if (!existing) {
|
|
140
|
+
const id = crypto.randomUUID();
|
|
141
|
+
db.prepare(
|
|
142
|
+
`INSERT INTO agents (id, agent_id, name, class, privacy_tier, capabilities, skills,
|
|
143
|
+
transport_type, api_key_encrypted, api_base_url, classification, transport_config,
|
|
144
|
+
is_active, last_used_at, status, created_at, updated_at)
|
|
145
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, 'online', ?, ?)`,
|
|
146
|
+
).run(
|
|
147
|
+
id,
|
|
148
|
+
credential.agentId,
|
|
149
|
+
credential.displayName,
|
|
150
|
+
credential.classification ?? 'custom',
|
|
151
|
+
credential.privacyTier,
|
|
152
|
+
JSON.stringify(credential.capabilities),
|
|
153
|
+
JSON.stringify(credential.skills),
|
|
154
|
+
credential.transportType ?? 'http',
|
|
155
|
+
apiKeyEncrypted,
|
|
156
|
+
credential.apiBaseUrl,
|
|
157
|
+
credential.classification ?? null,
|
|
158
|
+
JSON.stringify(credential.transportConfig),
|
|
159
|
+
credential.isActive ? 1 : 0,
|
|
160
|
+
credential.lastUsedAt
|
|
161
|
+
? Math.floor(new Date(credential.lastUsedAt).getTime() / 1000)
|
|
162
|
+
: null,
|
|
163
|
+
nowTs,
|
|
164
|
+
nowTs,
|
|
165
|
+
);
|
|
166
|
+
syncJunctionTables(db, id, credential.capabilities, credential.skills);
|
|
167
|
+
} else {
|
|
168
|
+
db.prepare(
|
|
169
|
+
`UPDATE agents SET name = ?, class = ?, privacy_tier = ?, capabilities = ?, skills = ?,
|
|
170
|
+
transport_type = ?, api_key_encrypted = ?, api_base_url = ?, classification = ?,
|
|
171
|
+
transport_config = ?, is_active = ?, updated_at = ? WHERE agent_id = ?`,
|
|
172
|
+
).run(
|
|
173
|
+
credential.displayName,
|
|
174
|
+
credential.classification ?? 'custom',
|
|
175
|
+
credential.privacyTier,
|
|
176
|
+
JSON.stringify(credential.capabilities),
|
|
177
|
+
JSON.stringify(credential.skills),
|
|
178
|
+
credential.transportType ?? 'http',
|
|
179
|
+
apiKeyEncrypted,
|
|
180
|
+
credential.apiBaseUrl,
|
|
181
|
+
credential.classification ?? null,
|
|
182
|
+
JSON.stringify(credential.transportConfig),
|
|
183
|
+
credential.isActive ? 1 : 0,
|
|
184
|
+
nowTs,
|
|
185
|
+
credential.agentId,
|
|
186
|
+
);
|
|
187
|
+
syncJunctionTables(db, existing.id, credential.capabilities, credential.skills);
|
|
188
|
+
}
|
|
189
|
+
} finally {
|
|
190
|
+
db.close();
|
|
191
|
+
}
|
|
83
192
|
|
|
84
193
|
const result = await this.get(credential.agentId);
|
|
85
194
|
if (!result) throw new Error(`Failed to register agent: ${credential.agentId}`);
|
|
@@ -87,54 +196,110 @@ export class AgentRegistryAccessor implements AgentRegistryAPI {
|
|
|
87
196
|
}
|
|
88
197
|
|
|
89
198
|
async get(agentId: string): Promise<AgentCredential | null> {
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
.
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
199
|
+
await this.ensureDb();
|
|
200
|
+
const db = openDb(this.projectPath);
|
|
201
|
+
try {
|
|
202
|
+
const row = db.prepare('SELECT * FROM agents WHERE agent_id = ?').get(agentId) as
|
|
203
|
+
| AgentDbRow
|
|
204
|
+
| undefined;
|
|
205
|
+
if (!row) return null;
|
|
206
|
+
return rowToCredential(row, this.projectPath);
|
|
207
|
+
} finally {
|
|
208
|
+
db.close();
|
|
209
|
+
}
|
|
97
210
|
}
|
|
98
211
|
|
|
99
212
|
async list(filter?: AgentListFilter): Promise<AgentCredential[]> {
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
213
|
+
await this.ensureDb();
|
|
214
|
+
const db = openDb(this.projectPath);
|
|
215
|
+
try {
|
|
216
|
+
const rows =
|
|
217
|
+
filter?.active !== undefined
|
|
218
|
+
? (db
|
|
219
|
+
.prepare('SELECT * FROM agents WHERE is_active = ?')
|
|
220
|
+
.all(filter.active ? 1 : 0) as unknown as AgentDbRow[])
|
|
221
|
+
: (db.prepare('SELECT * FROM agents').all() as unknown as AgentDbRow[]);
|
|
222
|
+
return Promise.all(rows.map((row) => rowToCredential(row, this.projectPath)));
|
|
223
|
+
} finally {
|
|
224
|
+
db.close();
|
|
225
|
+
}
|
|
110
226
|
}
|
|
111
227
|
|
|
112
228
|
async update(
|
|
113
229
|
agentId: string,
|
|
114
230
|
updates: Partial<Omit<AgentCredential, 'agentId' | 'createdAt'>>,
|
|
115
231
|
): Promise<AgentCredential> {
|
|
116
|
-
// C2 fix: pre-flight check — fail fast if agent doesn't exist
|
|
117
232
|
const existing = await this.get(agentId);
|
|
118
233
|
if (!existing) throw new Error(`Agent not found: ${agentId}`);
|
|
119
234
|
|
|
120
|
-
const
|
|
121
|
-
const
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
if (updates.classification !== undefined) values['classification'] = updates.classification;
|
|
126
|
-
if (updates.privacyTier !== undefined) values['privacyTier'] = updates.privacyTier;
|
|
127
|
-
if (updates.capabilities !== undefined)
|
|
128
|
-
values['capabilities'] = JSON.stringify(updates.capabilities);
|
|
129
|
-
if (updates.skills !== undefined) values['skills'] = JSON.stringify(updates.skills);
|
|
130
|
-
if (updates.transportConfig !== undefined)
|
|
131
|
-
values['transportConfig'] = JSON.stringify(updates.transportConfig);
|
|
132
|
-
if (updates.isActive !== undefined) values['isActive'] = updates.isActive;
|
|
133
|
-
if (updates.apiKey !== undefined) {
|
|
134
|
-
values['apiKeyEncrypted'] = await encrypt(updates.apiKey, this.projectPath);
|
|
135
|
-
}
|
|
235
|
+
const nowTs = Math.floor(Date.now() / 1000);
|
|
236
|
+
const db = openDb(this.projectPath);
|
|
237
|
+
try {
|
|
238
|
+
const sets: string[] = ['updated_at = ?'];
|
|
239
|
+
const params: unknown[] = [nowTs];
|
|
136
240
|
|
|
137
|
-
|
|
241
|
+
if (updates.displayName !== undefined) {
|
|
242
|
+
sets.push('name = ?');
|
|
243
|
+
params.push(updates.displayName);
|
|
244
|
+
}
|
|
245
|
+
if (updates.apiBaseUrl !== undefined) {
|
|
246
|
+
sets.push('api_base_url = ?');
|
|
247
|
+
params.push(updates.apiBaseUrl);
|
|
248
|
+
}
|
|
249
|
+
if (updates.classification !== undefined) {
|
|
250
|
+
sets.push('classification = ?');
|
|
251
|
+
params.push(updates.classification);
|
|
252
|
+
}
|
|
253
|
+
if (updates.privacyTier !== undefined) {
|
|
254
|
+
sets.push('privacy_tier = ?');
|
|
255
|
+
params.push(updates.privacyTier);
|
|
256
|
+
}
|
|
257
|
+
if (updates.capabilities !== undefined) {
|
|
258
|
+
sets.push('capabilities = ?');
|
|
259
|
+
params.push(JSON.stringify(updates.capabilities));
|
|
260
|
+
}
|
|
261
|
+
if (updates.skills !== undefined) {
|
|
262
|
+
sets.push('skills = ?');
|
|
263
|
+
params.push(JSON.stringify(updates.skills));
|
|
264
|
+
}
|
|
265
|
+
if (updates.transportType !== undefined) {
|
|
266
|
+
sets.push('transport_type = ?');
|
|
267
|
+
params.push(updates.transportType);
|
|
268
|
+
}
|
|
269
|
+
if (updates.transportConfig !== undefined) {
|
|
270
|
+
sets.push('transport_config = ?');
|
|
271
|
+
params.push(JSON.stringify(updates.transportConfig));
|
|
272
|
+
}
|
|
273
|
+
if (updates.isActive !== undefined) {
|
|
274
|
+
sets.push('is_active = ?');
|
|
275
|
+
params.push(updates.isActive ? 1 : 0);
|
|
276
|
+
}
|
|
277
|
+
if (updates.apiKey !== undefined) {
|
|
278
|
+
const encrypted = await encrypt(updates.apiKey, this.projectPath);
|
|
279
|
+
sets.push('api_key_encrypted = ?');
|
|
280
|
+
params.push(encrypted);
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
params.push(agentId);
|
|
284
|
+
db.prepare(`UPDATE agents SET ${sets.join(', ')} WHERE agent_id = ?`).run(
|
|
285
|
+
...(params as Array<string | number | null>),
|
|
286
|
+
);
|
|
287
|
+
|
|
288
|
+
// Sync junction tables if capabilities or skills changed
|
|
289
|
+
if (updates.capabilities !== undefined || updates.skills !== undefined) {
|
|
290
|
+
const agentRow = db.prepare('SELECT id FROM agents WHERE agent_id = ?').get(agentId) as {
|
|
291
|
+
id: string;
|
|
292
|
+
};
|
|
293
|
+
syncJunctionTables(
|
|
294
|
+
db,
|
|
295
|
+
agentRow.id,
|
|
296
|
+
updates.capabilities ?? existing.capabilities,
|
|
297
|
+
updates.skills ?? existing.skills,
|
|
298
|
+
);
|
|
299
|
+
}
|
|
300
|
+
} finally {
|
|
301
|
+
db.close();
|
|
302
|
+
}
|
|
138
303
|
|
|
139
304
|
const result = await this.get(agentId);
|
|
140
305
|
if (!result) throw new Error(`Agent not found after update: ${agentId}`);
|
|
@@ -142,18 +307,21 @@ export class AgentRegistryAccessor implements AgentRegistryAPI {
|
|
|
142
307
|
}
|
|
143
308
|
|
|
144
309
|
async remove(agentId: string): Promise<void> {
|
|
145
|
-
// H2 fix: pre-flight check — throw if agent doesn't exist
|
|
146
310
|
const existing = await this.get(agentId);
|
|
147
311
|
if (!existing) throw new Error(`Agent not found: ${agentId}`);
|
|
148
312
|
|
|
149
|
-
|
|
313
|
+
const db = openDb(this.projectPath);
|
|
314
|
+
try {
|
|
315
|
+
db.prepare('DELETE FROM agents WHERE agent_id = ?').run(agentId);
|
|
316
|
+
} finally {
|
|
317
|
+
db.close();
|
|
318
|
+
}
|
|
150
319
|
}
|
|
151
320
|
|
|
152
321
|
async rotateKey(agentId: string): Promise<{ agentId: string; newApiKey: string }> {
|
|
153
322
|
const credential = await this.get(agentId);
|
|
154
323
|
if (!credential) throw new Error(`Agent not found: ${agentId}`);
|
|
155
324
|
|
|
156
|
-
// Call cloud API to rotate key
|
|
157
325
|
const response = await fetch(`${credential.apiBaseUrl}/agents/${agentId}/rotate-key`, {
|
|
158
326
|
method: 'POST',
|
|
159
327
|
headers: {
|
|
@@ -170,30 +338,38 @@ export class AgentRegistryAccessor implements AgentRegistryAPI {
|
|
|
170
338
|
const newApiKey = data.data?.apiKey;
|
|
171
339
|
if (!newApiKey) throw new Error('Cloud API did not return a new API key');
|
|
172
340
|
|
|
173
|
-
// Re-encrypt and store locally
|
|
174
341
|
await this.update(agentId, { apiKey: newApiKey });
|
|
175
|
-
|
|
176
|
-
// C1 fix: return only agentId, not plaintext key — callers use get() to retrieve
|
|
177
342
|
return { agentId, newApiKey: `${newApiKey.substring(0, 8)}...rotated` };
|
|
178
343
|
}
|
|
179
344
|
|
|
180
345
|
async getActive(): Promise<AgentCredential | null> {
|
|
181
|
-
|
|
182
|
-
const
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
346
|
+
await this.ensureDb();
|
|
347
|
+
const db = openDb(this.projectPath);
|
|
348
|
+
try {
|
|
349
|
+
const row = db
|
|
350
|
+
.prepare(
|
|
351
|
+
'SELECT * FROM agents WHERE is_active = 1 ORDER BY last_used_at DESC, created_at DESC LIMIT 1',
|
|
352
|
+
)
|
|
353
|
+
.get() as AgentDbRow | undefined;
|
|
354
|
+
if (!row) return null;
|
|
355
|
+
return rowToCredential(row, this.projectPath);
|
|
356
|
+
} finally {
|
|
357
|
+
db.close();
|
|
358
|
+
}
|
|
191
359
|
}
|
|
192
360
|
|
|
193
361
|
async markUsed(agentId: string): Promise<void> {
|
|
194
|
-
await this.
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
362
|
+
await this.ensureDb();
|
|
363
|
+
const nowTs = Math.floor(Date.now() / 1000);
|
|
364
|
+
const db = openDb(this.projectPath);
|
|
365
|
+
try {
|
|
366
|
+
db.prepare('UPDATE agents SET last_used_at = ?, updated_at = ? WHERE agent_id = ?').run(
|
|
367
|
+
nowTs,
|
|
368
|
+
nowTs,
|
|
369
|
+
agentId,
|
|
370
|
+
);
|
|
371
|
+
} finally {
|
|
372
|
+
db.close();
|
|
373
|
+
}
|
|
198
374
|
}
|
|
199
375
|
}
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
* @epic T029
|
|
12
12
|
*/
|
|
13
13
|
|
|
14
|
-
import { eq, or } from 'drizzle-orm';
|
|
14
|
+
import { and, eq, isNotNull, or } from 'drizzle-orm';
|
|
15
15
|
import * as brainSchema from './brain-schema.js';
|
|
16
16
|
import { getBrainDb } from './brain-sqlite.js';
|
|
17
17
|
|
|
@@ -177,6 +177,142 @@ export async function taskExistsInTasksDb(
|
|
|
177
177
|
* if (await sessionExistsInTasksDb('ses_abc', db)) { /* safe to reference *\/ }
|
|
178
178
|
* ```
|
|
179
179
|
*/
|
|
180
|
+
/**
|
|
181
|
+
* Reconcile orphaned cross-DB references in brain.db.
|
|
182
|
+
*
|
|
183
|
+
* Scans brain.db for references to tasks/sessions that no longer exist in
|
|
184
|
+
* tasks.db and cleans them up:
|
|
185
|
+
* - brain_decisions with stale context_task_id or context_epic_id → nullify
|
|
186
|
+
* - brain_observations with stale source_session_id → nullify
|
|
187
|
+
* - brain_memory_links with stale task_id → delete row
|
|
188
|
+
*
|
|
189
|
+
* This is the background reconciliation pass mentioned in the module doc.
|
|
190
|
+
* Safe to run at any frequency — idempotent.
|
|
191
|
+
*
|
|
192
|
+
* @param cwd - Optional working directory
|
|
193
|
+
* @returns Counts of orphaned references cleaned up
|
|
194
|
+
*/
|
|
195
|
+
export async function reconcileOrphanedRefs(cwd?: string): Promise<{
|
|
196
|
+
decisionsFixed: number;
|
|
197
|
+
observationsFixed: number;
|
|
198
|
+
linksRemoved: number;
|
|
199
|
+
}> {
|
|
200
|
+
let brainDb: Awaited<ReturnType<typeof getBrainDb>> | null = null;
|
|
201
|
+
const result = { decisionsFixed: 0, observationsFixed: 0, linksRemoved: 0 };
|
|
202
|
+
|
|
203
|
+
try {
|
|
204
|
+
brainDb = await getBrainDb(cwd);
|
|
205
|
+
} catch {
|
|
206
|
+
return result;
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
const { getDb } = await import('./sqlite.js');
|
|
210
|
+
let tasksDb: Awaited<ReturnType<typeof getDb>>;
|
|
211
|
+
try {
|
|
212
|
+
tasksDb = await getDb(cwd);
|
|
213
|
+
} catch {
|
|
214
|
+
return result;
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
try {
|
|
218
|
+
// 1. Find decisions with stale context_task_id
|
|
219
|
+
const decisionsWithTaskRef = await brainDb
|
|
220
|
+
.select({
|
|
221
|
+
id: brainSchema.brainDecisions.id,
|
|
222
|
+
contextTaskId: brainSchema.brainDecisions.contextTaskId,
|
|
223
|
+
contextEpicId: brainSchema.brainDecisions.contextEpicId,
|
|
224
|
+
})
|
|
225
|
+
.from(brainSchema.brainDecisions)
|
|
226
|
+
.where(
|
|
227
|
+
or(
|
|
228
|
+
isNotNull(brainSchema.brainDecisions.contextTaskId),
|
|
229
|
+
isNotNull(brainSchema.brainDecisions.contextEpicId),
|
|
230
|
+
),
|
|
231
|
+
)
|
|
232
|
+
.all();
|
|
233
|
+
|
|
234
|
+
for (const d of decisionsWithTaskRef) {
|
|
235
|
+
if (d.contextTaskId) {
|
|
236
|
+
const exists = await taskExistsInTasksDb(d.contextTaskId, tasksDb);
|
|
237
|
+
if (!exists) {
|
|
238
|
+
await brainDb
|
|
239
|
+
.update(brainSchema.brainDecisions)
|
|
240
|
+
.set({ contextTaskId: null })
|
|
241
|
+
.where(eq(brainSchema.brainDecisions.id, d.id));
|
|
242
|
+
result.decisionsFixed++;
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
if (d.contextEpicId) {
|
|
246
|
+
const exists = await taskExistsInTasksDb(d.contextEpicId, tasksDb);
|
|
247
|
+
if (!exists) {
|
|
248
|
+
await brainDb
|
|
249
|
+
.update(brainSchema.brainDecisions)
|
|
250
|
+
.set({ contextEpicId: null })
|
|
251
|
+
.where(eq(brainSchema.brainDecisions.id, d.id));
|
|
252
|
+
result.decisionsFixed++;
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
// 2. Find observations with stale source_session_id
|
|
258
|
+
const obsWithSessionRef = await brainDb
|
|
259
|
+
.select({
|
|
260
|
+
id: brainSchema.brainObservations.id,
|
|
261
|
+
sourceSessionId: brainSchema.brainObservations.sourceSessionId,
|
|
262
|
+
})
|
|
263
|
+
.from(brainSchema.brainObservations)
|
|
264
|
+
.where(isNotNull(brainSchema.brainObservations.sourceSessionId))
|
|
265
|
+
.all();
|
|
266
|
+
|
|
267
|
+
for (const o of obsWithSessionRef) {
|
|
268
|
+
{
|
|
269
|
+
const exists = o.sourceSessionId
|
|
270
|
+
? await sessionExistsInTasksDb(o.sourceSessionId, tasksDb)
|
|
271
|
+
: false;
|
|
272
|
+
if (!exists) {
|
|
273
|
+
await brainDb
|
|
274
|
+
.update(brainSchema.brainObservations)
|
|
275
|
+
.set({ sourceSessionId: null })
|
|
276
|
+
.where(eq(brainSchema.brainObservations.id, o.id));
|
|
277
|
+
result.observationsFixed++;
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
// 3. Find memory links with stale task_id
|
|
283
|
+
const allLinks = await brainDb
|
|
284
|
+
.select({
|
|
285
|
+
memoryType: brainSchema.brainMemoryLinks.memoryType,
|
|
286
|
+
memoryId: brainSchema.brainMemoryLinks.memoryId,
|
|
287
|
+
taskId: brainSchema.brainMemoryLinks.taskId,
|
|
288
|
+
linkType: brainSchema.brainMemoryLinks.linkType,
|
|
289
|
+
})
|
|
290
|
+
.from(brainSchema.brainMemoryLinks)
|
|
291
|
+
.all();
|
|
292
|
+
|
|
293
|
+
for (const link of allLinks) {
|
|
294
|
+
const exists = await taskExistsInTasksDb(link.taskId, tasksDb);
|
|
295
|
+
if (!exists) {
|
|
296
|
+
await brainDb
|
|
297
|
+
.delete(brainSchema.brainMemoryLinks)
|
|
298
|
+
.where(
|
|
299
|
+
and(
|
|
300
|
+
eq(brainSchema.brainMemoryLinks.memoryType, link.memoryType),
|
|
301
|
+
eq(brainSchema.brainMemoryLinks.memoryId, link.memoryId),
|
|
302
|
+
eq(brainSchema.brainMemoryLinks.taskId, link.taskId),
|
|
303
|
+
eq(brainSchema.brainMemoryLinks.linkType, link.linkType),
|
|
304
|
+
),
|
|
305
|
+
);
|
|
306
|
+
result.linksRemoved++;
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
} catch {
|
|
310
|
+
// Non-fatal best-effort reconciliation
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
return result;
|
|
314
|
+
}
|
|
315
|
+
|
|
180
316
|
export async function sessionExistsInTasksDb(
|
|
181
317
|
sessionId: string,
|
|
182
318
|
tasksDb: Awaited<ReturnType<typeof import('./sqlite.js').getDb>>,
|
|
@@ -190,3 +326,41 @@ export async function sessionExistsInTasksDb(
|
|
|
190
326
|
.all();
|
|
191
327
|
return result.length > 0;
|
|
192
328
|
}
|
|
329
|
+
|
|
330
|
+
/**
|
|
331
|
+
* Verify an agent exists in signaldock.db before creating cross-DB references.
|
|
332
|
+
* Returns true if the agent_id exists in signaldock.db agents table.
|
|
333
|
+
*
|
|
334
|
+
* Provides write-guard for agent_instances and agent_error_log in tasks.db
|
|
335
|
+
* that reference agents whose identity lives in signaldock.db.
|
|
336
|
+
*
|
|
337
|
+
* @param agentId - Agent slug (e.g. 'cleo-db-lead') to verify
|
|
338
|
+
* @param cwd - Optional working directory
|
|
339
|
+
* @returns True if the agent exists in signaldock.db
|
|
340
|
+
*
|
|
341
|
+
* @task T238
|
|
342
|
+
*/
|
|
343
|
+
export async function agentExistsInSignaldockDb(agentId: string, cwd?: string): Promise<boolean> {
|
|
344
|
+
try {
|
|
345
|
+
const { getSignaldockDbPath } = await import('./signaldock-sqlite.js');
|
|
346
|
+
const { existsSync } = await import('node:fs');
|
|
347
|
+
const dbPath = getSignaldockDbPath(cwd);
|
|
348
|
+
if (!existsSync(dbPath)) return false;
|
|
349
|
+
|
|
350
|
+
const { createRequire } = await import('node:module');
|
|
351
|
+
const _require = createRequire(import.meta.url);
|
|
352
|
+
const { DatabaseSync } = _require('node:sqlite') as typeof import('node:sqlite');
|
|
353
|
+
const db = new DatabaseSync(dbPath);
|
|
354
|
+
try {
|
|
355
|
+
const row = db.prepare('SELECT id FROM agents WHERE agent_id = ?').get(agentId) as
|
|
356
|
+
| { id: string }
|
|
357
|
+
| undefined;
|
|
358
|
+
return !!row;
|
|
359
|
+
} finally {
|
|
360
|
+
db.close();
|
|
361
|
+
}
|
|
362
|
+
} catch {
|
|
363
|
+
// signaldock.db may not exist yet — non-fatal
|
|
364
|
+
return false;
|
|
365
|
+
}
|
|
366
|
+
}
|
package/src/store/provider.ts
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* Store provider abstraction layer.
|
|
3
3
|
*
|
|
4
4
|
* Defines the StoreProvider interface backed by SQLite (ADR-006).
|
|
5
|
-
* CLI and
|
|
5
|
+
* CLI and dispatch engine use StoreProvider for all data access.
|
|
6
6
|
*
|
|
7
7
|
* @epic T4454
|
|
8
8
|
* @task W1-T6
|
|
@@ -104,7 +104,7 @@ export interface StoreProvider {
|
|
|
104
104
|
|
|
105
105
|
// ---- High-level domain operations ----
|
|
106
106
|
// These wrap core business logic (validation, ID generation, logging, etc.)
|
|
107
|
-
// and are the primary API for CLI commands and
|
|
107
|
+
// and are the primary API for CLI commands and dispatch engine.
|
|
108
108
|
// @task T4656
|
|
109
109
|
// @epic T4654
|
|
110
110
|
|