opencode-telos 1.0.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 +927 -0
- package/dist/code-intelligence/analyzer.d.ts +9 -0
- package/dist/code-intelligence/analyzer.d.ts.map +1 -0
- package/dist/code-intelligence/analyzer.js +321 -0
- package/dist/code-intelligence/analyzer.js.map +1 -0
- package/dist/code-intelligence/ast/cache.d.ts +16 -0
- package/dist/code-intelligence/ast/cache.d.ts.map +1 -0
- package/dist/code-intelligence/ast/cache.js +44 -0
- package/dist/code-intelligence/ast/cache.js.map +1 -0
- package/dist/code-intelligence/ast/common.d.ts +8 -0
- package/dist/code-intelligence/ast/common.d.ts.map +1 -0
- package/dist/code-intelligence/ast/common.js +42 -0
- package/dist/code-intelligence/ast/common.js.map +1 -0
- package/dist/code-intelligence/ast/component.d.ts +10 -0
- package/dist/code-intelligence/ast/component.d.ts.map +1 -0
- package/dist/code-intelligence/ast/component.js +38 -0
- package/dist/code-intelligence/ast/component.js.map +1 -0
- package/dist/code-intelligence/ast/fallback.d.ts +9 -0
- package/dist/code-intelligence/ast/fallback.d.ts.map +1 -0
- package/dist/code-intelligence/ast/fallback.js +38 -0
- package/dist/code-intelligence/ast/fallback.js.map +1 -0
- package/dist/code-intelligence/ast/index.d.ts +5 -0
- package/dist/code-intelligence/ast/index.d.ts.map +1 -0
- package/dist/code-intelligence/ast/index.js +5 -0
- package/dist/code-intelligence/ast/index.js.map +1 -0
- package/dist/code-intelligence/ast/ir.d.ts +72 -0
- package/dist/code-intelligence/ast/ir.d.ts.map +1 -0
- package/dist/code-intelligence/ast/ir.js +2 -0
- package/dist/code-intelligence/ast/ir.js.map +1 -0
- package/dist/code-intelligence/ast/metrics.d.ts +25 -0
- package/dist/code-intelligence/ast/metrics.d.ts.map +1 -0
- package/dist/code-intelligence/ast/metrics.js +38 -0
- package/dist/code-intelligence/ast/metrics.js.map +1 -0
- package/dist/code-intelligence/ast/registry.d.ts +5 -0
- package/dist/code-intelligence/ast/registry.d.ts.map +1 -0
- package/dist/code-intelligence/ast/registry.js +22 -0
- package/dist/code-intelligence/ast/registry.js.map +1 -0
- package/dist/code-intelligence/ast/tree-sitter.d.ts +8 -0
- package/dist/code-intelligence/ast/tree-sitter.d.ts.map +1 -0
- package/dist/code-intelligence/ast/tree-sitter.js +247 -0
- package/dist/code-intelligence/ast/tree-sitter.js.map +1 -0
- package/dist/code-intelligence/ast/typescript.d.ts +8 -0
- package/dist/code-intelligence/ast/typescript.d.ts.map +1 -0
- package/dist/code-intelligence/ast/typescript.js +147 -0
- package/dist/code-intelligence/ast/typescript.js.map +1 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +18 -0
- package/dist/index.js.map +1 -0
- package/dist/mcp/server.d.ts +27 -0
- package/dist/mcp/server.d.ts.map +1 -0
- package/dist/mcp/server.js +67 -0
- package/dist/mcp/server.js.map +1 -0
- package/dist/opencode/hooks.d.ts +9 -0
- package/dist/opencode/hooks.d.ts.map +1 -0
- package/dist/opencode/hooks.js +583 -0
- package/dist/opencode/hooks.js.map +1 -0
- package/dist/opencode/router/categories.d.ts +31 -0
- package/dist/opencode/router/categories.d.ts.map +1 -0
- package/dist/opencode/router/categories.js +165 -0
- package/dist/opencode/router/categories.js.map +1 -0
- package/dist/opencode/router/embeddings.d.ts +41 -0
- package/dist/opencode/router/embeddings.d.ts.map +1 -0
- package/dist/opencode/router/embeddings.js +136 -0
- package/dist/opencode/router/embeddings.js.map +1 -0
- package/dist/opencode/router/graph-state-snapshot.d.ts +35 -0
- package/dist/opencode/router/graph-state-snapshot.d.ts.map +1 -0
- package/dist/opencode/router/graph-state-snapshot.js +129 -0
- package/dist/opencode/router/graph-state-snapshot.js.map +1 -0
- package/dist/opencode/router/index.d.ts +21 -0
- package/dist/opencode/router/index.d.ts.map +1 -0
- package/dist/opencode/router/index.js +23 -0
- package/dist/opencode/router/index.js.map +1 -0
- package/dist/opencode/router/intent-classifier.d.ts +35 -0
- package/dist/opencode/router/intent-classifier.d.ts.map +1 -0
- package/dist/opencode/router/intent-classifier.js +108 -0
- package/dist/opencode/router/intent-classifier.js.map +1 -0
- package/dist/opencode/router/semantic-nudge.d.ts +42 -0
- package/dist/opencode/router/semantic-nudge.d.ts.map +1 -0
- package/dist/opencode/router/semantic-nudge.js +73 -0
- package/dist/opencode/router/semantic-nudge.js.map +1 -0
- package/dist/opencode/router/state-gate.d.ts +25 -0
- package/dist/opencode/router/state-gate.d.ts.map +1 -0
- package/dist/opencode/router/state-gate.js +178 -0
- package/dist/opencode/router/state-gate.js.map +1 -0
- package/dist/opencode/router/tool-embeddings.d.ts +36 -0
- package/dist/opencode/router/tool-embeddings.d.ts.map +1 -0
- package/dist/opencode/router/tool-embeddings.js +140 -0
- package/dist/opencode/router/tool-embeddings.js.map +1 -0
- package/dist/opencode/router/tool-registry.d.ts +45 -0
- package/dist/opencode/router/tool-registry.d.ts.map +1 -0
- package/dist/opencode/router/tool-registry.js +103 -0
- package/dist/opencode/router/tool-registry.js.map +1 -0
- package/dist/opencode/router/tool-taxonomy.d.ts +51 -0
- package/dist/opencode/router/tool-taxonomy.d.ts.map +1 -0
- package/dist/opencode/router/tool-taxonomy.js +250 -0
- package/dist/opencode/router/tool-taxonomy.js.map +1 -0
- package/dist/opencode/router/tools-composite.d.ts +21 -0
- package/dist/opencode/router/tools-composite.d.ts.map +1 -0
- package/dist/opencode/router/tools-composite.js +684 -0
- package/dist/opencode/router/tools-composite.js.map +1 -0
- package/dist/opencode/shell-hooks.d.ts +7 -0
- package/dist/opencode/shell-hooks.d.ts.map +1 -0
- package/dist/opencode/shell-hooks.js +96 -0
- package/dist/opencode/shell-hooks.js.map +1 -0
- package/dist/opencode/system-prompt.d.ts +10 -0
- package/dist/opencode/system-prompt.d.ts.map +1 -0
- package/dist/opencode/system-prompt.js +600 -0
- package/dist/opencode/system-prompt.js.map +1 -0
- package/dist/opencode/tools.d.ts +8 -0
- package/dist/opencode/tools.d.ts.map +1 -0
- package/dist/opencode/tools.js +3731 -0
- package/dist/opencode/tools.js.map +1 -0
- package/dist/opencode/workflows/chains.d.ts +52 -0
- package/dist/opencode/workflows/chains.d.ts.map +1 -0
- package/dist/opencode/workflows/chains.js +170 -0
- package/dist/opencode/workflows/chains.js.map +1 -0
- package/dist/opencode/workflows/executor.d.ts +52 -0
- package/dist/opencode/workflows/executor.d.ts.map +1 -0
- package/dist/opencode/workflows/executor.js +130 -0
- package/dist/opencode/workflows/executor.js.map +1 -0
- package/dist/opencode/workflows/index.d.ts +14 -0
- package/dist/opencode/workflows/index.d.ts.map +1 -0
- package/dist/opencode/workflows/index.js +15 -0
- package/dist/opencode/workflows/index.js.map +1 -0
- package/dist/opencode/workflows/tools-workflow.d.ts +24 -0
- package/dist/opencode/workflows/tools-workflow.d.ts.map +1 -0
- package/dist/opencode/workflows/tools-workflow.js +85 -0
- package/dist/opencode/workflows/tools-workflow.js.map +1 -0
- package/dist/opencode/workflows/types.d.ts +32 -0
- package/dist/opencode/workflows/types.d.ts.map +1 -0
- package/dist/opencode/workflows/types.js +13 -0
- package/dist/opencode/workflows/types.js.map +1 -0
- package/dist/sdd/analysis/compliance.d.ts +30 -0
- package/dist/sdd/analysis/compliance.d.ts.map +1 -0
- package/dist/sdd/analysis/compliance.js +251 -0
- package/dist/sdd/analysis/compliance.js.map +1 -0
- package/dist/sdd/analysis/scalability.d.ts +15 -0
- package/dist/sdd/analysis/scalability.d.ts.map +1 -0
- package/dist/sdd/analysis/scalability.js +72 -0
- package/dist/sdd/analysis/scalability.js.map +1 -0
- package/dist/sdd/analysis/security.d.ts +25 -0
- package/dist/sdd/analysis/security.d.ts.map +1 -0
- package/dist/sdd/analysis/security.js +94 -0
- package/dist/sdd/analysis/security.js.map +1 -0
- package/dist/sdd/brownfield/scanner.d.ts +31 -0
- package/dist/sdd/brownfield/scanner.d.ts.map +1 -0
- package/dist/sdd/brownfield/scanner.js +228 -0
- package/dist/sdd/brownfield/scanner.js.map +1 -0
- package/dist/sdd/cache/manager.d.ts +237 -0
- package/dist/sdd/cache/manager.d.ts.map +1 -0
- package/dist/sdd/cache/manager.js +770 -0
- package/dist/sdd/cache/manager.js.map +1 -0
- package/dist/sdd/cache/snapshot-store.d.ts +39 -0
- package/dist/sdd/cache/snapshot-store.d.ts.map +1 -0
- package/dist/sdd/cache/snapshot-store.js +156 -0
- package/dist/sdd/cache/snapshot-store.js.map +1 -0
- package/dist/sdd/changes/manager.d.ts +58 -0
- package/dist/sdd/changes/manager.d.ts.map +1 -0
- package/dist/sdd/changes/manager.js +235 -0
- package/dist/sdd/changes/manager.js.map +1 -0
- package/dist/sdd/cicd/generators.d.ts +16 -0
- package/dist/sdd/cicd/generators.d.ts.map +1 -0
- package/dist/sdd/cicd/generators.js +1042 -0
- package/dist/sdd/cicd/generators.js.map +1 -0
- package/dist/sdd/code-quality/complexity.d.ts +38 -0
- package/dist/sdd/code-quality/complexity.d.ts.map +1 -0
- package/dist/sdd/code-quality/complexity.js +161 -0
- package/dist/sdd/code-quality/complexity.js.map +1 -0
- package/dist/sdd/code-quality/conventions.d.ts +33 -0
- package/dist/sdd/code-quality/conventions.d.ts.map +1 -0
- package/dist/sdd/code-quality/conventions.js +193 -0
- package/dist/sdd/code-quality/conventions.js.map +1 -0
- package/dist/sdd/code-quality/dependencies.d.ts +27 -0
- package/dist/sdd/code-quality/dependencies.d.ts.map +1 -0
- package/dist/sdd/code-quality/dependencies.js +142 -0
- package/dist/sdd/code-quality/dependencies.js.map +1 -0
- package/dist/sdd/code-quality/import-analyzer.d.ts +49 -0
- package/dist/sdd/code-quality/import-analyzer.d.ts.map +1 -0
- package/dist/sdd/code-quality/import-analyzer.js +213 -0
- package/dist/sdd/code-quality/import-analyzer.js.map +1 -0
- package/dist/sdd/code-quality/metrics.d.ts +35 -0
- package/dist/sdd/code-quality/metrics.d.ts.map +1 -0
- package/dist/sdd/code-quality/metrics.js +172 -0
- package/dist/sdd/code-quality/metrics.js.map +1 -0
- package/dist/sdd/code-quality/smells.d.ts +38 -0
- package/dist/sdd/code-quality/smells.d.ts.map +1 -0
- package/dist/sdd/code-quality/smells.js +319 -0
- package/dist/sdd/code-quality/smells.js.map +1 -0
- package/dist/sdd/code-quality/symbol-parser.d.ts +28 -0
- package/dist/sdd/code-quality/symbol-parser.d.ts.map +1 -0
- package/dist/sdd/code-quality/symbol-parser.js +230 -0
- package/dist/sdd/code-quality/symbol-parser.js.map +1 -0
- package/dist/sdd/code-quality/usage-tracker.d.ts +59 -0
- package/dist/sdd/code-quality/usage-tracker.d.ts.map +1 -0
- package/dist/sdd/code-quality/usage-tracker.js +402 -0
- package/dist/sdd/code-quality/usage-tracker.js.map +1 -0
- package/dist/sdd/code-quality/utils.d.ts +6 -0
- package/dist/sdd/code-quality/utils.d.ts.map +1 -0
- package/dist/sdd/code-quality/utils.js +14 -0
- package/dist/sdd/code-quality/utils.js.map +1 -0
- package/dist/sdd/codegen/generator.d.ts +42 -0
- package/dist/sdd/codegen/generator.d.ts.map +1 -0
- package/dist/sdd/codegen/generator.js +1023 -0
- package/dist/sdd/codegen/generator.js.map +1 -0
- package/dist/sdd/constitution/validator.d.ts +37 -0
- package/dist/sdd/constitution/validator.d.ts.map +1 -0
- package/dist/sdd/constitution/validator.js +192 -0
- package/dist/sdd/constitution/validator.js.map +1 -0
- package/dist/sdd/cost/estimator.d.ts +31 -0
- package/dist/sdd/cost/estimator.d.ts.map +1 -0
- package/dist/sdd/cost/estimator.js +92 -0
- package/dist/sdd/cost/estimator.js.map +1 -0
- package/dist/sdd/coverage/tracker.d.ts +47 -0
- package/dist/sdd/coverage/tracker.d.ts.map +1 -0
- package/dist/sdd/coverage/tracker.js +251 -0
- package/dist/sdd/coverage/tracker.js.map +1 -0
- package/dist/sdd/disaster/recovery.d.ts +11 -0
- package/dist/sdd/disaster/recovery.d.ts.map +1 -0
- package/dist/sdd/disaster/recovery.js +55 -0
- package/dist/sdd/disaster/recovery.js.map +1 -0
- package/dist/sdd/discovery/adaptive.d.ts +14 -0
- package/dist/sdd/discovery/adaptive.d.ts.map +1 -0
- package/dist/sdd/discovery/adaptive.js +145 -0
- package/dist/sdd/discovery/adaptive.js.map +1 -0
- package/dist/sdd/discovery/briefing-analyzer.d.ts +66 -0
- package/dist/sdd/discovery/briefing-analyzer.d.ts.map +1 -0
- package/dist/sdd/discovery/briefing-analyzer.js +672 -0
- package/dist/sdd/discovery/briefing-analyzer.js.map +1 -0
- package/dist/sdd/discovery/briefing.d.ts +109 -0
- package/dist/sdd/discovery/briefing.d.ts.map +1 -0
- package/dist/sdd/discovery/briefing.js +617 -0
- package/dist/sdd/discovery/briefing.js.map +1 -0
- package/dist/sdd/discovery/graph-builder.d.ts +10 -0
- package/dist/sdd/discovery/graph-builder.d.ts.map +1 -0
- package/dist/sdd/discovery/graph-builder.js +510 -0
- package/dist/sdd/discovery/graph-builder.js.map +1 -0
- package/dist/sdd/documentation/generator.d.ts +7 -0
- package/dist/sdd/documentation/generator.d.ts.map +1 -0
- package/dist/sdd/documentation/generator.js +119 -0
- package/dist/sdd/documentation/generator.js.map +1 -0
- package/dist/sdd/domain/types.d.ts +460 -0
- package/dist/sdd/domain/types.d.ts.map +1 -0
- package/dist/sdd/domain/types.js +25 -0
- package/dist/sdd/domain/types.js.map +1 -0
- package/dist/sdd/drift/detector.d.ts +28 -0
- package/dist/sdd/drift/detector.d.ts.map +1 -0
- package/dist/sdd/drift/detector.js +379 -0
- package/dist/sdd/drift/detector.js.map +1 -0
- package/dist/sdd/drift/exclusion.d.ts +54 -0
- package/dist/sdd/drift/exclusion.d.ts.map +1 -0
- package/dist/sdd/drift/exclusion.js +179 -0
- package/dist/sdd/drift/exclusion.js.map +1 -0
- package/dist/sdd/drift/signals.d.ts +52 -0
- package/dist/sdd/drift/signals.d.ts.map +1 -0
- package/dist/sdd/drift/signals.js +470 -0
- package/dist/sdd/drift/signals.js.map +1 -0
- package/dist/sdd/enforcement/interceptor.d.ts +47 -0
- package/dist/sdd/enforcement/interceptor.d.ts.map +1 -0
- package/dist/sdd/enforcement/interceptor.js +365 -0
- package/dist/sdd/enforcement/interceptor.js.map +1 -0
- package/dist/sdd/enforcement/workflow-tracker.d.ts +66 -0
- package/dist/sdd/enforcement/workflow-tracker.d.ts.map +1 -0
- package/dist/sdd/enforcement/workflow-tracker.js +229 -0
- package/dist/sdd/enforcement/workflow-tracker.js.map +1 -0
- package/dist/sdd/graph/engine.d.ts +44 -0
- package/dist/sdd/graph/engine.d.ts.map +1 -0
- package/dist/sdd/graph/engine.js +203 -0
- package/dist/sdd/graph/engine.js.map +1 -0
- package/dist/sdd/graph/index.d.ts +160 -0
- package/dist/sdd/graph/index.d.ts.map +1 -0
- package/dist/sdd/graph/index.js +624 -0
- package/dist/sdd/graph/index.js.map +1 -0
- package/dist/sdd/graph/integrity-guard.d.ts +129 -0
- package/dist/sdd/graph/integrity-guard.d.ts.map +1 -0
- package/dist/sdd/graph/integrity-guard.js +263 -0
- package/dist/sdd/graph/integrity-guard.js.map +1 -0
- package/dist/sdd/graph/integrity.d.ts +79 -0
- package/dist/sdd/graph/integrity.d.ts.map +1 -0
- package/dist/sdd/graph/integrity.js +462 -0
- package/dist/sdd/graph/integrity.js.map +1 -0
- package/dist/sdd/graph/pruner.d.ts +27 -0
- package/dist/sdd/graph/pruner.d.ts.map +1 -0
- package/dist/sdd/graph/pruner.js +203 -0
- package/dist/sdd/graph/pruner.js.map +1 -0
- package/dist/sdd/graph/traverse.d.ts +43 -0
- package/dist/sdd/graph/traverse.d.ts.map +1 -0
- package/dist/sdd/graph/traverse.js +265 -0
- package/dist/sdd/graph/traverse.js.map +1 -0
- package/dist/sdd/incidents/manager.d.ts +10 -0
- package/dist/sdd/incidents/manager.d.ts.map +1 -0
- package/dist/sdd/incidents/manager.js +63 -0
- package/dist/sdd/incidents/manager.js.map +1 -0
- package/dist/sdd/knowledge/transfer.d.ts +24 -0
- package/dist/sdd/knowledge/transfer.d.ts.map +1 -0
- package/dist/sdd/knowledge/transfer.js +94 -0
- package/dist/sdd/knowledge/transfer.js.map +1 -0
- package/dist/sdd/migrations/fixes.d.ts +2 -0
- package/dist/sdd/migrations/fixes.d.ts.map +1 -0
- package/dist/sdd/migrations/fixes.js +159 -0
- package/dist/sdd/migrations/fixes.js.map +1 -0
- package/dist/sdd/migrations/index.d.ts +2 -0
- package/dist/sdd/migrations/index.d.ts.map +1 -0
- package/dist/sdd/migrations/index.js +5 -0
- package/dist/sdd/migrations/index.js.map +1 -0
- package/dist/sdd/migrations/migration-runner.d.ts +41 -0
- package/dist/sdd/migrations/migration-runner.d.ts.map +1 -0
- package/dist/sdd/migrations/migration-runner.js +91 -0
- package/dist/sdd/migrations/migration-runner.js.map +1 -0
- package/dist/sdd/monitoring/setup.d.ts +40 -0
- package/dist/sdd/monitoring/setup.d.ts.map +1 -0
- package/dist/sdd/monitoring/setup.js +177 -0
- package/dist/sdd/monitoring/setup.js.map +1 -0
- package/dist/sdd/monitoring/telemetry.d.ts +18 -0
- package/dist/sdd/monitoring/telemetry.d.ts.map +1 -0
- package/dist/sdd/monitoring/telemetry.js +37 -0
- package/dist/sdd/monitoring/telemetry.js.map +1 -0
- package/dist/sdd/patterns/anti-patterns.d.ts +21 -0
- package/dist/sdd/patterns/anti-patterns.d.ts.map +1 -0
- package/dist/sdd/patterns/anti-patterns.js +286 -0
- package/dist/sdd/patterns/anti-patterns.js.map +1 -0
- package/dist/sdd/patterns/ast-clones.d.ts +23 -0
- package/dist/sdd/patterns/ast-clones.d.ts.map +1 -0
- package/dist/sdd/patterns/ast-clones.js +171 -0
- package/dist/sdd/patterns/ast-clones.js.map +1 -0
- package/dist/sdd/patterns/config-drift.d.ts +16 -0
- package/dist/sdd/patterns/config-drift.d.ts.map +1 -0
- package/dist/sdd/patterns/config-drift.js +322 -0
- package/dist/sdd/patterns/config-drift.js.map +1 -0
- package/dist/sdd/patterns/contradictions.d.ts +38 -0
- package/dist/sdd/patterns/contradictions.d.ts.map +1 -0
- package/dist/sdd/patterns/contradictions.js +237 -0
- package/dist/sdd/patterns/contradictions.js.map +1 -0
- package/dist/sdd/patterns/learner.d.ts +49 -0
- package/dist/sdd/patterns/learner.d.ts.map +1 -0
- package/dist/sdd/patterns/learner.js +226 -0
- package/dist/sdd/patterns/learner.js.map +1 -0
- package/dist/sdd/permissions/access.d.ts +69 -0
- package/dist/sdd/permissions/access.d.ts.map +1 -0
- package/dist/sdd/permissions/access.js +333 -0
- package/dist/sdd/permissions/access.js.map +1 -0
- package/dist/sdd/persistence/repository.d.ts +60 -0
- package/dist/sdd/persistence/repository.d.ts.map +1 -0
- package/dist/sdd/persistence/repository.js +96 -0
- package/dist/sdd/persistence/repository.js.map +1 -0
- package/dist/sdd/persistence/sqlite.d.ts +122 -0
- package/dist/sdd/persistence/sqlite.d.ts.map +1 -0
- package/dist/sdd/persistence/sqlite.js +602 -0
- package/dist/sdd/persistence/sqlite.js.map +1 -0
- package/dist/sdd/persistence/yaml.d.ts +41 -0
- package/dist/sdd/persistence/yaml.d.ts.map +1 -0
- package/dist/sdd/persistence/yaml.js +382 -0
- package/dist/sdd/persistence/yaml.js.map +1 -0
- package/dist/sdd/promises/classifier.d.ts +48 -0
- package/dist/sdd/promises/classifier.d.ts.map +1 -0
- package/dist/sdd/promises/classifier.js +215 -0
- package/dist/sdd/promises/classifier.js.map +1 -0
- package/dist/sdd/promises/tracker.d.ts +20 -0
- package/dist/sdd/promises/tracker.d.ts.map +1 -0
- package/dist/sdd/promises/tracker.js +204 -0
- package/dist/sdd/promises/tracker.js.map +1 -0
- package/dist/sdd/quality/scorer.d.ts +44 -0
- package/dist/sdd/quality/scorer.d.ts.map +1 -0
- package/dist/sdd/quality/scorer.js +216 -0
- package/dist/sdd/quality/scorer.js.map +1 -0
- package/dist/sdd/rollback/manager.d.ts +45 -0
- package/dist/sdd/rollback/manager.d.ts.map +1 -0
- package/dist/sdd/rollback/manager.js +266 -0
- package/dist/sdd/rollback/manager.js.map +1 -0
- package/dist/sdd/session/handoff.d.ts +52 -0
- package/dist/sdd/session/handoff.d.ts.map +1 -0
- package/dist/sdd/session/handoff.js +264 -0
- package/dist/sdd/session/handoff.js.map +1 -0
- package/dist/sdd/sla/tracker.d.ts +11 -0
- package/dist/sdd/sla/tracker.d.ts.map +1 -0
- package/dist/sdd/sla/tracker.js +52 -0
- package/dist/sdd/sla/tracker.js.map +1 -0
- package/dist/sdd/sync/git-sync.d.ts +61 -0
- package/dist/sdd/sync/git-sync.d.ts.map +1 -0
- package/dist/sdd/sync/git-sync.js +297 -0
- package/dist/sdd/sync/git-sync.js.map +1 -0
- package/dist/sdd/toggle/state.d.ts +8 -0
- package/dist/sdd/toggle/state.d.ts.map +1 -0
- package/dist/sdd/toggle/state.js +32 -0
- package/dist/sdd/toggle/state.js.map +1 -0
- package/dist/sdd/transactions/manager.d.ts +12 -0
- package/dist/sdd/transactions/manager.d.ts.map +1 -0
- package/dist/sdd/transactions/manager.js +80 -0
- package/dist/sdd/transactions/manager.js.map +1 -0
- package/dist/sdd/validation/coverage-index.d.ts +117 -0
- package/dist/sdd/validation/coverage-index.d.ts.map +1 -0
- package/dist/sdd/validation/coverage-index.js +251 -0
- package/dist/sdd/validation/coverage-index.js.map +1 -0
- package/dist/sdd/validation/executable.d.ts +26 -0
- package/dist/sdd/validation/executable.d.ts.map +1 -0
- package/dist/sdd/validation/executable.js +122 -0
- package/dist/sdd/validation/executable.js.map +1 -0
- package/dist/sdd/validation/smart-validator.d.ts +53 -0
- package/dist/sdd/validation/smart-validator.d.ts.map +1 -0
- package/dist/sdd/validation/smart-validator.js +347 -0
- package/dist/sdd/validation/smart-validator.js.map +1 -0
- package/dist/sdd/validation/validator.d.ts +39 -0
- package/dist/sdd/validation/validator.d.ts.map +1 -0
- package/dist/sdd/validation/validator.js +512 -0
- package/dist/sdd/validation/validator.js.map +1 -0
- package/dist/sdd/workflow/exporter.d.ts +36 -0
- package/dist/sdd/workflow/exporter.d.ts.map +1 -0
- package/dist/sdd/workflow/exporter.js +112 -0
- package/dist/sdd/workflow/exporter.js.map +1 -0
- package/dist/sdd/workflows/ab-testing.d.ts +18 -0
- package/dist/sdd/workflows/ab-testing.d.ts.map +1 -0
- package/dist/sdd/workflows/ab-testing.js +67 -0
- package/dist/sdd/workflows/ab-testing.js.map +1 -0
- package/dist/sdd/workflows/bug-fix.d.ts +13 -0
- package/dist/sdd/workflows/bug-fix.d.ts.map +1 -0
- package/dist/sdd/workflows/bug-fix.js +65 -0
- package/dist/sdd/workflows/bug-fix.js.map +1 -0
- package/dist/sdd/workflows/data-migration.d.ts +14 -0
- package/dist/sdd/workflows/data-migration.d.ts.map +1 -0
- package/dist/sdd/workflows/data-migration.js +68 -0
- package/dist/sdd/workflows/data-migration.js.map +1 -0
- package/dist/sdd/workflows/deprecation.d.ts +15 -0
- package/dist/sdd/workflows/deprecation.d.ts.map +1 -0
- package/dist/sdd/workflows/deprecation.js +68 -0
- package/dist/sdd/workflows/deprecation.js.map +1 -0
- package/dist/sdd/workflows/feature-flags.d.ts +14 -0
- package/dist/sdd/workflows/feature-flags.d.ts.map +1 -0
- package/dist/sdd/workflows/feature-flags.js +73 -0
- package/dist/sdd/workflows/feature-flags.js.map +1 -0
- package/dist/sdd/workflows/hotfix.d.ts +13 -0
- package/dist/sdd/workflows/hotfix.d.ts.map +1 -0
- package/dist/sdd/workflows/hotfix.js +67 -0
- package/dist/sdd/workflows/hotfix.js.map +1 -0
- package/dist/sdd/workflows/multi-tenancy.d.ts +13 -0
- package/dist/sdd/workflows/multi-tenancy.d.ts.map +1 -0
- package/dist/sdd/workflows/multi-tenancy.js +68 -0
- package/dist/sdd/workflows/multi-tenancy.js.map +1 -0
- package/dist/sdd/workflows/onboarding.d.ts +7 -0
- package/dist/sdd/workflows/onboarding.d.ts.map +1 -0
- package/dist/sdd/workflows/onboarding.js +43 -0
- package/dist/sdd/workflows/onboarding.js.map +1 -0
- package/dist/sdd/workflows/refactoring.d.ts +14 -0
- package/dist/sdd/workflows/refactoring.d.ts.map +1 -0
- package/dist/sdd/workflows/refactoring.js +73 -0
- package/dist/sdd/workflows/refactoring.js.map +1 -0
- package/dist/server/events.d.ts +64 -0
- package/dist/server/events.d.ts.map +1 -0
- package/dist/server/events.js +149 -0
- package/dist/server/events.js.map +1 -0
- package/dist/server/server.d.ts +33 -0
- package/dist/server/server.d.ts.map +1 -0
- package/dist/server/server.js +1019 -0
- package/dist/server/server.js.map +1 -0
- package/marketplace.json +39 -0
- package/package.json +65 -0
- package/src/code-intelligence/analyzer.ts +350 -0
- package/src/code-intelligence/ast/cache.ts +61 -0
- package/src/code-intelligence/ast/common.ts +62 -0
- package/src/code-intelligence/ast/component.ts +39 -0
- package/src/code-intelligence/ast/fallback.ts +44 -0
- package/src/code-intelligence/ast/index.ts +4 -0
- package/src/code-intelligence/ast/ir.ts +91 -0
- package/src/code-intelligence/ast/metrics.ts +65 -0
- package/src/code-intelligence/ast/registry.ts +28 -0
- package/src/code-intelligence/ast/tree-sitter.ts +226 -0
- package/src/code-intelligence/ast/typescript.ts +140 -0
- package/src/index.ts +22 -0
- package/src/mcp/server.ts +77 -0
- package/src/opencode/hooks.ts +728 -0
- package/src/opencode/router/categories.ts +192 -0
- package/src/opencode/router/embeddings.ts +149 -0
- package/src/opencode/router/graph-state-snapshot.ts +163 -0
- package/src/opencode/router/index.ts +44 -0
- package/src/opencode/router/intent-classifier.ts +140 -0
- package/src/opencode/router/semantic-nudge.ts +89 -0
- package/src/opencode/router/state-gate.ts +192 -0
- package/src/opencode/router/tool-embeddings.ts +162 -0
- package/src/opencode/router/tool-registry.ts +135 -0
- package/src/opencode/router/tool-taxonomy.ts +284 -0
- package/src/opencode/router/tools-composite.ts +685 -0
- package/src/opencode/shell-hooks.ts +115 -0
- package/src/opencode/system-prompt.ts +617 -0
- package/src/opencode/tools.ts +4102 -0
- package/src/opencode/workflows/chains.ts +205 -0
- package/src/opencode/workflows/executor.ts +172 -0
- package/src/opencode/workflows/index.ts +21 -0
- package/src/opencode/workflows/tools-workflow.ts +91 -0
- package/src/opencode/workflows/types.ts +42 -0
- package/src/sdd/analysis/compliance.ts +279 -0
- package/src/sdd/analysis/scalability.ts +97 -0
- package/src/sdd/analysis/security.ts +135 -0
- package/src/sdd/brownfield/scanner.ts +276 -0
- package/src/sdd/cache/manager.ts +899 -0
- package/src/sdd/cache/snapshot-store.ts +185 -0
- package/src/sdd/changes/manager.ts +326 -0
- package/src/sdd/cicd/generators.ts +1095 -0
- package/src/sdd/code-quality/complexity.ts +235 -0
- package/src/sdd/code-quality/conventions.ts +220 -0
- package/src/sdd/code-quality/dependencies.ts +203 -0
- package/src/sdd/code-quality/import-analyzer.ts +294 -0
- package/src/sdd/code-quality/metrics.ts +232 -0
- package/src/sdd/code-quality/smells.ts +415 -0
- package/src/sdd/code-quality/symbol-parser.ts +335 -0
- package/src/sdd/code-quality/usage-tracker.ts +527 -0
- package/src/sdd/code-quality/utils.ts +13 -0
- package/src/sdd/codegen/generator.ts +1181 -0
- package/src/sdd/constitution/validator.ts +253 -0
- package/src/sdd/cost/estimator.ts +147 -0
- package/src/sdd/coverage/tracker.ts +342 -0
- package/src/sdd/disaster/recovery.ts +79 -0
- package/src/sdd/discovery/adaptive.ts +167 -0
- package/src/sdd/discovery/briefing-analyzer.ts +802 -0
- package/src/sdd/discovery/briefing.ts +770 -0
- package/src/sdd/discovery/graph-builder.ts +598 -0
- package/src/sdd/documentation/generator.ts +158 -0
- package/src/sdd/domain/types.ts +658 -0
- package/src/sdd/drift/detector.ts +465 -0
- package/src/sdd/drift/exclusion.ts +223 -0
- package/src/sdd/drift/signals.ts +577 -0
- package/src/sdd/enforcement/interceptor.ts +444 -0
- package/src/sdd/enforcement/workflow-tracker.ts +263 -0
- package/src/sdd/graph/engine.ts +277 -0
- package/src/sdd/graph/index.ts +700 -0
- package/src/sdd/graph/integrity-guard.ts +348 -0
- package/src/sdd/graph/integrity.ts +628 -0
- package/src/sdd/graph/pruner.ts +221 -0
- package/src/sdd/graph/traverse.ts +331 -0
- package/src/sdd/incidents/manager.ts +87 -0
- package/src/sdd/knowledge/transfer.ts +140 -0
- package/src/sdd/migrations/fixes.ts +154 -0
- package/src/sdd/migrations/index.ts +14 -0
- package/src/sdd/migrations/migration-runner.ts +118 -0
- package/src/sdd/monitoring/setup.ts +237 -0
- package/src/sdd/monitoring/telemetry.ts +44 -0
- package/src/sdd/patterns/anti-patterns.ts +333 -0
- package/src/sdd/patterns/ast-clones.ts +214 -0
- package/src/sdd/patterns/config-drift.ts +346 -0
- package/src/sdd/patterns/contradictions.ts +323 -0
- package/src/sdd/patterns/learner.ts +266 -0
- package/src/sdd/permissions/access.ts +478 -0
- package/src/sdd/persistence/repository.ts +166 -0
- package/src/sdd/persistence/sqlite.ts +703 -0
- package/src/sdd/persistence/yaml.ts +409 -0
- package/src/sdd/promises/classifier.ts +253 -0
- package/src/sdd/promises/tracker.ts +258 -0
- package/src/sdd/quality/scorer.ts +263 -0
- package/src/sdd/rollback/manager.ts +361 -0
- package/src/sdd/session/handoff.ts +354 -0
- package/src/sdd/sla/tracker.ts +68 -0
- package/src/sdd/sync/git-sync.ts +401 -0
- package/src/sdd/toggle/state.ts +38 -0
- package/src/sdd/transactions/manager.ts +93 -0
- package/src/sdd/validation/coverage-index.ts +339 -0
- package/src/sdd/validation/executable.ts +127 -0
- package/src/sdd/validation/smart-validator.ts +470 -0
- package/src/sdd/validation/validator.ts +641 -0
- package/src/sdd/workflow/exporter.ts +169 -0
- package/src/sdd/workflows/ab-testing.ts +90 -0
- package/src/sdd/workflows/bug-fix.ts +81 -0
- package/src/sdd/workflows/data-migration.ts +86 -0
- package/src/sdd/workflows/deprecation.ts +87 -0
- package/src/sdd/workflows/feature-flags.ts +91 -0
- package/src/sdd/workflows/hotfix.ts +83 -0
- package/src/sdd/workflows/multi-tenancy.ts +84 -0
- package/src/sdd/workflows/onboarding.ts +82 -0
- package/src/sdd/workflows/refactoring.ts +90 -0
- package/src/server/events.ts +184 -0
- package/src/server/server.ts +1088 -0
|
@@ -0,0 +1,703 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
KnowledgeGraph,
|
|
3
|
+
AnyNode,
|
|
4
|
+
NodeType,
|
|
5
|
+
NodeStatus,
|
|
6
|
+
Relationship,
|
|
7
|
+
RelationshipType,
|
|
8
|
+
} from "../domain/types.js"
|
|
9
|
+
import { GraphIndices } from "../graph/index.js"
|
|
10
|
+
import { ensureDir } from "./yaml.js"
|
|
11
|
+
import { join } from "path"
|
|
12
|
+
import { getCacheManager } from "../cache/manager.js"
|
|
13
|
+
import type { GraphRepository } from "./repository.js"
|
|
14
|
+
import { recordLegitimateSave, validateGraphIntegrity } from "../graph/integrity-guard.js"
|
|
15
|
+
|
|
16
|
+
let dbCounter = 0
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* SQLite-backed graph repository.
|
|
20
|
+
* Uses Bun's built-in SQLite for storage with native indexing.
|
|
21
|
+
*
|
|
22
|
+
* Benefits over YAML:
|
|
23
|
+
* - O(log n) queries by type/status/id (indexed)
|
|
24
|
+
* - Atomic writes via transactions
|
|
25
|
+
* - Lazy loading: can query subsets without loading full graph
|
|
26
|
+
* - Better concurrency for multi-process scenarios
|
|
27
|
+
* - Handles 10,000+ nodes efficiently
|
|
28
|
+
*/
|
|
29
|
+
export class SqliteGraphRepository {
|
|
30
|
+
private baseDir: string
|
|
31
|
+
private dbPath: string
|
|
32
|
+
private db: any
|
|
33
|
+
private static cache: Map<string, { graph: KnowledgeGraph; indices: GraphIndices }> = new Map()
|
|
34
|
+
|
|
35
|
+
constructor(projectDir: string) {
|
|
36
|
+
this.baseDir = join(projectDir, ".sdd")
|
|
37
|
+
this.dbPath = join(this.baseDir, "graph.db")
|
|
38
|
+
this.db = null
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
private getDb(): any {
|
|
42
|
+
if (this.db) return this.db
|
|
43
|
+
|
|
44
|
+
ensureDir(this.baseDir)
|
|
45
|
+
|
|
46
|
+
// Use Bun's built-in SQLite
|
|
47
|
+
const { Database } = require("bun:sqlite")
|
|
48
|
+
this.db = new Database(this.dbPath)
|
|
49
|
+
|
|
50
|
+
// Enable WAL mode for better concurrency
|
|
51
|
+
this.db.exec("PRAGMA journal_mode=WAL")
|
|
52
|
+
this.db.exec("PRAGMA synchronous=NORMAL")
|
|
53
|
+
|
|
54
|
+
// Create tables if they don't exist
|
|
55
|
+
this.db.exec(`
|
|
56
|
+
CREATE TABLE IF NOT EXISTS graph_metadata (
|
|
57
|
+
key TEXT PRIMARY KEY,
|
|
58
|
+
value TEXT
|
|
59
|
+
);
|
|
60
|
+
|
|
61
|
+
CREATE TABLE IF NOT EXISTS nodes (
|
|
62
|
+
id TEXT PRIMARY KEY,
|
|
63
|
+
type TEXT NOT NULL,
|
|
64
|
+
name TEXT NOT NULL,
|
|
65
|
+
status TEXT NOT NULL,
|
|
66
|
+
version INTEGER DEFAULT 1,
|
|
67
|
+
description TEXT,
|
|
68
|
+
metadata_json TEXT,
|
|
69
|
+
created_at TEXT,
|
|
70
|
+
updated_at TEXT,
|
|
71
|
+
created_by TEXT,
|
|
72
|
+
change_id TEXT,
|
|
73
|
+
previous_version INTEGER
|
|
74
|
+
);
|
|
75
|
+
|
|
76
|
+
CREATE INDEX IF NOT EXISTS idx_nodes_type ON nodes(type);
|
|
77
|
+
CREATE INDEX IF NOT EXISTS idx_nodes_status ON nodes(status);
|
|
78
|
+
CREATE INDEX IF NOT EXISTS idx_nodes_name ON nodes(name);
|
|
79
|
+
|
|
80
|
+
CREATE TABLE IF NOT EXISTS relationships (
|
|
81
|
+
id TEXT PRIMARY KEY,
|
|
82
|
+
from_id TEXT NOT NULL,
|
|
83
|
+
to_id TEXT NOT NULL,
|
|
84
|
+
type TEXT NOT NULL,
|
|
85
|
+
metadata_json TEXT
|
|
86
|
+
);
|
|
87
|
+
|
|
88
|
+
CREATE INDEX IF NOT EXISTS idx_rels_from ON relationships(from_id);
|
|
89
|
+
CREATE INDEX IF NOT EXISTS idx_rels_to ON relationships(to_id);
|
|
90
|
+
CREATE INDEX IF NOT EXISTS idx_rels_type ON relationships(type);
|
|
91
|
+
CREATE INDEX IF NOT EXISTS idx_rels_from_type ON relationships(from_id, type);
|
|
92
|
+
CREATE INDEX IF NOT EXISTS idx_rels_to_type ON relationships(to_id, type);
|
|
93
|
+
`)
|
|
94
|
+
|
|
95
|
+
return this.db
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
isInitialized(): boolean {
|
|
99
|
+
try {
|
|
100
|
+
const db = this.getDb()
|
|
101
|
+
const result = db.query("SELECT value FROM graph_metadata WHERE key = 'project_id'").get()
|
|
102
|
+
return !!result
|
|
103
|
+
} catch {
|
|
104
|
+
return false
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
loadGraph(): KnowledgeGraph {
|
|
109
|
+
// Check cache with revalidation
|
|
110
|
+
const cached = SqliteGraphRepository.cache.get(this.dbPath)
|
|
111
|
+
if (cached) {
|
|
112
|
+
// Revalidation: check if db was modified externally
|
|
113
|
+
const cacheMgr = getCacheManager(require("path").dirname(this.baseDir))
|
|
114
|
+
if (!cacheMgr.checkCrossProcessInvalidation(this.dbPath)) {
|
|
115
|
+
return structuredClone(cached.graph)
|
|
116
|
+
}
|
|
117
|
+
// DB was modified externally, invalidate cache
|
|
118
|
+
SqliteGraphRepository.cache.delete(this.dbPath)
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
const db = this.getDb()
|
|
122
|
+
|
|
123
|
+
// Load metadata
|
|
124
|
+
const metaRows = db.query("SELECT key, value FROM graph_metadata").all()
|
|
125
|
+
const metaMap = new Map<string, string>()
|
|
126
|
+
for (const row of metaRows) {
|
|
127
|
+
metaMap.set((row as any).key, (row as any).value)
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
// Load all nodes
|
|
131
|
+
const nodeRows = db.query("SELECT * FROM nodes").all() as any[]
|
|
132
|
+
const nodes: AnyNode[] = nodeRows.map(row => ({
|
|
133
|
+
id: row.id,
|
|
134
|
+
type: row.type,
|
|
135
|
+
name: row.name,
|
|
136
|
+
description: row.description || undefined,
|
|
137
|
+
status: row.status,
|
|
138
|
+
version: row.version,
|
|
139
|
+
metadata: row.metadata_json ? JSON.parse(row.metadata_json) : {},
|
|
140
|
+
created_at: row.created_at,
|
|
141
|
+
updated_at: row.updated_at,
|
|
142
|
+
created_by: row.created_by || undefined,
|
|
143
|
+
change_id: row.change_id || undefined,
|
|
144
|
+
previous_version: row.previous_version || undefined,
|
|
145
|
+
})) as AnyNode[]
|
|
146
|
+
|
|
147
|
+
// Load all relationships
|
|
148
|
+
const relRows = db.query("SELECT * FROM relationships").all() as any[]
|
|
149
|
+
const relationships: Relationship[] = relRows.map(row => ({
|
|
150
|
+
id: row.id,
|
|
151
|
+
from: row.from_id,
|
|
152
|
+
to: row.to_id,
|
|
153
|
+
type: row.type,
|
|
154
|
+
metadata: row.metadata_json ? JSON.parse(row.metadata_json) : {},
|
|
155
|
+
}))
|
|
156
|
+
|
|
157
|
+
const graph: KnowledgeGraph = {
|
|
158
|
+
version: metaMap.get("version") || "1.0.0",
|
|
159
|
+
project_id: metaMap.get("project_id") || "unknown",
|
|
160
|
+
nodes,
|
|
161
|
+
relationships,
|
|
162
|
+
metadata: {
|
|
163
|
+
created_at: metaMap.get("created_at") || new Date().toISOString(),
|
|
164
|
+
updated_at: metaMap.get("updated_at") || new Date().toISOString(),
|
|
165
|
+
sdd_version: metaMap.get("sdd_version") || "1.0.0",
|
|
166
|
+
},
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
// Build indices and cache
|
|
170
|
+
const indices = GraphIndices.from(graph)
|
|
171
|
+
SqliteGraphRepository.cache.set(this.dbPath, { graph, indices })
|
|
172
|
+
|
|
173
|
+
// Anti-bypass: check for out-of-band modifications
|
|
174
|
+
const projectDir = require("path").dirname(this.baseDir)
|
|
175
|
+
try {
|
|
176
|
+
const tamperResult = validateGraphIntegrity(projectDir, graph)
|
|
177
|
+
if (tamperResult.tampered) {
|
|
178
|
+
;(graph.metadata as any).__tamper_warning = tamperResult.reason
|
|
179
|
+
}
|
|
180
|
+
} catch {}
|
|
181
|
+
|
|
182
|
+
return structuredClone(graph)
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
saveGraph(graph: KnowledgeGraph): void {
|
|
186
|
+
const db = this.getDb()
|
|
187
|
+
|
|
188
|
+
// Use transaction for atomicity
|
|
189
|
+
db.exec("BEGIN TRANSACTION")
|
|
190
|
+
|
|
191
|
+
try {
|
|
192
|
+
// Differential persistence: update only changed rows and delete only
|
|
193
|
+
// rows that disappeared. This keeps SQLite useful for large graphs.
|
|
194
|
+
const upsertMeta = db.prepare(
|
|
195
|
+
"INSERT INTO graph_metadata (key, value) VALUES (?, ?) ON CONFLICT(key) DO UPDATE SET value = excluded.value",
|
|
196
|
+
)
|
|
197
|
+
upsertMeta.run("project_id", graph.project_id)
|
|
198
|
+
upsertMeta.run("version", graph.version)
|
|
199
|
+
upsertMeta.run("created_at", graph.metadata.created_at)
|
|
200
|
+
upsertMeta.run("updated_at", graph.metadata.updated_at)
|
|
201
|
+
upsertMeta.run("sdd_version", graph.metadata.sdd_version)
|
|
202
|
+
|
|
203
|
+
// Save nodes in batches for performance
|
|
204
|
+
const upsertNode = db.prepare(`
|
|
205
|
+
INSERT INTO nodes (id, type, name, status, version, description, metadata_json, created_at, updated_at, created_by, change_id, previous_version)
|
|
206
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
207
|
+
ON CONFLICT(id) DO UPDATE SET
|
|
208
|
+
type=excluded.type, name=excluded.name, status=excluded.status,
|
|
209
|
+
version=excluded.version, description=excluded.description,
|
|
210
|
+
metadata_json=excluded.metadata_json, updated_at=excluded.updated_at,
|
|
211
|
+
created_by=excluded.created_by, change_id=excluded.change_id,
|
|
212
|
+
previous_version=excluded.previous_version
|
|
213
|
+
`)
|
|
214
|
+
|
|
215
|
+
for (const node of graph.nodes) {
|
|
216
|
+
upsertNode.run(
|
|
217
|
+
node.id,
|
|
218
|
+
node.type,
|
|
219
|
+
node.name,
|
|
220
|
+
node.status,
|
|
221
|
+
node.version,
|
|
222
|
+
node.description || null,
|
|
223
|
+
JSON.stringify(node.metadata),
|
|
224
|
+
node.created_at,
|
|
225
|
+
node.updated_at,
|
|
226
|
+
node.created_by || null,
|
|
227
|
+
node.change_id || null,
|
|
228
|
+
node.previous_version || null,
|
|
229
|
+
)
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
// Save relationships in batches
|
|
233
|
+
const upsertRel = db.prepare(`
|
|
234
|
+
INSERT INTO relationships (id, from_id, to_id, type, metadata_json)
|
|
235
|
+
VALUES (?, ?, ?, ?, ?)
|
|
236
|
+
ON CONFLICT(id) DO UPDATE SET
|
|
237
|
+
from_id=excluded.from_id, to_id=excluded.to_id,
|
|
238
|
+
type=excluded.type, metadata_json=excluded.metadata_json
|
|
239
|
+
`)
|
|
240
|
+
|
|
241
|
+
for (const rel of graph.relationships) {
|
|
242
|
+
upsertRel.run(
|
|
243
|
+
rel.id,
|
|
244
|
+
rel.from,
|
|
245
|
+
rel.to,
|
|
246
|
+
rel.type,
|
|
247
|
+
JSON.stringify(rel.metadata),
|
|
248
|
+
)
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
const nodeIds = new Set(graph.nodes.map((node) => node.id))
|
|
252
|
+
const existingNodeIds = db.query("SELECT id FROM nodes").all() as Array<{ id: string }>
|
|
253
|
+
const deleteNode = db.prepare("DELETE FROM nodes WHERE id = ?")
|
|
254
|
+
for (const row of existingNodeIds) if (!nodeIds.has(row.id)) deleteNode.run(row.id)
|
|
255
|
+
|
|
256
|
+
const relationshipIds = new Set(graph.relationships.map((relationship) => relationship.id))
|
|
257
|
+
const existingRelationshipIds = db.query("SELECT id FROM relationships").all() as Array<{ id: string }>
|
|
258
|
+
const deleteRelationship = db.prepare("DELETE FROM relationships WHERE id = ?")
|
|
259
|
+
for (const row of existingRelationshipIds) if (!relationshipIds.has(row.id)) deleteRelationship.run(row.id)
|
|
260
|
+
|
|
261
|
+
db.exec("COMMIT")
|
|
262
|
+
} catch (e) {
|
|
263
|
+
db.exec("ROLLBACK")
|
|
264
|
+
throw e
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
// Compare against the immutable cached snapshot before replacing it.
|
|
268
|
+
const cached = SqliteGraphRepository.cache.get(this.dbPath)
|
|
269
|
+
const { computeDirtyState } = require("../graph/index.js")
|
|
270
|
+
const snapshot = structuredClone(graph) as KnowledgeGraph
|
|
271
|
+
const dirty = computeDirtyState(cached?.graph || null, snapshot)
|
|
272
|
+
const indices = GraphIndices.from(snapshot)
|
|
273
|
+
SqliteGraphRepository.cache.set(this.dbPath, { graph: snapshot, indices })
|
|
274
|
+
/*
|
|
275
|
+
if (cached) {
|
|
276
|
+
const oldGraph = cached.graph
|
|
277
|
+
const { computeDirtyState } = require("../graph/index.js")
|
|
278
|
+
const dirty = computeDirtyState(oldGraph, graph)
|
|
279
|
+
|
|
280
|
+
if (!dirty.allChanged && dirty.dirtyNodeIds.size <= 50) {
|
|
281
|
+
// Incremental update
|
|
282
|
+
for (const nodeId of dirty.dirtyNodeIds) {
|
|
283
|
+
const oldNode = oldGraph.nodes.find(n => n.id === nodeId)
|
|
284
|
+
const newNode = graph.nodes.find(n => n.id === nodeId)
|
|
285
|
+
if (oldNode && newNode) {
|
|
286
|
+
cached.indices.updateNode(oldNode, newNode)
|
|
287
|
+
} else if (newNode) {
|
|
288
|
+
cached.indices.addNode(newNode)
|
|
289
|
+
} else if (oldNode) {
|
|
290
|
+
cached.indices.removeNode(nodeId)
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
const oldRelKeys = new Set(oldGraph.relationships.map(r => `${r.from}||${r.to}||${r.type}`))
|
|
294
|
+
const newRelKeys = new Set(graph.relationships.map(r => `${r.from}||${r.to}||${r.type}`))
|
|
295
|
+
for (const rel of graph.relationships) {
|
|
296
|
+
const key = `${rel.from}||${rel.to}||${rel.type}`
|
|
297
|
+
if (!oldRelKeys.has(key)) cached.indices.addRelationship(rel)
|
|
298
|
+
}
|
|
299
|
+
for (const rel of oldGraph.relationships) {
|
|
300
|
+
const key = `${rel.from}||${rel.to}||${rel.type}`
|
|
301
|
+
if (!newRelKeys.has(key)) cached.indices.removeRelationship(rel)
|
|
302
|
+
}
|
|
303
|
+
} else {
|
|
304
|
+
// Full rebuild needed
|
|
305
|
+
SqliteGraphRepository.cache.delete(this.dbPath)
|
|
306
|
+
const indices = GraphIndices.from(graph)
|
|
307
|
+
SqliteGraphRepository.cache.set(this.dbPath, { graph, indices })
|
|
308
|
+
}
|
|
309
|
+
} else {
|
|
310
|
+
const indices = GraphIndices.from(graph)
|
|
311
|
+
SqliteGraphRepository.cache.set(this.dbPath, { graph, indices })
|
|
312
|
+
}
|
|
313
|
+
*/
|
|
314
|
+
|
|
315
|
+
// Update incremental hash
|
|
316
|
+
const cacheMgr = getCacheManager(require("path").dirname(this.baseDir))
|
|
317
|
+
cacheMgr.initGraphHash(graph.nodes.length, graph.relationships.length)
|
|
318
|
+
|
|
319
|
+
// A: Granular invalidation — only invalidate caches for changed types
|
|
320
|
+
if (dirty.allChanged || dirty.dirtyTypes.size > 10) {
|
|
321
|
+
// Too many types changed — full invalidation is faster
|
|
322
|
+
cacheMgr.invalidateAll()
|
|
323
|
+
} else if (dirty.dirtyTypes.size > 0) {
|
|
324
|
+
// A: Partial invalidation — only affected types
|
|
325
|
+
cacheMgr.invalidatePartial([...dirty.dirtyTypes])
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
// G: Save graph snapshot to disk for cross-session restore
|
|
329
|
+
cacheMgr.saveGraphSnapshot(graph)
|
|
330
|
+
|
|
331
|
+
// Anti-bypass: record legitimate save for integrity tracking
|
|
332
|
+
const projectDir = require("path").dirname(this.baseDir)
|
|
333
|
+
try {
|
|
334
|
+
recordLegitimateSave(projectDir, graph)
|
|
335
|
+
} catch {}
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
getIndices(): GraphIndices {
|
|
339
|
+
const cached = SqliteGraphRepository.cache.get(this.dbPath)
|
|
340
|
+
if (cached) return cached.indices
|
|
341
|
+
|
|
342
|
+
const graph = this.loadGraph()
|
|
343
|
+
return GraphIndices.from(graph)
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
getStorageType(): "sqlite" {
|
|
347
|
+
return "sqlite"
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
isCacheValid(): boolean {
|
|
351
|
+
return SqliteGraphRepository.cache.has(this.dbPath)
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
invalidateCache(): void {
|
|
355
|
+
SqliteGraphRepository.cache.delete(this.dbPath)
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
ensureSddDir(): void {
|
|
359
|
+
ensureDir(this.baseDir)
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
createProject(projectId: string, name: string, description?: string): KnowledgeGraph {
|
|
363
|
+
this.ensureSddDir()
|
|
364
|
+
const now = new Date().toISOString()
|
|
365
|
+
const graph: KnowledgeGraph = {
|
|
366
|
+
version: "1.0.0",
|
|
367
|
+
project_id: projectId,
|
|
368
|
+
nodes: [
|
|
369
|
+
{
|
|
370
|
+
id: projectId,
|
|
371
|
+
type: "project",
|
|
372
|
+
name,
|
|
373
|
+
description,
|
|
374
|
+
status: "DRAFT",
|
|
375
|
+
version: 1,
|
|
376
|
+
metadata: { name, description },
|
|
377
|
+
created_at: now,
|
|
378
|
+
updated_at: now,
|
|
379
|
+
},
|
|
380
|
+
],
|
|
381
|
+
relationships: [],
|
|
382
|
+
metadata: {
|
|
383
|
+
created_at: now,
|
|
384
|
+
updated_at: now,
|
|
385
|
+
sdd_version: "1.0.0",
|
|
386
|
+
},
|
|
387
|
+
}
|
|
388
|
+
this.saveGraph(graph)
|
|
389
|
+
return graph
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
createSnapshot(description: string): string {
|
|
393
|
+
const graph = this.loadGraph()
|
|
394
|
+
const timestamp = new Date().toISOString().replace(/[:.]/g, "-")
|
|
395
|
+
const snapshotId = `snapshot-${timestamp}`
|
|
396
|
+
const snapshotPath = join(this.baseDir, "snapshots", `${snapshotId}.json`)
|
|
397
|
+
|
|
398
|
+
ensureDir(join(this.baseDir, "snapshots"))
|
|
399
|
+
const { writeJson } = require("./yaml.js")
|
|
400
|
+
writeJson(snapshotPath, {
|
|
401
|
+
id: snapshotId,
|
|
402
|
+
timestamp: new Date().toISOString(),
|
|
403
|
+
description,
|
|
404
|
+
graph_state: graph,
|
|
405
|
+
})
|
|
406
|
+
|
|
407
|
+
return snapshotId
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
listSnapshots(): string[] {
|
|
411
|
+
const { readdirSync, existsSync } = require("fs")
|
|
412
|
+
const snapDir = join(this.baseDir, "snapshots")
|
|
413
|
+
if (!existsSync(snapDir)) return []
|
|
414
|
+
return readdirSync(snapDir)
|
|
415
|
+
.filter((f: string) => f.endsWith(".json"))
|
|
416
|
+
.map((f: string) => join(snapDir, f))
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
migrateTo(target: "yaml" | "sqlite", projectDir: string): GraphRepository {
|
|
420
|
+
const graph = this.loadGraph()
|
|
421
|
+
|
|
422
|
+
if (target === "yaml") {
|
|
423
|
+
const { YamlGraphRepository } = require("./yaml.js")
|
|
424
|
+
const repo = new YamlGraphRepository(projectDir)
|
|
425
|
+
repo.saveGraph(graph)
|
|
426
|
+
return repo
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
// Already SQLite
|
|
430
|
+
return this
|
|
431
|
+
}
|
|
432
|
+
|
|
433
|
+
// ── Optimized queries (don't need full graph load) ──────────────
|
|
434
|
+
|
|
435
|
+
getNodeCount(): number {
|
|
436
|
+
const db = this.getDb()
|
|
437
|
+
const result = db.query("SELECT COUNT(*) as count FROM nodes").get() as any
|
|
438
|
+
return result?.count || 0
|
|
439
|
+
}
|
|
440
|
+
|
|
441
|
+
getRelationshipCount(): number {
|
|
442
|
+
const db = this.getDb()
|
|
443
|
+
const result = db.query("SELECT COUNT(*) as count FROM relationships").get() as any
|
|
444
|
+
return result?.count || 0
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
getNodesByType(type: NodeType): AnyNode[] {
|
|
448
|
+
// Check per-type cache first
|
|
449
|
+
const cacheMgr = getCacheManager(require("path").dirname(this.baseDir))
|
|
450
|
+
const versionNum = (() => { try { return new Date(this.loadGraph().metadata.updated_at).getTime() } catch { return 0 } })()
|
|
451
|
+
const cached = cacheMgr.getCachedNodesByType(type, versionNum)
|
|
452
|
+
if (cached) return cached
|
|
453
|
+
|
|
454
|
+
const db = this.getDb()
|
|
455
|
+
const rows = db.query("SELECT * FROM nodes WHERE type = ?").all(type) as any[]
|
|
456
|
+
const nodes = rows.map(row => ({
|
|
457
|
+
id: row.id,
|
|
458
|
+
type: row.type,
|
|
459
|
+
name: row.name,
|
|
460
|
+
description: row.description || undefined,
|
|
461
|
+
status: row.status,
|
|
462
|
+
version: row.version,
|
|
463
|
+
metadata: row.metadata_json ? JSON.parse(row.metadata_json) : {},
|
|
464
|
+
created_at: row.created_at,
|
|
465
|
+
updated_at: row.updated_at,
|
|
466
|
+
})) as AnyNode[]
|
|
467
|
+
|
|
468
|
+
cacheMgr.setCachedNodesByType(type, nodes, versionNum)
|
|
469
|
+
return nodes
|
|
470
|
+
}
|
|
471
|
+
|
|
472
|
+
getNodesByStatus(status: NodeStatus): AnyNode[] {
|
|
473
|
+
const db = this.getDb()
|
|
474
|
+
const rows = db.query("SELECT * FROM nodes WHERE status = ?").all(status) as any[]
|
|
475
|
+
return rows.map(row => ({
|
|
476
|
+
id: row.id,
|
|
477
|
+
type: row.type,
|
|
478
|
+
name: row.name,
|
|
479
|
+
description: row.description || undefined,
|
|
480
|
+
status: row.status,
|
|
481
|
+
version: row.version,
|
|
482
|
+
metadata: row.metadata_json ? JSON.parse(row.metadata_json) : {},
|
|
483
|
+
created_at: row.created_at,
|
|
484
|
+
updated_at: row.updated_at,
|
|
485
|
+
})) as AnyNode[]
|
|
486
|
+
}
|
|
487
|
+
|
|
488
|
+
getNodeById(id: string): AnyNode | undefined {
|
|
489
|
+
const db = this.getDb()
|
|
490
|
+
const row = db.query("SELECT * FROM nodes WHERE id = ?").get(id) as any
|
|
491
|
+
if (!row) return undefined
|
|
492
|
+
return {
|
|
493
|
+
id: row.id,
|
|
494
|
+
type: row.type,
|
|
495
|
+
name: row.name,
|
|
496
|
+
description: row.description || undefined,
|
|
497
|
+
status: row.status,
|
|
498
|
+
version: row.version,
|
|
499
|
+
metadata: row.metadata_json ? JSON.parse(row.metadata_json) : {},
|
|
500
|
+
created_at: row.created_at,
|
|
501
|
+
updated_at: row.updated_at,
|
|
502
|
+
} as AnyNode
|
|
503
|
+
}
|
|
504
|
+
|
|
505
|
+
getRelationshipsForNode(nodeId: string): Relationship[] {
|
|
506
|
+
const db = this.getDb()
|
|
507
|
+
const rows = db.query(
|
|
508
|
+
"SELECT * FROM relationships WHERE from_id = ? OR to_id = ?"
|
|
509
|
+
).all(nodeId, nodeId) as any[]
|
|
510
|
+
return rows.map(row => ({
|
|
511
|
+
id: row.id,
|
|
512
|
+
from: row.from_id,
|
|
513
|
+
to: row.to_id,
|
|
514
|
+
type: row.type,
|
|
515
|
+
metadata: row.metadata_json ? JSON.parse(row.metadata_json) : {},
|
|
516
|
+
}))
|
|
517
|
+
}
|
|
518
|
+
|
|
519
|
+
/**
|
|
520
|
+
* Search nodes by text using SQLite's LIKE (fast with index).
|
|
521
|
+
*/
|
|
522
|
+
searchNodes(query: string, type?: NodeType): AnyNode[] {
|
|
523
|
+
const db = this.getDb()
|
|
524
|
+
const q = `%${query.toLowerCase()}%`
|
|
525
|
+
|
|
526
|
+
let sql = "SELECT * FROM nodes WHERE (LOWER(name) LIKE ? OR LOWER(id) LIKE ? OR LOWER(metadata_json) LIKE ?)"
|
|
527
|
+
const params: any[] = [q, q, q]
|
|
528
|
+
|
|
529
|
+
if (type) {
|
|
530
|
+
sql += " AND type = ?"
|
|
531
|
+
params.push(type)
|
|
532
|
+
}
|
|
533
|
+
|
|
534
|
+
sql += " LIMIT 50"
|
|
535
|
+
|
|
536
|
+
const rows = db.query(sql).all(...params) as any[]
|
|
537
|
+
return rows.map(row => ({
|
|
538
|
+
id: row.id,
|
|
539
|
+
type: row.type,
|
|
540
|
+
name: row.name,
|
|
541
|
+
description: row.description || undefined,
|
|
542
|
+
status: row.status,
|
|
543
|
+
version: row.version,
|
|
544
|
+
metadata: row.metadata_json ? JSON.parse(row.metadata_json) : {},
|
|
545
|
+
created_at: row.created_at,
|
|
546
|
+
updated_at: row.updated_at,
|
|
547
|
+
})) as AnyNode[]
|
|
548
|
+
}
|
|
549
|
+
|
|
550
|
+
// ── Lightweight queries for dashboard (avoid full graph load) ───
|
|
551
|
+
|
|
552
|
+
/**
|
|
553
|
+
* Get counts only — O(1), no graph load.
|
|
554
|
+
*/
|
|
555
|
+
getGraphCounts(): { nodeCount: number; relCount: number } {
|
|
556
|
+
const db = this.getDb()
|
|
557
|
+
const nodeRow = db.query("SELECT COUNT(*) as c FROM nodes").get() as any
|
|
558
|
+
const relRow = db.query("SELECT COUNT(*) as c FROM relationships").get() as any
|
|
559
|
+
return {
|
|
560
|
+
nodeCount: nodeRow?.c || 0,
|
|
561
|
+
relCount: relRow?.c || 0,
|
|
562
|
+
}
|
|
563
|
+
}
|
|
564
|
+
|
|
565
|
+
/**
|
|
566
|
+
* Get graph metadata only — O(1), no node/rel load.
|
|
567
|
+
*/
|
|
568
|
+
getMetadata(): Record<string, string> {
|
|
569
|
+
const db = this.getDb()
|
|
570
|
+
const rows = db.query("SELECT key, value FROM graph_metadata").all() as any[]
|
|
571
|
+
const map: Record<string, string> = {}
|
|
572
|
+
for (const row of rows) {
|
|
573
|
+
map[row.key] = row.value
|
|
574
|
+
}
|
|
575
|
+
return map
|
|
576
|
+
}
|
|
577
|
+
|
|
578
|
+
/**
|
|
579
|
+
* Get paginated node summary (id, type, name, status, version).
|
|
580
|
+
* Lightweight — no metadata/description loaded.
|
|
581
|
+
*/
|
|
582
|
+
getNodesSummary(offset: number, limit: number, type?: string): { nodes: Array<{ id: string; type: string; name: string; status: string; version: number }>; total: number } {
|
|
583
|
+
const db = this.getDb()
|
|
584
|
+
|
|
585
|
+
let countSql = "SELECT COUNT(*) as c FROM nodes"
|
|
586
|
+
let dataSql = "SELECT id, type, name, status, version FROM nodes"
|
|
587
|
+
const params: any[] = []
|
|
588
|
+
|
|
589
|
+
if (type) {
|
|
590
|
+
countSql += " WHERE type = ?"
|
|
591
|
+
dataSql += " WHERE type = ?"
|
|
592
|
+
params.push(type)
|
|
593
|
+
}
|
|
594
|
+
|
|
595
|
+
const totalRow = db.query(countSql).get(...params) as any
|
|
596
|
+
const total = totalRow?.c || 0
|
|
597
|
+
|
|
598
|
+
dataSql += " ORDER BY type, name LIMIT ? OFFSET ?"
|
|
599
|
+
const rows = db.query(dataSql).all(...params, limit, offset) as any[]
|
|
600
|
+
|
|
601
|
+
return {
|
|
602
|
+
nodes: rows.map(row => ({
|
|
603
|
+
id: row.id,
|
|
604
|
+
type: row.type,
|
|
605
|
+
name: row.name,
|
|
606
|
+
status: row.status,
|
|
607
|
+
version: row.version,
|
|
608
|
+
})),
|
|
609
|
+
total,
|
|
610
|
+
}
|
|
611
|
+
}
|
|
612
|
+
|
|
613
|
+
/**
|
|
614
|
+
* Get paginated relationships (id, from, to, type).
|
|
615
|
+
* Lightweight — no metadata loaded.
|
|
616
|
+
*/
|
|
617
|
+
getRelationshipsSummary(offset: number, limit: number): { relationships: Array<{ id: string; from: string; to: string; type: string }>; total: number } {
|
|
618
|
+
const db = this.getDb()
|
|
619
|
+
|
|
620
|
+
const totalRow = db.query("SELECT COUNT(*) as c FROM relationships").get() as any
|
|
621
|
+
const total = totalRow?.c || 0
|
|
622
|
+
|
|
623
|
+
const rows = db.query(
|
|
624
|
+
"SELECT id, from_id, to_id, type FROM relationships LIMIT ? OFFSET ?"
|
|
625
|
+
).all(limit, offset) as any[]
|
|
626
|
+
|
|
627
|
+
return {
|
|
628
|
+
relationships: rows.map(row => ({
|
|
629
|
+
id: row.id,
|
|
630
|
+
from: row.from_id,
|
|
631
|
+
to: row.to_id,
|
|
632
|
+
type: row.type,
|
|
633
|
+
})),
|
|
634
|
+
total,
|
|
635
|
+
}
|
|
636
|
+
}
|
|
637
|
+
|
|
638
|
+
/**
|
|
639
|
+
* Get all node types with counts — O(n) but lightweight (no metadata).
|
|
640
|
+
*/
|
|
641
|
+
getNodeTypeCounts(): Array<{ type: string; count: number }> {
|
|
642
|
+
const db = this.getDb()
|
|
643
|
+
const rows = db.query(
|
|
644
|
+
"SELECT type, COUNT(*) as c FROM nodes GROUP BY type ORDER BY c DESC"
|
|
645
|
+
).all() as any[]
|
|
646
|
+
return rows.map(row => ({ type: row.type, count: row.c }))
|
|
647
|
+
}
|
|
648
|
+
|
|
649
|
+
/**
|
|
650
|
+
* Get all status counts — O(n) but lightweight.
|
|
651
|
+
*/
|
|
652
|
+
getStatusCounts(): Array<{ status: string; count: number }> {
|
|
653
|
+
const db = this.getDb()
|
|
654
|
+
const rows = db.query(
|
|
655
|
+
"SELECT status, COUNT(*) as c FROM nodes GROUP BY status ORDER BY c DESC"
|
|
656
|
+
).all() as any[]
|
|
657
|
+
return rows.map(row => ({ status: row.status, count: row.c }))
|
|
658
|
+
}
|
|
659
|
+
|
|
660
|
+
/**
|
|
661
|
+
* Get all nodes (for small graphs or when full data is needed).
|
|
662
|
+
* Returns just the dashboard-relevant fields.
|
|
663
|
+
*/
|
|
664
|
+
getAllNodesSummary(): Array<{ id: string; type: string; name: string; status: string; version: number }> {
|
|
665
|
+
const db = this.getDb()
|
|
666
|
+
const rows = db.query(
|
|
667
|
+
"SELECT id, type, name, status, version FROM nodes ORDER BY type, name"
|
|
668
|
+
).all() as any[]
|
|
669
|
+
return rows.map(row => ({
|
|
670
|
+
id: row.id,
|
|
671
|
+
type: row.type,
|
|
672
|
+
name: row.name,
|
|
673
|
+
status: row.status,
|
|
674
|
+
version: row.version,
|
|
675
|
+
}))
|
|
676
|
+
}
|
|
677
|
+
|
|
678
|
+
/**
|
|
679
|
+
* Get all relationships (for small graphs or when full data is needed).
|
|
680
|
+
* Returns just the dashboard-relevant fields.
|
|
681
|
+
*/
|
|
682
|
+
getAllRelationshipsSummary(): Array<{ id: string; from: string; to: string; type: string }> {
|
|
683
|
+
const db = this.getDb()
|
|
684
|
+
const rows = db.query(
|
|
685
|
+
"SELECT id, from_id, to_id, type FROM relationships"
|
|
686
|
+
).all() as any[]
|
|
687
|
+
return rows.map(row => ({
|
|
688
|
+
id: row.id,
|
|
689
|
+
from: row.from_id,
|
|
690
|
+
to: row.to_id,
|
|
691
|
+
type: row.type,
|
|
692
|
+
}))
|
|
693
|
+
}
|
|
694
|
+
|
|
695
|
+
/**
|
|
696
|
+
* Get updated_at timestamp — O(1).
|
|
697
|
+
*/
|
|
698
|
+
getUpdatedAt(): string {
|
|
699
|
+
const db = this.getDb()
|
|
700
|
+
const row = db.query("SELECT value FROM graph_metadata WHERE key = 'updated_at'").get() as any
|
|
701
|
+
return row?.value || ""
|
|
702
|
+
}
|
|
703
|
+
}
|