@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.
Files changed (561) hide show
  1. package/dist/audit/reconstruct.d.ts +13 -43
  2. package/dist/audit/reconstruct.d.ts.map +1 -1
  3. package/dist/audit/reconstruct.js +295 -290
  4. package/dist/audit/reconstruct.js.map +1 -1
  5. package/dist/bootstrap.d.ts.map +1 -1
  6. package/dist/bootstrap.js +8 -2
  7. package/dist/bootstrap.js.map +1 -1
  8. package/dist/dispatch/mutate-projection.d.ts.map +1 -1
  9. package/dist/dispatch/mutate-projection.js +12 -0
  10. package/dist/dispatch/mutate-projection.js.map +1 -1
  11. package/dist/dispatch/mvi-projection.d.ts +29 -6
  12. package/dist/dispatch/mvi-projection.d.ts.map +1 -1
  13. package/dist/dispatch/mvi-projection.js +109 -139
  14. package/dist/dispatch/mvi-projection.js.map +1 -1
  15. package/dist/docs/docs-read-model.d.ts +3 -2
  16. package/dist/docs/docs-read-model.d.ts.map +1 -1
  17. package/dist/docs/docs-read-model.js +4 -3
  18. package/dist/docs/docs-read-model.js.map +1 -1
  19. package/dist/docs/export-document.js +5100 -2297
  20. package/dist/docs/export-document.js.map +3 -3
  21. package/dist/docs/projection.d.ts +67 -0
  22. package/dist/docs/projection.d.ts.map +1 -0
  23. package/dist/docs/projection.js +370 -0
  24. package/dist/docs/projection.js.map +1 -0
  25. package/dist/doctor/acceptance-drift.d.ts +6 -2
  26. package/dist/doctor/acceptance-drift.d.ts.map +1 -1
  27. package/dist/doctor/acceptance-drift.js +43 -5
  28. package/dist/doctor/acceptance-drift.js.map +1 -1
  29. package/dist/doctor/knowledge-summary.d.ts +41 -0
  30. package/dist/doctor/knowledge-summary.d.ts.map +1 -0
  31. package/dist/doctor/knowledge-summary.js +81 -0
  32. package/dist/doctor/knowledge-summary.js.map +1 -0
  33. package/dist/doctor/knowledge.d.ts +192 -0
  34. package/dist/doctor/knowledge.d.ts.map +1 -0
  35. package/dist/doctor/knowledge.js +1864 -0
  36. package/dist/doctor/knowledge.js.map +1 -0
  37. package/dist/git/work-tree.d.ts +64 -0
  38. package/dist/git/work-tree.d.ts.map +1 -0
  39. package/dist/git/work-tree.js +111 -0
  40. package/dist/git/work-tree.js.map +1 -0
  41. package/dist/hooks/handlers/task-hooks.d.ts +8 -5
  42. package/dist/hooks/handlers/task-hooks.d.ts.map +1 -1
  43. package/dist/hooks/handlers/task-hooks.js +15 -60
  44. package/dist/hooks/handlers/task-hooks.js.map +1 -1
  45. package/dist/identity/cleo-identity.d.ts +13 -0
  46. package/dist/identity/cleo-identity.d.ts.map +1 -1
  47. package/dist/identity/cleo-identity.js +20 -6
  48. package/dist/identity/cleo-identity.js.map +1 -1
  49. package/dist/injection.d.ts.map +1 -1
  50. package/dist/injection.js +29 -13
  51. package/dist/injection.js.map +1 -1
  52. package/dist/internal.d.ts +2 -0
  53. package/dist/internal.d.ts.map +1 -1
  54. package/dist/internal.js +2 -0
  55. package/dist/internal.js.map +1 -1
  56. package/dist/lifecycle/verification/satisfies-validator.d.ts.map +1 -1
  57. package/dist/lifecycle/verification/satisfies-validator.js +124 -120
  58. package/dist/lifecycle/verification/satisfies-validator.js.map +1 -1
  59. package/dist/llm/plugin-facade.js +4018 -1726
  60. package/dist/llm/plugin-facade.js.map +3 -3
  61. package/dist/memory/brain-backfill.d.ts +27 -12
  62. package/dist/memory/brain-backfill.d.ts.map +1 -1
  63. package/dist/memory/brain-backfill.js +325 -134
  64. package/dist/memory/brain-backfill.js.map +1 -1
  65. package/dist/memory/brain-doctor.d.ts +21 -0
  66. package/dist/memory/brain-doctor.d.ts.map +1 -1
  67. package/dist/memory/brain-doctor.js +111 -53
  68. package/dist/memory/brain-doctor.js.map +1 -1
  69. package/dist/memory/brain-links.d.ts.map +1 -1
  70. package/dist/memory/brain-links.js +31 -4
  71. package/dist/memory/brain-links.js.map +1 -1
  72. package/dist/memory/brain-reasoning.d.ts.map +1 -1
  73. package/dist/memory/brain-reasoning.js +28 -2
  74. package/dist/memory/brain-reasoning.js.map +1 -1
  75. package/dist/memory/brain-reconciler.d.ts +14 -19
  76. package/dist/memory/brain-reconciler.d.ts.map +1 -1
  77. package/dist/memory/brain-reconciler.js +70 -97
  78. package/dist/memory/brain-reconciler.js.map +1 -1
  79. package/dist/memory/brain-search.d.ts +2 -0
  80. package/dist/memory/brain-search.d.ts.map +1 -1
  81. package/dist/memory/brain-search.js +59 -29
  82. package/dist/memory/brain-search.js.map +1 -1
  83. package/dist/memory/brain-similarity.d.ts.map +1 -1
  84. package/dist/memory/brain-similarity.js +5 -4
  85. package/dist/memory/brain-similarity.js.map +1 -1
  86. package/dist/memory/brain-stub-prune.d.ts +31 -9
  87. package/dist/memory/brain-stub-prune.d.ts.map +1 -1
  88. package/dist/memory/brain-stub-prune.js +65 -18
  89. package/dist/memory/brain-stub-prune.js.map +1 -1
  90. package/dist/memory/brain-writer-handlers.d.ts +10 -1
  91. package/dist/memory/brain-writer-handlers.d.ts.map +1 -1
  92. package/dist/memory/brain-writer-handlers.js +23 -3
  93. package/dist/memory/brain-writer-handlers.js.map +1 -1
  94. package/dist/memory/brain-writer-thread.d.ts +11 -1
  95. package/dist/memory/brain-writer-thread.d.ts.map +1 -1
  96. package/dist/memory/brain-writer-thread.js +87 -20
  97. package/dist/memory/brain-writer-thread.js.map +1 -1
  98. package/dist/memory/brain-writer-worker.js +8 -1
  99. package/dist/memory/brain-writer-worker.js.map +1 -1
  100. package/dist/memory/decision-cross-link.d.ts +39 -0
  101. package/dist/memory/decision-cross-link.d.ts.map +1 -1
  102. package/dist/memory/decision-cross-link.js +316 -0
  103. package/dist/memory/decision-cross-link.js.map +1 -1
  104. package/dist/memory/decisions.d.ts +4 -1
  105. package/dist/memory/decisions.d.ts.map +1 -1
  106. package/dist/memory/decisions.js +7 -24
  107. package/dist/memory/decisions.js.map +1 -1
  108. package/dist/memory/dispatch-trace.d.ts +12 -5
  109. package/dist/memory/dispatch-trace.d.ts.map +1 -1
  110. package/dist/memory/dispatch-trace.js +17 -7
  111. package/dist/memory/dispatch-trace.js.map +1 -1
  112. package/dist/memory/eligibility.d.ts +51 -0
  113. package/dist/memory/eligibility.d.ts.map +1 -0
  114. package/dist/memory/eligibility.js +77 -0
  115. package/dist/memory/eligibility.js.map +1 -0
  116. package/dist/memory/engine-compat.d.ts +2 -0
  117. package/dist/memory/engine-compat.d.ts.map +1 -1
  118. package/dist/memory/engine-compat.js +10 -0
  119. package/dist/memory/engine-compat.js.map +1 -1
  120. package/dist/memory/extraction-gate.d.ts +21 -7
  121. package/dist/memory/extraction-gate.d.ts.map +1 -1
  122. package/dist/memory/extraction-gate.js +178 -216
  123. package/dist/memory/extraction-gate.js.map +1 -1
  124. package/dist/memory/graph-auto-populate.d.ts +38 -5
  125. package/dist/memory/graph-auto-populate.d.ts.map +1 -1
  126. package/dist/memory/graph-auto-populate.js +182 -60
  127. package/dist/memory/graph-auto-populate.js.map +1 -1
  128. package/dist/memory/graph-memory-bridge.d.ts +14 -1
  129. package/dist/memory/graph-memory-bridge.d.ts.map +1 -1
  130. package/dist/memory/graph-memory-bridge.js +66 -28
  131. package/dist/memory/graph-memory-bridge.js.map +1 -1
  132. package/dist/memory/index.d.ts +1 -19
  133. package/dist/memory/index.d.ts.map +1 -1
  134. package/dist/memory/index.js +1 -50
  135. package/dist/memory/index.js.map +1 -1
  136. package/dist/memory/learnings.d.ts.map +1 -1
  137. package/dist/memory/learnings.js +2 -23
  138. package/dist/memory/learnings.js.map +1 -1
  139. package/dist/memory/manifest-filter.d.ts +21 -0
  140. package/dist/memory/manifest-filter.d.ts.map +1 -0
  141. package/dist/memory/manifest-filter.js +51 -0
  142. package/dist/memory/manifest-filter.js.map +1 -0
  143. package/dist/memory/manifest-ingestion.d.ts +28 -30
  144. package/dist/memory/manifest-ingestion.d.ts.map +1 -1
  145. package/dist/memory/manifest-ingestion.js +104 -235
  146. package/dist/memory/manifest-ingestion.js.map +1 -1
  147. package/dist/memory/observer-reflector.d.ts +2 -0
  148. package/dist/memory/observer-reflector.d.ts.map +1 -1
  149. package/dist/memory/observer-reflector.js +6 -49
  150. package/dist/memory/observer-reflector.js.map +1 -1
  151. package/dist/memory/patterns.d.ts +10 -0
  152. package/dist/memory/patterns.d.ts.map +1 -1
  153. package/dist/memory/patterns.js +25 -33
  154. package/dist/memory/patterns.js.map +1 -1
  155. package/dist/memory/pipeline-manifest-sqlite.d.ts +72 -9
  156. package/dist/memory/pipeline-manifest-sqlite.d.ts.map +1 -1
  157. package/dist/memory/pipeline-manifest-sqlite.js +508 -412
  158. package/dist/memory/pipeline-manifest-sqlite.js.map +1 -1
  159. package/dist/memory/retrieval/build-retrieval-bundle.d.ts.map +1 -1
  160. package/dist/memory/retrieval/build-retrieval-bundle.js +16 -15
  161. package/dist/memory/retrieval/build-retrieval-bundle.js.map +1 -1
  162. package/dist/memory/retrieval/fetch.d.ts +7 -0
  163. package/dist/memory/retrieval/fetch.d.ts.map +1 -1
  164. package/dist/memory/retrieval/fetch.js +14 -11
  165. package/dist/memory/retrieval/fetch.js.map +1 -1
  166. package/dist/memory/retrieval/observe.d.ts +7 -1
  167. package/dist/memory/retrieval/observe.d.ts.map +1 -1
  168. package/dist/memory/retrieval/observe.js +58 -4
  169. package/dist/memory/retrieval/observe.js.map +1 -1
  170. package/dist/memory/retrieval/search.d.ts +14 -1
  171. package/dist/memory/retrieval/search.d.ts.map +1 -1
  172. package/dist/memory/retrieval/search.js +133 -69
  173. package/dist/memory/retrieval/search.js.map +1 -1
  174. package/dist/memory/retrieval/telemetry.d.ts +31 -0
  175. package/dist/memory/retrieval/telemetry.d.ts.map +1 -0
  176. package/dist/memory/retrieval/telemetry.js +53 -0
  177. package/dist/memory/retrieval/telemetry.js.map +1 -0
  178. package/dist/nexus/analyze-orchestrator.d.ts +41 -9
  179. package/dist/nexus/analyze-orchestrator.d.ts.map +1 -1
  180. package/dist/nexus/analyze-orchestrator.js +257 -58
  181. package/dist/nexus/analyze-orchestrator.js.map +1 -1
  182. package/dist/nexus/api-contracts.d.ts +2 -6
  183. package/dist/nexus/api-contracts.d.ts.map +1 -1
  184. package/dist/nexus/api-contracts.js +11 -2
  185. package/dist/nexus/api-contracts.js.map +1 -1
  186. package/dist/nexus/context.d.ts.map +1 -1
  187. package/dist/nexus/context.js +14 -37
  188. package/dist/nexus/context.js.map +1 -1
  189. package/dist/nexus/diff.d.ts.map +1 -1
  190. package/dist/nexus/diff.js +2 -1
  191. package/dist/nexus/diff.js.map +1 -1
  192. package/dist/nexus/identity.d.ts +29 -3
  193. package/dist/nexus/identity.d.ts.map +1 -1
  194. package/dist/nexus/identity.js +63 -12
  195. package/dist/nexus/identity.js.map +1 -1
  196. package/dist/nexus/impact.d.ts +21 -19
  197. package/dist/nexus/impact.d.ts.map +1 -1
  198. package/dist/nexus/impact.js +96 -192
  199. package/dist/nexus/impact.js.map +1 -1
  200. package/dist/nexus/knowledge.d.ts +80 -0
  201. package/dist/nexus/knowledge.d.ts.map +1 -0
  202. package/dist/nexus/knowledge.js +786 -0
  203. package/dist/nexus/knowledge.js.map +1 -0
  204. package/dist/nexus/living-brain.d.ts +8 -5
  205. package/dist/nexus/living-brain.d.ts.map +1 -1
  206. package/dist/nexus/living-brain.js +252 -188
  207. package/dist/nexus/living-brain.js.map +1 -1
  208. package/dist/nexus/registry.d.ts +11 -2
  209. package/dist/nexus/registry.d.ts.map +1 -1
  210. package/dist/nexus/registry.js +144 -128
  211. package/dist/nexus/registry.js.map +1 -1
  212. package/dist/nexus/source-roots.d.ts +16 -0
  213. package/dist/nexus/source-roots.d.ts.map +1 -0
  214. package/dist/nexus/source-roots.js +174 -0
  215. package/dist/nexus/source-roots.js.map +1 -0
  216. package/dist/nexus/task-evidence.d.ts +22 -0
  217. package/dist/nexus/task-evidence.d.ts.map +1 -0
  218. package/dist/nexus/task-evidence.js +210 -0
  219. package/dist/nexus/task-evidence.js.map +1 -0
  220. package/dist/nexus/tasks-bridge.d.ts +14 -7
  221. package/dist/nexus/tasks-bridge.d.ts.map +1 -1
  222. package/dist/nexus/tasks-bridge.js +81 -40
  223. package/dist/nexus/tasks-bridge.js.map +1 -1
  224. package/dist/orchestrate/lifecycle-ops.d.ts.map +1 -1
  225. package/dist/orchestrate/lifecycle-ops.js +170 -120
  226. package/dist/orchestrate/lifecycle-ops.js.map +1 -1
  227. package/dist/orchestrate/query-ops.d.ts +6 -7
  228. package/dist/orchestrate/query-ops.d.ts.map +1 -1
  229. package/dist/orchestrate/query-ops.js +509 -532
  230. package/dist/orchestrate/query-ops.js.map +1 -1
  231. package/dist/orchestration/bootstrap.d.ts +15 -1
  232. package/dist/orchestration/bootstrap.d.ts.map +1 -1
  233. package/dist/orchestration/bootstrap.js +21 -10
  234. package/dist/orchestration/bootstrap.js.map +1 -1
  235. package/dist/orchestration/index.d.ts +35 -3
  236. package/dist/orchestration/index.d.ts.map +1 -1
  237. package/dist/orchestration/index.js +64 -35
  238. package/dist/orchestration/index.js.map +1 -1
  239. package/dist/orchestration/lead-rollup.d.ts +24 -1
  240. package/dist/orchestration/lead-rollup.d.ts.map +1 -1
  241. package/dist/orchestration/lead-rollup.js +31 -11
  242. package/dist/orchestration/lead-rollup.js.map +1 -1
  243. package/dist/orchestration/spawn-prompt.d.ts.map +1 -1
  244. package/dist/orchestration/spawn-prompt.js +16 -41
  245. package/dist/orchestration/spawn-prompt.js.map +1 -1
  246. package/dist/orchestration/unblock.d.ts +15 -1
  247. package/dist/orchestration/unblock.d.ts.map +1 -1
  248. package/dist/orchestration/unblock.js +23 -12
  249. package/dist/orchestration/unblock.js.map +1 -1
  250. package/dist/orchestration/validate-spawn.d.ts.map +1 -1
  251. package/dist/orchestration/validate-spawn.js +3 -3
  252. package/dist/orchestration/validate-spawn.js.map +1 -1
  253. package/dist/orchestration/waves.d.ts +29 -13
  254. package/dist/orchestration/waves.d.ts.map +1 -1
  255. package/dist/orchestration/waves.js +43 -55
  256. package/dist/orchestration/waves.js.map +1 -1
  257. package/dist/paths.d.ts +17 -163
  258. package/dist/paths.d.ts.map +1 -1
  259. package/dist/paths.js +145 -496
  260. package/dist/paths.js.map +1 -1
  261. package/dist/project-info.d.ts +2 -11
  262. package/dist/project-info.d.ts.map +1 -1
  263. package/dist/project-info.js +3 -31
  264. package/dist/project-info.js.map +1 -1
  265. package/dist/project-scope.d.ts +239 -0
  266. package/dist/project-scope.d.ts.map +1 -0
  267. package/dist/project-scope.js +473 -0
  268. package/dist/project-scope.js.map +1 -0
  269. package/dist/release/pr-evidence.d.ts +16 -3
  270. package/dist/release/pr-evidence.d.ts.map +1 -1
  271. package/dist/release/pr-evidence.js +53 -7
  272. package/dist/release/pr-evidence.js.map +1 -1
  273. package/dist/render/nexus/graph/index.d.ts.map +1 -1
  274. package/dist/render/nexus/graph/index.js +4 -2
  275. package/dist/render/nexus/graph/index.js.map +1 -1
  276. package/dist/render/orchestration/audit-reconstruct.d.ts +11 -0
  277. package/dist/render/orchestration/audit-reconstruct.d.ts.map +1 -1
  278. package/dist/render/orchestration/audit-reconstruct.js +21 -6
  279. package/dist/render/orchestration/audit-reconstruct.js.map +1 -1
  280. package/dist/render/tasks/show.js +2 -1
  281. package/dist/render/tasks/show.js.map +1 -1
  282. package/dist/resources/spawn-wrapper.d.ts +82 -14
  283. package/dist/resources/spawn-wrapper.d.ts.map +1 -1
  284. package/dist/resources/spawn-wrapper.js +585 -27
  285. package/dist/resources/spawn-wrapper.js.map +1 -1
  286. package/dist/selfimprove/fix-gen.js +4026 -1734
  287. package/dist/selfimprove/fix-gen.js.map +3 -3
  288. package/dist/sequence/index.d.ts.map +1 -1
  289. package/dist/sequence/index.js +76 -68
  290. package/dist/sequence/index.js.map +1 -1
  291. package/dist/session/canon-lint.d.ts +24 -3
  292. package/dist/session/canon-lint.d.ts.map +1 -1
  293. package/dist/session/canon-lint.js +72 -31
  294. package/dist/session/canon-lint.js.map +1 -1
  295. package/dist/session/engine-ops.d.ts +1 -4
  296. package/dist/session/engine-ops.d.ts.map +1 -1
  297. package/dist/session/engine-ops.js +6 -2
  298. package/dist/session/engine-ops.js.map +1 -1
  299. package/dist/sessions/briefing.d.ts +11 -1
  300. package/dist/sessions/briefing.d.ts.map +1 -1
  301. package/dist/sessions/briefing.js +76 -8
  302. package/dist/sessions/briefing.js.map +1 -1
  303. package/dist/sessions/handoff.d.ts +3 -1
  304. package/dist/sessions/handoff.d.ts.map +1 -1
  305. package/dist/sessions/handoff.js +2 -0
  306. package/dist/sessions/handoff.js.map +1 -1
  307. package/dist/shutdown-deadline.d.ts +24 -33
  308. package/dist/shutdown-deadline.d.ts.map +1 -1
  309. package/dist/shutdown-deadline.js +71 -14
  310. package/dist/shutdown-deadline.js.map +1 -1
  311. package/dist/shutdown.d.ts +21 -10
  312. package/dist/shutdown.d.ts.map +1 -1
  313. package/dist/shutdown.js +89 -42
  314. package/dist/shutdown.js.map +1 -1
  315. package/dist/skills/index.d.ts +1 -1
  316. package/dist/skills/index.d.ts.map +1 -1
  317. package/dist/skills/index.js +1 -1
  318. package/dist/skills/index.js.map +1 -1
  319. package/dist/skills/orchestrator/validator.d.ts +87 -20
  320. package/dist/skills/orchestrator/validator.d.ts.map +1 -1
  321. package/dist/skills/orchestrator/validator.js +330 -241
  322. package/dist/skills/orchestrator/validator.js.map +1 -1
  323. package/dist/store/agent-resolver.d.ts.map +1 -1
  324. package/dist/store/agent-resolver.js +16 -9
  325. package/dist/store/agent-resolver.js.map +1 -1
  326. package/dist/store/attachment-store.d.ts +4 -1
  327. package/dist/store/attachment-store.d.ts.map +1 -1
  328. package/dist/store/attachment-store.js +20 -3
  329. package/dist/store/attachment-store.js.map +1 -1
  330. package/dist/store/background-jobs.d.ts +426 -105
  331. package/dist/store/background-jobs.d.ts.map +1 -1
  332. package/dist/store/background-jobs.js +1208 -252
  333. package/dist/store/background-jobs.js.map +1 -1
  334. package/dist/store/background-ops.d.ts +145 -8
  335. package/dist/store/background-ops.d.ts.map +1 -1
  336. package/dist/store/background-ops.js +459 -15
  337. package/dist/store/background-ops.js.map +1 -1
  338. package/dist/store/backup-inspect.d.ts +48 -4
  339. package/dist/store/backup-inspect.d.ts.map +1 -1
  340. package/dist/store/backup-inspect.js +384 -4
  341. package/dist/store/backup-inspect.js.map +1 -1
  342. package/dist/store/converters.d.ts.map +1 -1
  343. package/dist/store/converters.js +19 -2
  344. package/dist/store/converters.js.map +1 -1
  345. package/dist/store/data-accessor.d.ts +9 -1
  346. package/dist/store/data-accessor.d.ts.map +1 -1
  347. package/dist/store/data-accessor.js +22 -5
  348. package/dist/store/data-accessor.js.map +1 -1
  349. package/dist/store/data-safety-central.d.ts.map +1 -1
  350. package/dist/store/data-safety-central.js +272 -232
  351. package/dist/store/data-safety-central.js.map +1 -1
  352. package/dist/store/db-helpers.d.ts +19 -3
  353. package/dist/store/db-helpers.d.ts.map +1 -1
  354. package/dist/store/db-helpers.js +42 -58
  355. package/dist/store/db-helpers.js.map +1 -1
  356. package/dist/store/dual-scope-db.d.ts +63 -4
  357. package/dist/store/dual-scope-db.d.ts.map +1 -1
  358. package/dist/store/dual-scope-db.js +166 -19
  359. package/dist/store/dual-scope-db.js.map +1 -1
  360. package/dist/store/exodus/archive.d.ts +21 -7
  361. package/dist/store/exodus/archive.d.ts.map +1 -1
  362. package/dist/store/exodus/archive.js +60 -18
  363. package/dist/store/exodus/archive.js.map +1 -1
  364. package/dist/store/exodus/migrate.d.ts.map +1 -1
  365. package/dist/store/exodus/migrate.js +27 -23
  366. package/dist/store/exodus/migrate.js.map +1 -1
  367. package/dist/store/exodus/on-open.d.ts +16 -27
  368. package/dist/store/exodus/on-open.d.ts.map +1 -1
  369. package/dist/store/exodus/on-open.js +121 -169
  370. package/dist/store/exodus/on-open.js.map +1 -1
  371. package/dist/store/exodus/recovery.d.ts +90 -0
  372. package/dist/store/exodus/recovery.d.ts.map +1 -0
  373. package/dist/store/exodus/recovery.js +434 -0
  374. package/dist/store/exodus/recovery.js.map +1 -0
  375. package/dist/store/exodus/types.d.ts +15 -0
  376. package/dist/store/exodus/types.d.ts.map +1 -1
  377. package/dist/store/memory-accessor.d.ts +52 -3
  378. package/dist/store/memory-accessor.d.ts.map +1 -1
  379. package/dist/store/memory-accessor.js +122 -7
  380. package/dist/store/memory-accessor.js.map +1 -1
  381. package/dist/store/nexus-sqlite.d.ts +24 -6
  382. package/dist/store/nexus-sqlite.d.ts.map +1 -1
  383. package/dist/store/nexus-sqlite.js +39 -20
  384. package/dist/store/nexus-sqlite.js.map +1 -1
  385. package/dist/store/ports/domain-binding.d.ts.map +1 -1
  386. package/dist/store/ports/domain-binding.js +27 -5
  387. package/dist/store/ports/domain-binding.js.map +1 -1
  388. package/dist/store/schema/background-jobs.d.ts +181 -2
  389. package/dist/store/schema/background-jobs.d.ts.map +1 -1
  390. package/dist/store/schema/background-jobs.js +27 -3
  391. package/dist/store/schema/background-jobs.js.map +1 -1
  392. package/dist/store/schema/cleo-global/skills.d.ts +2 -2
  393. package/dist/store/schema/cleo-project/lifecycle.d.ts +2 -2
  394. package/dist/store/schema/cleo-project/runtime.d.ts +1 -1
  395. package/dist/store/schema/cleo-project/tasks-core.d.ts +1 -1
  396. package/dist/store/schema/lifecycle.d.ts +2 -2
  397. package/dist/store/schema/skills-schema.d.ts +2 -2
  398. package/dist/store/schema/tasks.d.ts +1 -1
  399. package/dist/store/session-store.d.ts +3 -1
  400. package/dist/store/session-store.d.ts.map +1 -1
  401. package/dist/store/session-store.js +252 -207
  402. package/dist/store/session-store.js.map +1 -1
  403. package/dist/store/sqlite-data-accessor.d.ts +39 -4
  404. package/dist/store/sqlite-data-accessor.d.ts.map +1 -1
  405. package/dist/store/sqlite-data-accessor.js +689 -527
  406. package/dist/store/sqlite-data-accessor.js.map +1 -1
  407. package/dist/store/tasks-sqlite.d.ts +3 -1
  408. package/dist/store/tasks-sqlite.d.ts.map +1 -1
  409. package/dist/store/tasks-sqlite.js +309 -279
  410. package/dist/store/tasks-sqlite.js.map +1 -1
  411. package/dist/store/validation-schemas.d.ts +8 -8
  412. package/dist/store/writer-lease.d.ts +80 -8
  413. package/dist/store/writer-lease.d.ts.map +1 -1
  414. package/dist/store/writer-lease.js +503 -134
  415. package/dist/store/writer-lease.js.map +1 -1
  416. package/dist/system/audit.d.ts +2 -1
  417. package/dist/system/audit.d.ts.map +1 -1
  418. package/dist/system/audit.js +118 -71
  419. package/dist/system/audit.js.map +1 -1
  420. package/dist/system/backup.d.ts.map +1 -1
  421. package/dist/system/backup.js +5 -5
  422. package/dist/system/backup.js.map +1 -1
  423. package/dist/system/inject-generate.js +1 -1
  424. package/dist/task-work/index.d.ts +3 -0
  425. package/dist/task-work/index.d.ts.map +1 -1
  426. package/dist/task-work/index.js +34 -37
  427. package/dist/task-work/index.js.map +1 -1
  428. package/dist/tasks/ac-coverage-gate.d.ts.map +1 -1
  429. package/dist/tasks/ac-coverage-gate.js +4 -0
  430. package/dist/tasks/ac-coverage-gate.js.map +1 -1
  431. package/dist/tasks/ac-immutability.d.ts +7 -4
  432. package/dist/tasks/ac-immutability.d.ts.map +1 -1
  433. package/dist/tasks/ac-immutability.js +19 -17
  434. package/dist/tasks/ac-immutability.js.map +1 -1
  435. package/dist/tasks/ac-table.d.ts +5 -5
  436. package/dist/tasks/ac-table.d.ts.map +1 -1
  437. package/dist/tasks/ac-table.js +26 -12
  438. package/dist/tasks/ac-table.js.map +1 -1
  439. package/dist/tasks/acceptance-input.d.ts +52 -0
  440. package/dist/tasks/acceptance-input.d.ts.map +1 -0
  441. package/dist/tasks/acceptance-input.js +259 -0
  442. package/dist/tasks/acceptance-input.js.map +1 -0
  443. package/dist/tasks/add.d.ts +67 -29
  444. package/dist/tasks/add.d.ts.map +1 -1
  445. package/dist/tasks/add.js +255 -97
  446. package/dist/tasks/add.js.map +1 -1
  447. package/dist/tasks/complete.d.ts +16 -1
  448. package/dist/tasks/complete.d.ts.map +1 -1
  449. package/dist/tasks/complete.js +152 -55
  450. package/dist/tasks/complete.js.map +1 -1
  451. package/dist/tasks/decompose.d.ts +103 -0
  452. package/dist/tasks/decompose.d.ts.map +1 -0
  453. package/dist/tasks/decompose.js +224 -0
  454. package/dist/tasks/decompose.js.map +1 -0
  455. package/dist/tasks/delete.d.ts +5 -8
  456. package/dist/tasks/delete.d.ts.map +1 -1
  457. package/dist/tasks/delete.js +4 -3
  458. package/dist/tasks/delete.js.map +1 -1
  459. package/dist/tasks/dependency-check.d.ts +59 -0
  460. package/dist/tasks/dependency-check.d.ts.map +1 -1
  461. package/dist/tasks/dependency-check.js +73 -0
  462. package/dist/tasks/dependency-check.js.map +1 -1
  463. package/dist/tasks/deps-ready.d.ts +13 -1
  464. package/dist/tasks/deps-ready.d.ts.map +1 -1
  465. package/dist/tasks/deps-ready.js +16 -5
  466. package/dist/tasks/deps-ready.js.map +1 -1
  467. package/dist/tasks/engine-converters.d.ts +7 -0
  468. package/dist/tasks/engine-converters.d.ts.map +1 -1
  469. package/dist/tasks/engine-converters.js +8 -1
  470. package/dist/tasks/engine-converters.js.map +1 -1
  471. package/dist/tasks/evidence.d.ts +54 -26
  472. package/dist/tasks/evidence.d.ts.map +1 -1
  473. package/dist/tasks/evidence.js +292 -40
  474. package/dist/tasks/evidence.js.map +1 -1
  475. package/dist/tasks/find.d.ts +16 -12
  476. package/dist/tasks/find.d.ts.map +1 -1
  477. package/dist/tasks/find.js +107 -93
  478. package/dist/tasks/find.js.map +1 -1
  479. package/dist/tasks/gate-runner.d.ts +88 -14
  480. package/dist/tasks/gate-runner.d.ts.map +1 -1
  481. package/dist/tasks/gate-runner.js +596 -253
  482. package/dist/tasks/gate-runner.js.map +1 -1
  483. package/dist/tasks/hierarchy-policy.d.ts +8 -0
  484. package/dist/tasks/hierarchy-policy.d.ts.map +1 -1
  485. package/dist/tasks/hierarchy-policy.js +9 -2
  486. package/dist/tasks/hierarchy-policy.js.map +1 -1
  487. package/dist/tasks/hierarchy.d.ts +67 -1
  488. package/dist/tasks/hierarchy.d.ts.map +1 -1
  489. package/dist/tasks/hierarchy.js +81 -1
  490. package/dist/tasks/hierarchy.js.map +1 -1
  491. package/dist/tasks/index.d.ts +3 -0
  492. package/dist/tasks/index.d.ts.map +1 -1
  493. package/dist/tasks/index.js +3 -0
  494. package/dist/tasks/index.js.map +1 -1
  495. package/dist/tasks/infer-add-params.d.ts +1 -20
  496. package/dist/tasks/infer-add-params.d.ts.map +1 -1
  497. package/dist/tasks/infer-add-params.js +2 -203
  498. package/dist/tasks/infer-add-params.js.map +1 -1
  499. package/dist/tasks/list.d.ts +7 -2
  500. package/dist/tasks/list.d.ts.map +1 -1
  501. package/dist/tasks/list.js +24 -36
  502. package/dist/tasks/list.js.map +1 -1
  503. package/dist/tasks/ops.d.ts +6 -61
  504. package/dist/tasks/ops.d.ts.map +1 -1
  505. package/dist/tasks/ops.js +5 -53
  506. package/dist/tasks/ops.js.map +1 -1
  507. package/dist/tasks/plan.d.ts +15 -1
  508. package/dist/tasks/plan.d.ts.map +1 -1
  509. package/dist/tasks/plan.js +23 -25
  510. package/dist/tasks/plan.js.map +1 -1
  511. package/dist/tasks/population.d.ts +46 -0
  512. package/dist/tasks/population.d.ts.map +1 -0
  513. package/dist/tasks/population.js +88 -0
  514. package/dist/tasks/population.js.map +1 -0
  515. package/dist/tasks/reconcile-scope.d.ts +157 -0
  516. package/dist/tasks/reconcile-scope.d.ts.map +1 -0
  517. package/dist/tasks/reconcile-scope.js +242 -0
  518. package/dist/tasks/reconcile-scope.js.map +1 -0
  519. package/dist/tasks/req.d.ts +51 -12
  520. package/dist/tasks/req.d.ts.map +1 -1
  521. package/dist/tasks/req.js +125 -69
  522. package/dist/tasks/req.js.map +1 -1
  523. package/dist/tasks/session-scope.d.ts +6 -31
  524. package/dist/tasks/session-scope.d.ts.map +1 -1
  525. package/dist/tasks/session-scope.js +3 -17
  526. package/dist/tasks/session-scope.js.map +1 -1
  527. package/dist/tasks/severity-attestation.d.ts +39 -10
  528. package/dist/tasks/severity-attestation.d.ts.map +1 -1
  529. package/dist/tasks/severity-attestation.js +75 -36
  530. package/dist/tasks/severity-attestation.js.map +1 -1
  531. package/dist/tasks/task-next.d.ts +5 -0
  532. package/dist/tasks/task-next.d.ts.map +1 -1
  533. package/dist/tasks/task-next.js +10 -9
  534. package/dist/tasks/task-next.js.map +1 -1
  535. package/dist/tasks/task-reparent.d.ts.map +1 -1
  536. package/dist/tasks/task-reparent.js +3 -13
  537. package/dist/tasks/task-reparent.js.map +1 -1
  538. package/dist/tasks/update.d.ts +20 -43
  539. package/dist/tasks/update.d.ts.map +1 -1
  540. package/dist/tasks/update.js +64 -49
  541. package/dist/tasks/update.js.map +1 -1
  542. package/dist/validation/engine-ops.d.ts +17 -1
  543. package/dist/validation/engine-ops.d.ts.map +1 -1
  544. package/dist/validation/engine-ops.js +149 -11
  545. package/dist/validation/engine-ops.js.map +1 -1
  546. package/dist/workgraph/reparent-preflight.d.ts +1 -1
  547. package/dist/workgraph/reparent-preflight.d.ts.map +1 -1
  548. package/dist/workgraph/reparent-preflight.js +6 -1
  549. package/dist/workgraph/reparent-preflight.js.map +1 -1
  550. package/dist/workgraph/scaffold-apply.d.ts.map +1 -1
  551. package/dist/workgraph/scaffold-apply.js +81 -76
  552. package/dist/workgraph/scaffold-apply.js.map +1 -1
  553. package/dist/workgraph/structure-validation.d.ts +1 -1
  554. package/dist/workgraph/structure-validation.d.ts.map +1 -1
  555. package/dist/workgraph/structure-validation.js +6 -1
  556. package/dist/workgraph/structure-validation.js.map +1 -1
  557. package/migrations/drizzle-tasks/20260919180000_t12263-job-ownership-fences/migration.sql +34 -0
  558. package/migrations/drizzle-tasks/20260919184500_t12265-durable-pending-proposals/migration.sql +4 -0
  559. package/package.json +18 -13
  560. package/schemas/config.schema.json +2 -2
  561. package/templates/CLEO-INJECTION.md +103 -101
@@ -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, projectRoot) {
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], projectRoot);
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], projectRoot);
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], projectRoot);
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], projectRoot);
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, projectRoot);
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
- const intersectResult = await checkCommitContentIntersect(sha, taskId, projectRoot);
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], projectRoot);
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], projectRoot);
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`) continue to use `projectRoot` as `cwd` —
854
- * git resolves commits correctly from any directory sharing the object store.
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 projectRoot - Absolute path for git operations (may be worktree path).
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, projectRoot) {
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 projectRoot is a worktree path the
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. git operations
871
- // below (gitShowFiles) still use the original projectRoot — git shares its
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, projectRoot);
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 = execFileSync('git', ['rev-parse', '--show-toplevel'], {
1131
- cwd,
1132
- encoding: 'utf-8',
1133
- stdio: ['ignore', 'pipe', 'ignore'],
1134
- }).trim();
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
- return projectRoot; // not a git checkout — nothing better to offer
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 siblingCommitSha = siblingCommit?.sha;
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(projectRoot, f.path);
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, projectRoot);
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, projectRoot);
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}` });