@cleocode/core 2026.9.7 → 2026.9.9
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/audit/reconstruct.d.ts +13 -43
- package/dist/audit/reconstruct.d.ts.map +1 -1
- package/dist/audit/reconstruct.js +295 -290
- package/dist/audit/reconstruct.js.map +1 -1
- package/dist/bootstrap.d.ts.map +1 -1
- package/dist/bootstrap.js +8 -2
- package/dist/bootstrap.js.map +1 -1
- package/dist/dispatch/mutate-projection.d.ts.map +1 -1
- package/dist/dispatch/mutate-projection.js +12 -0
- package/dist/dispatch/mutate-projection.js.map +1 -1
- package/dist/dispatch/mvi-projection.d.ts +29 -6
- package/dist/dispatch/mvi-projection.d.ts.map +1 -1
- package/dist/dispatch/mvi-projection.js +109 -139
- package/dist/dispatch/mvi-projection.js.map +1 -1
- package/dist/docs/docs-read-model.d.ts +3 -2
- package/dist/docs/docs-read-model.d.ts.map +1 -1
- package/dist/docs/docs-read-model.js +4 -3
- package/dist/docs/docs-read-model.js.map +1 -1
- package/dist/docs/export-document.js +5100 -2297
- package/dist/docs/export-document.js.map +3 -3
- package/dist/docs/projection.d.ts +67 -0
- package/dist/docs/projection.d.ts.map +1 -0
- package/dist/docs/projection.js +370 -0
- package/dist/docs/projection.js.map +1 -0
- package/dist/doctor/acceptance-drift.d.ts +6 -2
- package/dist/doctor/acceptance-drift.d.ts.map +1 -1
- package/dist/doctor/acceptance-drift.js +43 -5
- package/dist/doctor/acceptance-drift.js.map +1 -1
- package/dist/doctor/knowledge-summary.d.ts +41 -0
- package/dist/doctor/knowledge-summary.d.ts.map +1 -0
- package/dist/doctor/knowledge-summary.js +81 -0
- package/dist/doctor/knowledge-summary.js.map +1 -0
- package/dist/doctor/knowledge.d.ts +192 -0
- package/dist/doctor/knowledge.d.ts.map +1 -0
- package/dist/doctor/knowledge.js +1864 -0
- package/dist/doctor/knowledge.js.map +1 -0
- package/dist/git/work-tree.d.ts +64 -0
- package/dist/git/work-tree.d.ts.map +1 -0
- package/dist/git/work-tree.js +111 -0
- package/dist/git/work-tree.js.map +1 -0
- package/dist/hooks/handlers/task-hooks.d.ts +8 -5
- package/dist/hooks/handlers/task-hooks.d.ts.map +1 -1
- package/dist/hooks/handlers/task-hooks.js +15 -60
- package/dist/hooks/handlers/task-hooks.js.map +1 -1
- package/dist/identity/cleo-identity.d.ts +13 -0
- package/dist/identity/cleo-identity.d.ts.map +1 -1
- package/dist/identity/cleo-identity.js +20 -6
- package/dist/identity/cleo-identity.js.map +1 -1
- package/dist/injection.d.ts.map +1 -1
- package/dist/injection.js +29 -13
- package/dist/injection.js.map +1 -1
- package/dist/internal.d.ts +2 -0
- package/dist/internal.d.ts.map +1 -1
- package/dist/internal.js +2 -0
- package/dist/internal.js.map +1 -1
- package/dist/lifecycle/verification/satisfies-validator.d.ts.map +1 -1
- package/dist/lifecycle/verification/satisfies-validator.js +124 -120
- package/dist/lifecycle/verification/satisfies-validator.js.map +1 -1
- package/dist/llm/plugin-facade.js +4018 -1726
- package/dist/llm/plugin-facade.js.map +3 -3
- package/dist/memory/brain-backfill.d.ts +27 -12
- package/dist/memory/brain-backfill.d.ts.map +1 -1
- package/dist/memory/brain-backfill.js +325 -134
- package/dist/memory/brain-backfill.js.map +1 -1
- package/dist/memory/brain-doctor.d.ts +21 -0
- package/dist/memory/brain-doctor.d.ts.map +1 -1
- package/dist/memory/brain-doctor.js +111 -53
- package/dist/memory/brain-doctor.js.map +1 -1
- package/dist/memory/brain-links.d.ts.map +1 -1
- package/dist/memory/brain-links.js +31 -4
- package/dist/memory/brain-links.js.map +1 -1
- package/dist/memory/brain-reasoning.d.ts.map +1 -1
- package/dist/memory/brain-reasoning.js +28 -2
- package/dist/memory/brain-reasoning.js.map +1 -1
- package/dist/memory/brain-reconciler.d.ts +14 -19
- package/dist/memory/brain-reconciler.d.ts.map +1 -1
- package/dist/memory/brain-reconciler.js +70 -97
- package/dist/memory/brain-reconciler.js.map +1 -1
- package/dist/memory/brain-search.d.ts +2 -0
- package/dist/memory/brain-search.d.ts.map +1 -1
- package/dist/memory/brain-search.js +59 -29
- package/dist/memory/brain-search.js.map +1 -1
- package/dist/memory/brain-similarity.d.ts.map +1 -1
- package/dist/memory/brain-similarity.js +5 -4
- package/dist/memory/brain-similarity.js.map +1 -1
- package/dist/memory/brain-stub-prune.d.ts +31 -9
- package/dist/memory/brain-stub-prune.d.ts.map +1 -1
- package/dist/memory/brain-stub-prune.js +65 -18
- package/dist/memory/brain-stub-prune.js.map +1 -1
- package/dist/memory/brain-writer-handlers.d.ts +10 -1
- package/dist/memory/brain-writer-handlers.d.ts.map +1 -1
- package/dist/memory/brain-writer-handlers.js +23 -3
- package/dist/memory/brain-writer-handlers.js.map +1 -1
- package/dist/memory/brain-writer-thread.d.ts +31 -1
- package/dist/memory/brain-writer-thread.d.ts.map +1 -1
- package/dist/memory/brain-writer-thread.js +166 -24
- package/dist/memory/brain-writer-thread.js.map +1 -1
- package/dist/memory/brain-writer-worker.js +8 -1
- package/dist/memory/brain-writer-worker.js.map +1 -1
- package/dist/memory/decision-cross-link.d.ts +39 -0
- package/dist/memory/decision-cross-link.d.ts.map +1 -1
- package/dist/memory/decision-cross-link.js +316 -0
- package/dist/memory/decision-cross-link.js.map +1 -1
- package/dist/memory/decisions.d.ts +4 -1
- package/dist/memory/decisions.d.ts.map +1 -1
- package/dist/memory/decisions.js +7 -24
- package/dist/memory/decisions.js.map +1 -1
- package/dist/memory/dispatch-trace.d.ts +12 -5
- package/dist/memory/dispatch-trace.d.ts.map +1 -1
- package/dist/memory/dispatch-trace.js +17 -7
- package/dist/memory/dispatch-trace.js.map +1 -1
- package/dist/memory/eligibility.d.ts +51 -0
- package/dist/memory/eligibility.d.ts.map +1 -0
- package/dist/memory/eligibility.js +77 -0
- package/dist/memory/eligibility.js.map +1 -0
- package/dist/memory/engine-compat.d.ts +2 -0
- package/dist/memory/engine-compat.d.ts.map +1 -1
- package/dist/memory/engine-compat.js +10 -0
- package/dist/memory/engine-compat.js.map +1 -1
- package/dist/memory/extraction-gate.d.ts +21 -7
- package/dist/memory/extraction-gate.d.ts.map +1 -1
- package/dist/memory/extraction-gate.js +178 -216
- package/dist/memory/extraction-gate.js.map +1 -1
- package/dist/memory/graph-auto-populate.d.ts +38 -5
- package/dist/memory/graph-auto-populate.d.ts.map +1 -1
- package/dist/memory/graph-auto-populate.js +182 -60
- package/dist/memory/graph-auto-populate.js.map +1 -1
- package/dist/memory/graph-memory-bridge.d.ts +14 -1
- package/dist/memory/graph-memory-bridge.d.ts.map +1 -1
- package/dist/memory/graph-memory-bridge.js +66 -28
- package/dist/memory/graph-memory-bridge.js.map +1 -1
- package/dist/memory/index.d.ts +1 -19
- package/dist/memory/index.d.ts.map +1 -1
- package/dist/memory/index.js +1 -50
- package/dist/memory/index.js.map +1 -1
- package/dist/memory/learnings.d.ts.map +1 -1
- package/dist/memory/learnings.js +2 -23
- package/dist/memory/learnings.js.map +1 -1
- package/dist/memory/manifest-filter.d.ts +21 -0
- package/dist/memory/manifest-filter.d.ts.map +1 -0
- package/dist/memory/manifest-filter.js +51 -0
- package/dist/memory/manifest-filter.js.map +1 -0
- package/dist/memory/manifest-ingestion.d.ts +28 -30
- package/dist/memory/manifest-ingestion.d.ts.map +1 -1
- package/dist/memory/manifest-ingestion.js +104 -235
- package/dist/memory/manifest-ingestion.js.map +1 -1
- package/dist/memory/observer-reflector.d.ts +2 -0
- package/dist/memory/observer-reflector.d.ts.map +1 -1
- package/dist/memory/observer-reflector.js +6 -49
- package/dist/memory/observer-reflector.js.map +1 -1
- package/dist/memory/patterns.d.ts +10 -0
- package/dist/memory/patterns.d.ts.map +1 -1
- package/dist/memory/patterns.js +25 -33
- package/dist/memory/patterns.js.map +1 -1
- package/dist/memory/pipeline-manifest-sqlite.d.ts +72 -9
- package/dist/memory/pipeline-manifest-sqlite.d.ts.map +1 -1
- package/dist/memory/pipeline-manifest-sqlite.js +508 -412
- package/dist/memory/pipeline-manifest-sqlite.js.map +1 -1
- package/dist/memory/retrieval/build-retrieval-bundle.d.ts.map +1 -1
- package/dist/memory/retrieval/build-retrieval-bundle.js +16 -15
- package/dist/memory/retrieval/build-retrieval-bundle.js.map +1 -1
- package/dist/memory/retrieval/fetch.d.ts +7 -0
- package/dist/memory/retrieval/fetch.d.ts.map +1 -1
- package/dist/memory/retrieval/fetch.js +14 -11
- package/dist/memory/retrieval/fetch.js.map +1 -1
- package/dist/memory/retrieval/observe.d.ts +7 -1
- package/dist/memory/retrieval/observe.d.ts.map +1 -1
- package/dist/memory/retrieval/observe.js +58 -4
- package/dist/memory/retrieval/observe.js.map +1 -1
- package/dist/memory/retrieval/search.d.ts +14 -1
- package/dist/memory/retrieval/search.d.ts.map +1 -1
- package/dist/memory/retrieval/search.js +133 -69
- package/dist/memory/retrieval/search.js.map +1 -1
- package/dist/memory/retrieval/telemetry.d.ts +31 -0
- package/dist/memory/retrieval/telemetry.d.ts.map +1 -0
- package/dist/memory/retrieval/telemetry.js +53 -0
- package/dist/memory/retrieval/telemetry.js.map +1 -0
- package/dist/nexus/analyze-orchestrator.d.ts +41 -9
- package/dist/nexus/analyze-orchestrator.d.ts.map +1 -1
- package/dist/nexus/analyze-orchestrator.js +257 -58
- package/dist/nexus/analyze-orchestrator.js.map +1 -1
- package/dist/nexus/api-contracts.d.ts +2 -6
- package/dist/nexus/api-contracts.d.ts.map +1 -1
- package/dist/nexus/api-contracts.js +11 -2
- package/dist/nexus/api-contracts.js.map +1 -1
- package/dist/nexus/context.d.ts.map +1 -1
- package/dist/nexus/context.js +14 -37
- package/dist/nexus/context.js.map +1 -1
- package/dist/nexus/diff.d.ts.map +1 -1
- package/dist/nexus/diff.js +2 -1
- package/dist/nexus/diff.js.map +1 -1
- package/dist/nexus/identity.d.ts +29 -3
- package/dist/nexus/identity.d.ts.map +1 -1
- package/dist/nexus/identity.js +63 -12
- package/dist/nexus/identity.js.map +1 -1
- package/dist/nexus/impact.d.ts +21 -19
- package/dist/nexus/impact.d.ts.map +1 -1
- package/dist/nexus/impact.js +96 -192
- package/dist/nexus/impact.js.map +1 -1
- package/dist/nexus/knowledge.d.ts +80 -0
- package/dist/nexus/knowledge.d.ts.map +1 -0
- package/dist/nexus/knowledge.js +786 -0
- package/dist/nexus/knowledge.js.map +1 -0
- package/dist/nexus/living-brain.d.ts +8 -5
- package/dist/nexus/living-brain.d.ts.map +1 -1
- package/dist/nexus/living-brain.js +252 -188
- package/dist/nexus/living-brain.js.map +1 -1
- package/dist/nexus/registry.d.ts +11 -2
- package/dist/nexus/registry.d.ts.map +1 -1
- package/dist/nexus/registry.js +144 -128
- package/dist/nexus/registry.js.map +1 -1
- package/dist/nexus/source-roots.d.ts +16 -0
- package/dist/nexus/source-roots.d.ts.map +1 -0
- package/dist/nexus/source-roots.js +174 -0
- package/dist/nexus/source-roots.js.map +1 -0
- package/dist/nexus/task-evidence.d.ts +22 -0
- package/dist/nexus/task-evidence.d.ts.map +1 -0
- package/dist/nexus/task-evidence.js +210 -0
- package/dist/nexus/task-evidence.js.map +1 -0
- package/dist/nexus/tasks-bridge.d.ts +14 -7
- package/dist/nexus/tasks-bridge.d.ts.map +1 -1
- package/dist/nexus/tasks-bridge.js +81 -40
- package/dist/nexus/tasks-bridge.js.map +1 -1
- package/dist/orchestrate/lifecycle-ops.d.ts.map +1 -1
- package/dist/orchestrate/lifecycle-ops.js +170 -120
- package/dist/orchestrate/lifecycle-ops.js.map +1 -1
- package/dist/orchestrate/query-ops.d.ts +6 -7
- package/dist/orchestrate/query-ops.d.ts.map +1 -1
- package/dist/orchestrate/query-ops.js +509 -532
- package/dist/orchestrate/query-ops.js.map +1 -1
- package/dist/orchestration/bootstrap.d.ts +15 -1
- package/dist/orchestration/bootstrap.d.ts.map +1 -1
- package/dist/orchestration/bootstrap.js +21 -10
- package/dist/orchestration/bootstrap.js.map +1 -1
- package/dist/orchestration/index.d.ts +35 -3
- package/dist/orchestration/index.d.ts.map +1 -1
- package/dist/orchestration/index.js +64 -35
- package/dist/orchestration/index.js.map +1 -1
- package/dist/orchestration/lead-rollup.d.ts +24 -1
- package/dist/orchestration/lead-rollup.d.ts.map +1 -1
- package/dist/orchestration/lead-rollup.js +31 -11
- package/dist/orchestration/lead-rollup.js.map +1 -1
- package/dist/orchestration/spawn-prompt.d.ts.map +1 -1
- package/dist/orchestration/spawn-prompt.js +16 -41
- package/dist/orchestration/spawn-prompt.js.map +1 -1
- package/dist/orchestration/unblock.d.ts +15 -1
- package/dist/orchestration/unblock.d.ts.map +1 -1
- package/dist/orchestration/unblock.js +23 -12
- package/dist/orchestration/unblock.js.map +1 -1
- package/dist/orchestration/validate-spawn.d.ts.map +1 -1
- package/dist/orchestration/validate-spawn.js +3 -3
- package/dist/orchestration/validate-spawn.js.map +1 -1
- package/dist/orchestration/waves.d.ts +29 -13
- package/dist/orchestration/waves.d.ts.map +1 -1
- package/dist/orchestration/waves.js +43 -55
- package/dist/orchestration/waves.js.map +1 -1
- package/dist/paths.d.ts +17 -163
- package/dist/paths.d.ts.map +1 -1
- package/dist/paths.js +145 -496
- package/dist/paths.js.map +1 -1
- package/dist/project-info.d.ts +2 -11
- package/dist/project-info.d.ts.map +1 -1
- package/dist/project-info.js +3 -31
- package/dist/project-info.js.map +1 -1
- package/dist/project-scope.d.ts +239 -0
- package/dist/project-scope.d.ts.map +1 -0
- package/dist/project-scope.js +473 -0
- package/dist/project-scope.js.map +1 -0
- package/dist/release/pr-evidence.d.ts +16 -3
- package/dist/release/pr-evidence.d.ts.map +1 -1
- package/dist/release/pr-evidence.js +53 -7
- package/dist/release/pr-evidence.js.map +1 -1
- package/dist/render/nexus/graph/index.d.ts.map +1 -1
- package/dist/render/nexus/graph/index.js +4 -2
- package/dist/render/nexus/graph/index.js.map +1 -1
- package/dist/render/orchestration/audit-reconstruct.d.ts +11 -0
- package/dist/render/orchestration/audit-reconstruct.d.ts.map +1 -1
- package/dist/render/orchestration/audit-reconstruct.js +21 -6
- package/dist/render/orchestration/audit-reconstruct.js.map +1 -1
- package/dist/render/tasks/show.js +2 -1
- package/dist/render/tasks/show.js.map +1 -1
- package/dist/resources/spawn-wrapper.d.ts +82 -14
- package/dist/resources/spawn-wrapper.d.ts.map +1 -1
- package/dist/resources/spawn-wrapper.js +585 -27
- package/dist/resources/spawn-wrapper.js.map +1 -1
- package/dist/selfimprove/fix-gen.js +4026 -1734
- package/dist/selfimprove/fix-gen.js.map +3 -3
- package/dist/sequence/index.d.ts.map +1 -1
- package/dist/sequence/index.js +76 -68
- package/dist/sequence/index.js.map +1 -1
- package/dist/session/canon-lint.d.ts +24 -3
- package/dist/session/canon-lint.d.ts.map +1 -1
- package/dist/session/canon-lint.js +72 -31
- package/dist/session/canon-lint.js.map +1 -1
- package/dist/session/engine-ops.d.ts +1 -4
- package/dist/session/engine-ops.d.ts.map +1 -1
- package/dist/session/engine-ops.js +6 -2
- package/dist/session/engine-ops.js.map +1 -1
- package/dist/sessions/briefing.d.ts +11 -1
- package/dist/sessions/briefing.d.ts.map +1 -1
- package/dist/sessions/briefing.js +76 -8
- package/dist/sessions/briefing.js.map +1 -1
- package/dist/sessions/handoff.d.ts +3 -1
- package/dist/sessions/handoff.d.ts.map +1 -1
- package/dist/sessions/handoff.js +2 -0
- package/dist/sessions/handoff.js.map +1 -1
- package/dist/shutdown-deadline.d.ts +24 -33
- package/dist/shutdown-deadline.d.ts.map +1 -1
- package/dist/shutdown-deadline.js +71 -14
- package/dist/shutdown-deadline.js.map +1 -1
- package/dist/shutdown.d.ts +21 -10
- package/dist/shutdown.d.ts.map +1 -1
- package/dist/shutdown.js +91 -35
- package/dist/shutdown.js.map +1 -1
- package/dist/skills/index.d.ts +1 -1
- package/dist/skills/index.d.ts.map +1 -1
- package/dist/skills/index.js +1 -1
- package/dist/skills/index.js.map +1 -1
- package/dist/skills/orchestrator/validator.d.ts +87 -20
- package/dist/skills/orchestrator/validator.d.ts.map +1 -1
- package/dist/skills/orchestrator/validator.js +330 -241
- package/dist/skills/orchestrator/validator.js.map +1 -1
- package/dist/store/agent-resolver.d.ts.map +1 -1
- package/dist/store/agent-resolver.js +16 -9
- package/dist/store/agent-resolver.js.map +1 -1
- package/dist/store/attachment-store.d.ts +4 -1
- package/dist/store/attachment-store.d.ts.map +1 -1
- package/dist/store/attachment-store.js +20 -3
- package/dist/store/attachment-store.js.map +1 -1
- package/dist/store/background-jobs.d.ts +426 -105
- package/dist/store/background-jobs.d.ts.map +1 -1
- package/dist/store/background-jobs.js +1208 -252
- package/dist/store/background-jobs.js.map +1 -1
- package/dist/store/background-ops.d.ts +145 -8
- package/dist/store/background-ops.d.ts.map +1 -1
- package/dist/store/background-ops.js +459 -15
- package/dist/store/background-ops.js.map +1 -1
- package/dist/store/backup-inspect.d.ts +48 -4
- package/dist/store/backup-inspect.d.ts.map +1 -1
- package/dist/store/backup-inspect.js +384 -4
- package/dist/store/backup-inspect.js.map +1 -1
- package/dist/store/converters.d.ts.map +1 -1
- package/dist/store/converters.js +19 -2
- package/dist/store/converters.js.map +1 -1
- package/dist/store/data-accessor.d.ts +9 -1
- package/dist/store/data-accessor.d.ts.map +1 -1
- package/dist/store/data-accessor.js +22 -5
- package/dist/store/data-accessor.js.map +1 -1
- package/dist/store/data-safety-central.d.ts.map +1 -1
- package/dist/store/data-safety-central.js +272 -232
- package/dist/store/data-safety-central.js.map +1 -1
- package/dist/store/db-helpers.d.ts +19 -3
- package/dist/store/db-helpers.d.ts.map +1 -1
- package/dist/store/db-helpers.js +42 -58
- package/dist/store/db-helpers.js.map +1 -1
- package/dist/store/dual-scope-db.d.ts +63 -4
- package/dist/store/dual-scope-db.d.ts.map +1 -1
- package/dist/store/dual-scope-db.js +166 -19
- package/dist/store/dual-scope-db.js.map +1 -1
- package/dist/store/exodus/archive.d.ts +21 -7
- package/dist/store/exodus/archive.d.ts.map +1 -1
- package/dist/store/exodus/archive.js +60 -18
- package/dist/store/exodus/archive.js.map +1 -1
- package/dist/store/exodus/migrate.d.ts.map +1 -1
- package/dist/store/exodus/migrate.js +27 -23
- package/dist/store/exodus/migrate.js.map +1 -1
- package/dist/store/exodus/on-open.d.ts +16 -27
- package/dist/store/exodus/on-open.d.ts.map +1 -1
- package/dist/store/exodus/on-open.js +121 -169
- package/dist/store/exodus/on-open.js.map +1 -1
- package/dist/store/exodus/recovery.d.ts +90 -0
- package/dist/store/exodus/recovery.d.ts.map +1 -0
- package/dist/store/exodus/recovery.js +434 -0
- package/dist/store/exodus/recovery.js.map +1 -0
- package/dist/store/exodus/types.d.ts +15 -0
- package/dist/store/exodus/types.d.ts.map +1 -1
- package/dist/store/memory-accessor.d.ts +52 -3
- package/dist/store/memory-accessor.d.ts.map +1 -1
- package/dist/store/memory-accessor.js +122 -7
- package/dist/store/memory-accessor.js.map +1 -1
- package/dist/store/nexus-sqlite.d.ts +24 -6
- package/dist/store/nexus-sqlite.d.ts.map +1 -1
- package/dist/store/nexus-sqlite.js +39 -20
- package/dist/store/nexus-sqlite.js.map +1 -1
- package/dist/store/ports/domain-binding.d.ts.map +1 -1
- package/dist/store/ports/domain-binding.js +27 -5
- package/dist/store/ports/domain-binding.js.map +1 -1
- package/dist/store/schema/background-jobs.d.ts +181 -2
- package/dist/store/schema/background-jobs.d.ts.map +1 -1
- package/dist/store/schema/background-jobs.js +27 -3
- package/dist/store/schema/background-jobs.js.map +1 -1
- package/dist/store/schema/cleo-global/skills.d.ts +2 -2
- package/dist/store/schema/cleo-project/lifecycle.d.ts +2 -2
- package/dist/store/schema/cleo-project/runtime.d.ts +1 -1
- package/dist/store/schema/cleo-project/tasks-core.d.ts +1 -1
- package/dist/store/schema/lifecycle.d.ts +2 -2
- package/dist/store/schema/skills-schema.d.ts +2 -2
- package/dist/store/schema/tasks.d.ts +1 -1
- package/dist/store/session-store.d.ts +3 -1
- package/dist/store/session-store.d.ts.map +1 -1
- package/dist/store/session-store.js +252 -207
- package/dist/store/session-store.js.map +1 -1
- package/dist/store/sqlite-data-accessor.d.ts +39 -4
- package/dist/store/sqlite-data-accessor.d.ts.map +1 -1
- package/dist/store/sqlite-data-accessor.js +689 -527
- package/dist/store/sqlite-data-accessor.js.map +1 -1
- package/dist/store/tasks-sqlite.d.ts +3 -1
- package/dist/store/tasks-sqlite.d.ts.map +1 -1
- package/dist/store/tasks-sqlite.js +309 -279
- package/dist/store/tasks-sqlite.js.map +1 -1
- package/dist/store/validation-schemas.d.ts +8 -8
- package/dist/store/writer-lease.d.ts +80 -8
- package/dist/store/writer-lease.d.ts.map +1 -1
- package/dist/store/writer-lease.js +503 -134
- package/dist/store/writer-lease.js.map +1 -1
- package/dist/system/audit.d.ts +2 -1
- package/dist/system/audit.d.ts.map +1 -1
- package/dist/system/audit.js +118 -71
- package/dist/system/audit.js.map +1 -1
- package/dist/system/backup.d.ts.map +1 -1
- package/dist/system/backup.js +5 -5
- package/dist/system/backup.js.map +1 -1
- package/dist/system/inject-generate.js +1 -1
- package/dist/task-work/index.d.ts +3 -0
- package/dist/task-work/index.d.ts.map +1 -1
- package/dist/task-work/index.js +34 -37
- package/dist/task-work/index.js.map +1 -1
- package/dist/tasks/ac-coverage-gate.d.ts.map +1 -1
- package/dist/tasks/ac-coverage-gate.js +4 -0
- package/dist/tasks/ac-coverage-gate.js.map +1 -1
- package/dist/tasks/ac-immutability.d.ts +7 -4
- package/dist/tasks/ac-immutability.d.ts.map +1 -1
- package/dist/tasks/ac-immutability.js +19 -17
- package/dist/tasks/ac-immutability.js.map +1 -1
- package/dist/tasks/ac-table.d.ts +5 -5
- package/dist/tasks/ac-table.d.ts.map +1 -1
- package/dist/tasks/ac-table.js +26 -12
- package/dist/tasks/ac-table.js.map +1 -1
- package/dist/tasks/acceptance-input.d.ts +52 -0
- package/dist/tasks/acceptance-input.d.ts.map +1 -0
- package/dist/tasks/acceptance-input.js +259 -0
- package/dist/tasks/acceptance-input.js.map +1 -0
- package/dist/tasks/add.d.ts +67 -29
- package/dist/tasks/add.d.ts.map +1 -1
- package/dist/tasks/add.js +255 -97
- package/dist/tasks/add.js.map +1 -1
- package/dist/tasks/complete.d.ts +16 -1
- package/dist/tasks/complete.d.ts.map +1 -1
- package/dist/tasks/complete.js +152 -55
- package/dist/tasks/complete.js.map +1 -1
- package/dist/tasks/decompose.d.ts +103 -0
- package/dist/tasks/decompose.d.ts.map +1 -0
- package/dist/tasks/decompose.js +224 -0
- package/dist/tasks/decompose.js.map +1 -0
- package/dist/tasks/delete.d.ts +5 -8
- package/dist/tasks/delete.d.ts.map +1 -1
- package/dist/tasks/delete.js +4 -3
- package/dist/tasks/delete.js.map +1 -1
- package/dist/tasks/dependency-check.d.ts +59 -0
- package/dist/tasks/dependency-check.d.ts.map +1 -1
- package/dist/tasks/dependency-check.js +73 -0
- package/dist/tasks/dependency-check.js.map +1 -1
- package/dist/tasks/deps-ready.d.ts +13 -1
- package/dist/tasks/deps-ready.d.ts.map +1 -1
- package/dist/tasks/deps-ready.js +16 -5
- package/dist/tasks/deps-ready.js.map +1 -1
- package/dist/tasks/engine-converters.d.ts +7 -0
- package/dist/tasks/engine-converters.d.ts.map +1 -1
- package/dist/tasks/engine-converters.js +8 -1
- package/dist/tasks/engine-converters.js.map +1 -1
- package/dist/tasks/evidence.d.ts +54 -26
- package/dist/tasks/evidence.d.ts.map +1 -1
- package/dist/tasks/evidence.js +292 -40
- package/dist/tasks/evidence.js.map +1 -1
- package/dist/tasks/find.d.ts +16 -12
- package/dist/tasks/find.d.ts.map +1 -1
- package/dist/tasks/find.js +107 -93
- package/dist/tasks/find.js.map +1 -1
- package/dist/tasks/gate-runner.d.ts +88 -14
- package/dist/tasks/gate-runner.d.ts.map +1 -1
- package/dist/tasks/gate-runner.js +596 -253
- package/dist/tasks/gate-runner.js.map +1 -1
- package/dist/tasks/hierarchy-policy.d.ts +8 -0
- package/dist/tasks/hierarchy-policy.d.ts.map +1 -1
- package/dist/tasks/hierarchy-policy.js +9 -2
- package/dist/tasks/hierarchy-policy.js.map +1 -1
- package/dist/tasks/hierarchy.d.ts +67 -1
- package/dist/tasks/hierarchy.d.ts.map +1 -1
- package/dist/tasks/hierarchy.js +81 -1
- package/dist/tasks/hierarchy.js.map +1 -1
- package/dist/tasks/index.d.ts +3 -0
- package/dist/tasks/index.d.ts.map +1 -1
- package/dist/tasks/index.js +3 -0
- package/dist/tasks/index.js.map +1 -1
- package/dist/tasks/infer-add-params.d.ts +1 -20
- package/dist/tasks/infer-add-params.d.ts.map +1 -1
- package/dist/tasks/infer-add-params.js +2 -203
- package/dist/tasks/infer-add-params.js.map +1 -1
- package/dist/tasks/list.d.ts +7 -2
- package/dist/tasks/list.d.ts.map +1 -1
- package/dist/tasks/list.js +24 -36
- package/dist/tasks/list.js.map +1 -1
- package/dist/tasks/ops.d.ts +6 -61
- package/dist/tasks/ops.d.ts.map +1 -1
- package/dist/tasks/ops.js +5 -53
- package/dist/tasks/ops.js.map +1 -1
- package/dist/tasks/plan.d.ts +15 -1
- package/dist/tasks/plan.d.ts.map +1 -1
- package/dist/tasks/plan.js +23 -25
- package/dist/tasks/plan.js.map +1 -1
- package/dist/tasks/population.d.ts +46 -0
- package/dist/tasks/population.d.ts.map +1 -0
- package/dist/tasks/population.js +88 -0
- package/dist/tasks/population.js.map +1 -0
- package/dist/tasks/reconcile-scope.d.ts +157 -0
- package/dist/tasks/reconcile-scope.d.ts.map +1 -0
- package/dist/tasks/reconcile-scope.js +242 -0
- package/dist/tasks/reconcile-scope.js.map +1 -0
- package/dist/tasks/req.d.ts +51 -12
- package/dist/tasks/req.d.ts.map +1 -1
- package/dist/tasks/req.js +125 -69
- package/dist/tasks/req.js.map +1 -1
- package/dist/tasks/session-scope.d.ts +6 -31
- package/dist/tasks/session-scope.d.ts.map +1 -1
- package/dist/tasks/session-scope.js +3 -17
- package/dist/tasks/session-scope.js.map +1 -1
- package/dist/tasks/severity-attestation.d.ts +39 -10
- package/dist/tasks/severity-attestation.d.ts.map +1 -1
- package/dist/tasks/severity-attestation.js +75 -36
- package/dist/tasks/severity-attestation.js.map +1 -1
- package/dist/tasks/task-next.d.ts +5 -0
- package/dist/tasks/task-next.d.ts.map +1 -1
- package/dist/tasks/task-next.js +10 -9
- package/dist/tasks/task-next.js.map +1 -1
- package/dist/tasks/task-reparent.d.ts.map +1 -1
- package/dist/tasks/task-reparent.js +3 -13
- package/dist/tasks/task-reparent.js.map +1 -1
- package/dist/tasks/update.d.ts +20 -43
- package/dist/tasks/update.d.ts.map +1 -1
- package/dist/tasks/update.js +64 -49
- package/dist/tasks/update.js.map +1 -1
- package/dist/teardown-signal.d.ts +72 -0
- package/dist/teardown-signal.d.ts.map +1 -0
- package/dist/teardown-signal.js +108 -0
- package/dist/teardown-signal.js.map +1 -0
- package/dist/validation/engine-ops.d.ts +17 -1
- package/dist/validation/engine-ops.d.ts.map +1 -1
- package/dist/validation/engine-ops.js +149 -11
- package/dist/validation/engine-ops.js.map +1 -1
- package/dist/workgraph/reparent-preflight.d.ts +1 -1
- package/dist/workgraph/reparent-preflight.d.ts.map +1 -1
- package/dist/workgraph/reparent-preflight.js +6 -1
- package/dist/workgraph/reparent-preflight.js.map +1 -1
- package/dist/workgraph/scaffold-apply.d.ts.map +1 -1
- package/dist/workgraph/scaffold-apply.js +81 -76
- package/dist/workgraph/scaffold-apply.js.map +1 -1
- package/dist/workgraph/structure-validation.d.ts +1 -1
- package/dist/workgraph/structure-validation.d.ts.map +1 -1
- package/dist/workgraph/structure-validation.js +6 -1
- package/dist/workgraph/structure-validation.js.map +1 -1
- package/migrations/drizzle-tasks/20260919180000_t12263-job-ownership-fences/migration.sql +34 -0
- package/migrations/drizzle-tasks/20260919184500_t12265-durable-pending-proposals/migration.sql +4 -0
- package/package.json +18 -13
- package/schemas/config.schema.json +2 -2
- package/templates/CLEO-INJECTION.md +103 -101
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
* which tasks touched those nodes?
|
|
18
18
|
*
|
|
19
19
|
* Design constraints:
|
|
20
|
-
* -
|
|
20
|
+
* - Substrate errors are recorded in coverage; ambiguity returns qualified candidates.
|
|
21
21
|
* - conduit.db absence is a graceful no-op: conduitThreads returns [].
|
|
22
22
|
* - All return shapes are defined in packages/contracts/src/nexus-living-brain-ops.ts.
|
|
23
23
|
* - REUSES existing primitives: T1067 bridge, T1066 edge writers, existing
|
|
@@ -29,11 +29,15 @@
|
|
|
29
29
|
import { existsSync } from 'node:fs';
|
|
30
30
|
import { engineError, engineSuccess } from '../engine-result.js';
|
|
31
31
|
import { reasonWhySymbol } from '../memory/brain-reasoning.js';
|
|
32
|
+
import { isCurrentDecisionCodeEvidence } from '../memory/decision-cross-link.js';
|
|
32
33
|
import { EDGE_TYPES } from '../memory/edge-types.js';
|
|
34
|
+
import { graphMemoryAuthority, memoryEligibilityClause } from '../memory/eligibility.js';
|
|
33
35
|
import { getConduitDbPath } from '../store/conduit-sqlite.js';
|
|
34
36
|
import { getBrainDb, getBrainNativeDb } from '../store/memory-sqlite.js';
|
|
35
37
|
import { getNexusDb, getNexusNativeDb } from '../store/nexus-sqlite.js';
|
|
36
38
|
import { typedAll, typedGet } from '../store/typed-query.js';
|
|
39
|
+
import { assessKnowledgeCoverage, KnowledgeSymbolAmbiguityError, recordKnowledgeGap, resolveKnowledgeSymbol, } from './knowledge.js';
|
|
40
|
+
import { getTaskKnowledgeEvidence } from './task-evidence.js';
|
|
37
41
|
import { getSymbolsForTask, getTasksForSymbol } from './tasks-bridge.js';
|
|
38
42
|
// ---------------------------------------------------------------------------
|
|
39
43
|
// Internal: map ImpactResult riskLevel → RiskTier
|
|
@@ -52,13 +56,15 @@ function toRiskTier(riskLevel) {
|
|
|
52
56
|
case 'low':
|
|
53
57
|
return 'LOW';
|
|
54
58
|
default:
|
|
55
|
-
return '
|
|
59
|
+
return 'UNKNOWN';
|
|
56
60
|
}
|
|
57
61
|
}
|
|
58
62
|
/**
|
|
59
63
|
* Return the highest risk tier from an array.
|
|
60
64
|
*/
|
|
61
65
|
function maxRiskTier(tiers) {
|
|
66
|
+
if (tiers.length === 0 || tiers.includes('UNKNOWN'))
|
|
67
|
+
return 'UNKNOWN';
|
|
62
68
|
const order = ['NONE', 'LOW', 'MEDIUM', 'HIGH', 'CRITICAL'];
|
|
63
69
|
let max = 0;
|
|
64
70
|
for (const t of tiers) {
|
|
@@ -81,14 +87,16 @@ function maxRiskTier(tiers) {
|
|
|
81
87
|
* - **SENTIENT**: Tier-2 proposals whose sourceId matches this symbol
|
|
82
88
|
* - **CONDUIT**: message threads mentioning this symbol (empty if conduit.db absent)
|
|
83
89
|
*
|
|
84
|
-
*
|
|
90
|
+
* Substrate failures are exposed through coverage; ambiguous names are rejected.
|
|
85
91
|
*
|
|
86
92
|
* @param symbolId - Nexus node ID or symbol name (partial match accepted for nexus lookup)
|
|
87
93
|
* @param projectRoot - Absolute path to project root
|
|
88
94
|
* @returns Full cross-substrate context
|
|
89
95
|
*/
|
|
90
96
|
export async function getSymbolFullContext(symbolId, projectRoot) {
|
|
97
|
+
const coverage = await assessKnowledgeCoverage(projectRoot);
|
|
91
98
|
const result = {
|
|
99
|
+
coverage,
|
|
92
100
|
symbolId,
|
|
93
101
|
nexus: null,
|
|
94
102
|
brainMemories: [],
|
|
@@ -100,20 +108,18 @@ export async function getSymbolFullContext(symbolId, projectRoot) {
|
|
|
100
108
|
// ---- NEXUS substrate ----
|
|
101
109
|
let resolvedSymbolId = symbolId;
|
|
102
110
|
try {
|
|
103
|
-
await getNexusDb();
|
|
104
|
-
const nexusNative = getNexusNativeDb();
|
|
111
|
+
await getNexusDb(projectRoot);
|
|
112
|
+
const nexusNative = getNexusNativeDb(projectRoot);
|
|
105
113
|
if (nexusNative) {
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
LIMIT 1`), symbolId);
|
|
116
|
-
}
|
|
114
|
+
const candidates = typedAll(nexusNative.prepare(`SELECT id, kind, name, file_path, label, community_id FROM nexus_nodes`));
|
|
115
|
+
const selected = resolveKnowledgeSymbol(symbolId, candidates.map((node) => ({
|
|
116
|
+
id: node.id,
|
|
117
|
+
name: node.name,
|
|
118
|
+
label: node.label,
|
|
119
|
+
kind: node.kind,
|
|
120
|
+
filePath: node.file_path,
|
|
121
|
+
})));
|
|
122
|
+
const symbolNode = candidates.find((node) => node.id === selected?.id);
|
|
117
123
|
if (symbolNode) {
|
|
118
124
|
resolvedSymbolId = symbolNode.id;
|
|
119
125
|
// Callers: relations where target_id = symbolNode.id.
|
|
@@ -182,6 +188,9 @@ export async function getSymbolFullContext(symbolId, projectRoot) {
|
|
|
182
188
|
}
|
|
183
189
|
}
|
|
184
190
|
catch (err) {
|
|
191
|
+
if (err instanceof KnowledgeSymbolAmbiguityError)
|
|
192
|
+
throw err;
|
|
193
|
+
recordKnowledgeGap(coverage, 'failed', err instanceof Error ? err.message : String(err));
|
|
185
194
|
console.warn('[living-brain] NEXUS substrate error:', err instanceof Error ? err.message : String(err));
|
|
186
195
|
}
|
|
187
196
|
// ---- BRAIN substrate ----
|
|
@@ -200,12 +209,12 @@ export async function getSymbolFullContext(symbolId, projectRoot) {
|
|
|
200
209
|
];
|
|
201
210
|
const placeholders = codeEdgeTypes.map(() => '?').join(', ');
|
|
202
211
|
// brain → symbol edges (from_id is brain node, to_id is symbol)
|
|
203
|
-
const brainToSymbolEdges = typedAll(brainNative.prepare(`SELECT from_id, to_id, edge_type, weight
|
|
212
|
+
const brainToSymbolEdges = typedAll(brainNative.prepare(`SELECT from_id, to_id, edge_type, weight, provenance
|
|
204
213
|
FROM brain_page_edges
|
|
205
214
|
WHERE to_id = ? AND edge_type IN (${placeholders})
|
|
206
215
|
LIMIT 100`), resolvedSymbolId, ...codeEdgeTypes);
|
|
207
216
|
// symbol → observation edges (from_id is symbol/file, to_id is brain node)
|
|
208
|
-
const symbolToBrainEdges = typedAll(brainNative.prepare(`SELECT from_id, to_id, edge_type, weight
|
|
217
|
+
const symbolToBrainEdges = typedAll(brainNative.prepare(`SELECT from_id, to_id, edge_type, weight, provenance
|
|
209
218
|
FROM brain_page_edges
|
|
210
219
|
WHERE from_id = ? AND edge_type = ?
|
|
211
220
|
LIMIT 100`), resolvedSymbolId, EDGE_TYPES.AFFECTS);
|
|
@@ -213,6 +222,8 @@ export async function getSymbolFullContext(symbolId, projectRoot) {
|
|
|
213
222
|
const brainNodeIds = new Set();
|
|
214
223
|
const edgeByBrainId = new Map();
|
|
215
224
|
for (const edge of brainToSymbolEdges) {
|
|
225
|
+
if (!isCurrentDecisionCodeEvidence(brainNative, edge.provenance))
|
|
226
|
+
continue;
|
|
216
227
|
brainNodeIds.add(edge.from_id);
|
|
217
228
|
edgeByBrainId.set(edge.from_id, edge);
|
|
218
229
|
}
|
|
@@ -226,6 +237,11 @@ export async function getSymbolFullContext(symbolId, projectRoot) {
|
|
|
226
237
|
FROM brain_page_nodes WHERE id = ? LIMIT 1`), nodeId);
|
|
227
238
|
const edge = edgeByBrainId.get(nodeId);
|
|
228
239
|
if (brainNode && edge) {
|
|
240
|
+
const authority = graphMemoryAuthority(brainNative, brainNode.id, brainNode.node_type);
|
|
241
|
+
if (authority === 'historical')
|
|
242
|
+
continue;
|
|
243
|
+
if (authority === 'unverified')
|
|
244
|
+
recordKnowledgeGap(coverage, 'partial', `Graph memory source is unverified: ${brainNode.id}`);
|
|
229
245
|
// Filter out conduit_mentions_symbol — those go to conduitThreads
|
|
230
246
|
if (edge.edge_type === EDGE_TYPES.CONDUIT_MENTIONS_SYMBOL) {
|
|
231
247
|
result.conduitThreads.push({
|
|
@@ -235,6 +251,7 @@ export async function getSymbolFullContext(symbolId, projectRoot) {
|
|
|
235
251
|
}
|
|
236
252
|
else {
|
|
237
253
|
result.brainMemories.push({
|
|
254
|
+
authority,
|
|
238
255
|
nodeId: brainNode.id,
|
|
239
256
|
nodeType: brainNode.node_type,
|
|
240
257
|
label: brainNode.label,
|
|
@@ -248,6 +265,9 @@ export async function getSymbolFullContext(symbolId, projectRoot) {
|
|
|
248
265
|
}
|
|
249
266
|
}
|
|
250
267
|
catch (err) {
|
|
268
|
+
if (err instanceof KnowledgeSymbolAmbiguityError)
|
|
269
|
+
throw err;
|
|
270
|
+
recordKnowledgeGap(coverage, 'failed', err instanceof Error ? err.message : String(err));
|
|
251
271
|
console.warn('[living-brain] BRAIN substrate error:', err instanceof Error ? err.message : String(err));
|
|
252
272
|
}
|
|
253
273
|
// ---- TASKS substrate ----
|
|
@@ -261,6 +281,9 @@ export async function getSymbolFullContext(symbolId, projectRoot) {
|
|
|
261
281
|
}));
|
|
262
282
|
}
|
|
263
283
|
catch (err) {
|
|
284
|
+
if (err instanceof KnowledgeSymbolAmbiguityError)
|
|
285
|
+
throw err;
|
|
286
|
+
recordKnowledgeGap(coverage, 'failed', err instanceof Error ? err.message : String(err));
|
|
264
287
|
console.warn('[living-brain] TASKS substrate error:', err instanceof Error ? err.message : String(err));
|
|
265
288
|
}
|
|
266
289
|
// ---- SENTIENT substrate ----
|
|
@@ -299,6 +322,9 @@ export async function getSymbolFullContext(symbolId, projectRoot) {
|
|
|
299
322
|
}
|
|
300
323
|
}
|
|
301
324
|
catch (err) {
|
|
325
|
+
if (err instanceof KnowledgeSymbolAmbiguityError)
|
|
326
|
+
throw err;
|
|
327
|
+
recordKnowledgeGap(coverage, 'failed', err instanceof Error ? err.message : String(err));
|
|
302
328
|
console.warn('[living-brain] SENTIENT substrate error:', err instanceof Error ? err.message : String(err));
|
|
303
329
|
}
|
|
304
330
|
// ---- CONDUIT substrate ----
|
|
@@ -315,6 +341,8 @@ export async function getSymbolFullContext(symbolId, projectRoot) {
|
|
|
315
341
|
catch {
|
|
316
342
|
// Non-fatal: conduit check is best-effort
|
|
317
343
|
}
|
|
344
|
+
if (!result.nexus)
|
|
345
|
+
recordKnowledgeGap(coverage, 'missing', `No indexed symbol matches '${symbolId}'.`);
|
|
318
346
|
return result;
|
|
319
347
|
}
|
|
320
348
|
// ---------------------------------------------------------------------------
|
|
@@ -331,158 +359,133 @@ export async function getSymbolFullContext(symbolId, projectRoot) {
|
|
|
331
359
|
* - Queries brain decisions linked to this task via brain_memory_links
|
|
332
360
|
* - Computes aggregate risk tier
|
|
333
361
|
*
|
|
334
|
-
*
|
|
362
|
+
* Substrate failures are exposed through coverage; ambiguous names are rejected.
|
|
363
|
+
* Historical file associations survive optional impact failure. UNKNOWN entries
|
|
364
|
+
* use zero numeric placeholders; only blastRadius.symbolsAnalyzed counts completed
|
|
365
|
+
* assessments, and file precision does not establish that a symbol changed.
|
|
335
366
|
*
|
|
336
367
|
* @param taskId - Task ID (e.g., 'T001')
|
|
337
368
|
* @param projectRoot - Absolute path to project root
|
|
338
369
|
* @returns Full task code impact analysis
|
|
339
370
|
*/
|
|
340
371
|
export async function getTaskCodeImpact(taskId, projectRoot) {
|
|
372
|
+
const coverage = await assessKnowledgeCoverage(projectRoot);
|
|
341
373
|
const result = {
|
|
374
|
+
coverage,
|
|
342
375
|
taskId,
|
|
343
376
|
files: [],
|
|
344
377
|
symbols: [],
|
|
345
|
-
blastRadius: { totalAffected: 0, maxRisk: '
|
|
378
|
+
blastRadius: { totalAffected: 0, maxRisk: 'UNKNOWN', symbolsAnalyzed: 0 },
|
|
346
379
|
brainObservations: [],
|
|
347
380
|
decisions: [],
|
|
348
|
-
riskScore: '
|
|
381
|
+
riskScore: 'UNKNOWN',
|
|
349
382
|
};
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
const { getDb } = await import('../store/sqlite.js');
|
|
354
|
-
const { eq } = await import('drizzle-orm');
|
|
355
|
-
const { tasks: tasksTable } = await import('../store/tasks-schema.js');
|
|
356
|
-
const tasksDb = await getDb(projectRoot);
|
|
357
|
-
const rows = await tasksDb
|
|
358
|
-
.select({ filesJson: tasksTable.filesJson })
|
|
359
|
-
.from(tasksTable)
|
|
360
|
-
.where(eq(tasksTable.id, taskId))
|
|
361
|
-
.all();
|
|
362
|
-
if (rows[0]?.filesJson) {
|
|
363
|
-
filesJson = rows[0].filesJson;
|
|
364
|
-
}
|
|
365
|
-
}
|
|
366
|
-
catch {
|
|
367
|
-
// Fallback: try to get files from brain_page_edges task edges
|
|
368
|
-
}
|
|
369
|
-
if (!filesJson) {
|
|
370
|
-
// Try to infer from task_touches_symbol edges
|
|
371
|
-
try {
|
|
372
|
-
await getBrainDb(projectRoot);
|
|
373
|
-
const brainNative = getBrainNativeDb(projectRoot);
|
|
374
|
-
await getNexusDb();
|
|
375
|
-
const nexusNative = getNexusNativeDb();
|
|
376
|
-
if (brainNative && nexusNative) {
|
|
377
|
-
const taskEdges = typedAll(brainNative.prepare(`SELECT to_id FROM brain_page_edges
|
|
378
|
-
WHERE from_id = ? AND edge_type = ?
|
|
379
|
-
LIMIT 100`), `task:${taskId}`, EDGE_TYPES.TASK_TOUCHES_SYMBOL);
|
|
380
|
-
const filePaths = new Set();
|
|
381
|
-
for (const edge of taskEdges) {
|
|
382
|
-
const node = typedGet(nexusNative.prepare(`SELECT file_path FROM nexus_nodes WHERE id = ? LIMIT 1`), edge.to_id);
|
|
383
|
-
if (node?.file_path)
|
|
384
|
-
filePaths.add(node.file_path);
|
|
385
|
-
}
|
|
386
|
-
if (filePaths.size > 0) {
|
|
387
|
-
filesJson = JSON.stringify(Array.from(filePaths));
|
|
388
|
-
}
|
|
389
|
-
}
|
|
390
|
-
}
|
|
391
|
-
catch {
|
|
392
|
-
// Give up on file resolution
|
|
393
|
-
}
|
|
394
|
-
}
|
|
395
|
-
if (filesJson) {
|
|
396
|
-
try {
|
|
397
|
-
const parsed = JSON.parse(filesJson);
|
|
398
|
-
if (Array.isArray(parsed)) {
|
|
399
|
-
result.files = parsed.filter((f) => typeof f === 'string');
|
|
400
|
-
}
|
|
401
|
-
}
|
|
402
|
-
catch {
|
|
403
|
-
// malformed JSON
|
|
404
|
-
}
|
|
405
|
-
}
|
|
383
|
+
const taskEvidence = await getTaskKnowledgeEvidence(taskId, projectRoot, coverage);
|
|
384
|
+
result.files = taskEvidence.files.map((file) => file.path);
|
|
385
|
+
result.findings = taskEvidence.findings;
|
|
406
386
|
// ---- Symbols via T1067 bridge ----
|
|
407
387
|
let symbolIds = [];
|
|
388
|
+
const evidenceBySymbol = new Map();
|
|
408
389
|
try {
|
|
409
|
-
const symbolRefs = await getSymbolsForTask(taskId, projectRoot);
|
|
390
|
+
const symbolRefs = await getSymbolsForTask(taskId, projectRoot, taskEvidence);
|
|
391
|
+
for (const ref of symbolRefs)
|
|
392
|
+
evidenceBySymbol.set(ref.nexusNodeId, ref);
|
|
410
393
|
symbolIds = symbolRefs.map((s) => s.nexusNodeId);
|
|
411
394
|
}
|
|
412
395
|
catch (err) {
|
|
396
|
+
if (err instanceof KnowledgeSymbolAmbiguityError)
|
|
397
|
+
throw err;
|
|
398
|
+
recordKnowledgeGap(coverage, 'failed', err instanceof Error ? err.message : String(err));
|
|
413
399
|
console.warn('[living-brain] getSymbolsForTask failed:', err instanceof Error ? err.message : String(err));
|
|
414
400
|
}
|
|
415
401
|
// ---- Impact BFS per symbol ----
|
|
416
402
|
if (symbolIds.length > 0) {
|
|
417
403
|
try {
|
|
418
|
-
await getNexusDb();
|
|
419
|
-
const nexusNative = getNexusNativeDb();
|
|
420
|
-
if (nexusNative)
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
result.blastRadius
|
|
478
|
-
|
|
479
|
-
maxRisk: maxRiskTier(symbolEntries.map((s) => s.riskLevel)),
|
|
480
|
-
symbolsAnalyzed: symbolEntries.length,
|
|
481
|
-
};
|
|
482
|
-
result.riskScore = result.blastRadius.maxRisk;
|
|
404
|
+
await getNexusDb(projectRoot);
|
|
405
|
+
const nexusNative = getNexusNativeDb(projectRoot);
|
|
406
|
+
if (!nexusNative)
|
|
407
|
+
throw new Error('Task impact graph connection is unavailable.');
|
|
408
|
+
// Historical association is independent of the optional impact engine.
|
|
409
|
+
const readSymbol = nexusNative.prepare('SELECT id, name, kind, file_path, label FROM nexus_nodes WHERE id = ?');
|
|
410
|
+
for (const symbolId of symbolIds) {
|
|
411
|
+
const node = typedGet(readSymbol, symbolId);
|
|
412
|
+
if (!node)
|
|
413
|
+
continue;
|
|
414
|
+
result.symbols.push({
|
|
415
|
+
nexusNodeId: symbolId,
|
|
416
|
+
precision: evidenceBySymbol.get(symbolId)?.precision ?? 'file',
|
|
417
|
+
evidence: evidenceBySymbol.get(symbolId)?.evidence ?? [],
|
|
418
|
+
label: node.name ?? node.label,
|
|
419
|
+
kind: node.kind,
|
|
420
|
+
filePath: node.file_path,
|
|
421
|
+
riskLevel: 'UNKNOWN',
|
|
422
|
+
totalAffected: 0,
|
|
423
|
+
directCallers: 0,
|
|
424
|
+
});
|
|
425
|
+
}
|
|
426
|
+
const { analyzeImpact } = await import('@cleocode/nexus');
|
|
427
|
+
// Load all nodes + relations once
|
|
428
|
+
const allNodes = typedAll(nexusNative.prepare(`SELECT id, name, kind, file_path, label, is_exported FROM nexus_nodes LIMIT 50001`));
|
|
429
|
+
// T11545: `weight` moved to the sibling nexus_relation_weights table and
|
|
430
|
+
// is unused by the GraphRelation mapping below — select only structural cols.
|
|
431
|
+
const allRelations = typedAll(nexusNative.prepare(`SELECT id, source_id, target_id, type, confidence FROM nexus_relations LIMIT 200001`));
|
|
432
|
+
if (allNodes.length > 50000 || allRelations.length > 200000) {
|
|
433
|
+
recordKnowledgeGap(coverage, 'partial', 'Impact graph exceeds the 50000-node or 200000-relationship assessment limit.');
|
|
434
|
+
coverage.nextAction = `cleo doctor knowledge --task ${taskId}`;
|
|
435
|
+
}
|
|
436
|
+
// Map to GraphNode / GraphRelation contracts
|
|
437
|
+
const graphNodes = allNodes.map((n) => ({
|
|
438
|
+
id: n.id,
|
|
439
|
+
name: n.name ?? n.label,
|
|
440
|
+
kind: n.kind,
|
|
441
|
+
filePath: n.file_path ?? '',
|
|
442
|
+
startLine: 0,
|
|
443
|
+
endLine: 0,
|
|
444
|
+
language: 'unknown',
|
|
445
|
+
exported: n.is_exported === 1,
|
|
446
|
+
}));
|
|
447
|
+
const graphRelations = allRelations.map((r) => ({
|
|
448
|
+
source: r.source_id,
|
|
449
|
+
target: r.target_id,
|
|
450
|
+
type: r.type,
|
|
451
|
+
confidence: r.confidence ?? 1.0,
|
|
452
|
+
}));
|
|
453
|
+
for (const entry of result.symbols.slice(0, 50)) {
|
|
454
|
+
const impactResult = analyzeImpact(entry.nexusNodeId, graphNodes, graphRelations);
|
|
455
|
+
entry.riskLevel =
|
|
456
|
+
coverage.status !== 'current'
|
|
457
|
+
? 'UNKNOWN'
|
|
458
|
+
: impactResult.totalAffected === 0
|
|
459
|
+
? 'NONE'
|
|
460
|
+
: toRiskTier(impactResult.riskLevel);
|
|
461
|
+
entry.totalAffected = impactResult.totalAffected;
|
|
462
|
+
entry.directCallers = impactResult.affectedByDepth.depth1_willBreak.length;
|
|
463
|
+
result.blastRadius.symbolsAnalyzed += 1;
|
|
464
|
+
result.blastRadius.totalAffected += impactResult.totalAffected;
|
|
483
465
|
}
|
|
466
|
+
result.blastRadius.maxRisk = maxRiskTier(result.symbols.map((entry) => entry.riskLevel));
|
|
467
|
+
result.riskScore = result.blastRadius.maxRisk;
|
|
484
468
|
}
|
|
485
469
|
catch (err) {
|
|
470
|
+
if (err instanceof KnowledgeSymbolAmbiguityError)
|
|
471
|
+
throw err;
|
|
472
|
+
const failure = err instanceof Error ? err.message : String(err);
|
|
473
|
+
recordKnowledgeGap(coverage, 'failed', `Task impact assessment failed: ${failure}`);
|
|
474
|
+
coverage.nextAction = `cleo doctor knowledge --task ${taskId}`;
|
|
475
|
+
result.findings.push({
|
|
476
|
+
id: `task-impact:${taskId}`,
|
|
477
|
+
projectId: coverage.projectId,
|
|
478
|
+
affectedRecordIds: [taskId, ...symbolIds],
|
|
479
|
+
description: `Optional impact assessment failed: ${failure}. Inspect the diagnostic and retry the task footprint after the analyzer is available. Historical associations remain evidence, not proof that each symbol changed.`,
|
|
480
|
+
evidence: taskEvidence.files.flatMap((file) => file.evidence),
|
|
481
|
+
repairClass: 'agent-resolvable',
|
|
482
|
+
state: 'failed',
|
|
483
|
+
proposedAction: null,
|
|
484
|
+
verification: [
|
|
485
|
+
'Repeat the task footprint with a working impact analyzer; retain the same independently supported file and symbol associations.',
|
|
486
|
+
],
|
|
487
|
+
recovery: null,
|
|
488
|
+
});
|
|
486
489
|
console.warn('[living-brain] blast radius analysis failed:', err instanceof Error ? err.message : String(err));
|
|
487
490
|
}
|
|
488
491
|
}
|
|
@@ -490,8 +493,8 @@ export async function getTaskCodeImpact(taskId, projectRoot) {
|
|
|
490
493
|
try {
|
|
491
494
|
await getBrainDb(projectRoot);
|
|
492
495
|
const brainNative = getBrainNativeDb(projectRoot);
|
|
493
|
-
await getNexusDb();
|
|
494
|
-
const nexusNative = getNexusNativeDb();
|
|
496
|
+
await getNexusDb(projectRoot);
|
|
497
|
+
const nexusNative = getNexusNativeDb(projectRoot);
|
|
495
498
|
if (brainNative && nexusNative && result.files.length > 0) {
|
|
496
499
|
for (const filePath of result.files) {
|
|
497
500
|
// Find nexus file node for this path
|
|
@@ -499,12 +502,12 @@ export async function getTaskCodeImpact(taskId, projectRoot) {
|
|
|
499
502
|
if (!fileNode)
|
|
500
503
|
continue;
|
|
501
504
|
// Find modified_by edges from this file node to observation nodes
|
|
502
|
-
const modEdges = typedAll(brainNative.prepare(`SELECT from_id, to_id, edge_type, weight
|
|
505
|
+
const modEdges = typedAll(brainNative.prepare(`SELECT from_id, to_id, edge_type, weight, provenance
|
|
503
506
|
FROM brain_page_edges
|
|
504
507
|
WHERE from_id = ? AND edge_type = ?
|
|
505
508
|
LIMIT 20`), fileNode.id, EDGE_TYPES.AFFECTS);
|
|
506
509
|
// Also check reverse (observation → file via modified_by)
|
|
507
|
-
const modByEdges = typedAll(brainNative.prepare(`SELECT from_id, to_id, edge_type, weight
|
|
510
|
+
const modByEdges = typedAll(brainNative.prepare(`SELECT from_id, to_id, edge_type, weight, provenance
|
|
508
511
|
FROM brain_page_edges
|
|
509
512
|
WHERE to_id = ? AND edge_type = 'modified_by'
|
|
510
513
|
LIMIT 20`), fileNode.id);
|
|
@@ -530,6 +533,9 @@ export async function getTaskCodeImpact(taskId, projectRoot) {
|
|
|
530
533
|
}
|
|
531
534
|
}
|
|
532
535
|
catch (err) {
|
|
536
|
+
if (err instanceof KnowledgeSymbolAmbiguityError)
|
|
537
|
+
throw err;
|
|
538
|
+
recordKnowledgeGap(coverage, 'failed', err instanceof Error ? err.message : String(err));
|
|
533
539
|
console.warn('[living-brain] brain observations query failed:', err instanceof Error ? err.message : String(err));
|
|
534
540
|
}
|
|
535
541
|
// ---- Decisions from brain_memory_links ----
|
|
@@ -542,7 +548,7 @@ export async function getTaskCodeImpact(taskId, projectRoot) {
|
|
|
542
548
|
WHERE task_id = ? AND memory_type = 'decision'
|
|
543
549
|
LIMIT 20`), taskId);
|
|
544
550
|
for (const link of linkRows) {
|
|
545
|
-
const decisionRow = typedGet(brainNative.prepare(`SELECT id, decision FROM brain_decisions WHERE id =
|
|
551
|
+
const decisionRow = typedGet(brainNative.prepare(`SELECT id, decision FROM main.brain_decisions AS source WHERE id = ?${memoryEligibilityClause('decisions', 'source')} LIMIT 1`), link.memory_id);
|
|
546
552
|
if (decisionRow) {
|
|
547
553
|
result.decisions.push({
|
|
548
554
|
decisionId: decisionRow.id,
|
|
@@ -554,8 +560,32 @@ export async function getTaskCodeImpact(taskId, projectRoot) {
|
|
|
554
560
|
}
|
|
555
561
|
}
|
|
556
562
|
catch (err) {
|
|
563
|
+
if (err instanceof KnowledgeSymbolAmbiguityError)
|
|
564
|
+
throw err;
|
|
565
|
+
recordKnowledgeGap(coverage, 'failed', err instanceof Error ? err.message : String(err));
|
|
557
566
|
console.warn('[living-brain] decisions query failed:', err instanceof Error ? err.message : String(err));
|
|
558
567
|
}
|
|
568
|
+
if (result.symbols.length === 0) {
|
|
569
|
+
recordKnowledgeGap(coverage, coverage.maintenanceState === 'pending' ? 'partial' : 'missing', coverage.maintenanceState === 'pending'
|
|
570
|
+
? 'Task evidence assessment is deferred; zero matches do not establish missing evidence.'
|
|
571
|
+
: 'No task evidence has been resolved to indexed symbols.');
|
|
572
|
+
}
|
|
573
|
+
if (symbolIds.length > 50) {
|
|
574
|
+
coverage.nextAction = `cleo doctor knowledge --task ${taskId}`;
|
|
575
|
+
recordKnowledgeGap(coverage, 'partial', 'Impact is bounded to 50 task symbols; additional associations remain unassessed.');
|
|
576
|
+
}
|
|
577
|
+
if (result.symbols.length < symbolIds.length) {
|
|
578
|
+
recordKnowledgeGap(coverage, 'partial', 'Some task-linked symbols are absent from the graph.');
|
|
579
|
+
}
|
|
580
|
+
if (result.blastRadius.symbolsAnalyzed < result.symbols.length) {
|
|
581
|
+
coverage.limitations.push('Impact counts include only completed analyzer results. Zero counts for unassessed symbols are placeholders, not evidence of NONE; their risk remains UNKNOWN.');
|
|
582
|
+
}
|
|
583
|
+
if (coverage.status !== 'current') {
|
|
584
|
+
result.riskScore = 'UNKNOWN';
|
|
585
|
+
result.blastRadius.maxRisk = 'UNKNOWN';
|
|
586
|
+
for (const entry of result.symbols)
|
|
587
|
+
entry.riskLevel = 'UNKNOWN';
|
|
588
|
+
}
|
|
559
589
|
return result;
|
|
560
590
|
}
|
|
561
591
|
// ---------------------------------------------------------------------------
|
|
@@ -569,7 +599,7 @@ export async function getTaskCodeImpact(taskId, projectRoot) {
|
|
|
569
599
|
* - tasksForNodes: for each code node, which tasks touched it (T1067 reverse-lookup)
|
|
570
600
|
* - plasticitySignal: sum of weights on all anchoring edges
|
|
571
601
|
*
|
|
572
|
-
*
|
|
602
|
+
* Substrate failures are exposed through coverage; ambiguous names are rejected.
|
|
573
603
|
*
|
|
574
604
|
* @param entryId - Brain entry node ID (format: '<type>:<source-id>')
|
|
575
605
|
* @param projectRoot - Absolute path to project root
|
|
@@ -591,18 +621,20 @@ export async function getBrainEntryCodeAnchors(entryId, projectRoot) {
|
|
|
591
621
|
try {
|
|
592
622
|
await getBrainDb(projectRoot);
|
|
593
623
|
const brainNative = getBrainNativeDb(projectRoot);
|
|
594
|
-
await getNexusDb();
|
|
595
|
-
const nexusNative = getNexusNativeDb();
|
|
624
|
+
await getNexusDb(projectRoot);
|
|
625
|
+
const nexusNative = getNexusNativeDb(projectRoot);
|
|
596
626
|
if (!brainNative || !nexusNative)
|
|
597
627
|
return result;
|
|
598
628
|
const placeholders = anchorEdgeTypes.map(() => '?').join(', ');
|
|
599
629
|
// brain entry → code node edges
|
|
600
|
-
const anchorEdges = typedAll(brainNative.prepare(`SELECT from_id, to_id, edge_type, weight
|
|
630
|
+
const anchorEdges = typedAll(brainNative.prepare(`SELECT from_id, to_id, edge_type, weight, provenance
|
|
601
631
|
FROM brain_page_edges
|
|
602
632
|
WHERE from_id = ? AND edge_type IN (${placeholders})
|
|
603
633
|
LIMIT 100`), entryId, ...anchorEdgeTypes);
|
|
604
634
|
let totalWeight = 0;
|
|
605
635
|
for (const edge of anchorEdges) {
|
|
636
|
+
if (!isCurrentDecisionCodeEvidence(brainNative, edge.provenance))
|
|
637
|
+
continue;
|
|
606
638
|
// Verify the target exists in nexus
|
|
607
639
|
const nexusNode = typedGet(nexusNative.prepare(`SELECT id, kind, name, file_path, label FROM nexus_nodes WHERE id = ? LIMIT 1`), edge.to_id);
|
|
608
640
|
if (nexusNode) {
|
|
@@ -656,7 +688,7 @@ export async function getBrainEntryCodeAnchors(entryId, projectRoot) {
|
|
|
656
688
|
* 2. `getTasksForSymbol(symbolId)` — tasks that touch this symbol
|
|
657
689
|
* 3. Brain observations/decisions via `code_reference`, `modified_by`, `documents` edges
|
|
658
690
|
*
|
|
659
|
-
*
|
|
691
|
+
* Substrate failures are exposed through coverage; ambiguous names are rejected.
|
|
660
692
|
*
|
|
661
693
|
* @param symbolId - Nexus node ID or symbol name (partial match accepted)
|
|
662
694
|
* @param projectRoot - Absolute path to project root
|
|
@@ -665,35 +697,39 @@ export async function getBrainEntryCodeAnchors(entryId, projectRoot) {
|
|
|
665
697
|
* @epic T1042
|
|
666
698
|
*/
|
|
667
699
|
export async function reasonImpactOfChange(symbolId, projectRoot) {
|
|
700
|
+
const coverage = await assessKnowledgeCoverage(projectRoot);
|
|
668
701
|
const result = {
|
|
702
|
+
coverage,
|
|
669
703
|
symbolId,
|
|
670
704
|
structural: {
|
|
671
705
|
directCallers: 0,
|
|
672
706
|
likelyAffected: 0,
|
|
673
707
|
mayNeedTesting: 0,
|
|
674
708
|
totalAffected: 0,
|
|
675
|
-
riskLevel: '
|
|
709
|
+
riskLevel: 'UNKNOWN',
|
|
676
710
|
},
|
|
677
711
|
openTasks: [],
|
|
678
712
|
brainRiskNotes: [],
|
|
679
|
-
mergedRiskScore: '
|
|
713
|
+
mergedRiskScore: 'UNKNOWN',
|
|
680
714
|
narrative: `No impact data available for symbol '${symbolId}'.`,
|
|
681
715
|
};
|
|
682
716
|
// ---- Resolve nexus node ID (may be a name) ----
|
|
683
717
|
let resolvedId = symbolId;
|
|
684
718
|
try {
|
|
685
|
-
await getNexusDb();
|
|
686
|
-
const nexusNative = getNexusNativeDb();
|
|
719
|
+
await getNexusDb(projectRoot);
|
|
720
|
+
const nexusNative = getNexusNativeDb(projectRoot);
|
|
687
721
|
if (nexusNative) {
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
722
|
+
const candidates = typedAll(nexusNative.prepare(`SELECT id, kind, name, file_path, label, community_id FROM nexus_nodes`));
|
|
723
|
+
const nexusNode = resolveKnowledgeSymbol(symbolId, candidates.map((node) => ({
|
|
724
|
+
id: node.id,
|
|
725
|
+
name: node.name,
|
|
726
|
+
label: node.label,
|
|
727
|
+
kind: node.kind,
|
|
728
|
+
filePath: node.file_path,
|
|
729
|
+
})));
|
|
692
730
|
if (!nexusNode) {
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
WHERE LOWER(name) = LOWER(?) AND kind NOT IN ('community', 'process', 'folder')
|
|
696
|
-
LIMIT 1`), symbolId);
|
|
731
|
+
recordKnowledgeGap(coverage, 'missing', `No indexed symbol matches '${symbolId}'.`);
|
|
732
|
+
return result;
|
|
697
733
|
}
|
|
698
734
|
if (nexusNode) {
|
|
699
735
|
resolvedId = nexusNode.id;
|
|
@@ -701,12 +737,15 @@ export async function reasonImpactOfChange(symbolId, projectRoot) {
|
|
|
701
737
|
}
|
|
702
738
|
}
|
|
703
739
|
catch (err) {
|
|
740
|
+
if (err instanceof KnowledgeSymbolAmbiguityError)
|
|
741
|
+
throw err;
|
|
742
|
+
recordKnowledgeGap(coverage, 'failed', err instanceof Error ? err.message : String(err));
|
|
704
743
|
console.warn('[living-brain] reasonImpactOfChange nexus resolve failed:', err instanceof Error ? err.message : String(err));
|
|
705
744
|
}
|
|
706
745
|
// ---- Structural blast radius via analyzeImpact ----
|
|
707
746
|
try {
|
|
708
|
-
await getNexusDb();
|
|
709
|
-
const nexusNative = getNexusNativeDb();
|
|
747
|
+
await getNexusDb(projectRoot);
|
|
748
|
+
const nexusNative = getNexusNativeDb(projectRoot);
|
|
710
749
|
if (nexusNative) {
|
|
711
750
|
const { analyzeImpact } = await import('@cleocode/nexus');
|
|
712
751
|
const allNodes = typedAll(nexusNative.prepare(`SELECT id, name, kind, file_path, label, is_exported FROM nexus_nodes LIMIT 50000`));
|
|
@@ -729,33 +768,24 @@ export async function reasonImpactOfChange(symbolId, projectRoot) {
|
|
|
729
768
|
type: r.type,
|
|
730
769
|
confidence: r.confidence ?? 1.0,
|
|
731
770
|
}));
|
|
732
|
-
|
|
733
|
-
try {
|
|
734
|
-
impactResult = analyzeImpact(resolvedId, graphNodes, graphRelations);
|
|
735
|
-
}
|
|
736
|
-
catch {
|
|
737
|
-
impactResult = {
|
|
738
|
-
target: resolvedId,
|
|
739
|
-
riskLevel: 'low',
|
|
740
|
-
summary: '',
|
|
741
|
-
affectedByDepth: {
|
|
742
|
-
depth1_willBreak: [],
|
|
743
|
-
depth2_likelyAffected: [],
|
|
744
|
-
depth3_mayNeedTesting: [],
|
|
745
|
-
},
|
|
746
|
-
totalAffected: 0,
|
|
747
|
-
};
|
|
748
|
-
}
|
|
771
|
+
const impactResult = analyzeImpact(resolvedId, graphNodes, graphRelations);
|
|
749
772
|
result.structural = {
|
|
750
773
|
directCallers: impactResult.affectedByDepth.depth1_willBreak.length,
|
|
751
774
|
likelyAffected: impactResult.affectedByDepth.depth2_likelyAffected.length,
|
|
752
775
|
mayNeedTesting: impactResult.affectedByDepth.depth3_mayNeedTesting.length,
|
|
753
776
|
totalAffected: impactResult.totalAffected,
|
|
754
|
-
riskLevel:
|
|
777
|
+
riskLevel: coverage.status !== 'current'
|
|
778
|
+
? 'UNKNOWN'
|
|
779
|
+
: impactResult.totalAffected === 0
|
|
780
|
+
? 'NONE'
|
|
781
|
+
: toRiskTier(impactResult.riskLevel),
|
|
755
782
|
};
|
|
756
783
|
}
|
|
757
784
|
}
|
|
758
785
|
catch (err) {
|
|
786
|
+
if (err instanceof KnowledgeSymbolAmbiguityError)
|
|
787
|
+
throw err;
|
|
788
|
+
recordKnowledgeGap(coverage, 'failed', err instanceof Error ? err.message : String(err));
|
|
759
789
|
console.warn('[living-brain] reasonImpactOfChange structural analysis failed:', err instanceof Error ? err.message : String(err));
|
|
760
790
|
}
|
|
761
791
|
// ---- Open tasks via task_touches_symbol ----
|
|
@@ -768,6 +798,9 @@ export async function reasonImpactOfChange(symbolId, projectRoot) {
|
|
|
768
798
|
}));
|
|
769
799
|
}
|
|
770
800
|
catch (err) {
|
|
801
|
+
if (err instanceof KnowledgeSymbolAmbiguityError)
|
|
802
|
+
throw err;
|
|
803
|
+
recordKnowledgeGap(coverage, 'failed', err instanceof Error ? err.message : String(err));
|
|
771
804
|
console.warn('[living-brain] reasonImpactOfChange open-tasks lookup failed:', err instanceof Error ? err.message : String(err));
|
|
772
805
|
}
|
|
773
806
|
// ---- Brain risk notes via code_reference / documents / modified_by edges ----
|
|
@@ -783,18 +816,20 @@ export async function reasonImpactOfChange(symbolId, projectRoot) {
|
|
|
783
816
|
];
|
|
784
817
|
const placeholders = riskEdgeTypes.map(() => '?').join(', ');
|
|
785
818
|
// Brain nodes → symbol (brain references this symbol)
|
|
786
|
-
const brainToSymbolEdges = typedAll(brainNative.prepare(`SELECT from_id, to_id, edge_type, weight
|
|
819
|
+
const brainToSymbolEdges = typedAll(brainNative.prepare(`SELECT from_id, to_id, edge_type, weight, provenance
|
|
787
820
|
FROM brain_page_edges
|
|
788
821
|
WHERE to_id = ? AND edge_type IN (${placeholders})
|
|
789
822
|
LIMIT 50`), resolvedId, ...riskEdgeTypes);
|
|
790
823
|
// symbol → brain nodes (symbol points to observations)
|
|
791
|
-
const symbolToBrainEdges = typedAll(brainNative.prepare(`SELECT from_id, to_id, edge_type, weight
|
|
824
|
+
const symbolToBrainEdges = typedAll(brainNative.prepare(`SELECT from_id, to_id, edge_type, weight, provenance
|
|
792
825
|
FROM brain_page_edges
|
|
793
826
|
WHERE from_id = ? AND edge_type = ?
|
|
794
827
|
LIMIT 50`), resolvedId, EDGE_TYPES.AFFECTS);
|
|
795
828
|
const seenIds = new Set();
|
|
796
829
|
const processEdges = (edges, isReverse) => {
|
|
797
830
|
for (const edge of edges) {
|
|
831
|
+
if (!isCurrentDecisionCodeEvidence(brainNative, edge.provenance))
|
|
832
|
+
continue;
|
|
798
833
|
const nodeId = isReverse ? edge.from_id : edge.to_id;
|
|
799
834
|
if (seenIds.has(nodeId))
|
|
800
835
|
continue;
|
|
@@ -802,7 +837,13 @@ export async function reasonImpactOfChange(symbolId, projectRoot) {
|
|
|
802
837
|
const brainNode = typedGet(brainNative.prepare(`SELECT id, node_type, label, quality_score
|
|
803
838
|
FROM brain_page_nodes WHERE id = ? LIMIT 1`), nodeId);
|
|
804
839
|
if (brainNode) {
|
|
840
|
+
const authority = graphMemoryAuthority(brainNative, brainNode.id, brainNode.node_type);
|
|
841
|
+
if (authority === 'historical')
|
|
842
|
+
continue;
|
|
843
|
+
if (authority === 'unverified')
|
|
844
|
+
recordKnowledgeGap(coverage, 'partial', `Graph memory source is unverified: ${brainNode.id}`);
|
|
805
845
|
const riskNote = {
|
|
846
|
+
authority,
|
|
806
847
|
nodeId: brainNode.id,
|
|
807
848
|
nodeType: brainNode.node_type,
|
|
808
849
|
label: brainNode.label,
|
|
@@ -818,6 +859,9 @@ export async function reasonImpactOfChange(symbolId, projectRoot) {
|
|
|
818
859
|
}
|
|
819
860
|
}
|
|
820
861
|
catch (err) {
|
|
862
|
+
if (err instanceof KnowledgeSymbolAmbiguityError)
|
|
863
|
+
throw err;
|
|
864
|
+
recordKnowledgeGap(coverage, 'failed', err instanceof Error ? err.message : String(err));
|
|
821
865
|
console.warn('[living-brain] reasonImpactOfChange brain risk notes failed:', err instanceof Error ? err.message : String(err));
|
|
822
866
|
}
|
|
823
867
|
// ---- Compute merged risk score ----
|
|
@@ -841,7 +885,7 @@ export async function reasonImpactOfChange(symbolId, projectRoot) {
|
|
|
841
885
|
const openCount = result.openTasks.length;
|
|
842
886
|
const riskNoteCount = result.brainRiskNotes.length;
|
|
843
887
|
result.narrative =
|
|
844
|
-
`
|
|
888
|
+
`Static analysis of ${symLabel} identifies ${d1} direct caller${d1 !== 1 ? 's' : ''} (d=1)` +
|
|
845
889
|
(d2 > 0 ? `, likely affect ${d2} at d=2` : '') +
|
|
846
890
|
(openCount > 0
|
|
847
891
|
? `, and is referenced in ${openCount} open task${openCount !== 1 ? 's' : ''}`
|
|
@@ -850,6 +894,11 @@ export async function reasonImpactOfChange(symbolId, projectRoot) {
|
|
|
850
894
|
? ` and ${riskNoteCount} BRAIN risk note${riskNoteCount !== 1 ? 's' : ''}`
|
|
851
895
|
: '') +
|
|
852
896
|
`. Merged risk: ${result.mergedRiskScore}.`;
|
|
897
|
+
if (coverage.status !== 'current') {
|
|
898
|
+
result.mergedRiskScore = 'UNKNOWN';
|
|
899
|
+
result.structural.riskLevel = 'UNKNOWN';
|
|
900
|
+
result.narrative = `Impact cannot be fully assessed for ${symLabel}. Coverage: ${coverage.status}. ${coverage.reasons.join(' ')}`;
|
|
901
|
+
}
|
|
853
902
|
return result;
|
|
854
903
|
}
|
|
855
904
|
// ---------------------------------------------------------------------------
|
|
@@ -862,6 +911,9 @@ export async function nexusFullContext(symbolId, projectRoot) {
|
|
|
862
911
|
return engineSuccess(result);
|
|
863
912
|
}
|
|
864
913
|
catch (error) {
|
|
914
|
+
if (error instanceof KnowledgeSymbolAmbiguityError) {
|
|
915
|
+
return engineError(error.code, error.message, { details: { candidates: error.candidates } });
|
|
916
|
+
}
|
|
865
917
|
return engineError('E_INTERNAL', error instanceof Error ? error.message : String(error));
|
|
866
918
|
}
|
|
867
919
|
}
|
|
@@ -872,6 +924,9 @@ export async function nexusTaskFootprint(taskId, projectRoot) {
|
|
|
872
924
|
return engineSuccess(result);
|
|
873
925
|
}
|
|
874
926
|
catch (error) {
|
|
927
|
+
if (error instanceof KnowledgeSymbolAmbiguityError) {
|
|
928
|
+
return engineError(error.code, error.message, { details: { candidates: error.candidates } });
|
|
929
|
+
}
|
|
875
930
|
return engineError('E_INTERNAL', error instanceof Error ? error.message : String(error));
|
|
876
931
|
}
|
|
877
932
|
}
|
|
@@ -882,6 +937,9 @@ export async function nexusBrainAnchors(entryId, projectRoot) {
|
|
|
882
937
|
return engineSuccess(result);
|
|
883
938
|
}
|
|
884
939
|
catch (error) {
|
|
940
|
+
if (error instanceof KnowledgeSymbolAmbiguityError) {
|
|
941
|
+
return engineError(error.code, error.message, { details: { candidates: error.candidates } });
|
|
942
|
+
}
|
|
885
943
|
return engineError('E_INTERNAL', error instanceof Error ? error.message : String(error));
|
|
886
944
|
}
|
|
887
945
|
}
|
|
@@ -892,6 +950,9 @@ export async function nexusImpactFull(symbolId, projectRoot) {
|
|
|
892
950
|
return engineSuccess(result);
|
|
893
951
|
}
|
|
894
952
|
catch (error) {
|
|
953
|
+
if (error instanceof KnowledgeSymbolAmbiguityError) {
|
|
954
|
+
return engineError(error.code, error.message, { details: { candidates: error.candidates } });
|
|
955
|
+
}
|
|
895
956
|
return engineError('E_INTERNAL', error instanceof Error ? error.message : String(error));
|
|
896
957
|
}
|
|
897
958
|
}
|
|
@@ -902,6 +963,9 @@ export async function nexusWhy(symbolId, projectRoot) {
|
|
|
902
963
|
return engineSuccess(result);
|
|
903
964
|
}
|
|
904
965
|
catch (error) {
|
|
966
|
+
if (error instanceof KnowledgeSymbolAmbiguityError) {
|
|
967
|
+
return engineError(error.code, error.message, { details: { candidates: error.candidates } });
|
|
968
|
+
}
|
|
905
969
|
return engineError('E_INTERNAL', error instanceof Error ? error.message : String(error));
|
|
906
970
|
}
|
|
907
971
|
}
|