@cleocode/core 2026.9.8 → 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 +11 -1
- package/dist/memory/brain-writer-thread.d.ts.map +1 -1
- package/dist/memory/brain-writer-thread.js +87 -20
- 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 +89 -42
- 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/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
|
@@ -0,0 +1,786 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared coverage assessment and unambiguous symbol resolution.
|
|
3
|
+
*
|
|
4
|
+
* Code placed in `packages/core/` per Package-Boundary Check — verified
|
|
5
|
+
* against AGENTS.md. These services do not invoke a language model.
|
|
6
|
+
*/
|
|
7
|
+
import { execFile } from 'node:child_process';
|
|
8
|
+
import { createHash } from 'node:crypto';
|
|
9
|
+
import { realpathSync } from 'node:fs';
|
|
10
|
+
import fs from 'node:fs/promises';
|
|
11
|
+
import { isAbsolute, relative, resolve } from 'node:path';
|
|
12
|
+
import { promisify } from 'node:util';
|
|
13
|
+
import { legacyProjectId } from '@cleocode/paths';
|
|
14
|
+
import { min } from 'drizzle-orm';
|
|
15
|
+
import { z } from 'zod';
|
|
16
|
+
import { worktreeScope } from '../paths.js';
|
|
17
|
+
import { getProjectInfoSync } from '../project-info.js';
|
|
18
|
+
import { getNexusDb, getNexusNativeDb, nexusSchema } from '../store/nexus-sqlite.js';
|
|
19
|
+
import { generateProjectHash } from './hash.js';
|
|
20
|
+
import { resolveSourceRoots } from './source-roots.js';
|
|
21
|
+
const execFileAsync = promisify(execFile);
|
|
22
|
+
const sourceRootSchema = z
|
|
23
|
+
.object({
|
|
24
|
+
requestedPath: z.string().refine(isAbsolute, 'Root path must be absolute'),
|
|
25
|
+
canonicalPath: z.string().refine(isAbsolute, 'Canonical path must be absolute').nullable(),
|
|
26
|
+
graphPrefix: z.string(),
|
|
27
|
+
explicitlyIncluded: z.boolean(),
|
|
28
|
+
revision: z
|
|
29
|
+
.string()
|
|
30
|
+
.regex(/^(?:[a-f0-9]{40}|[a-f0-9]{64})$/)
|
|
31
|
+
.nullable(),
|
|
32
|
+
status: z.enum(['available', 'unversioned', 'missing', 'failed', 'pending']),
|
|
33
|
+
diagnostics: z.array(z.string()),
|
|
34
|
+
})
|
|
35
|
+
.superRefine((root, context) => {
|
|
36
|
+
if (root.explicitlyIncluded !== (root.graphPrefix !== '') ||
|
|
37
|
+
isAbsolute(root.graphPrefix) ||
|
|
38
|
+
root.graphPrefix.split('/').includes('..') ||
|
|
39
|
+
root.graphPrefix.includes('\\') ||
|
|
40
|
+
(root.explicitlyIncluded &&
|
|
41
|
+
root.canonicalPath !== null &&
|
|
42
|
+
root.canonicalPath !== root.requestedPath))
|
|
43
|
+
context.addIssue({
|
|
44
|
+
code: 'custom',
|
|
45
|
+
message: 'Invalid root graph prefix or inclusion ownership',
|
|
46
|
+
});
|
|
47
|
+
if (root.status === 'available'
|
|
48
|
+
? !root.revision || !root.canonicalPath
|
|
49
|
+
: root.revision !== null || !root.diagnostics.length)
|
|
50
|
+
context.addIssue({
|
|
51
|
+
code: 'custom',
|
|
52
|
+
message: 'Root status requires a revision or explicit diagnostic',
|
|
53
|
+
});
|
|
54
|
+
if (root.status === 'unversioned' && root.explicitlyIncluded)
|
|
55
|
+
context.addIssue({
|
|
56
|
+
code: 'custom',
|
|
57
|
+
message: 'An explicitly included repository cannot be unversioned',
|
|
58
|
+
});
|
|
59
|
+
});
|
|
60
|
+
const sourceRootsSchema = z
|
|
61
|
+
.object({
|
|
62
|
+
projectId: z.string().min(1),
|
|
63
|
+
projectRoot: z.string().refine(isAbsolute),
|
|
64
|
+
sourceRoot: z.string().refine(isAbsolute),
|
|
65
|
+
assessedAt: z.iso.datetime(),
|
|
66
|
+
roots: z.array(sourceRootSchema).min(1),
|
|
67
|
+
})
|
|
68
|
+
.superRefine((assessment, context) => {
|
|
69
|
+
const prefixes = new Set();
|
|
70
|
+
const canonical = new Set();
|
|
71
|
+
for (const root of assessment.roots) {
|
|
72
|
+
if (prefixes.has(root.graphPrefix) ||
|
|
73
|
+
(root.canonicalPath !== null && canonical.has(root.canonicalPath)) ||
|
|
74
|
+
resolve(assessment.sourceRoot, root.graphPrefix) !== root.requestedPath)
|
|
75
|
+
context.addIssue({ code: 'custom', message: 'Duplicate or mismatched root ownership' });
|
|
76
|
+
prefixes.add(root.graphPrefix);
|
|
77
|
+
if (root.canonicalPath)
|
|
78
|
+
canonical.add(root.canonicalPath);
|
|
79
|
+
}
|
|
80
|
+
if (assessment.roots[0]?.graphPrefix !== '')
|
|
81
|
+
context.addIssue({ code: 'custom', message: 'Source root must be the first observation' });
|
|
82
|
+
});
|
|
83
|
+
const analysisCapabilitySchema = z.enum([
|
|
84
|
+
'file-evidence',
|
|
85
|
+
'documentary-evidence',
|
|
86
|
+
'configuration-evidence',
|
|
87
|
+
'schema-evidence',
|
|
88
|
+
'data-evidence',
|
|
89
|
+
'resource-evidence',
|
|
90
|
+
'declarations',
|
|
91
|
+
'imports',
|
|
92
|
+
'call-references',
|
|
93
|
+
'access-references',
|
|
94
|
+
'type-heritage',
|
|
95
|
+
'sql-schema-objects',
|
|
96
|
+
'sql-migrations',
|
|
97
|
+
'sql-triggers',
|
|
98
|
+
'sql-constraints',
|
|
99
|
+
'sql-literal-references',
|
|
100
|
+
'sql-dynamic-references',
|
|
101
|
+
]);
|
|
102
|
+
const fileCapabilitiesSchema = z
|
|
103
|
+
.object({
|
|
104
|
+
role: z.enum([
|
|
105
|
+
'executable',
|
|
106
|
+
'sql',
|
|
107
|
+
'documentation',
|
|
108
|
+
'configuration',
|
|
109
|
+
'schema',
|
|
110
|
+
'generated-data',
|
|
111
|
+
'data',
|
|
112
|
+
'asset',
|
|
113
|
+
'unknown',
|
|
114
|
+
]),
|
|
115
|
+
classification: z.object({
|
|
116
|
+
basis: z.enum(['path', 'content', 'path-and-content', 'unknown']),
|
|
117
|
+
reason: z
|
|
118
|
+
.string()
|
|
119
|
+
.refine((reason) => reason.trim().length > 0, 'Classification reason must be nonempty'),
|
|
120
|
+
}),
|
|
121
|
+
requested: z
|
|
122
|
+
.array(analysisCapabilitySchema)
|
|
123
|
+
.refine((values) => new Set(values).size === values.length, 'Requested capabilities must be unique'),
|
|
124
|
+
completed: z
|
|
125
|
+
.array(analysisCapabilitySchema)
|
|
126
|
+
.refine((values) => new Set(values).size === values.length, 'Completed capabilities must be unique'),
|
|
127
|
+
limitations: z.array(z.string()),
|
|
128
|
+
})
|
|
129
|
+
.superRefine((value, context) => {
|
|
130
|
+
if (value.completed.some((capability) => !value.requested.includes(capability)))
|
|
131
|
+
context.addIssue({ code: 'custom', message: 'Completed capabilities must be requested' });
|
|
132
|
+
if (value.role !== 'unknown' && value.classification.basis === 'unknown')
|
|
133
|
+
context.addIssue({
|
|
134
|
+
code: 'custom',
|
|
135
|
+
message: 'A known role requires positive classification evidence',
|
|
136
|
+
});
|
|
137
|
+
});
|
|
138
|
+
const assessmentSchema = z.object({
|
|
139
|
+
generation: z.uuid().optional(),
|
|
140
|
+
sourceRoots: sourceRootsSchema.optional(),
|
|
141
|
+
sourceRoot: z.string(),
|
|
142
|
+
assessedRevision: z.string().nullable(),
|
|
143
|
+
assessedAt: z.string(),
|
|
144
|
+
includedRepositories: z.array(z.string()).optional(),
|
|
145
|
+
references: z
|
|
146
|
+
.array(z.object({
|
|
147
|
+
kind: z.enum([
|
|
148
|
+
'unmodeled-source',
|
|
149
|
+
'ambiguous',
|
|
150
|
+
'external',
|
|
151
|
+
'dynamic',
|
|
152
|
+
'shadowed',
|
|
153
|
+
'unresolved',
|
|
154
|
+
]),
|
|
155
|
+
filePath: z.string(),
|
|
156
|
+
sourceId: z.string(),
|
|
157
|
+
targetId: z.string().optional(),
|
|
158
|
+
targetName: z.string(),
|
|
159
|
+
relationship: z.enum(['calls', 'accesses']),
|
|
160
|
+
reason: z.string(),
|
|
161
|
+
candidateIds: z.array(z.string()).optional(),
|
|
162
|
+
generation: z.string().optional(),
|
|
163
|
+
publicationGeneration: z.uuid().optional(),
|
|
164
|
+
span: z
|
|
165
|
+
.object({
|
|
166
|
+
startIndex: z.number().int().nonnegative(),
|
|
167
|
+
endIndex: z.number().int().nonnegative(),
|
|
168
|
+
startLine: z.number().int().positive(),
|
|
169
|
+
endLine: z.number().int().positive(),
|
|
170
|
+
startColumn: z.number().int().nonnegative(),
|
|
171
|
+
endColumn: z.number().int().nonnegative(),
|
|
172
|
+
offsetEncoding: z.literal('utf16'),
|
|
173
|
+
})
|
|
174
|
+
.refine((span) => span.endIndex >= span.startIndex && span.endLine >= span.startLine, 'Reference span must be an ordered original source range')
|
|
175
|
+
.optional(),
|
|
176
|
+
}))
|
|
177
|
+
.optional(),
|
|
178
|
+
files: z.array(z.object({
|
|
179
|
+
path: z.string(),
|
|
180
|
+
status: z.enum(['analyzed', 'excluded', 'unsupported', 'oversized', 'failed']),
|
|
181
|
+
capabilities: fileCapabilitiesSchema.optional(),
|
|
182
|
+
reason: z.string().optional(),
|
|
183
|
+
mtimeMs: z.number().optional(),
|
|
184
|
+
size: z.number().optional(),
|
|
185
|
+
contentHash: z.string().optional(),
|
|
186
|
+
})),
|
|
187
|
+
});
|
|
188
|
+
/**
|
|
189
|
+
* Read validated generation provenance without treating malformed metadata as healthy.
|
|
190
|
+
* @param projectRoot - Explicit project root, or the ambient canonical project when omitted.
|
|
191
|
+
* @returns The published assessment, or null for a legacy generation.
|
|
192
|
+
* @remarks Reads only through the canonical project store. Malformed metadata throws.
|
|
193
|
+
* @example
|
|
194
|
+
* ```ts
|
|
195
|
+
* const generation = await readKnowledgeIndexAssessment(projectRoot);
|
|
196
|
+
* ```
|
|
197
|
+
*/
|
|
198
|
+
export async function readKnowledgeIndexAssessment(projectRoot) {
|
|
199
|
+
await getNexusDb(projectRoot);
|
|
200
|
+
const native = getNexusNativeDb(projectRoot);
|
|
201
|
+
if (!native)
|
|
202
|
+
throw new Error('The graph database is unavailable.');
|
|
203
|
+
const row = native
|
|
204
|
+
.prepare(`SELECT value FROM main._nexus_meta WHERE key = 'graph_assessment'`)
|
|
205
|
+
.get();
|
|
206
|
+
if (!row)
|
|
207
|
+
return null;
|
|
208
|
+
if (typeof row.value !== 'string')
|
|
209
|
+
throw new Error('Graph assessment metadata is not text.');
|
|
210
|
+
const assessment = assessmentSchema.parse(JSON.parse(row.value));
|
|
211
|
+
if (assessment.sourceRoots) {
|
|
212
|
+
const prefixes = assessment.sourceRoots.roots
|
|
213
|
+
.filter((root) => root.explicitlyIncluded)
|
|
214
|
+
.map((root) => root.graphPrefix);
|
|
215
|
+
if (assessment.sourceRoots.sourceRoot !== assessment.sourceRoot ||
|
|
216
|
+
assessment.sourceRoots.roots[0]?.revision !== assessment.assessedRevision ||
|
|
217
|
+
JSON.stringify(prefixes) !== JSON.stringify(assessment.includedRepositories ?? []))
|
|
218
|
+
throw new Error('Root observations disagree with graph source scope or revision.');
|
|
219
|
+
}
|
|
220
|
+
return assessment;
|
|
221
|
+
}
|
|
222
|
+
/**
|
|
223
|
+
* An unresolved short name with exact identifiers the caller can choose from.
|
|
224
|
+
* @remarks Consumers preserve the candidate list in their error envelope.
|
|
225
|
+
* @example
|
|
226
|
+
* ```ts
|
|
227
|
+
* if (error instanceof KnowledgeSymbolAmbiguityError) return error.candidates;
|
|
228
|
+
* ```
|
|
229
|
+
*/
|
|
230
|
+
export class KnowledgeSymbolAmbiguityError extends Error {
|
|
231
|
+
/** Stable machine-readable failure code. */
|
|
232
|
+
code = 'E_AMBIGUOUS_SYMBOL';
|
|
233
|
+
/** Every best-matching candidate; no checkout is silently selected. */
|
|
234
|
+
candidates;
|
|
235
|
+
/**
|
|
236
|
+
* Create an ambiguity error preserving candidates for structured envelopes.
|
|
237
|
+
* @param query - Unresolved short symbol name.
|
|
238
|
+
* @param candidates - All equally eligible qualified identifiers.
|
|
239
|
+
*/
|
|
240
|
+
constructor(query, candidates) {
|
|
241
|
+
super(`Symbol '${query}' is ambiguous; use an exact candidate identifier.`);
|
|
242
|
+
this.name = 'KnowledgeSymbolAmbiguityError';
|
|
243
|
+
this.candidates = candidates;
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
/**
|
|
247
|
+
* Resolve exact identifiers, then exact names, then partial names without choosing a tie.
|
|
248
|
+
* @param query - Qualified graph identifier or symbol name.
|
|
249
|
+
* @param nodes - Candidate symbols from the scoped graph.
|
|
250
|
+
* @returns The unique candidate, or null if none matches.
|
|
251
|
+
* @remarks Ambiguous short names throw an error carrying every eligible candidate.
|
|
252
|
+
* @example
|
|
253
|
+
* ```ts
|
|
254
|
+
* const target = resolveKnowledgeSymbol('src/api.ts::serve', candidates);
|
|
255
|
+
* ```
|
|
256
|
+
*/
|
|
257
|
+
export function resolveKnowledgeSymbol(query, nodes) {
|
|
258
|
+
const idMatch = nodes.find((node) => node.id === query);
|
|
259
|
+
if (idMatch)
|
|
260
|
+
return idMatch;
|
|
261
|
+
const lowered = query.toLowerCase();
|
|
262
|
+
const symbols = nodes.filter((node) => !['community', 'process', 'folder'].includes(node.kind));
|
|
263
|
+
const exact = symbols.filter((node) => (node.name ?? node.label).toLowerCase() === lowered);
|
|
264
|
+
const matches = exact.length
|
|
265
|
+
? exact
|
|
266
|
+
: symbols.filter((node) => (node.name ?? node.label).toLowerCase().includes(lowered));
|
|
267
|
+
if (matches.length > 1)
|
|
268
|
+
throw new KnowledgeSymbolAmbiguityError(query, matches);
|
|
269
|
+
return matches[0] ?? null;
|
|
270
|
+
}
|
|
271
|
+
/**
|
|
272
|
+
* Add an explicit coverage limitation without hiding a prior diagnostic failure.
|
|
273
|
+
* @param coverage - Assessment to update in place.
|
|
274
|
+
* @param status - Newly observed coverage status.
|
|
275
|
+
* @param reason - Inspectable reason supporting the status.
|
|
276
|
+
* @returns Nothing; the supplied assessment retains the strongest observed defect.
|
|
277
|
+
* @remarks A partial result cannot overwrite a prior missing or failed result.
|
|
278
|
+
* @example
|
|
279
|
+
* ```ts
|
|
280
|
+
* recordKnowledgeGap(coverage, 'missing', 'No indexed symbol matches the evidence.');
|
|
281
|
+
* ```
|
|
282
|
+
*/
|
|
283
|
+
export function recordKnowledgeGap(coverage, status, reason) {
|
|
284
|
+
const severity = {
|
|
285
|
+
current: 0,
|
|
286
|
+
partial: 1,
|
|
287
|
+
stale: 2,
|
|
288
|
+
missing: 3,
|
|
289
|
+
failed: 4,
|
|
290
|
+
};
|
|
291
|
+
if (severity[status] > severity[coverage.status])
|
|
292
|
+
coverage.status = status;
|
|
293
|
+
if (!coverage.reasons.includes(reason))
|
|
294
|
+
coverage.reasons.push(reason);
|
|
295
|
+
}
|
|
296
|
+
/**
|
|
297
|
+
* Assess graph coverage within the caller's maintenance budget (two seconds by default).
|
|
298
|
+
*
|
|
299
|
+
* Deferred work is read-only and cannot apply a repair after the response. A
|
|
300
|
+
* synchronous native query cannot be preempted by JavaScript's event loop.
|
|
301
|
+
* @param projectRoot - Canonical project root whose knowledge is assessed.
|
|
302
|
+
* @param projectId - Existing project identity when supplied by the caller.
|
|
303
|
+
* @param budgetMs - Maximum asynchronous foreground assessment time.
|
|
304
|
+
* @returns Coverage with explicit reasons and a next action when deferred.
|
|
305
|
+
* @remarks This service does not invoke models or mutate derived knowledge.
|
|
306
|
+
* @example
|
|
307
|
+
* ```ts
|
|
308
|
+
* const coverage = await assessKnowledgeCoverage(projectRoot, undefined, 2000);
|
|
309
|
+
* ```
|
|
310
|
+
*/
|
|
311
|
+
export async function assessKnowledgeCoverage(projectRoot, projectId, budgetMs = 2000) {
|
|
312
|
+
const capturedRoot = resolve(projectRoot);
|
|
313
|
+
const inherited = worktreeScope.getStore();
|
|
314
|
+
if (inherited?.execution && resolve(inherited.execution.identity.projectRoot) !== capturedRoot)
|
|
315
|
+
throw new Error('Coverage project differs from captured execution scope.');
|
|
316
|
+
return worktreeScope.run({ ...inherited, worktreeRoot: capturedRoot, projectHash: generateProjectHash(capturedRoot) }, () => assessScopedCoverage(capturedRoot, projectId, budgetMs));
|
|
317
|
+
}
|
|
318
|
+
/** Disclose remaining work without erasing stronger observed defects. */
|
|
319
|
+
function markCoveragePending(coverage) {
|
|
320
|
+
recordKnowledgeGap(coverage, 'partial', 'Coverage assessment exceeded its shared maintenance deadline.');
|
|
321
|
+
coverage.maintenanceState = 'pending';
|
|
322
|
+
coverage.nextAction = 'cleo doctor knowledge';
|
|
323
|
+
}
|
|
324
|
+
/** Retain captured path ownership and observed progress through a deferred response. */
|
|
325
|
+
async function assessScopedCoverage(projectRoot, projectId, budgetMs) {
|
|
326
|
+
const deadline = Date.now() + Math.max(0, budgetMs);
|
|
327
|
+
const info = getProjectInfoSync(projectRoot);
|
|
328
|
+
const inventory = {
|
|
329
|
+
requested: null,
|
|
330
|
+
completed: 0,
|
|
331
|
+
unassessed: null,
|
|
332
|
+
changed: 0,
|
|
333
|
+
missing: 0,
|
|
334
|
+
failed: 0,
|
|
335
|
+
};
|
|
336
|
+
const capabilities = {
|
|
337
|
+
requestedFiles: null,
|
|
338
|
+
assessedFiles: 0,
|
|
339
|
+
unassessedFiles: null,
|
|
340
|
+
excludedFiles: null,
|
|
341
|
+
legacyFiles: 0,
|
|
342
|
+
incompleteFiles: 0,
|
|
343
|
+
extractionFailedFiles: 0,
|
|
344
|
+
byRole: {},
|
|
345
|
+
byCapability: {},
|
|
346
|
+
};
|
|
347
|
+
const coverage = {
|
|
348
|
+
capabilities,
|
|
349
|
+
status: 'partial',
|
|
350
|
+
projectId: projectId ?? (info?.projectId || info?.projectHash || legacyProjectId(projectRoot)),
|
|
351
|
+
assessedRevision: null,
|
|
352
|
+
indexedRevision: null,
|
|
353
|
+
assessedAt: new Date().toISOString(),
|
|
354
|
+
reasons: [],
|
|
355
|
+
evidence: [],
|
|
356
|
+
limitations: ['Static analysis cannot prove that all runtime callers have been discovered.'],
|
|
357
|
+
inventory,
|
|
358
|
+
};
|
|
359
|
+
let timer;
|
|
360
|
+
const deferred = new Promise((resolveDeferred) => {
|
|
361
|
+
timer = setTimeout(() => {
|
|
362
|
+
markCoveragePending(coverage);
|
|
363
|
+
// A returned snapshot cannot be rewritten by a late read. The timer does
|
|
364
|
+
// not preempt synchronous native database or filesystem work.
|
|
365
|
+
resolveDeferred({
|
|
366
|
+
...coverage,
|
|
367
|
+
inventory: { ...inventory },
|
|
368
|
+
capabilities: structuredClone(capabilities),
|
|
369
|
+
reasons: [...coverage.reasons],
|
|
370
|
+
evidence: [...coverage.evidence],
|
|
371
|
+
limitations: [...coverage.limitations],
|
|
372
|
+
});
|
|
373
|
+
}, Math.max(0, deadline - Date.now()));
|
|
374
|
+
});
|
|
375
|
+
try {
|
|
376
|
+
return await Promise.race([
|
|
377
|
+
assessCoverage(projectRoot, projectId, deadline, coverage, inventory),
|
|
378
|
+
deferred,
|
|
379
|
+
]);
|
|
380
|
+
}
|
|
381
|
+
finally {
|
|
382
|
+
if (timer !== undefined)
|
|
383
|
+
clearTimeout(timer);
|
|
384
|
+
}
|
|
385
|
+
}
|
|
386
|
+
/** Account for one persisted role without equating resource evidence with executable coverage. */
|
|
387
|
+
function assessFileCapabilities(file, coverage) {
|
|
388
|
+
const summary = coverage.capabilities;
|
|
389
|
+
if (!summary)
|
|
390
|
+
return;
|
|
391
|
+
if (file.status === 'excluded') {
|
|
392
|
+
coverage.limitations.push(`Excluded source: ${file.path}: ${file.reason ?? 'No exclusion reason recorded'}`);
|
|
393
|
+
return;
|
|
394
|
+
}
|
|
395
|
+
summary.assessedFiles++;
|
|
396
|
+
if (summary.unassessedFiles !== null)
|
|
397
|
+
summary.unassessedFiles--;
|
|
398
|
+
let incomplete = false;
|
|
399
|
+
const report = file.capabilities;
|
|
400
|
+
if (!report) {
|
|
401
|
+
summary.legacyFiles++;
|
|
402
|
+
incomplete = true;
|
|
403
|
+
recordKnowledgeGap(coverage, 'partial', `Legacy report lacks role and capability provenance: ${file.path}`);
|
|
404
|
+
}
|
|
405
|
+
else {
|
|
406
|
+
summary.byRole[report.role] = (summary.byRole[report.role] ?? 0) + 1;
|
|
407
|
+
for (const capability of report.requested) {
|
|
408
|
+
const count = summary.byCapability[capability] ?? {
|
|
409
|
+
requestedFiles: 0,
|
|
410
|
+
completedFiles: 0,
|
|
411
|
+
incompleteFiles: 0,
|
|
412
|
+
};
|
|
413
|
+
count.requestedFiles++;
|
|
414
|
+
if (report.completed.includes(capability))
|
|
415
|
+
count.completedFiles++;
|
|
416
|
+
else
|
|
417
|
+
count.incompleteFiles++;
|
|
418
|
+
summary.byCapability[capability] = count;
|
|
419
|
+
}
|
|
420
|
+
const missing = report.requested.filter((capability) => !report.completed.includes(capability));
|
|
421
|
+
const required = report.role === 'executable' || report.role === 'unknown'
|
|
422
|
+
? [
|
|
423
|
+
'file-evidence',
|
|
424
|
+
'declarations',
|
|
425
|
+
'imports',
|
|
426
|
+
'call-references',
|
|
427
|
+
'access-references',
|
|
428
|
+
'type-heritage',
|
|
429
|
+
]
|
|
430
|
+
: report.role === 'sql'
|
|
431
|
+
? [
|
|
432
|
+
'file-evidence',
|
|
433
|
+
'sql-schema-objects',
|
|
434
|
+
'sql-migrations',
|
|
435
|
+
'sql-triggers',
|
|
436
|
+
'sql-constraints',
|
|
437
|
+
'sql-literal-references',
|
|
438
|
+
'sql-dynamic-references',
|
|
439
|
+
]
|
|
440
|
+
: ['file-evidence'];
|
|
441
|
+
const unrequested = required.filter((capability) => !report.requested.includes(capability));
|
|
442
|
+
if (missing.length || unrequested.length || report.role === 'unknown') {
|
|
443
|
+
incomplete = true;
|
|
444
|
+
recordKnowledgeGap(coverage, 'partial', `Incomplete ${report.role} capabilities: ${file.path}; uncompleted=${missing.join(',') || 'none'}; unrequested=${unrequested.join(',') || 'none'}`);
|
|
445
|
+
}
|
|
446
|
+
for (const limitation of report.limitations)
|
|
447
|
+
if (!coverage.limitations.includes(limitation))
|
|
448
|
+
coverage.limitations.push(limitation);
|
|
449
|
+
}
|
|
450
|
+
if (file.status === 'failed') {
|
|
451
|
+
summary.extractionFailedFiles++;
|
|
452
|
+
incomplete = true;
|
|
453
|
+
recordKnowledgeGap(coverage, 'failed', `Extraction failed: ${file.path}${file.reason ? `: ${file.reason}` : ''}`);
|
|
454
|
+
}
|
|
455
|
+
if (file.status === 'unsupported' || file.status === 'oversized') {
|
|
456
|
+
if (!report ||
|
|
457
|
+
report.role === 'executable' ||
|
|
458
|
+
report.role === 'sql' ||
|
|
459
|
+
report.role === 'unknown' ||
|
|
460
|
+
incomplete) {
|
|
461
|
+
incomplete = true;
|
|
462
|
+
recordKnowledgeGap(coverage, 'partial', `${file.status}: ${file.path}`);
|
|
463
|
+
}
|
|
464
|
+
else
|
|
465
|
+
coverage.limitations.push(`${file.status}: ${file.path}${file.reason ? `: ${file.reason}` : ''}`);
|
|
466
|
+
}
|
|
467
|
+
if (incomplete)
|
|
468
|
+
summary.incompleteFiles++;
|
|
469
|
+
}
|
|
470
|
+
/**
|
|
471
|
+
* Assess the complete persisted inventory using cooperative async file checks.
|
|
472
|
+
* Legacy indexes remain partial without revision/content provenance. Population
|
|
473
|
+
* size never supplies an artificial freshness ceiling; the original deadline
|
|
474
|
+
* bounds further work and preserves an explicit unassessed remainder.
|
|
475
|
+
*/
|
|
476
|
+
async function assessCoverage(projectRoot, projectId, deadline, coverage, inventory) {
|
|
477
|
+
const info = getProjectInfoSync(projectRoot);
|
|
478
|
+
if (Date.now() >= deadline) {
|
|
479
|
+
markCoveragePending(coverage);
|
|
480
|
+
return coverage;
|
|
481
|
+
}
|
|
482
|
+
try {
|
|
483
|
+
const db = await getNexusDb(projectRoot);
|
|
484
|
+
if (Date.now() >= deadline) {
|
|
485
|
+
markCoveragePending(coverage);
|
|
486
|
+
return coverage;
|
|
487
|
+
}
|
|
488
|
+
const table = nexusSchema.nexusNodes;
|
|
489
|
+
const files = db
|
|
490
|
+
.select({ filePath: table.filePath, indexedAt: min(table.indexedAt) })
|
|
491
|
+
.from(table)
|
|
492
|
+
.groupBy(table.filePath)
|
|
493
|
+
.all();
|
|
494
|
+
const assessment = await readKnowledgeIndexAssessment(projectRoot);
|
|
495
|
+
if (files.length === 0 && !assessment) {
|
|
496
|
+
inventory.requested = 0;
|
|
497
|
+
inventory.unassessed = 0;
|
|
498
|
+
coverage.capabilities = {
|
|
499
|
+
requestedFiles: 0,
|
|
500
|
+
assessedFiles: 0,
|
|
501
|
+
unassessedFiles: 0,
|
|
502
|
+
excludedFiles: 0,
|
|
503
|
+
legacyFiles: 0,
|
|
504
|
+
incompleteFiles: 0,
|
|
505
|
+
extractionFailedFiles: 0,
|
|
506
|
+
byRole: {},
|
|
507
|
+
byCapability: {},
|
|
508
|
+
};
|
|
509
|
+
coverage.status = 'missing';
|
|
510
|
+
coverage.reasons.push('No indexed graph is available; run cleo nexus analyze.');
|
|
511
|
+
return coverage;
|
|
512
|
+
}
|
|
513
|
+
if (assessment) {
|
|
514
|
+
const sourceFiles = assessment.files.filter((file) => file.status !== 'excluded');
|
|
515
|
+
inventory.requested = sourceFiles.length;
|
|
516
|
+
inventory.unassessed = sourceFiles.length;
|
|
517
|
+
if (coverage.capabilities) {
|
|
518
|
+
coverage.capabilities.requestedFiles = sourceFiles.length;
|
|
519
|
+
coverage.capabilities.unassessedFiles = sourceFiles.length;
|
|
520
|
+
coverage.capabilities.excludedFiles = assessment.files.length - sourceFiles.length;
|
|
521
|
+
}
|
|
522
|
+
if (Date.now() >= deadline) {
|
|
523
|
+
markCoveragePending(coverage);
|
|
524
|
+
return coverage;
|
|
525
|
+
}
|
|
526
|
+
coverage.indexedRevision = assessment.assessedRevision;
|
|
527
|
+
const sourceRoot = resolve(assessment.sourceRoot);
|
|
528
|
+
if (!assessment.sourceRoots) {
|
|
529
|
+
try {
|
|
530
|
+
const { stdout } = await execFileAsync('git', ['rev-parse', 'HEAD'], {
|
|
531
|
+
cwd: sourceRoot,
|
|
532
|
+
timeout: 500,
|
|
533
|
+
});
|
|
534
|
+
coverage.assessedRevision = stdout.trim() || null;
|
|
535
|
+
}
|
|
536
|
+
catch {
|
|
537
|
+
coverage.assessedRevision = null;
|
|
538
|
+
}
|
|
539
|
+
coverage.status =
|
|
540
|
+
coverage.indexedRevision && coverage.assessedRevision ? 'current' : 'partial';
|
|
541
|
+
if (!coverage.indexedRevision || !coverage.assessedRevision) {
|
|
542
|
+
coverage.reasons.push('The source or index revision could not be established.');
|
|
543
|
+
}
|
|
544
|
+
else if (coverage.indexedRevision !== coverage.assessedRevision) {
|
|
545
|
+
recordKnowledgeGap(coverage, 'stale', 'The source revision differs from the indexed revision.');
|
|
546
|
+
}
|
|
547
|
+
}
|
|
548
|
+
else {
|
|
549
|
+
const verifiedIdentity = projectId ?? (info?.projectId || info?.projectHash);
|
|
550
|
+
if (assessment.sourceRoots.projectRoot !== realpathSync(projectRoot) ||
|
|
551
|
+
(verifiedIdentity !== undefined && verifiedIdentity !== assessment.sourceRoots.projectId))
|
|
552
|
+
throw new Error('Recorded source ownership differs from the requested project binding.');
|
|
553
|
+
coverage.projectId = assessment.sourceRoots.projectId;
|
|
554
|
+
coverage.status = 'current';
|
|
555
|
+
}
|
|
556
|
+
if (!assessment.sourceRoots) {
|
|
557
|
+
recordKnowledgeGap(coverage, 'partial', 'Legacy generation has no verified per-root ownership or revision observations.');
|
|
558
|
+
}
|
|
559
|
+
else {
|
|
560
|
+
const observed = await resolveSourceRoots({
|
|
561
|
+
projectId: assessment.sourceRoots.projectId,
|
|
562
|
+
projectRoot: assessment.sourceRoots.projectRoot,
|
|
563
|
+
sourceRoot,
|
|
564
|
+
deadline,
|
|
565
|
+
includedRepositories: assessment.includedRepositories ??
|
|
566
|
+
assessment.sourceRoots.roots
|
|
567
|
+
.filter((root) => root.explicitlyIncluded)
|
|
568
|
+
.map((root) => root.graphPrefix),
|
|
569
|
+
});
|
|
570
|
+
coverage.assessedRevision = observed.roots[0]?.revision ?? null;
|
|
571
|
+
if (observed.roots.length !== assessment.sourceRoots.roots.length)
|
|
572
|
+
recordKnowledgeGap(coverage, 'stale', 'Configured source-root population changed.');
|
|
573
|
+
for (const root of observed.roots) {
|
|
574
|
+
const indexed = assessment.sourceRoots.roots.find((candidate) => candidate.graphPrefix === root.graphPrefix);
|
|
575
|
+
if (!indexed ||
|
|
576
|
+
indexed.canonicalPath !== root.canonicalPath ||
|
|
577
|
+
indexed.revision !== root.revision)
|
|
578
|
+
recordKnowledgeGap(coverage, 'stale', `Source ownership or revision changed: ${root.requestedPath}`);
|
|
579
|
+
if (root.status !== 'available')
|
|
580
|
+
recordKnowledgeGap(coverage, root.status === 'failed' || root.status === 'missing' ? 'failed' : 'partial', `${root.requestedPath}: ${root.diagnostics.join('; ')}`);
|
|
581
|
+
coverage.evidence.push({
|
|
582
|
+
id: `source_root:${root.graphPrefix || '.'}`,
|
|
583
|
+
projectId: coverage.projectId,
|
|
584
|
+
source: 'index',
|
|
585
|
+
revision: indexed?.revision ?? null,
|
|
586
|
+
precision: 'project',
|
|
587
|
+
});
|
|
588
|
+
}
|
|
589
|
+
}
|
|
590
|
+
if (files.length === 0)
|
|
591
|
+
recordKnowledgeGap(coverage, 'missing', 'The published graph has no indexed nodes.');
|
|
592
|
+
if (assessment.references?.length) {
|
|
593
|
+
recordKnowledgeGap(coverage, 'partial', `${assessment.references.length} unresolved or unmodeled static references remain; known callers are incomplete. Inspect assessment.references in cleo nexus status.`);
|
|
594
|
+
coverage.nextAction = 'cleo nexus status';
|
|
595
|
+
}
|
|
596
|
+
for (const file of assessment.files) {
|
|
597
|
+
if (Date.now() >= deadline) {
|
|
598
|
+
markCoveragePending(coverage);
|
|
599
|
+
return coverage;
|
|
600
|
+
}
|
|
601
|
+
assessFileCapabilities(file, coverage);
|
|
602
|
+
}
|
|
603
|
+
for (const file of sourceFiles) {
|
|
604
|
+
if (Date.now() >= deadline) {
|
|
605
|
+
markCoveragePending(coverage);
|
|
606
|
+
return coverage;
|
|
607
|
+
}
|
|
608
|
+
const absolute = resolve(sourceRoot, file.path);
|
|
609
|
+
const relativePath = relative(sourceRoot, absolute);
|
|
610
|
+
if (relativePath.startsWith('..') || isAbsolute(relativePath)) {
|
|
611
|
+
inventory.failed++;
|
|
612
|
+
inventory.completed++;
|
|
613
|
+
inventory.unassessed--;
|
|
614
|
+
recordKnowledgeGap(coverage, 'failed', `Indexed path is outside source ownership: ${file.path}`);
|
|
615
|
+
continue;
|
|
616
|
+
}
|
|
617
|
+
try {
|
|
618
|
+
const stat = await fs.stat(absolute);
|
|
619
|
+
if (Date.now() >= deadline) {
|
|
620
|
+
markCoveragePending(coverage);
|
|
621
|
+
return coverage;
|
|
622
|
+
}
|
|
623
|
+
if (!stat.isFile())
|
|
624
|
+
throw new Error('Indexed source is not a regular file');
|
|
625
|
+
let changed = false;
|
|
626
|
+
if (!file.contentHash) {
|
|
627
|
+
recordKnowledgeGap(coverage, 'partial', `No source content fingerprint: ${file.path}`);
|
|
628
|
+
coverage.nextAction = 'cleo nexus analyze';
|
|
629
|
+
}
|
|
630
|
+
else {
|
|
631
|
+
const content = await fs.readFile(absolute, {
|
|
632
|
+
signal: AbortSignal.timeout(Math.max(1, deadline - Date.now())),
|
|
633
|
+
});
|
|
634
|
+
if (Date.now() >= deadline) {
|
|
635
|
+
markCoveragePending(coverage);
|
|
636
|
+
return coverage;
|
|
637
|
+
}
|
|
638
|
+
if (createHash('sha256').update(content).digest('hex') !== file.contentHash) {
|
|
639
|
+
changed = true;
|
|
640
|
+
recordKnowledgeGap(coverage, 'stale', `Source content changed after indexing: ${file.path}`);
|
|
641
|
+
coverage.nextAction = 'cleo nexus analyze';
|
|
642
|
+
}
|
|
643
|
+
}
|
|
644
|
+
if (file.mtimeMs === undefined || file.size === undefined) {
|
|
645
|
+
recordKnowledgeGap(coverage, 'partial', `No file freshness evidence: ${file.path}`);
|
|
646
|
+
}
|
|
647
|
+
else if (stat.mtimeMs !== file.mtimeMs || stat.size !== file.size) {
|
|
648
|
+
changed = true;
|
|
649
|
+
recordKnowledgeGap(coverage, 'stale', `Source changed after indexing: ${file.path}`);
|
|
650
|
+
}
|
|
651
|
+
if (changed)
|
|
652
|
+
inventory.changed++;
|
|
653
|
+
}
|
|
654
|
+
catch (error) {
|
|
655
|
+
if (Date.now() >= deadline) {
|
|
656
|
+
markCoveragePending(coverage);
|
|
657
|
+
return coverage;
|
|
658
|
+
}
|
|
659
|
+
if (error instanceof Error &&
|
|
660
|
+
'code' in error &&
|
|
661
|
+
(error.code === 'ENOENT' || error.code === 'ENOTDIR')) {
|
|
662
|
+
inventory.missing++;
|
|
663
|
+
recordKnowledgeGap(coverage, 'stale', `Indexed source is missing: ${file.path}`);
|
|
664
|
+
}
|
|
665
|
+
else {
|
|
666
|
+
inventory.failed++;
|
|
667
|
+
recordKnowledgeGap(coverage, 'failed', `Source freshness read failed: ${file.path}: ${error instanceof Error ? error.message : String(error)}`);
|
|
668
|
+
}
|
|
669
|
+
}
|
|
670
|
+
inventory.completed++;
|
|
671
|
+
inventory.unassessed--;
|
|
672
|
+
}
|
|
673
|
+
if (Date.now() >= deadline) {
|
|
674
|
+
markCoveragePending(coverage);
|
|
675
|
+
return coverage;
|
|
676
|
+
}
|
|
677
|
+
try {
|
|
678
|
+
const { stdout } = await execFileAsync('git', ['ls-files', '--cached', '--others', '--exclude-standard', '-z'], {
|
|
679
|
+
cwd: sourceRoot,
|
|
680
|
+
timeout: Math.max(1, Math.min(500, deadline - Date.now())),
|
|
681
|
+
maxBuffer: 1024 * 1024,
|
|
682
|
+
});
|
|
683
|
+
const recorded = new Set(assessment.files.map((file) => file.path));
|
|
684
|
+
const added = stdout.split('\0').filter((path) => path && !recorded.has(path));
|
|
685
|
+
if (added.length)
|
|
686
|
+
recordKnowledgeGap(coverage, 'partial', 'Unindexed files exist in the configured source root.');
|
|
687
|
+
}
|
|
688
|
+
catch {
|
|
689
|
+
if (Date.now() >= deadline)
|
|
690
|
+
markCoveragePending(coverage);
|
|
691
|
+
else
|
|
692
|
+
recordKnowledgeGap(coverage, 'partial', 'Unindexed-file detection was unavailable.');
|
|
693
|
+
}
|
|
694
|
+
if (Date.now() >= deadline)
|
|
695
|
+
markCoveragePending(coverage);
|
|
696
|
+
coverage.evidence.push({
|
|
697
|
+
id: 'graph_assessment',
|
|
698
|
+
projectId: coverage.projectId,
|
|
699
|
+
source: 'index',
|
|
700
|
+
revision: coverage.indexedRevision,
|
|
701
|
+
precision: 'project',
|
|
702
|
+
});
|
|
703
|
+
return coverage;
|
|
704
|
+
}
|
|
705
|
+
coverage.reasons.push('The index has no verified generation revision or complete extraction report.');
|
|
706
|
+
coverage.evidence.push({
|
|
707
|
+
id: 'nexus_nodes',
|
|
708
|
+
projectId: coverage.projectId,
|
|
709
|
+
source: 'index',
|
|
710
|
+
revision: null,
|
|
711
|
+
precision: 'project',
|
|
712
|
+
});
|
|
713
|
+
const legacyFiles = files.filter((file) => file.filePath !== null);
|
|
714
|
+
inventory.requested = legacyFiles.length;
|
|
715
|
+
inventory.unassessed = legacyFiles.length;
|
|
716
|
+
const root = resolve(projectRoot);
|
|
717
|
+
for (const file of legacyFiles) {
|
|
718
|
+
if (Date.now() >= deadline) {
|
|
719
|
+
markCoveragePending(coverage);
|
|
720
|
+
return coverage;
|
|
721
|
+
}
|
|
722
|
+
if (!file.filePath) {
|
|
723
|
+
inventory.failed++;
|
|
724
|
+
inventory.completed++;
|
|
725
|
+
inventory.unassessed--;
|
|
726
|
+
recordKnowledgeGap(coverage, 'failed', 'Indexed source path is empty.');
|
|
727
|
+
continue;
|
|
728
|
+
}
|
|
729
|
+
const absolute = resolve(root, file.filePath);
|
|
730
|
+
const relativePath = relative(root, absolute);
|
|
731
|
+
if (relativePath.startsWith('..') || isAbsolute(relativePath)) {
|
|
732
|
+
inventory.failed++;
|
|
733
|
+
inventory.completed++;
|
|
734
|
+
inventory.unassessed--;
|
|
735
|
+
recordKnowledgeGap(coverage, 'failed', `Indexed path is outside project ownership: ${file.filePath}`);
|
|
736
|
+
continue;
|
|
737
|
+
}
|
|
738
|
+
try {
|
|
739
|
+
const timestamp = file.indexedAt?.includes('T')
|
|
740
|
+
? file.indexedAt
|
|
741
|
+
: `${file.indexedAt?.replace(' ', 'T')}Z`;
|
|
742
|
+
const indexedAt = Date.parse(timestamp);
|
|
743
|
+
if (!Number.isFinite(indexedAt)) {
|
|
744
|
+
coverage.reasons.push(`Index timestamp is missing or invalid: ${file.filePath}`);
|
|
745
|
+
}
|
|
746
|
+
else {
|
|
747
|
+
const stat = await fs.stat(absolute);
|
|
748
|
+
if (Date.now() >= deadline) {
|
|
749
|
+
markCoveragePending(coverage);
|
|
750
|
+
return coverage;
|
|
751
|
+
}
|
|
752
|
+
if (!stat.isFile())
|
|
753
|
+
throw new Error('Indexed source is not a regular file');
|
|
754
|
+
if (stat.mtimeMs > indexedAt) {
|
|
755
|
+
inventory.changed++;
|
|
756
|
+
recordKnowledgeGap(coverage, 'stale', `Source changed after indexing: ${file.filePath}`);
|
|
757
|
+
}
|
|
758
|
+
}
|
|
759
|
+
}
|
|
760
|
+
catch (error) {
|
|
761
|
+
if (Date.now() >= deadline) {
|
|
762
|
+
markCoveragePending(coverage);
|
|
763
|
+
return coverage;
|
|
764
|
+
}
|
|
765
|
+
if (error instanceof Error &&
|
|
766
|
+
'code' in error &&
|
|
767
|
+
(error.code === 'ENOENT' || error.code === 'ENOTDIR')) {
|
|
768
|
+
inventory.missing++;
|
|
769
|
+
recordKnowledgeGap(coverage, 'stale', `Indexed source is missing: ${file.filePath}`);
|
|
770
|
+
}
|
|
771
|
+
else {
|
|
772
|
+
inventory.failed++;
|
|
773
|
+
recordKnowledgeGap(coverage, 'failed', `Source freshness read failed: ${file.filePath}: ${error instanceof Error ? error.message : String(error)}`);
|
|
774
|
+
}
|
|
775
|
+
}
|
|
776
|
+
inventory.completed++;
|
|
777
|
+
inventory.unassessed--;
|
|
778
|
+
}
|
|
779
|
+
}
|
|
780
|
+
catch (error) {
|
|
781
|
+
coverage.status = 'failed';
|
|
782
|
+
coverage.reasons.push(`Graph assessment failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
783
|
+
}
|
|
784
|
+
return coverage;
|
|
785
|
+
}
|
|
786
|
+
//# sourceMappingURL=knowledge.js.map
|