@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
package/dist/tasks/evidence.js
CHANGED
|
@@ -26,6 +26,7 @@ import { readFile, stat } from 'node:fs/promises';
|
|
|
26
26
|
import { dirname, isAbsolute, join, resolve as resolvePath } from 'node:path';
|
|
27
27
|
import { EvidenceParseError, ExitCode, GATE_EVIDENCE_REQUIREMENTS, parseEvidenceString, validateEvidenceForGate, } from '@cleocode/contracts';
|
|
28
28
|
import { CleoError } from '../errors.js';
|
|
29
|
+
import { describeMissingGitWorkTree, E_EVIDENCE_GIT_ROOT, findNestedGitWorkTree, isGitWorkTree, } from '../git/work-tree.js';
|
|
29
30
|
import { pushWarning } from '../output.js';
|
|
30
31
|
import { getEffectiveHead } from '../worktree/effective-head.js';
|
|
31
32
|
import { DISABLE_ENV, describeMemoryLimit } from './heavy-tool-limit.js';
|
|
@@ -132,11 +133,44 @@ export function parseEvidence(raw) {
|
|
|
132
133
|
throw err;
|
|
133
134
|
}
|
|
134
135
|
}
|
|
136
|
+
/**
|
|
137
|
+
* Validate a single parsed atom against the filesystem / git / tools.
|
|
138
|
+
*
|
|
139
|
+
* @param parsed - Parsed atom from {@link parseEvidence}
|
|
140
|
+
* @param projectRoot - Absolute path to project root (for resolving files, git)
|
|
141
|
+
* @param taskId - Optional CLEO task ID. When provided, enables branch-scope
|
|
142
|
+
* check (T9178), content-intersect check (T9245), worktree-aware HEAD
|
|
143
|
+
* resolution (T-WT-3), and git-show file fallback for branch-only files
|
|
144
|
+
* (T11959).
|
|
145
|
+
* @param siblingCommitSha - Optional sha of a sibling `commit:` atom from the
|
|
146
|
+
* same evidence string. When provided, `files:` paths are resolved against
|
|
147
|
+
* that commit's tree FIRST (T12107 / gh#1195) before falling back to the
|
|
148
|
+
* worktree and git refs — covers a merged commit whose files are not yet
|
|
149
|
+
* present in the local checkout.
|
|
150
|
+
* @param context - Current task, gate and acceptance criteria used to validate scoped proof.
|
|
151
|
+
* @returns Validation outcome with canonicalised form on success
|
|
152
|
+
* @example
|
|
153
|
+
* ```ts
|
|
154
|
+
* const result = await validateAtom(parsedAtom, projectRoot, task.id, undefined, context);
|
|
155
|
+
* ```
|
|
156
|
+
*
|
|
157
|
+
* @task T832
|
|
158
|
+
* @task T11959
|
|
159
|
+
* @task T12107
|
|
160
|
+
* @adr ADR-051 §3
|
|
161
|
+
*/
|
|
135
162
|
export async function validateAtom(parsed, projectRoot,
|
|
136
163
|
/** T9178: When provided, validates commit is on task/<taskId> branch. */
|
|
137
164
|
taskId,
|
|
138
165
|
/** T12107: sha of a sibling `commit:` atom in the same evidence string. */
|
|
139
|
-
siblingCommitSha) {
|
|
166
|
+
siblingCommitSha, context) {
|
|
167
|
+
if (parsed.kind === 'pr' && (!Number.isInteger(parsed.prNumber) || parsed.prNumber <= 0)) {
|
|
168
|
+
return {
|
|
169
|
+
ok: false,
|
|
170
|
+
codeName: 'E_EVIDENCE_INVALID',
|
|
171
|
+
reason: 'PR number must be a positive integer.',
|
|
172
|
+
};
|
|
173
|
+
}
|
|
140
174
|
// gh#1365: resolve the tree under test ONCE, here, and pass it down as a
|
|
141
175
|
// required parameter. Resolving inside each validator would centralise the
|
|
142
176
|
// logic but still let two of them resolve independently and drift — which is
|
|
@@ -151,7 +185,7 @@ siblingCommitSha) {
|
|
|
151
185
|
case 'commit':
|
|
152
186
|
return validateCommit(parsed.sha, roots, taskId);
|
|
153
187
|
case 'files':
|
|
154
|
-
return validateFiles(parsed.paths, roots, taskId, siblingCommitSha);
|
|
188
|
+
return validateFiles(parsed.paths, roots, taskId, context?.artifactCommitSha ?? siblingCommitSha, Boolean(context?.artifactCommitSha));
|
|
155
189
|
case 'test-run':
|
|
156
190
|
return validateTestRun(parsed.path, roots);
|
|
157
191
|
case 'tool':
|
|
@@ -173,7 +207,7 @@ siblingCommitSha) {
|
|
|
173
207
|
// db, which is CLEO's own record, not the repository's.
|
|
174
208
|
return validateDecision(parsed.decisionId, roots);
|
|
175
209
|
case 'pr':
|
|
176
|
-
return validatePrAtom(parsed.prNumber, roots);
|
|
210
|
+
return validatePrAtom(parsed.prNumber, roots, context);
|
|
177
211
|
case 'satisfies': {
|
|
178
212
|
// ADR-079-r2: 5-check validator pipeline shipped by T10507.
|
|
179
213
|
// Delegates to the dedicated validator module to keep the dispatch
|
|
@@ -309,15 +343,17 @@ function resolveIntegrationBranches(env, projectContext) {
|
|
|
309
343
|
*
|
|
310
344
|
* Checking the remote-tracking ref preserves verification after a merged local
|
|
311
345
|
* integration branch has been cleaned up.
|
|
346
|
+
*
|
|
347
|
+
* @param executionRoot - The repo the evidence is about, never the store root.
|
|
312
348
|
*/
|
|
313
|
-
async function findReachableIntegrationBranch(sha, branches,
|
|
349
|
+
async function findReachableIntegrationBranch(sha, branches, executionRoot) {
|
|
314
350
|
for (const branch of branches) {
|
|
315
351
|
const refs = [`refs/heads/${branch}`, `refs/remotes/origin/${branch}`];
|
|
316
352
|
for (const ref of refs) {
|
|
317
|
-
const exists = await runCommand('git', ['rev-parse', '--verify', ref],
|
|
353
|
+
const exists = await runCommand('git', ['rev-parse', '--verify', ref], executionRoot);
|
|
318
354
|
if (exists.exitCode !== 0)
|
|
319
355
|
continue;
|
|
320
|
-
const reachable = await runCommand('git', ['merge-base', '--is-ancestor', sha, ref],
|
|
356
|
+
const reachable = await runCommand('git', ['merge-base', '--is-ancestor', sha, ref], executionRoot);
|
|
321
357
|
if (reachable.exitCode === 0)
|
|
322
358
|
return branch;
|
|
323
359
|
}
|
|
@@ -333,6 +369,17 @@ async function validateCommit(sha, roots, taskId) {
|
|
|
333
369
|
codeName: 'E_EVIDENCE_INVALID',
|
|
334
370
|
};
|
|
335
371
|
}
|
|
372
|
+
// gh#1462: without a work tree every git call below fails, and the first one
|
|
373
|
+
// (`cat-file`) reported it as "Commit not found in repository" — which says
|
|
374
|
+
// the commit is absent, not that git never ran in a repository at all. Same
|
|
375
|
+
// distinction `pr:` needs, so it fails the same way.
|
|
376
|
+
if (!isGitWorkTree(executionRoot)) {
|
|
377
|
+
return {
|
|
378
|
+
ok: false,
|
|
379
|
+
reason: describeMissingGitWorkTree(executionRoot),
|
|
380
|
+
codeName: E_EVIDENCE_GIT_ROOT,
|
|
381
|
+
};
|
|
382
|
+
}
|
|
336
383
|
const exists = await runCommand('git', ['cat-file', '-e', `${sha}^{commit}`], executionRoot);
|
|
337
384
|
if (exists.exitCode !== 0) {
|
|
338
385
|
return {
|
|
@@ -352,7 +399,7 @@ async function validateCommit(sha, roots, taskId) {
|
|
|
352
399
|
const { loadProjectContext } = await import('../agents/variable-substitution.js');
|
|
353
400
|
const projectCtx = loadProjectContext(projectRoot);
|
|
354
401
|
const integrationBranches = resolveIntegrationBranches(process.env, projectCtx.loaded ? projectCtx.context : null);
|
|
355
|
-
const reachable = await runCommand('git', ['merge-base', '--is-ancestor', sha, effectiveHead],
|
|
402
|
+
const reachable = await runCommand('git', ['merge-base', '--is-ancestor', sha, effectiveHead], executionRoot);
|
|
356
403
|
if (reachable.exitCode !== 0) {
|
|
357
404
|
// DHQ-083 companion (a): when the commit is not reachable from the task
|
|
358
405
|
// branch HEAD, also accept commits reachable from the configured
|
|
@@ -398,7 +445,7 @@ async function validateCommit(sha, roots, taskId) {
|
|
|
398
445
|
const branchRef = `task/${taskId}`;
|
|
399
446
|
const branchExists = await runCommand('git', ['rev-parse', '--verify', branchRef], executionRoot);
|
|
400
447
|
if (branchExists.exitCode === 0) {
|
|
401
|
-
const onBranch = await runCommand('git', ['merge-base', '--is-ancestor', sha, branchRef],
|
|
448
|
+
const onBranch = await runCommand('git', ['merge-base', '--is-ancestor', sha, branchRef], executionRoot);
|
|
402
449
|
if (onBranch.exitCode !== 0) {
|
|
403
450
|
// T11959 / DHQ-083 companion (a): also accept commits reachable from
|
|
404
451
|
// the configured integration branches. This covers:
|
|
@@ -406,7 +453,7 @@ async function validateCommit(sha, roots, taskId) {
|
|
|
406
453
|
// - post-merge task branches that have been cleaned up (the SHA is now
|
|
407
454
|
// only reachable from main, not from `task/<id>` which no longer exists)
|
|
408
455
|
// gh#1116 / T12028: reuses the integrationBranches resolved above.
|
|
409
|
-
const reachableIntegrationBranch = await findReachableIntegrationBranch(sha, integrationBranches,
|
|
456
|
+
const reachableIntegrationBranch = await findReachableIntegrationBranch(sha, integrationBranches, executionRoot);
|
|
410
457
|
if (reachableIntegrationBranch === null) {
|
|
411
458
|
const branchList = integrationBranches.join(', ');
|
|
412
459
|
return {
|
|
@@ -418,14 +465,16 @@ async function validateCommit(sha, roots, taskId) {
|
|
|
418
465
|
}
|
|
419
466
|
}
|
|
420
467
|
// T9245: content-intersect check — diff MUST touch at least one AC file.
|
|
421
|
-
|
|
468
|
+
// gh#1462: the task row comes from the store, the diff from the repo under
|
|
469
|
+
// test — both roots, like every other mixed read on this switch.
|
|
470
|
+
const intersectResult = await checkCommitContentIntersect(sha, taskId, roots);
|
|
422
471
|
if (!intersectResult.ok) {
|
|
423
472
|
return intersectResult;
|
|
424
473
|
}
|
|
425
474
|
}
|
|
426
|
-
const short = await runCommand('git', ['rev-parse', '--short', sha],
|
|
475
|
+
const short = await runCommand('git', ['rev-parse', '--short', sha], executionRoot);
|
|
427
476
|
const shortSha = short.stdout.trim() || sha.slice(0, 7);
|
|
428
|
-
const full = await runCommand('git', ['rev-parse', sha],
|
|
477
|
+
const full = await runCommand('git', ['rev-parse', sha], executionRoot);
|
|
429
478
|
const fullSha = full.stdout.trim() || sha;
|
|
430
479
|
return { ok: true, atom: { kind: 'commit', sha: fullSha, shortSha } };
|
|
431
480
|
}
|
|
@@ -850,27 +899,26 @@ export function resolveCanonicalProjectRoot(projectRoot) {
|
|
|
850
899
|
* Fix (T-WT-2): This function calls `resolveCanonicalProjectRoot(projectRoot)`
|
|
851
900
|
* to obtain the main repo root before opening `tasks.db`. The canonical main
|
|
852
901
|
* DB is authoritative for all task metadata reads during gate verification.
|
|
853
|
-
* Git operations (`gitShowFiles`)
|
|
854
|
-
*
|
|
902
|
+
* Git operations (`gitShowFiles`) use `executionRoot` — the repo the evidence is
|
|
903
|
+
* about, which gh#1462 showed is not necessarily the store root.
|
|
855
904
|
*
|
|
856
905
|
* @param sha - Commit SHA whose diff is inspected.
|
|
857
906
|
* @param taskId - CLEO task ID used to load AC file declarations.
|
|
858
|
-
* @param
|
|
859
|
-
* DB reads use `resolveCanonicalProjectRoot(projectRoot)` internally.
|
|
907
|
+
* @param roots - Store root for the task row, execution root for the diff.
|
|
860
908
|
*
|
|
861
909
|
* @internal
|
|
862
910
|
* @task T9245
|
|
863
911
|
* @task T-WT-2
|
|
912
|
+
* @task gh#1462
|
|
864
913
|
* @adr ADR-051-worktree-extension
|
|
865
914
|
*/
|
|
866
|
-
async function checkCommitContentIntersect(sha, taskId,
|
|
915
|
+
async function checkCommitContentIntersect(sha, taskId, roots) {
|
|
916
|
+
const { storeRoot, executionRoot } = roots;
|
|
867
917
|
// BUG-C FIX (T-WT-2 / E-WORKTREE-IVTR): always read task metadata from the
|
|
868
|
-
// canonical (main) repository DB. When
|
|
918
|
+
// canonical (main) repository DB. When the store root is a worktree path the
|
|
869
919
|
// worktree's tasks.db is a stale spawn-time snapshot; the main DB is the
|
|
870
|
-
// authoritative source for task.files and task.acceptance.
|
|
871
|
-
|
|
872
|
-
// object store across worktrees, so any dir in the shared tree works.
|
|
873
|
-
const canonicalRoot = resolveCanonicalProjectRoot(projectRoot);
|
|
920
|
+
// authoritative source for task.files and task.acceptance.
|
|
921
|
+
const canonicalRoot = resolveCanonicalProjectRoot(storeRoot);
|
|
874
922
|
// Best-effort load — DB unavailability MUST NOT block verify.
|
|
875
923
|
let task = null;
|
|
876
924
|
try {
|
|
@@ -906,7 +954,7 @@ async function checkCommitContentIntersect(sha, taskId, projectRoot) {
|
|
|
906
954
|
* is still reported; it just cannot fail the gate.
|
|
907
955
|
*/
|
|
908
956
|
const enforcing = provenance === 'declared';
|
|
909
|
-
const diffFiles = await gitShowFiles(sha,
|
|
957
|
+
const diffFiles = await gitShowFiles(sha, executionRoot);
|
|
910
958
|
const acPreview = `${acFiles.slice(0, 5).join(', ')}${acFiles.length > 5 ? '…' : ''}`;
|
|
911
959
|
if (diffFiles.length === 0) {
|
|
912
960
|
const reason = `Commit ${sha.slice(0, 7)} touches no files — cannot satisfy implemented gate ` +
|
|
@@ -1026,7 +1074,7 @@ async function gitShowFileContentAtCommit(relPath, sha, projectRoot) {
|
|
|
1026
1074
|
* @task T11959
|
|
1027
1075
|
* @task T12107
|
|
1028
1076
|
*/
|
|
1029
|
-
async function validateFiles(paths, roots, taskId, commitSha) {
|
|
1077
|
+
async function validateFiles(paths, roots, taskId, commitSha, requireCommitArtifact = false) {
|
|
1030
1078
|
const { storeRoot: projectRoot, executionRoot } = roots;
|
|
1031
1079
|
if (paths.length === 0) {
|
|
1032
1080
|
return {
|
|
@@ -1051,6 +1099,13 @@ async function validateFiles(paths, roots, taskId, commitSha) {
|
|
|
1051
1099
|
if (commitSha) {
|
|
1052
1100
|
content = await gitShowFileContentAtCommit(p, commitSha, executionRoot);
|
|
1053
1101
|
}
|
|
1102
|
+
if (requireCommitArtifact && content === null) {
|
|
1103
|
+
return {
|
|
1104
|
+
ok: false,
|
|
1105
|
+
codeName: 'E_EVIDENCE_INSUFFICIENT',
|
|
1106
|
+
reason: `Cannot inspect ${p} at PR merge ${commitSha}; fetch that commit before recording evidence. Current checkout bytes cannot substitute.`,
|
|
1107
|
+
};
|
|
1108
|
+
}
|
|
1054
1109
|
if (content === null && existsSync(abs)) {
|
|
1055
1110
|
// Happy path — file exists on disk.
|
|
1056
1111
|
const st = await stat(abs);
|
|
@@ -1109,11 +1164,19 @@ async function validateFiles(paths, roots, taskId, commitSha) {
|
|
|
1109
1164
|
* pointing at a tmpdir, a non-git cwd) falls back to `projectRoot`, so
|
|
1110
1165
|
* single-checkout behaviour is bit-for-bit unchanged.
|
|
1111
1166
|
*
|
|
1167
|
+
* gh#1462 added the other direction: when `projectRoot` is a PARENT of the
|
|
1168
|
+
* checkout, neither the caller's cwd (which is that parent) nor `projectRoot`
|
|
1169
|
+
* is a git work tree, and `gh`/`git` run there fail with "fatal: not a git
|
|
1170
|
+
* repository". The checkout is a direct child in that layout, so it is used
|
|
1171
|
+
* when exactly one child is a work tree; zero or several candidates keep
|
|
1172
|
+
* `projectRoot` and the atom reports the layout problem distinctly.
|
|
1173
|
+
*
|
|
1112
1174
|
* @param projectRoot - Absolute CLEO store root.
|
|
1113
1175
|
* @param cwd - Directory the CLI was invoked from. Defaults to `process.cwd()`.
|
|
1114
1176
|
* @returns Absolute path of the tree to execute in.
|
|
1115
1177
|
*
|
|
1116
1178
|
* @task T12112 (gh#1220, gh#1226, gh#1230)
|
|
1179
|
+
* @task gh#1462
|
|
1117
1180
|
*/
|
|
1118
1181
|
export function resolveEvidenceExecutionRoot(projectRoot,
|
|
1119
1182
|
// This function's entire purpose is to recover the tree the CLI was INVOKED
|
|
@@ -1125,19 +1188,18 @@ export function resolveEvidenceExecutionRoot(projectRoot,
|
|
|
1125
1188
|
// and it only LOCATES a candidate; the same-project check below decides
|
|
1126
1189
|
// whether it is honoured.
|
|
1127
1190
|
cwd = process.cwd()) {
|
|
1128
|
-
let toplevel;
|
|
1191
|
+
let toplevel = null;
|
|
1129
1192
|
try {
|
|
1130
|
-
toplevel =
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1193
|
+
toplevel =
|
|
1194
|
+
execFileSync('git', ['rev-parse', '--show-toplevel'], {
|
|
1195
|
+
cwd,
|
|
1196
|
+
encoding: 'utf-8',
|
|
1197
|
+
stdio: ['ignore', 'pipe', 'ignore'],
|
|
1198
|
+
}).trim() || null;
|
|
1135
1199
|
}
|
|
1136
1200
|
catch {
|
|
1137
|
-
|
|
1201
|
+
toplevel = null; // not a git checkout — try the store root and its children
|
|
1138
1202
|
}
|
|
1139
|
-
if (!toplevel)
|
|
1140
|
-
return projectRoot;
|
|
1141
1203
|
const sameProject = (a, b) => {
|
|
1142
1204
|
const norm = (x) => {
|
|
1143
1205
|
try {
|
|
@@ -1150,8 +1212,19 @@ cwd = process.cwd()) {
|
|
|
1150
1212
|
return norm(a) === norm(b);
|
|
1151
1213
|
};
|
|
1152
1214
|
// Only redirect when the caller's tree is a worktree OF this project.
|
|
1153
|
-
if (sameProject(resolveCanonicalProjectRoot(toplevel), projectRoot))
|
|
1215
|
+
if (toplevel !== null && sameProject(resolveCanonicalProjectRoot(toplevel), projectRoot)) {
|
|
1154
1216
|
return toplevel;
|
|
1217
|
+
}
|
|
1218
|
+
// The ordinary single-project layout: the CLEO root IS the checkout.
|
|
1219
|
+
if (isGitWorkTree(projectRoot))
|
|
1220
|
+
return projectRoot;
|
|
1221
|
+
// gh#1462: the CLEO root is a PARENT of the checkout. `gh` and `git` run
|
|
1222
|
+
// from `projectRoot` fail with "fatal: not a git repository", which reads as
|
|
1223
|
+
// a broken tool or an unsatisfiable atom. Use the one direct child that is a
|
|
1224
|
+
// work tree; ambiguity is reported, not guessed.
|
|
1225
|
+
const nested = findNestedGitWorkTree(projectRoot);
|
|
1226
|
+
if (nested !== null)
|
|
1227
|
+
return nested;
|
|
1155
1228
|
return projectRoot;
|
|
1156
1229
|
}
|
|
1157
1230
|
async function validateTestRun(path, roots) {
|
|
@@ -1703,7 +1776,14 @@ async function validateDecision(decisionId, roots) {
|
|
|
1703
1776
|
*
|
|
1704
1777
|
* @task T9764
|
|
1705
1778
|
*/
|
|
1706
|
-
async function validatePrAtom(prNumber, roots) {
|
|
1779
|
+
async function validatePrAtom(prNumber, roots, context) {
|
|
1780
|
+
if (!context) {
|
|
1781
|
+
return {
|
|
1782
|
+
ok: false,
|
|
1783
|
+
codeName: 'E_EVIDENCE_INSUFFICIENT',
|
|
1784
|
+
reason: 'PR evidence requires current task, gate, and acceptance-criterion context.',
|
|
1785
|
+
};
|
|
1786
|
+
}
|
|
1707
1787
|
// Dynamic import keeps the verification module free of a static dependency
|
|
1708
1788
|
// on the release subtree, mirroring the pattern used by validateDecision.
|
|
1709
1789
|
const { resolvePrEvidenceAtom } = await import('../release/pr-evidence.js');
|
|
@@ -1727,6 +1807,33 @@ async function validatePrAtom(prNumber, roots) {
|
|
|
1727
1807
|
if (!result.ok) {
|
|
1728
1808
|
return { ok: false, reason: result.reason, codeName: result.codeName };
|
|
1729
1809
|
}
|
|
1810
|
+
if (result.changedFileCount !== result.changedPaths.length || result.changedPaths.length === 0) {
|
|
1811
|
+
return {
|
|
1812
|
+
ok: false,
|
|
1813
|
+
codeName: 'E_EVIDENCE_INSUFFICIENT',
|
|
1814
|
+
reason: `PR #${prNumber} changed-file coverage is incomplete or empty (${result.changedPaths.length}/${result.changedFileCount}); inspect the full diff before recording evidence.`,
|
|
1815
|
+
};
|
|
1816
|
+
}
|
|
1817
|
+
const declaredFiles = context.task.files ?? [];
|
|
1818
|
+
const taskMention = new RegExp(`(^|[^A-Za-z0-9])${context.task.id}([^A-Za-z0-9]|$)`);
|
|
1819
|
+
const explicitlyLinked = taskMention.test(`${result.title}\n${result.body}\n${result.headRefName}`);
|
|
1820
|
+
const scopeIntersects = declaredFiles.length > 0 && diffIntersectsAc(result.changedPaths, declaredFiles);
|
|
1821
|
+
if ((!explicitlyLinked && !scopeIntersects) || (declaredFiles.length > 0 && !scopeIntersects)) {
|
|
1822
|
+
return {
|
|
1823
|
+
ok: false,
|
|
1824
|
+
codeName: 'E_EVIDENCE_CONTENT_MISMATCH',
|
|
1825
|
+
reason: `PR #${prNumber} does not establish a relationship to task ${context.task.id}. Changed artifacts: ${result.changedPaths.join(', ')}. Declare task files or cite the exact task in the PR; declared scope must intersect the diff.`,
|
|
1826
|
+
};
|
|
1827
|
+
}
|
|
1828
|
+
if (context.gates.includes('implemented') &&
|
|
1829
|
+
classifyEvidenceTask(context) === 'code' &&
|
|
1830
|
+
result.changedPaths.every(isDocumentArtifact)) {
|
|
1831
|
+
return {
|
|
1832
|
+
ok: false,
|
|
1833
|
+
codeName: 'E_EVIDENCE_CONTENT_MISMATCH',
|
|
1834
|
+
reason: `PR #${prNumber} changes only documentation and cannot implement code task ${context.task.id}. Changed artifacts: ${result.changedPaths.join(', ')}.`,
|
|
1835
|
+
};
|
|
1836
|
+
}
|
|
1730
1837
|
return {
|
|
1731
1838
|
ok: true,
|
|
1732
1839
|
atom: {
|
|
@@ -1736,9 +1843,79 @@ async function validatePrAtom(prNumber, roots) {
|
|
|
1736
1843
|
mergedAt: result.mergedAt,
|
|
1737
1844
|
successCount: result.successCount,
|
|
1738
1845
|
totalChecks: result.totalChecks,
|
|
1846
|
+
changedPaths: result.changedPaths,
|
|
1847
|
+
taskId: context.task.id,
|
|
1739
1848
|
},
|
|
1740
1849
|
};
|
|
1741
1850
|
}
|
|
1851
|
+
function isDocumentArtifact(path) {
|
|
1852
|
+
return (/\.(md|mdx|rst|adoc|txt)$/i.test(path) ||
|
|
1853
|
+
/(?:^|\/)(README|LICENSE|CHANGELOG)(?:\.[^/]*)?$/i.test(path));
|
|
1854
|
+
}
|
|
1855
|
+
function classifyEvidenceTask(context) {
|
|
1856
|
+
if (context.task.kind === 'research' || context.task.kind === 'spike')
|
|
1857
|
+
return 'research';
|
|
1858
|
+
if (context.task.files?.length && context.task.files.every(isDocumentArtifact))
|
|
1859
|
+
return 'documentation';
|
|
1860
|
+
if (context.task.kind === 'bug')
|
|
1861
|
+
return 'code';
|
|
1862
|
+
if (context.task.labels?.some((label) => label === 'docs' || label === 'documentation'))
|
|
1863
|
+
return 'documentation';
|
|
1864
|
+
return 'code';
|
|
1865
|
+
}
|
|
1866
|
+
/**
|
|
1867
|
+
* Require explicit criterion linkage to inspected artifacts and real gate results.
|
|
1868
|
+
* @param context - Current task classification, requested gates and criterion records.
|
|
1869
|
+
* @param gate - Individual gate whose evidence is being assessed.
|
|
1870
|
+
* @param atoms - Independently validated artifacts, results and criterion references.
|
|
1871
|
+
* @returns A refusal reason when proof is insufficient, otherwise null.
|
|
1872
|
+
* @remarks PR state and CI provenance alone cannot establish every acceptance gate.
|
|
1873
|
+
* @example
|
|
1874
|
+
* ```ts
|
|
1875
|
+
* const refusal = checkTaskEvidenceContext(context, "implemented", validatedAtoms);
|
|
1876
|
+
* ```
|
|
1877
|
+
*/
|
|
1878
|
+
export function checkTaskEvidenceContext(context, gate, atoms) {
|
|
1879
|
+
const filePaths = atoms.flatMap((atom) => atom.kind === 'files' ? atom.files.map((file) => file.path) : []);
|
|
1880
|
+
const prAtoms = atoms.filter((atom) => atom.kind === 'pr');
|
|
1881
|
+
if (prAtoms.length > 1)
|
|
1882
|
+
return 'Record one PR and its merge-pinned artifacts per verification attempt; multiple merge identities are ambiguous.';
|
|
1883
|
+
for (const atom of prAtoms) {
|
|
1884
|
+
if (atom.taskId !== context.task.id || !atom.changedPaths?.length)
|
|
1885
|
+
return 'PR provenance lacks verified task scope; re-verify with current task context.';
|
|
1886
|
+
if (gate === 'implemented' && !filePaths.some((path) => atom.changedPaths?.includes(path)))
|
|
1887
|
+
return `PR #${atom.prNumber} requires files evidence for an artifact actually changed by that PR.`;
|
|
1888
|
+
if (gate === 'implemented' &&
|
|
1889
|
+
classifyEvidenceTask(context) === 'code' &&
|
|
1890
|
+
atom.changedPaths.every(isDocumentArtifact))
|
|
1891
|
+
return 'Documentation-only PR evidence cannot implement the current code task.';
|
|
1892
|
+
}
|
|
1893
|
+
if (!['implemented', 'testsPassed', 'qaPassed'].includes(gate))
|
|
1894
|
+
return null;
|
|
1895
|
+
if (classifyEvidenceTask(context) === 'code' &&
|
|
1896
|
+
(gate === 'testsPassed' || gate === 'qaPassed') &&
|
|
1897
|
+
!atoms.some((atom) => atom.kind === 'test-run' || (atom.kind === 'tool' && !atom.notApplicable))) {
|
|
1898
|
+
return `Code task ${context.task.id} requires an actual verification result for ${gate}; absence of a toolchain is not a passing result.`;
|
|
1899
|
+
}
|
|
1900
|
+
const linked = atoms.filter((atom) => atom.kind === 'satisfies' && atom.targetTaskId === context.task.id);
|
|
1901
|
+
if (context.criteria.length > 0 && linked.length === 0)
|
|
1902
|
+
return `Task ${context.task.id} requires explicit criterion linkage: add satisfies:${context.task.id}#AC<n> alongside artifacts and verification results.`;
|
|
1903
|
+
for (const atom of linked) {
|
|
1904
|
+
if (!context.criteria.some((criterion) => criterion.id === atom.resolvedAcUuid))
|
|
1905
|
+
return `Criterion ${atom.resolvedAcUuid ?? atom.targetAcAlias} is not in the current task criteria.`;
|
|
1906
|
+
}
|
|
1907
|
+
if (linked.length > 0 &&
|
|
1908
|
+
gate === 'implemented' &&
|
|
1909
|
+
filePaths.length === 0 &&
|
|
1910
|
+
!atoms.some((atom) => atom.kind === 'decision'))
|
|
1911
|
+
return 'Criterion implementation evidence requires inspected files or a sourced research decision.';
|
|
1912
|
+
if (classifyEvidenceTask(context) === 'code' &&
|
|
1913
|
+
gate === 'implemented' &&
|
|
1914
|
+
atoms.some((atom) => atom.kind === 'decision') &&
|
|
1915
|
+
!atoms.some((atom) => atom.kind === 'commit' || atom.kind === 'pr'))
|
|
1916
|
+
return 'A research decision alone cannot implement a code-fix task.';
|
|
1917
|
+
return null;
|
|
1918
|
+
}
|
|
1742
1919
|
/**
|
|
1743
1920
|
* Check that the provided evidence atoms satisfy the callsite-coverage
|
|
1744
1921
|
* requirement for tasks carrying the `callsite-coverage` label.
|
|
@@ -1881,11 +2058,13 @@ export function checkGateEvidenceMinimumDetailed(gate, atoms) {
|
|
|
1881
2058
|
* @param capturedBy - Agent identifier
|
|
1882
2059
|
* @param override - True when CLEO_OWNER_OVERRIDE is set
|
|
1883
2060
|
* @param overrideReason - Reason supplied with the override
|
|
2061
|
+
* @param context - Task and criterion context used to capture durable proof bindings.
|
|
2062
|
+
* @param gate - Gate associated with the captured result and artifact references.
|
|
1884
2063
|
* @returns Canonical GateEvidence ready to persist
|
|
1885
2064
|
*
|
|
1886
2065
|
* @task T832
|
|
1887
2066
|
*/
|
|
1888
|
-
export function composeGateEvidence(atoms, capturedBy, override, overrideReason) {
|
|
2067
|
+
export function composeGateEvidence(atoms, capturedBy, override, overrideReason, context, gate) {
|
|
1889
2068
|
const result = {
|
|
1890
2069
|
atoms,
|
|
1891
2070
|
capturedAt: new Date().toISOString(),
|
|
@@ -1896,6 +2075,34 @@ export function composeGateEvidence(atoms, capturedBy, override, overrideReason)
|
|
|
1896
2075
|
if (overrideReason)
|
|
1897
2076
|
result.overrideReason = overrideReason;
|
|
1898
2077
|
}
|
|
2078
|
+
if (context && gate) {
|
|
2079
|
+
const linkedIds = new Set(atoms.flatMap((atom) => atom.kind === 'satisfies' && atom.targetTaskId === context.task.id && atom.resolvedAcUuid
|
|
2080
|
+
? [atom.resolvedAcUuid]
|
|
2081
|
+
: []));
|
|
2082
|
+
const artifactPaths = atoms.flatMap((atom) => atom.kind === 'files' ? atom.files.map((file) => file.path) : []);
|
|
2083
|
+
const resultAtomIndices = atoms.flatMap((atom, index) => {
|
|
2084
|
+
if (gate === 'implemented')
|
|
2085
|
+
return atom.kind === 'commit' || atom.kind === 'pr' || atom.kind === 'decision'
|
|
2086
|
+
? [index]
|
|
2087
|
+
: [];
|
|
2088
|
+
return atom.kind === 'tool' || atom.kind === 'test-run' ? [index] : [];
|
|
2089
|
+
});
|
|
2090
|
+
result.scope = {
|
|
2091
|
+
taskId: context.task.id,
|
|
2092
|
+
gate,
|
|
2093
|
+
classification: classifyEvidenceTask(context),
|
|
2094
|
+
criteria: context.criteria
|
|
2095
|
+
.filter((criterion) => linkedIds.has(criterion.id))
|
|
2096
|
+
.map((criterion) => ({
|
|
2097
|
+
criterionId: criterion.id,
|
|
2098
|
+
criterionHash: createHash('sha256').update(criterion.text).digest('hex'),
|
|
2099
|
+
artifactPaths: artifactPaths.length
|
|
2100
|
+
? artifactPaths
|
|
2101
|
+
: (context.task.verification?.evidence?.implemented?.scope?.criteria.find((link) => link.criterionId === criterion.id)?.artifactPaths ?? []),
|
|
2102
|
+
resultAtomIndices,
|
|
2103
|
+
})),
|
|
2104
|
+
};
|
|
2105
|
+
}
|
|
1899
2106
|
return result;
|
|
1900
2107
|
}
|
|
1901
2108
|
/**
|
|
@@ -1964,6 +2171,42 @@ export function isHardAtom(atom) {
|
|
|
1964
2171
|
* @adr ADR-051 §5 / §8 (Decision 8)
|
|
1965
2172
|
*/
|
|
1966
2173
|
export async function revalidateEvidence(evidence, projectRoot, gate, taskId, options) {
|
|
2174
|
+
if (taskId && gate && !evidence.override) {
|
|
2175
|
+
const { getTaskAccessor } = await import('../store/data-accessor.js');
|
|
2176
|
+
const accessor = await getTaskAccessor(resolveCanonicalProjectRoot(projectRoot));
|
|
2177
|
+
const task = await accessor.loadSingleTask(taskId);
|
|
2178
|
+
if (!task)
|
|
2179
|
+
throw new CleoError(ExitCode.NOT_FOUND, `Evidence task ${taskId} is missing`);
|
|
2180
|
+
const context = {
|
|
2181
|
+
task,
|
|
2182
|
+
gates: [gate],
|
|
2183
|
+
criteria: await accessor.getAcRows(taskId),
|
|
2184
|
+
};
|
|
2185
|
+
let reason = checkTaskEvidenceContext(context, gate, evidence.atoms);
|
|
2186
|
+
if (!reason &&
|
|
2187
|
+
!(classifyEvidenceTask(context) !== 'code' &&
|
|
2188
|
+
isDecisionOnlyImplementation(task.verification?.evidence?.implemented) &&
|
|
2189
|
+
DECISION_ONLY_INAPPLICABLE_GATES.includes(gate))) {
|
|
2190
|
+
reason = checkGateEvidenceMinimum(gate, evidence.atoms);
|
|
2191
|
+
}
|
|
2192
|
+
if (!reason && evidence.scope) {
|
|
2193
|
+
if (evidence.scope.taskId !== taskId || evidence.scope.gate !== gate)
|
|
2194
|
+
reason = 'Evidence scope does not match the current task and gate.';
|
|
2195
|
+
for (const link of evidence.scope.criteria) {
|
|
2196
|
+
const criterion = context.criteria.find((row) => row.id === link.criterionId);
|
|
2197
|
+
if (!criterion ||
|
|
2198
|
+
createHash('sha256').update(criterion.text).digest('hex') !== link.criterionHash)
|
|
2199
|
+
reason = `Criterion ${link.criterionId} changed after verification; record fresh evidence.`;
|
|
2200
|
+
}
|
|
2201
|
+
}
|
|
2202
|
+
if (reason)
|
|
2203
|
+
return {
|
|
2204
|
+
stillValid: false,
|
|
2205
|
+
failedAtoms: [
|
|
2206
|
+
{ atom: evidence.atoms[0] ?? { kind: 'note', note: 'missing evidence' }, reason },
|
|
2207
|
+
],
|
|
2208
|
+
};
|
|
2209
|
+
}
|
|
1967
2210
|
// T9245: critical-gate override rejection.
|
|
1968
2211
|
// When the gate is `implemented` or `testsPassed`, evidence that has no
|
|
1969
2212
|
// non-override hard atom is rejected outright. We define "override-only"
|
|
@@ -2022,12 +2265,21 @@ export async function revalidateEvidence(evidence, projectRoot, gate, taskId, op
|
|
|
2022
2265
|
// checked FIRST (the file may still be absent from the local checkout
|
|
2023
2266
|
// at complete time when local main was never fast-forwarded).
|
|
2024
2267
|
const siblingCommit = evidence.atoms.find((a) => a.kind === 'commit');
|
|
2025
|
-
const
|
|
2268
|
+
const siblingPr = evidence.atoms.find((atom) => atom.kind === 'pr');
|
|
2269
|
+
const siblingCommitSha = siblingPr?.mergeCommitSha ?? siblingCommit?.sha;
|
|
2270
|
+
const executionRoot = resolveEvidenceExecutionRoot(projectRoot);
|
|
2026
2271
|
for (const f of atom.files) {
|
|
2027
|
-
const abs = isAbsolute(f.path) ? f.path : resolvePath(
|
|
2272
|
+
const abs = isAbsolute(f.path) ? f.path : resolvePath(executionRoot, f.path);
|
|
2028
2273
|
let content = null;
|
|
2029
2274
|
if (siblingCommitSha) {
|
|
2030
|
-
content = await gitShowFileContentAtCommit(f.path, siblingCommitSha,
|
|
2275
|
+
content = await gitShowFileContentAtCommit(f.path, siblingCommitSha, executionRoot);
|
|
2276
|
+
}
|
|
2277
|
+
if (siblingPr && content === null) {
|
|
2278
|
+
failed.push({
|
|
2279
|
+
atom,
|
|
2280
|
+
reason: `Cannot inspect ${f.path} at recorded PR merge ${siblingCommitSha}; current checkout bytes cannot substitute.`,
|
|
2281
|
+
});
|
|
2282
|
+
continue;
|
|
2031
2283
|
}
|
|
2032
2284
|
if (!content && existsSync(abs)) {
|
|
2033
2285
|
content = await readFile(abs);
|
|
@@ -2036,7 +2288,7 @@ export async function revalidateEvidence(evidence, projectRoot, gate, taskId, op
|
|
|
2036
2288
|
// T11959: git-show fallback — file may have been on task branch at
|
|
2037
2289
|
// verify time and is now on main after merge, or it may still only
|
|
2038
2290
|
// exist on the branch. Use the same resolution path as validateFiles.
|
|
2039
|
-
content = await gitShowFileContent(f.path, taskId,
|
|
2291
|
+
content = await gitShowFileContent(f.path, taskId, executionRoot);
|
|
2040
2292
|
}
|
|
2041
2293
|
if (!content) {
|
|
2042
2294
|
failed.push({ atom, reason: `File removed since verify: ${f.path}` });
|