@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
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* Pipeline Manifest SQLite Implementation
|
|
3
3
|
*
|
|
4
4
|
* Reimplements all 14 pipeline manifest operations using Drizzle ORM +
|
|
5
|
-
*
|
|
5
|
+
* Canonical docs_pipeline_manifest writes and provenance-aware legacy history reads.
|
|
6
6
|
*
|
|
7
7
|
* Provides a one-time migration function to import existing MANIFEST.jsonl
|
|
8
8
|
* entries into the new table.
|
|
@@ -13,29 +13,25 @@
|
|
|
13
13
|
import { createHash } from 'node:crypto';
|
|
14
14
|
import { existsSync, readFileSync, renameSync } from 'node:fs';
|
|
15
15
|
import { join } from 'node:path';
|
|
16
|
-
import {
|
|
17
|
-
import {
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
16
|
+
import { isDeepStrictEqual } from 'node:util';
|
|
17
|
+
import { eq, like, or } from 'drizzle-orm';
|
|
18
|
+
import { z } from 'zod';
|
|
19
|
+
import { createDocsReadModel } from '../docs/docs-read-model.js';
|
|
20
|
+
import { EngineResultError } from '../engine-result.js';
|
|
21
|
+
import { captureProjectScope, worktreeScope } from '../project-scope.js';
|
|
22
|
+
import { docsPipelineManifest as pipelineManifest } from '../store/schema/cleo-project/docs.js';
|
|
23
|
+
import { pipelineManifest as legacyManifest } from '../store/schema/manifest.js';
|
|
24
|
+
function manifestScope(cwd) {
|
|
25
|
+
return captureProjectScope(cwd ?? getProjectRoot(), worktreeScope.getStore());
|
|
21
26
|
}
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
* The bare call used to return whichever project was opened LAST in the
|
|
27
|
-
* process — under test isolation (or any multi-project run) that silently
|
|
28
|
-
* pointed manifest archiving at the wrong database.
|
|
29
|
-
*
|
|
30
|
-
* @param cwd - Project working directory.
|
|
31
|
-
*/
|
|
32
|
-
async function getNativeDb(cwd) {
|
|
33
|
-
const { getNativeDb: _getNativeDb } = await import('../store/sqlite.js');
|
|
34
|
-
return _getNativeDb(cwd);
|
|
27
|
+
async function getBinding(cwd) {
|
|
28
|
+
const scope = manifestScope(cwd);
|
|
29
|
+
const { bindTasksDomain } = await import('../store/sqlite.js');
|
|
30
|
+
return worktreeScope.run(scope, () => bindTasksDomain(scope.worktreeRoot));
|
|
35
31
|
}
|
|
36
32
|
import { createPage } from '../pagination.js';
|
|
37
33
|
import { getProjectRoot, resolveCleoDir } from '../paths.js';
|
|
38
|
-
import { filterManifestEntries
|
|
34
|
+
import { filterManifestEntries } from './manifest-filter.js';
|
|
39
35
|
export { filterManifestEntries };
|
|
40
36
|
function normalizeLimit(limit) {
|
|
41
37
|
return typeof limit === 'number' && limit > 0 ? limit : undefined;
|
|
@@ -46,37 +42,155 @@ function normalizeOffset(offset) {
|
|
|
46
42
|
function effectivePageLimit(limit, offset) {
|
|
47
43
|
return limit ?? (offset !== undefined ? 50 : undefined);
|
|
48
44
|
}
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
45
|
+
// ============================================================================
|
|
46
|
+
// Internal helpers
|
|
47
|
+
// ============================================================================
|
|
48
|
+
function readStoredRows(binding, includeArchived = false, id) {
|
|
49
|
+
const { db, store } = binding;
|
|
50
|
+
const modern = db
|
|
51
|
+
.select()
|
|
52
|
+
.from(pipelineManifest)
|
|
53
|
+
.where(id ? eq(pipelineManifest.id, id) : undefined)
|
|
54
|
+
.all();
|
|
55
|
+
const legacy = db
|
|
56
|
+
.select()
|
|
57
|
+
.from(legacyManifest)
|
|
58
|
+
.where(id ? eq(legacyManifest.id, id) : undefined)
|
|
59
|
+
.all();
|
|
60
|
+
const rows = new Map();
|
|
61
|
+
for (const [table, sourceRows] of [
|
|
62
|
+
[pipelineManifest, modern],
|
|
63
|
+
[legacyManifest, legacy],
|
|
64
|
+
]) {
|
|
65
|
+
const tableName = table === pipelineManifest ? 'docs_pipeline_manifest' : 'pipeline_manifest';
|
|
66
|
+
for (const row of sourceRows) {
|
|
67
|
+
const existing = rows.get(row.id);
|
|
68
|
+
if (existing) {
|
|
69
|
+
const { provenance, ...stored } = existing;
|
|
70
|
+
// Compare every persisted scalar, including raw content/metadata bytes and archival state.
|
|
71
|
+
// A short content hash or the lossy public projection cannot establish equality.
|
|
72
|
+
if (!isDeepStrictEqual(stored, row)) {
|
|
73
|
+
throw new EngineResultError({
|
|
74
|
+
code: 'E_MANIFEST_ID_CONFLICT',
|
|
75
|
+
message: `Manifest '${row.id}' has conflicting stored payloads; inspect both sources before repair.`,
|
|
76
|
+
details: {
|
|
77
|
+
entryId: row.id,
|
|
78
|
+
databasePath: store.dbPath,
|
|
79
|
+
candidates: [
|
|
80
|
+
{
|
|
81
|
+
table: provenance.tables[0],
|
|
82
|
+
payload: stored,
|
|
83
|
+
sha256: createHash('sha256').update(JSON.stringify(stored)).digest('hex'),
|
|
84
|
+
},
|
|
85
|
+
{
|
|
86
|
+
table: tableName,
|
|
87
|
+
payload: row,
|
|
88
|
+
sha256: createHash('sha256').update(JSON.stringify(row)).digest('hex'),
|
|
89
|
+
},
|
|
90
|
+
],
|
|
91
|
+
},
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
provenance.tables.push(tableName);
|
|
95
|
+
}
|
|
96
|
+
else {
|
|
97
|
+
rows.set(row.id, {
|
|
98
|
+
...row,
|
|
99
|
+
provenance: { databasePath: store.dbPath, tables: [tableName] },
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
}
|
|
54
103
|
}
|
|
55
|
-
|
|
56
|
-
|
|
104
|
+
return [...rows.values()]
|
|
105
|
+
.filter((row) => includeArchived || row.archivedAt === null)
|
|
106
|
+
.sort((a, b) => b.createdAt.localeCompare(a.createdAt) || a.id.localeCompare(b.id));
|
|
107
|
+
}
|
|
108
|
+
async function readRows(projectRoot, includeArchived = false, id) {
|
|
109
|
+
const binding = await getBinding(projectRoot);
|
|
110
|
+
return binding.db.transaction(() => readStoredRows(binding, includeArchived, id));
|
|
111
|
+
}
|
|
112
|
+
function requireModernRows(rows) {
|
|
113
|
+
const legacy = rows.filter((row) => row.provenance.tables.includes('pipeline_manifest'));
|
|
114
|
+
if (legacy.length) {
|
|
115
|
+
throw new EngineResultError({
|
|
116
|
+
code: 'E_MANIFEST_LEGACY_REPAIR_REQUIRED',
|
|
117
|
+
message: 'Legacy manifest evidence requires an explicit guarded repair before mutation.',
|
|
118
|
+
details: { entries: legacy.map((row) => ({ entryId: row.id, provenance: row.provenance })) },
|
|
119
|
+
});
|
|
57
120
|
}
|
|
58
|
-
|
|
59
|
-
|
|
121
|
+
}
|
|
122
|
+
function manifestFailure(code, error) {
|
|
123
|
+
if (error instanceof EngineResultError) {
|
|
124
|
+
return {
|
|
125
|
+
success: false,
|
|
126
|
+
error: { code: error.code, message: error.message, details: error.details },
|
|
127
|
+
};
|
|
60
128
|
}
|
|
61
|
-
|
|
62
|
-
|
|
129
|
+
const causes = [];
|
|
130
|
+
const seen = new Set();
|
|
131
|
+
let cause = error;
|
|
132
|
+
while (!seen.has(cause)) {
|
|
133
|
+
seen.add(cause);
|
|
134
|
+
causes.push(cause.message);
|
|
135
|
+
if (!(cause.cause instanceof Error))
|
|
136
|
+
break;
|
|
137
|
+
cause = cause.cause;
|
|
63
138
|
}
|
|
64
|
-
return {
|
|
65
|
-
conditions,
|
|
66
|
-
requiresInMemoryFiltering: filter.taskId !== undefined || filter.topic !== undefined || filter.actionable !== undefined,
|
|
67
|
-
};
|
|
139
|
+
return { success: false, error: { code, message: causes.join(' → ') } };
|
|
68
140
|
}
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
141
|
+
/**
|
|
142
|
+
* Insert authentic prepared manifest rows in one guarded project transaction.
|
|
143
|
+
*
|
|
144
|
+
* @remarks
|
|
145
|
+
* Preserves caller handle ownership and both storage histories. Identical complete
|
|
146
|
+
* payloads are idempotent; differing identities and legacy rows never authorize
|
|
147
|
+
* replacement. Any batch failure rolls back all inserted rows.
|
|
148
|
+
* @param rows - Complete persisted payloads, including raw content and metadata.
|
|
149
|
+
* @param projectRoot - Explicit project identity captured before asynchronous binding.
|
|
150
|
+
* @param expectedDb - Caller-owned canonical task-domain handle for this project.
|
|
151
|
+
* @returns Number of newly inserted rows; identical stored rows are skipped.
|
|
152
|
+
* @throws If database identity, historical evidence, or any transactional write fails.
|
|
153
|
+
* @example
|
|
154
|
+
* ```ts
|
|
155
|
+
* const inserted = await insertManifestRows(preparedRows, projectRoot, db);
|
|
156
|
+
* ```
|
|
157
|
+
*/
|
|
158
|
+
export async function insertManifestRows(rows, projectRoot, expectedDb) {
|
|
159
|
+
try {
|
|
160
|
+
const binding = await getBinding(projectRoot);
|
|
161
|
+
if (expectedDb !== binding.db) {
|
|
162
|
+
throw new EngineResultError({
|
|
163
|
+
code: 'E_MANIFEST_DATABASE_MISMATCH',
|
|
164
|
+
message: 'Supplied database is not the captured canonical project binding; ownership is unverified.',
|
|
165
|
+
details: { databasePath: binding.store.dbPath },
|
|
166
|
+
});
|
|
167
|
+
}
|
|
168
|
+
return binding.db.transaction(() => {
|
|
169
|
+
let inserted = 0;
|
|
170
|
+
for (const row of rows) {
|
|
171
|
+
const existing = readStoredRows(binding, true, row.id);
|
|
172
|
+
requireModernRows(existing);
|
|
173
|
+
if (existing[0]) {
|
|
174
|
+
const { provenance, ...stored } = existing[0];
|
|
175
|
+
if (!isDeepStrictEqual(stored, row)) {
|
|
176
|
+
throw new EngineResultError({
|
|
177
|
+
code: 'E_MANIFEST_ID_CONFLICT',
|
|
178
|
+
message: `Manifest '${row.id}' differs from the supplied payload; explicit repair is required.`,
|
|
179
|
+
details: { entryId: row.id, provenance, stored, incoming: row },
|
|
180
|
+
});
|
|
181
|
+
}
|
|
182
|
+
continue;
|
|
183
|
+
}
|
|
184
|
+
binding.db.insert(pipelineManifest).values(row).run();
|
|
185
|
+
inserted++;
|
|
186
|
+
}
|
|
187
|
+
return inserted;
|
|
188
|
+
}, { behavior: 'immediate' });
|
|
189
|
+
}
|
|
190
|
+
catch (error) {
|
|
191
|
+
throw new EngineResultError(manifestFailure('E_MANIFEST_INGEST', error instanceof Error ? error : new Error(String(error))).error);
|
|
192
|
+
}
|
|
76
193
|
}
|
|
77
|
-
// ============================================================================
|
|
78
|
-
// Internal helpers
|
|
79
|
-
// ============================================================================
|
|
80
194
|
function now() {
|
|
81
195
|
return new Date().toISOString().replace('T', ' ').slice(0, 19);
|
|
82
196
|
}
|
|
@@ -86,35 +200,72 @@ function computeContentHash(content) {
|
|
|
86
200
|
.digest('hex')
|
|
87
201
|
.slice(0, 16);
|
|
88
202
|
}
|
|
203
|
+
/** Validate only fields projected by the canonical reader; retain other provenance. */
|
|
204
|
+
const manifestMetadataSchema = z.looseObject({
|
|
205
|
+
file: z.string().optional(),
|
|
206
|
+
title: z.string().optional(),
|
|
207
|
+
topics: z.array(z.string()).optional(),
|
|
208
|
+
key_findings: z.array(z.string()).optional(),
|
|
209
|
+
actionable: z.boolean().optional(),
|
|
210
|
+
needs_followup: z.array(z.string()).optional(),
|
|
211
|
+
linked_tasks: z.array(z.string()).optional(),
|
|
212
|
+
confidence: z.number().optional(),
|
|
213
|
+
file_checksum: z.string().optional(),
|
|
214
|
+
duration_seconds: z.number().optional(),
|
|
215
|
+
});
|
|
216
|
+
function readRowMetadata(row) {
|
|
217
|
+
const details = {
|
|
218
|
+
entryId: row.id,
|
|
219
|
+
tables: row.provenance.tables,
|
|
220
|
+
metadataSha256: createHash('sha256')
|
|
221
|
+
.update(row.metadataJson ?? '')
|
|
222
|
+
.digest('hex'),
|
|
223
|
+
};
|
|
224
|
+
let parsed;
|
|
225
|
+
try {
|
|
226
|
+
parsed = manifestMetadataSchema.safeParse(row.metadataJson === null ? {} : JSON.parse(row.metadataJson));
|
|
227
|
+
}
|
|
228
|
+
catch (error) {
|
|
229
|
+
throw new EngineResultError({
|
|
230
|
+
code: 'E_MANIFEST_METADATA_INVALID',
|
|
231
|
+
message: `Manifest '${row.id}' metadata is not valid JSON: ${error instanceof Error ? error.message : String(error)}`,
|
|
232
|
+
details: { ...details, field: 'metadata_json' },
|
|
233
|
+
});
|
|
234
|
+
}
|
|
235
|
+
if (!parsed.success) {
|
|
236
|
+
const issues = parsed.error.issues.map((issue) => ({
|
|
237
|
+
field: issue.path.join('.') || 'metadata_json',
|
|
238
|
+
message: issue.message,
|
|
239
|
+
}));
|
|
240
|
+
throw new EngineResultError({
|
|
241
|
+
code: 'E_MANIFEST_METADATA_INVALID',
|
|
242
|
+
message: `Manifest '${row.id}' metadata violates the stored field contract`,
|
|
243
|
+
details: { ...details, field: issues[0]?.field ?? 'metadata_json', issues },
|
|
244
|
+
});
|
|
245
|
+
}
|
|
246
|
+
return parsed.data;
|
|
247
|
+
}
|
|
89
248
|
/**
|
|
90
|
-
* Convert a
|
|
91
|
-
* for backward-compatible output.
|
|
249
|
+
* Convert a validated canonical or historical row without rewriting stored bytes.
|
|
92
250
|
*/
|
|
93
251
|
function rowToEntry(row) {
|
|
94
|
-
|
|
95
|
-
if (row.metadataJson) {
|
|
96
|
-
try {
|
|
97
|
-
meta = JSON.parse(row.metadataJson);
|
|
98
|
-
}
|
|
99
|
-
catch {
|
|
100
|
-
// ignore malformed JSON
|
|
101
|
-
}
|
|
102
|
-
}
|
|
252
|
+
const meta = readRowMetadata(row);
|
|
103
253
|
return {
|
|
104
254
|
id: row.id,
|
|
105
|
-
|
|
106
|
-
|
|
255
|
+
provenance: row.provenance,
|
|
256
|
+
file: meta.file ?? row.sourceFile ?? '',
|
|
257
|
+
title: meta.title ?? row.type,
|
|
107
258
|
date: row.createdAt.slice(0, 10),
|
|
108
259
|
status: (row.status === 'active' ? 'completed' : row.status),
|
|
109
260
|
agent_type: row.type,
|
|
110
|
-
topics: meta
|
|
111
|
-
key_findings: meta
|
|
112
|
-
actionable: meta
|
|
113
|
-
needs_followup: meta
|
|
114
|
-
linked_tasks: meta
|
|
115
|
-
confidence: meta
|
|
116
|
-
file_checksum: meta
|
|
117
|
-
duration_seconds: meta
|
|
261
|
+
topics: meta.topics ?? [],
|
|
262
|
+
key_findings: meta.key_findings ?? [],
|
|
263
|
+
actionable: meta.actionable ?? true,
|
|
264
|
+
needs_followup: meta.needs_followup ?? [],
|
|
265
|
+
linked_tasks: meta.linked_tasks ?? (row.taskId ? [row.taskId] : []),
|
|
266
|
+
confidence: meta.confidence,
|
|
267
|
+
file_checksum: meta.file_checksum,
|
|
268
|
+
duration_seconds: meta.duration_seconds,
|
|
118
269
|
};
|
|
119
270
|
}
|
|
120
271
|
/**
|
|
@@ -159,7 +310,22 @@ function entryToRow(entry) {
|
|
|
159
310
|
// ============================================================================
|
|
160
311
|
// EngineResult-wrapped functions
|
|
161
312
|
// ============================================================================
|
|
162
|
-
/**
|
|
313
|
+
/**
|
|
314
|
+
* Retrieve a manifest and resolve its local file or canonical document reference.
|
|
315
|
+
*
|
|
316
|
+
* @remarks
|
|
317
|
+
* Supports `cleo://docs/<reference>` where the single percent-encoded segment is
|
|
318
|
+
* a document slug, attachment ID, or SHA-256 accepted by the canonical docs read
|
|
319
|
+
* model. URI syntax establishes no authority. Unsupported URIs and failed reads
|
|
320
|
+
* are explicit failures; missing ordinary files retain `fileExists: false`.
|
|
321
|
+
* @param researchId - Exact manifest identity, including historical entries.
|
|
322
|
+
* @param projectRoot - Explicit project directory used for both manifest and docs.
|
|
323
|
+
* @returns Manifest provenance and content, or a structured resolution failure.
|
|
324
|
+
* @example
|
|
325
|
+
* ```ts
|
|
326
|
+
* const result = await pipelineManifestShow('T001-report', '/project');
|
|
327
|
+
* ```
|
|
328
|
+
*/
|
|
163
329
|
export async function pipelineManifestShow(researchId, projectRoot) {
|
|
164
330
|
if (!researchId) {
|
|
165
331
|
return {
|
|
@@ -168,12 +334,8 @@ export async function pipelineManifestShow(researchId, projectRoot) {
|
|
|
168
334
|
};
|
|
169
335
|
}
|
|
170
336
|
try {
|
|
171
|
-
const
|
|
172
|
-
const rows = await
|
|
173
|
-
.select()
|
|
174
|
-
.from(pipelineManifest)
|
|
175
|
-
.where(eq(pipelineManifest.id, researchId))
|
|
176
|
-
.limit(1);
|
|
337
|
+
const scope = manifestScope(projectRoot);
|
|
338
|
+
const rows = await readRows(scope.worktreeRoot, true, researchId);
|
|
177
339
|
if (rows.length === 0) {
|
|
178
340
|
return {
|
|
179
341
|
success: false,
|
|
@@ -181,16 +343,67 @@ export async function pipelineManifestShow(researchId, projectRoot) {
|
|
|
181
343
|
};
|
|
182
344
|
}
|
|
183
345
|
const entry = rowToEntry(rows[0]);
|
|
184
|
-
const root = getProjectRoot(projectRoot);
|
|
185
346
|
let fileContent = null;
|
|
186
|
-
|
|
187
|
-
const
|
|
188
|
-
if (
|
|
189
|
-
|
|
347
|
+
if (/^[a-z][a-z\d+.-]*:/i.test(entry.file) && !/^[a-z]:[\\/]/i.test(entry.file)) {
|
|
348
|
+
const details = { entryId: researchId, reference: entry.file };
|
|
349
|
+
if (!entry.file.startsWith('cleo://docs/')) {
|
|
350
|
+
throw new EngineResultError({
|
|
351
|
+
code: 'E_MANIFEST_REFERENCE_UNSUPPORTED',
|
|
352
|
+
message: 'Only cleo://docs/<reference> document URIs are supported; no network lookup was attempted.',
|
|
353
|
+
details,
|
|
354
|
+
});
|
|
190
355
|
}
|
|
356
|
+
const encoded = entry.file.slice('cleo://docs/'.length);
|
|
357
|
+
let reference;
|
|
358
|
+
try {
|
|
359
|
+
reference = decodeURIComponent(encoded);
|
|
360
|
+
}
|
|
361
|
+
catch {
|
|
362
|
+
throw new EngineResultError({
|
|
363
|
+
code: 'E_MANIFEST_REFERENCE_INVALID',
|
|
364
|
+
message: 'Document reference contains invalid percent encoding.',
|
|
365
|
+
details,
|
|
366
|
+
});
|
|
367
|
+
}
|
|
368
|
+
if (!reference ||
|
|
369
|
+
reference === '.' ||
|
|
370
|
+
reference === '..' ||
|
|
371
|
+
/[/\\?#\s\x00-\x1f]/.test(reference)) {
|
|
372
|
+
throw new EngineResultError({
|
|
373
|
+
code: 'E_MANIFEST_REFERENCE_INVALID',
|
|
374
|
+
message: 'Document URI requires one nonempty reference without path, query, or fragment components.',
|
|
375
|
+
details,
|
|
376
|
+
});
|
|
377
|
+
}
|
|
378
|
+
fileContent = await worktreeScope.run(scope, async () => {
|
|
379
|
+
const model = createDocsReadModel(scope.worktreeRoot);
|
|
380
|
+
const doc = (await model.resolveLatest(reference)) ?? (await model.resolveByAttachmentId(reference));
|
|
381
|
+
if (!doc) {
|
|
382
|
+
throw new EngineResultError({
|
|
383
|
+
code: 'E_MANIFEST_DOC_NOT_FOUND',
|
|
384
|
+
message: 'Document reference was not found in the selected project.',
|
|
385
|
+
details,
|
|
386
|
+
});
|
|
387
|
+
}
|
|
388
|
+
const content = await model.fetchContent(doc);
|
|
389
|
+
if (content === null) {
|
|
390
|
+
throw new EngineResultError({
|
|
391
|
+
code: 'E_MANIFEST_DOC_CONTENT_UNAVAILABLE',
|
|
392
|
+
message: 'Document metadata resolved but its content is unavailable.',
|
|
393
|
+
details: { ...details, attachmentId: doc.id, sha256: doc.sha256 },
|
|
394
|
+
});
|
|
395
|
+
}
|
|
396
|
+
return content;
|
|
397
|
+
});
|
|
191
398
|
}
|
|
192
|
-
|
|
193
|
-
|
|
399
|
+
else if (entry.file) {
|
|
400
|
+
try {
|
|
401
|
+
fileContent = readFileSync(join(scope.worktreeRoot, entry.file), 'utf-8');
|
|
402
|
+
}
|
|
403
|
+
catch (error) {
|
|
404
|
+
if (!(error instanceof Error && 'code' in error && error.code === 'ENOENT'))
|
|
405
|
+
throw error;
|
|
406
|
+
}
|
|
194
407
|
}
|
|
195
408
|
return {
|
|
196
409
|
success: true,
|
|
@@ -198,84 +411,35 @@ export async function pipelineManifestShow(researchId, projectRoot) {
|
|
|
198
411
|
};
|
|
199
412
|
}
|
|
200
413
|
catch (error) {
|
|
201
|
-
return
|
|
202
|
-
success: false,
|
|
203
|
-
error: {
|
|
204
|
-
code: 'E_MANIFEST_SHOW',
|
|
205
|
-
message: error instanceof Error ? error.message : String(error),
|
|
206
|
-
},
|
|
207
|
-
};
|
|
414
|
+
return manifestFailure('E_MANIFEST_SHOW', error instanceof Error ? error : new Error(String(error)));
|
|
208
415
|
}
|
|
209
416
|
}
|
|
210
417
|
/** pipeline.manifest.list - List manifest entries with filters */
|
|
211
418
|
export async function pipelineManifestList(params, projectRoot) {
|
|
212
419
|
try {
|
|
213
|
-
const
|
|
214
|
-
const filter = { ...params };
|
|
215
|
-
if (params.type) {
|
|
216
|
-
filter.agent_type = params.type;
|
|
217
|
-
}
|
|
420
|
+
const entries = (await readRows(projectRoot)).map(rowToEntry);
|
|
218
421
|
const limit = normalizeLimit(params.limit);
|
|
219
422
|
const offset = normalizeOffset(params.offset);
|
|
220
423
|
const pageLimit = effectivePageLimit(limit, offset);
|
|
221
|
-
const
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
.get();
|
|
228
|
-
const total = totalRow?.count ?? 0;
|
|
229
|
-
if (!requiresInMemoryFiltering) {
|
|
230
|
-
const filteredRow = await db
|
|
231
|
-
.select({ count: count() })
|
|
232
|
-
.from(pipelineManifest)
|
|
233
|
-
.where(whereClause)
|
|
234
|
-
.get();
|
|
235
|
-
const filtered = filteredRow?.count ?? 0;
|
|
236
|
-
let query = db
|
|
237
|
-
.select()
|
|
238
|
-
.from(pipelineManifest)
|
|
239
|
-
.where(whereClause)
|
|
240
|
-
.orderBy(desc(pipelineManifest.createdAt));
|
|
241
|
-
if (pageLimit !== undefined) {
|
|
242
|
-
query = query.limit(pageLimit);
|
|
243
|
-
}
|
|
244
|
-
if (offset !== undefined) {
|
|
245
|
-
query = query.offset(offset);
|
|
246
|
-
}
|
|
247
|
-
const rows = await query;
|
|
248
|
-
return {
|
|
249
|
-
success: true,
|
|
250
|
-
data: { entries: rows.map(rowToEntry), total, filtered },
|
|
251
|
-
page: createPage({ total: filtered, limit: pageLimit, offset }),
|
|
252
|
-
};
|
|
253
|
-
}
|
|
254
|
-
const rows = await db
|
|
255
|
-
.select()
|
|
256
|
-
.from(pipelineManifest)
|
|
257
|
-
.where(whereClause)
|
|
258
|
-
.orderBy(desc(pipelineManifest.createdAt));
|
|
259
|
-
const filteredEntries = applyManifestMemoryOnlyFilters(rows.map(rowToEntry), filter);
|
|
260
|
-
const filtered = filteredEntries.length;
|
|
424
|
+
const filtered = filterManifestEntries(entries, {
|
|
425
|
+
...params,
|
|
426
|
+
agent_type: params.type ?? params.agent_type,
|
|
427
|
+
limit: undefined,
|
|
428
|
+
offset: undefined,
|
|
429
|
+
});
|
|
261
430
|
const start = offset ?? 0;
|
|
262
|
-
const pagedEntries = pageLimit !== undefined
|
|
263
|
-
? filteredEntries.slice(start, start + pageLimit)
|
|
264
|
-
: filteredEntries.slice(start);
|
|
265
431
|
return {
|
|
266
432
|
success: true,
|
|
267
|
-
data: {
|
|
268
|
-
|
|
433
|
+
data: {
|
|
434
|
+
entries: filtered.slice(start, pageLimit === undefined ? undefined : start + pageLimit),
|
|
435
|
+
total: entries.length,
|
|
436
|
+
filtered: filtered.length,
|
|
437
|
+
},
|
|
438
|
+
page: createPage({ total: filtered.length, limit: pageLimit, offset }),
|
|
269
439
|
};
|
|
270
440
|
}
|
|
271
441
|
catch (error) {
|
|
272
|
-
return
|
|
273
|
-
success: false,
|
|
274
|
-
error: {
|
|
275
|
-
code: 'E_MANIFEST_LIST',
|
|
276
|
-
message: error instanceof Error ? error.message : String(error),
|
|
277
|
-
},
|
|
278
|
-
};
|
|
442
|
+
return manifestFailure('E_MANIFEST_LIST', error instanceof Error ? error : new Error(String(error)));
|
|
279
443
|
}
|
|
280
444
|
}
|
|
281
445
|
/** pipeline.manifest.find - Find manifest entries by text (LIKE search on content + type) */
|
|
@@ -284,13 +448,23 @@ export async function pipelineManifestFind(query, options, projectRoot) {
|
|
|
284
448
|
return { success: false, error: { code: 'E_INVALID_INPUT', message: 'query is required' } };
|
|
285
449
|
}
|
|
286
450
|
try {
|
|
287
|
-
const
|
|
288
|
-
const
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
451
|
+
const binding = await getBinding(projectRoot);
|
|
452
|
+
const rows = binding.db.transaction(() => {
|
|
453
|
+
const merged = readStoredRows(binding);
|
|
454
|
+
const ids = new Set([
|
|
455
|
+
...binding.db
|
|
456
|
+
.select({ id: pipelineManifest.id })
|
|
457
|
+
.from(pipelineManifest)
|
|
458
|
+
.where(or(like(pipelineManifest.content, `%${query}%`), like(pipelineManifest.type, `%${query}%`)))
|
|
459
|
+
.all(),
|
|
460
|
+
...binding.db
|
|
461
|
+
.select({ id: legacyManifest.id })
|
|
462
|
+
.from(legacyManifest)
|
|
463
|
+
.where(or(like(legacyManifest.content, `%${query}%`), like(legacyManifest.type, `%${query}%`)))
|
|
464
|
+
.all(),
|
|
465
|
+
].map((row) => row.id));
|
|
466
|
+
return merged.filter((row) => ids.has(row.id));
|
|
467
|
+
});
|
|
294
468
|
const queryLower = query.toLowerCase();
|
|
295
469
|
const entries = rows.map(rowToEntry);
|
|
296
470
|
const scored = entries.map((entry) => {
|
|
@@ -323,24 +497,13 @@ export async function pipelineManifestFind(query, options, projectRoot) {
|
|
|
323
497
|
};
|
|
324
498
|
}
|
|
325
499
|
catch (error) {
|
|
326
|
-
return
|
|
327
|
-
success: false,
|
|
328
|
-
error: {
|
|
329
|
-
code: 'E_MANIFEST_FIND',
|
|
330
|
-
message: error instanceof Error ? error.message : String(error),
|
|
331
|
-
},
|
|
332
|
-
};
|
|
500
|
+
return manifestFailure('E_MANIFEST_FIND', error instanceof Error ? error : new Error(String(error)));
|
|
333
501
|
}
|
|
334
502
|
}
|
|
335
503
|
/** pipeline.manifest.pending - Get pending manifest items */
|
|
336
504
|
export async function pipelineManifestPending(epicId, projectRoot) {
|
|
337
505
|
try {
|
|
338
|
-
const
|
|
339
|
-
const rows = await db
|
|
340
|
-
.select()
|
|
341
|
-
.from(pipelineManifest)
|
|
342
|
-
.where(isNull(pipelineManifest.archivedAt))
|
|
343
|
-
.orderBy(desc(pipelineManifest.createdAt));
|
|
506
|
+
const rows = await readRows(projectRoot);
|
|
344
507
|
const entries = rows.map(rowToEntry);
|
|
345
508
|
let pending = entries.filter((e) => e.status === 'partial' ||
|
|
346
509
|
e.status === 'blocked' ||
|
|
@@ -363,23 +526,13 @@ export async function pipelineManifestPending(epicId, projectRoot) {
|
|
|
363
526
|
};
|
|
364
527
|
}
|
|
365
528
|
catch (error) {
|
|
366
|
-
return
|
|
367
|
-
success: false,
|
|
368
|
-
error: {
|
|
369
|
-
code: 'E_MANIFEST_PENDING',
|
|
370
|
-
message: error instanceof Error ? error.message : String(error),
|
|
371
|
-
},
|
|
372
|
-
};
|
|
529
|
+
return manifestFailure('E_MANIFEST_PENDING', error instanceof Error ? error : new Error(String(error)));
|
|
373
530
|
}
|
|
374
531
|
}
|
|
375
532
|
/** pipeline.manifest.stats - Manifest statistics */
|
|
376
533
|
export async function pipelineManifestStats(epicId, projectRoot) {
|
|
377
534
|
try {
|
|
378
|
-
const
|
|
379
|
-
const rows = await db
|
|
380
|
-
.select()
|
|
381
|
-
.from(pipelineManifest)
|
|
382
|
-
.where(isNull(pipelineManifest.archivedAt));
|
|
535
|
+
const rows = await readRows(projectRoot);
|
|
383
536
|
const entries = rows.map(rowToEntry);
|
|
384
537
|
let filtered = entries;
|
|
385
538
|
if (epicId) {
|
|
@@ -413,24 +566,13 @@ export async function pipelineManifestStats(epicId, projectRoot) {
|
|
|
413
566
|
};
|
|
414
567
|
}
|
|
415
568
|
catch (error) {
|
|
416
|
-
return
|
|
417
|
-
success: false,
|
|
418
|
-
error: {
|
|
419
|
-
code: 'E_MANIFEST_STATS',
|
|
420
|
-
message: error instanceof Error ? error.message : String(error),
|
|
421
|
-
},
|
|
422
|
-
};
|
|
569
|
+
return manifestFailure('E_MANIFEST_STATS', error instanceof Error ? error : new Error(String(error)));
|
|
423
570
|
}
|
|
424
571
|
}
|
|
425
572
|
/** pipeline.manifest.read - Read manifest entries with optional filter */
|
|
426
573
|
export async function pipelineManifestRead(filter, projectRoot) {
|
|
427
574
|
try {
|
|
428
|
-
const
|
|
429
|
-
const rows = await db
|
|
430
|
-
.select()
|
|
431
|
-
.from(pipelineManifest)
|
|
432
|
-
.where(isNull(pipelineManifest.archivedAt))
|
|
433
|
-
.orderBy(desc(pipelineManifest.createdAt));
|
|
575
|
+
const rows = await readRows(projectRoot);
|
|
434
576
|
const entries = rows.map(rowToEntry);
|
|
435
577
|
const filtered = filter ? filterManifestEntries(entries, filter) : entries;
|
|
436
578
|
return {
|
|
@@ -439,16 +581,10 @@ export async function pipelineManifestRead(filter, projectRoot) {
|
|
|
439
581
|
};
|
|
440
582
|
}
|
|
441
583
|
catch (error) {
|
|
442
|
-
return
|
|
443
|
-
success: false,
|
|
444
|
-
error: {
|
|
445
|
-
code: 'E_MANIFEST_READ',
|
|
446
|
-
message: error instanceof Error ? error.message : String(error),
|
|
447
|
-
},
|
|
448
|
-
};
|
|
584
|
+
return manifestFailure('E_MANIFEST_READ', error instanceof Error ? error : new Error(String(error)));
|
|
449
585
|
}
|
|
450
586
|
}
|
|
451
|
-
/**
|
|
587
|
+
/** Append to canonical manifest storage after checking both histories for unresolved identities. */
|
|
452
588
|
export async function pipelineManifestAppend(entry, projectRoot) {
|
|
453
589
|
if (!entry) {
|
|
454
590
|
return { success: false, error: { code: 'E_INVALID_INPUT', message: 'entry is required' } };
|
|
@@ -480,32 +616,30 @@ export async function pipelineManifestAppend(entry, projectRoot) {
|
|
|
480
616
|
};
|
|
481
617
|
}
|
|
482
618
|
try {
|
|
483
|
-
const
|
|
619
|
+
const binding = await getBinding(projectRoot);
|
|
484
620
|
const row = entryToRow(entry);
|
|
485
|
-
|
|
486
|
-
.
|
|
487
|
-
.
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
621
|
+
binding.db.transaction(() => {
|
|
622
|
+
requireModernRows(readStoredRows(binding, true, entry.id));
|
|
623
|
+
binding.db
|
|
624
|
+
.insert(pipelineManifest)
|
|
625
|
+
.values(row)
|
|
626
|
+
.onConflictDoUpdate({
|
|
627
|
+
target: pipelineManifest.id,
|
|
628
|
+
set: {
|
|
629
|
+
content: row.content,
|
|
630
|
+
contentHash: row.contentHash,
|
|
631
|
+
status: row.status,
|
|
632
|
+
metadataJson: row.metadataJson,
|
|
633
|
+
sourceFile: row.sourceFile,
|
|
634
|
+
taskId: row.taskId,
|
|
635
|
+
},
|
|
636
|
+
})
|
|
637
|
+
.run();
|
|
638
|
+
}, { behavior: 'immediate' });
|
|
499
639
|
return { success: true, data: { appended: true, entryId: entry.id } };
|
|
500
640
|
}
|
|
501
641
|
catch (error) {
|
|
502
|
-
return
|
|
503
|
-
success: false,
|
|
504
|
-
error: {
|
|
505
|
-
code: 'E_MANIFEST_APPEND',
|
|
506
|
-
message: error instanceof Error ? error.message : String(error),
|
|
507
|
-
},
|
|
508
|
-
};
|
|
642
|
+
return manifestFailure('E_MANIFEST_APPEND', error instanceof Error ? error : new Error(String(error)));
|
|
509
643
|
}
|
|
510
644
|
}
|
|
511
645
|
/** pipeline.manifest.archive - Archive old manifest entries by date */
|
|
@@ -520,118 +654,103 @@ export async function pipelineManifestArchive(beforeDate, projectRoot) {
|
|
|
520
654
|
};
|
|
521
655
|
}
|
|
522
656
|
try {
|
|
523
|
-
const
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
const toArchive = rows.filter((r) => r.createdAt.slice(0, 10) < beforeDate);
|
|
537
|
-
if (toArchive.length === 0) {
|
|
538
|
-
const remaining = rows.length;
|
|
657
|
+
const binding = await getBinding(projectRoot);
|
|
658
|
+
return binding.db.transaction(() => {
|
|
659
|
+
const rows = readStoredRows(binding);
|
|
660
|
+
const toArchive = rows.filter((row) => row.createdAt.slice(0, 10) < beforeDate);
|
|
661
|
+
requireModernRows(toArchive);
|
|
662
|
+
const archivedAt = now();
|
|
663
|
+
for (const row of toArchive) {
|
|
664
|
+
binding.db
|
|
665
|
+
.update(pipelineManifest)
|
|
666
|
+
.set({ archivedAt })
|
|
667
|
+
.where(eq(pipelineManifest.id, row.id))
|
|
668
|
+
.run();
|
|
669
|
+
}
|
|
539
670
|
return {
|
|
540
671
|
success: true,
|
|
541
|
-
data: { archived:
|
|
672
|
+
data: { archived: toArchive.length, remaining: rows.length - toArchive.length },
|
|
542
673
|
};
|
|
543
|
-
}
|
|
544
|
-
const archivedAt = now();
|
|
545
|
-
for (const row of toArchive) {
|
|
546
|
-
await db.update(pipelineManifest).set({ archivedAt }).where(eq(pipelineManifest.id, row.id));
|
|
547
|
-
}
|
|
548
|
-
const remaining = rows.length - toArchive.length;
|
|
549
|
-
return { success: true, data: { archived: toArchive.length, remaining } };
|
|
674
|
+
}, { behavior: 'immediate' });
|
|
550
675
|
}
|
|
551
676
|
catch (error) {
|
|
552
|
-
return
|
|
553
|
-
success: false,
|
|
554
|
-
error: {
|
|
555
|
-
code: 'E_MANIFEST_ARCHIVE',
|
|
556
|
-
message: error instanceof Error ? error.message : String(error),
|
|
557
|
-
},
|
|
558
|
-
};
|
|
677
|
+
return manifestFailure('E_MANIFEST_ARCHIVE', error instanceof Error ? error : new Error(String(error)));
|
|
559
678
|
}
|
|
560
679
|
}
|
|
561
680
|
/** pipeline.manifest.compact - Dedup by contentHash (keep newest by createdAt) */
|
|
562
681
|
export async function pipelineManifestCompact(projectRoot) {
|
|
563
682
|
try {
|
|
564
|
-
const
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
for (const row of rows) {
|
|
579
|
-
const hash = row.contentHash ?? computeContentHash(row.content);
|
|
580
|
-
if (seenHashes.has(hash) || seenIds.has(row.id)) {
|
|
581
|
-
toDelete.push(row.id);
|
|
683
|
+
const binding = await getBinding(projectRoot);
|
|
684
|
+
return binding.db.transaction(() => {
|
|
685
|
+
const rows = readStoredRows(binding);
|
|
686
|
+
requireModernRows(rows);
|
|
687
|
+
if (!rows.length)
|
|
688
|
+
return { success: true, data: { compacted: false, message: 'No entries found' } };
|
|
689
|
+
// Hashes can collide; only the full stored content establishes duplicate payloads.
|
|
690
|
+
const seen = new Set();
|
|
691
|
+
const toDelete = [];
|
|
692
|
+
for (const row of rows) {
|
|
693
|
+
if (seen.has(row.content))
|
|
694
|
+
toDelete.push(row.id);
|
|
695
|
+
else
|
|
696
|
+
seen.add(row.content);
|
|
582
697
|
}
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
malformedRemoved: 0,
|
|
597
|
-
duplicatesRemoved: toDelete.length,
|
|
598
|
-
remainingEntries: originalCount - toDelete.length,
|
|
599
|
-
},
|
|
600
|
-
};
|
|
698
|
+
for (const id of toDelete)
|
|
699
|
+
binding.db.delete(pipelineManifest).where(eq(pipelineManifest.id, id)).run();
|
|
700
|
+
return {
|
|
701
|
+
success: true,
|
|
702
|
+
data: {
|
|
703
|
+
compacted: true,
|
|
704
|
+
originalLines: rows.length,
|
|
705
|
+
malformedRemoved: 0,
|
|
706
|
+
duplicatesRemoved: toDelete.length,
|
|
707
|
+
remainingEntries: rows.length - toDelete.length,
|
|
708
|
+
},
|
|
709
|
+
};
|
|
710
|
+
}, { behavior: 'immediate' });
|
|
601
711
|
}
|
|
602
712
|
catch (error) {
|
|
603
|
-
return
|
|
604
|
-
success: false,
|
|
605
|
-
error: {
|
|
606
|
-
code: 'E_COMPACT_FAILED',
|
|
607
|
-
message: error instanceof Error ? error.message : String(error),
|
|
608
|
-
},
|
|
609
|
-
};
|
|
713
|
+
return manifestFailure('E_COMPACT_FAILED', error instanceof Error ? error : new Error(String(error)));
|
|
610
714
|
}
|
|
611
715
|
}
|
|
612
|
-
/**
|
|
716
|
+
/**
|
|
717
|
+
* Validate available manifest evidence explicitly linked to one task.
|
|
718
|
+
*
|
|
719
|
+
* @remarks
|
|
720
|
+
* This exported SDK helper is not a registered CLI operation. Selection uses
|
|
721
|
+
* exact linked-task membership; manifest ID wording establishes no ownership.
|
|
722
|
+
* Absent evidence, missing output, and blank output invalidate the assessment.
|
|
723
|
+
* Canonical document/read failures retain their structured diagnostics. Content
|
|
724
|
+
* availability does not establish implementation, testing, review, or authority.
|
|
725
|
+
* @param taskId - Exact task identity whose linked evidence is assessed.
|
|
726
|
+
* @param projectRoot - Project captured before any asynchronous store access.
|
|
727
|
+
* @returns Field and content assessment, or a structured diagnostic failure.
|
|
728
|
+
* @example
|
|
729
|
+
* ```ts
|
|
730
|
+
* const result = await pipelineManifestValidate('T001', '/project');
|
|
731
|
+
* ```
|
|
732
|
+
*/
|
|
613
733
|
export async function pipelineManifestValidate(taskId, projectRoot) {
|
|
614
734
|
if (!taskId) {
|
|
615
735
|
return { success: false, error: { code: 'E_INVALID_INPUT', message: 'taskId is required' } };
|
|
616
736
|
}
|
|
617
737
|
try {
|
|
618
|
-
const
|
|
619
|
-
const
|
|
620
|
-
const
|
|
621
|
-
.select()
|
|
622
|
-
.from(pipelineManifest)
|
|
623
|
-
.where(isNull(pipelineManifest.archivedAt));
|
|
624
|
-
const entries = rows.map(rowToEntry);
|
|
625
|
-
const linked = entries.filter((e) => e.id.startsWith(taskId) || e.linked_tasks?.includes(taskId));
|
|
738
|
+
const root = manifestScope(projectRoot).worktreeRoot;
|
|
739
|
+
const entries = await readManifestEntries(root);
|
|
740
|
+
const linked = entries.filter((entry) => entry.linked_tasks?.includes(taskId));
|
|
626
741
|
if (linked.length === 0) {
|
|
627
742
|
return {
|
|
628
743
|
success: true,
|
|
629
744
|
data: {
|
|
630
745
|
taskId,
|
|
631
|
-
valid:
|
|
746
|
+
valid: false,
|
|
632
747
|
entriesFound: 0,
|
|
633
748
|
message: `No research entries found for task ${taskId}`,
|
|
634
|
-
issues: [
|
|
749
|
+
issues: [
|
|
750
|
+
{ entryId: taskId, issue: 'No explicitly linked evidence found', severity: 'error' },
|
|
751
|
+
],
|
|
752
|
+
errorCount: 1,
|
|
753
|
+
warningCount: 0,
|
|
635
754
|
},
|
|
636
755
|
};
|
|
637
756
|
}
|
|
@@ -657,12 +776,34 @@ export async function pipelineManifestValidate(taskId, projectRoot) {
|
|
|
657
776
|
});
|
|
658
777
|
}
|
|
659
778
|
if (entry.file) {
|
|
660
|
-
const
|
|
661
|
-
if (!
|
|
779
|
+
const output = await pipelineManifestShow(entry.id, root);
|
|
780
|
+
if (!output.success)
|
|
781
|
+
return output;
|
|
782
|
+
const data = output.data;
|
|
783
|
+
if (!data ||
|
|
784
|
+
typeof data !== 'object' ||
|
|
785
|
+
!('fileExists' in data) ||
|
|
786
|
+
typeof data.fileExists !== 'boolean' ||
|
|
787
|
+
!('fileContent' in data) ||
|
|
788
|
+
(data.fileExists ? typeof data.fileContent !== 'string' : data.fileContent !== null)) {
|
|
789
|
+
throw new EngineResultError({
|
|
790
|
+
code: 'E_MANIFEST_RESULT_INVALID',
|
|
791
|
+
message: 'Canonical manifest show did not disclose consistent output availability',
|
|
792
|
+
details: { entryId: entry.id },
|
|
793
|
+
});
|
|
794
|
+
}
|
|
795
|
+
if (!data.fileExists) {
|
|
662
796
|
issues.push({
|
|
663
797
|
entryId: entry.id,
|
|
664
798
|
issue: `Output file not found: ${entry.file}`,
|
|
665
|
-
severity: '
|
|
799
|
+
severity: 'error',
|
|
800
|
+
});
|
|
801
|
+
}
|
|
802
|
+
else if (typeof data.fileContent === 'string' && data.fileContent.trim().length === 0) {
|
|
803
|
+
issues.push({
|
|
804
|
+
entryId: entry.id,
|
|
805
|
+
issue: `Output content is empty: ${entry.file}`,
|
|
806
|
+
severity: 'error',
|
|
666
807
|
});
|
|
667
808
|
}
|
|
668
809
|
}
|
|
@@ -688,23 +829,13 @@ export async function pipelineManifestValidate(taskId, projectRoot) {
|
|
|
688
829
|
};
|
|
689
830
|
}
|
|
690
831
|
catch (error) {
|
|
691
|
-
return
|
|
692
|
-
success: false,
|
|
693
|
-
error: {
|
|
694
|
-
code: 'E_MANIFEST_VALIDATE',
|
|
695
|
-
message: error instanceof Error ? error.message : String(error),
|
|
696
|
-
},
|
|
697
|
-
};
|
|
832
|
+
return manifestFailure('E_MANIFEST_VALIDATE', error instanceof Error ? error : new Error(String(error)));
|
|
698
833
|
}
|
|
699
834
|
}
|
|
700
835
|
/** pipeline.manifest.contradictions - Find entries with overlapping topics but conflicting key_findings */
|
|
701
836
|
export async function pipelineManifestContradictions(projectRoot, params) {
|
|
702
837
|
try {
|
|
703
|
-
const
|
|
704
|
-
const rows = await db
|
|
705
|
-
.select()
|
|
706
|
-
.from(pipelineManifest)
|
|
707
|
-
.where(isNull(pipelineManifest.archivedAt));
|
|
838
|
+
const rows = await readRows(projectRoot);
|
|
708
839
|
const entries = rows.map(rowToEntry);
|
|
709
840
|
// In-memory negation pattern matching (same logic as compat layer)
|
|
710
841
|
const byTopic = new Map();
|
|
@@ -766,23 +897,13 @@ export async function pipelineManifestContradictions(projectRoot, params) {
|
|
|
766
897
|
return { success: true, data: { contradictions } };
|
|
767
898
|
}
|
|
768
899
|
catch (error) {
|
|
769
|
-
return
|
|
770
|
-
success: false,
|
|
771
|
-
error: {
|
|
772
|
-
code: 'E_MANIFEST_CONTRADICTIONS',
|
|
773
|
-
message: error instanceof Error ? error.message : String(error),
|
|
774
|
-
},
|
|
775
|
-
};
|
|
900
|
+
return manifestFailure('E_MANIFEST_CONTRADICTIONS', error instanceof Error ? error : new Error(String(error)));
|
|
776
901
|
}
|
|
777
902
|
}
|
|
778
903
|
/** pipeline.manifest.superseded - Identify entries replaced by newer work on same topic */
|
|
779
904
|
export async function pipelineManifestSuperseded(projectRoot, params) {
|
|
780
905
|
try {
|
|
781
|
-
const
|
|
782
|
-
const rows = await db
|
|
783
|
-
.select()
|
|
784
|
-
.from(pipelineManifest)
|
|
785
|
-
.where(isNull(pipelineManifest.archivedAt));
|
|
906
|
+
const rows = await readRows(projectRoot);
|
|
786
907
|
const entries = rows.map(rowToEntry);
|
|
787
908
|
const byTopicAndType = new Map();
|
|
788
909
|
for (const entry of entries) {
|
|
@@ -813,13 +934,7 @@ export async function pipelineManifestSuperseded(projectRoot, params) {
|
|
|
813
934
|
return { success: true, data: { superseded } };
|
|
814
935
|
}
|
|
815
936
|
catch (error) {
|
|
816
|
-
return
|
|
817
|
-
success: false,
|
|
818
|
-
error: {
|
|
819
|
-
code: 'E_MANIFEST_SUPERSEDED',
|
|
820
|
-
message: error instanceof Error ? error.message : String(error),
|
|
821
|
-
},
|
|
822
|
-
};
|
|
937
|
+
return manifestFailure('E_MANIFEST_SUPERSEDED', error instanceof Error ? error : new Error(String(error)));
|
|
823
938
|
}
|
|
824
939
|
}
|
|
825
940
|
/** pipeline.manifest.link - Link manifest entry to a task */
|
|
@@ -831,72 +946,58 @@ export async function pipelineManifestLink(taskId, researchId, notes, projectRoo
|
|
|
831
946
|
};
|
|
832
947
|
}
|
|
833
948
|
try {
|
|
834
|
-
const
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
.
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
.update(pipelineManifest)
|
|
863
|
-
.set({
|
|
864
|
-
taskId: row.taskId ?? taskId,
|
|
865
|
-
metadataJson: JSON.stringify(meta),
|
|
866
|
-
})
|
|
867
|
-
.where(eq(pipelineManifest.id, researchId));
|
|
868
|
-
return { success: true, data: { taskId, researchId, linked: true, notes: notes || null } };
|
|
949
|
+
const binding = await getBinding(projectRoot);
|
|
950
|
+
return binding.db.transaction(() => {
|
|
951
|
+
const rows = readStoredRows(binding, true, researchId);
|
|
952
|
+
if (!rows.length)
|
|
953
|
+
throw new EngineResultError({
|
|
954
|
+
code: 'E_NOT_FOUND',
|
|
955
|
+
message: `Research entry '${researchId}' not found`,
|
|
956
|
+
});
|
|
957
|
+
requireModernRows(rows);
|
|
958
|
+
const row = rows[0];
|
|
959
|
+
const entry = rowToEntry(row);
|
|
960
|
+
if (entry.linked_tasks?.includes(taskId)) {
|
|
961
|
+
return { success: true, data: { taskId, researchId, linked: true, alreadyLinked: true } };
|
|
962
|
+
}
|
|
963
|
+
// Update linked_tasks in metadataJson
|
|
964
|
+
const updatedLinkedTasks = [...(entry.linked_tasks ?? []), taskId];
|
|
965
|
+
const meta = readRowMetadata(row);
|
|
966
|
+
meta['linked_tasks'] = updatedLinkedTasks;
|
|
967
|
+
binding.db
|
|
968
|
+
.update(pipelineManifest)
|
|
969
|
+
.set({
|
|
970
|
+
taskId: row.taskId ?? taskId,
|
|
971
|
+
metadataJson: JSON.stringify(meta),
|
|
972
|
+
})
|
|
973
|
+
.where(eq(pipelineManifest.id, researchId))
|
|
974
|
+
.run();
|
|
975
|
+
return { success: true, data: { taskId, researchId, linked: true, notes: notes || null } };
|
|
976
|
+
}, { behavior: 'immediate' });
|
|
869
977
|
}
|
|
870
978
|
catch (error) {
|
|
871
|
-
return
|
|
872
|
-
success: false,
|
|
873
|
-
error: {
|
|
874
|
-
code: 'E_MANIFEST_LINK',
|
|
875
|
-
message: error instanceof Error ? error.message : String(error),
|
|
876
|
-
},
|
|
877
|
-
};
|
|
979
|
+
return manifestFailure('E_MANIFEST_LINK', error instanceof Error ? error : new Error(String(error)));
|
|
878
980
|
}
|
|
879
981
|
}
|
|
880
982
|
// ============================================================================
|
|
881
983
|
// Helper exported for compat consumers
|
|
882
984
|
// ============================================================================
|
|
883
985
|
/**
|
|
884
|
-
* Read
|
|
885
|
-
*
|
|
986
|
+
* Read unarchived entries from both manifest histories with physical provenance.
|
|
987
|
+
* @param projectRoot - Explicit project root; takes priority over ambient project pins.
|
|
988
|
+
* @returns Entries retaining the existing fields and observed source tables/database path.
|
|
989
|
+
* @throws EngineResultError when the same identity has conflicting persisted payloads.
|
|
990
|
+
* @throws Error when storage reads fail; failure is never represented as an empty history.
|
|
991
|
+
* @remarks Identical rows are deduplicated only after comparing every stored scalar.
|
|
992
|
+
* Legacy-only evidence remains readable and is never implicitly migrated or rewritten.
|
|
993
|
+
* @example
|
|
994
|
+
* ```ts
|
|
995
|
+
* const entries = await readManifestEntries('/project');
|
|
996
|
+
* const sources = entries.map((entry) => entry.provenance.tables);
|
|
997
|
+
* ```
|
|
886
998
|
*/
|
|
887
999
|
export async function readManifestEntries(projectRoot) {
|
|
888
|
-
|
|
889
|
-
const db = await getDb(projectRoot);
|
|
890
|
-
const rows = await db
|
|
891
|
-
.select()
|
|
892
|
-
.from(pipelineManifest)
|
|
893
|
-
.where(isNull(pipelineManifest.archivedAt))
|
|
894
|
-
.orderBy(desc(pipelineManifest.createdAt));
|
|
895
|
-
return rows.map(rowToEntry);
|
|
896
|
-
}
|
|
897
|
-
catch {
|
|
898
|
-
return [];
|
|
899
|
-
}
|
|
1000
|
+
return (await readRows(projectRoot)).map(rowToEntry);
|
|
900
1001
|
}
|
|
901
1002
|
/**
|
|
902
1003
|
* Filter manifest entries by criteria (alias for backward compatibility).
|
|
@@ -924,7 +1025,7 @@ export async function distillManifestEntry(_entryId, _projectRoot) {
|
|
|
924
1025
|
* @returns Count of migrated and skipped entries.
|
|
925
1026
|
*/
|
|
926
1027
|
export async function migrateManifestJsonlToSqlite(projectRoot) {
|
|
927
|
-
const root =
|
|
1028
|
+
const root = manifestScope(projectRoot).worktreeRoot;
|
|
928
1029
|
const manifestPath = join(resolveCleoDir(root), 'MANIFEST.jsonl');
|
|
929
1030
|
if (!existsSync(manifestPath)) {
|
|
930
1031
|
return { migrated: 0, skipped: 0 };
|
|
@@ -946,7 +1047,8 @@ export async function migrateManifestJsonlToSqlite(projectRoot) {
|
|
|
946
1047
|
if (entries.length === 0) {
|
|
947
1048
|
return { migrated: 0, skipped: 0 };
|
|
948
1049
|
}
|
|
949
|
-
const
|
|
1050
|
+
const binding = await getBinding(projectRoot);
|
|
1051
|
+
const db = binding.db;
|
|
950
1052
|
let migrated = 0;
|
|
951
1053
|
let skipped = 0;
|
|
952
1054
|
for (const entry of entries) {
|
|
@@ -954,24 +1056,18 @@ export async function migrateManifestJsonlToSqlite(projectRoot) {
|
|
|
954
1056
|
skipped++;
|
|
955
1057
|
continue;
|
|
956
1058
|
}
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
.
|
|
961
|
-
|
|
962
|
-
.
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
}
|
|
967
|
-
try {
|
|
968
|
-
const row = entryToRow(entry);
|
|
969
|
-
await db.insert(pipelineManifest).values(row);
|
|
1059
|
+
const inserted = db.transaction(() => {
|
|
1060
|
+
const existing = readStoredRows(binding, true, entry.id);
|
|
1061
|
+
requireModernRows(existing);
|
|
1062
|
+
if (existing.length)
|
|
1063
|
+
return false;
|
|
1064
|
+
db.insert(pipelineManifest).values(entryToRow(entry)).run();
|
|
1065
|
+
return true;
|
|
1066
|
+
}, { behavior: 'immediate' });
|
|
1067
|
+
if (inserted)
|
|
970
1068
|
migrated++;
|
|
971
|
-
|
|
972
|
-
catch {
|
|
1069
|
+
else
|
|
973
1070
|
skipped++;
|
|
974
|
-
}
|
|
975
1071
|
}
|
|
976
1072
|
// Rename MANIFEST.jsonl to MANIFEST.jsonl.migrated
|
|
977
1073
|
try {
|