@cleocode/core 2026.6.11 → 2026.6.13

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 (414) hide show
  1. package/dist/conduit/local-transport.d.ts +12 -0
  2. package/dist/conduit/local-transport.d.ts.map +1 -1
  3. package/dist/conduit/local-transport.js +53 -23
  4. package/dist/conduit/local-transport.js.map +1 -1
  5. package/dist/crypto/credentials.d.ts +37 -0
  6. package/dist/crypto/credentials.d.ts.map +1 -1
  7. package/dist/crypto/credentials.js +110 -0
  8. package/dist/crypto/credentials.js.map +1 -1
  9. package/dist/dispatch/contracts/derive-output-contract.d.ts +86 -0
  10. package/dist/dispatch/contracts/derive-output-contract.d.ts.map +1 -0
  11. package/dist/dispatch/contracts/derive-output-contract.js +347 -0
  12. package/dist/dispatch/contracts/derive-output-contract.js.map +1 -0
  13. package/dist/dispatch/contracts/ensures-schema.d.ts +77 -0
  14. package/dist/dispatch/contracts/ensures-schema.d.ts.map +1 -0
  15. package/dist/dispatch/contracts/ensures-schema.js +91 -0
  16. package/dist/dispatch/contracts/ensures-schema.js.map +1 -0
  17. package/dist/dispatch/contracts/output-contracts.d.ts +27 -5
  18. package/dist/dispatch/contracts/output-contracts.d.ts.map +1 -1
  19. package/dist/dispatch/contracts/output-contracts.js +29 -6
  20. package/dist/dispatch/contracts/output-contracts.js.map +1 -1
  21. package/dist/docs/export-document.js +2309 -1262
  22. package/dist/docs/export-document.js.map +3 -3
  23. package/dist/go/driver.d.ts +132 -7
  24. package/dist/go/driver.d.ts.map +1 -1
  25. package/dist/go/driver.js +135 -10
  26. package/dist/go/driver.js.map +1 -1
  27. package/dist/go/index.d.ts +1 -1
  28. package/dist/go/index.d.ts.map +1 -1
  29. package/dist/go/index.js +1 -1
  30. package/dist/go/index.js.map +1 -1
  31. package/dist/index.d.ts +1 -0
  32. package/dist/index.d.ts.map +1 -1
  33. package/dist/index.js +5 -0
  34. package/dist/index.js.map +1 -1
  35. package/dist/internal.d.ts +13 -10
  36. package/dist/internal.d.ts.map +1 -1
  37. package/dist/internal.js +11 -11
  38. package/dist/internal.js.map +1 -1
  39. package/dist/lifecycle/engine-ops.d.ts.map +1 -1
  40. package/dist/lifecycle/engine-ops.js +7 -4
  41. package/dist/lifecycle/engine-ops.js.map +1 -1
  42. package/dist/lifecycle/ivtr-loop.d.ts +108 -183
  43. package/dist/lifecycle/ivtr-loop.d.ts.map +1 -1
  44. package/dist/lifecycle/ivtr-loop.js +207 -522
  45. package/dist/lifecycle/ivtr-loop.js.map +1 -1
  46. package/dist/llm/auxiliary-fallback.js +1 -1
  47. package/dist/llm/auxiliary-fallback.js.map +1 -1
  48. package/dist/llm/cli-ops.d.ts +14 -1
  49. package/dist/llm/cli-ops.d.ts.map +1 -1
  50. package/dist/llm/cli-ops.js +41 -12
  51. package/dist/llm/cli-ops.js.map +1 -1
  52. package/dist/llm/concrete-session.d.ts.map +1 -1
  53. package/dist/llm/concrete-session.js +4 -0
  54. package/dist/llm/concrete-session.js.map +1 -1
  55. package/dist/llm/credentials.d.ts +35 -0
  56. package/dist/llm/credentials.d.ts.map +1 -1
  57. package/dist/llm/credentials.js +49 -0
  58. package/dist/llm/credentials.js.map +1 -1
  59. package/dist/llm/index.d.ts +4 -0
  60. package/dist/llm/index.d.ts.map +1 -1
  61. package/dist/llm/index.js +4 -0
  62. package/dist/llm/index.js.map +1 -1
  63. package/dist/llm/pi/gondolin-loader.d.ts +241 -0
  64. package/dist/llm/pi/gondolin-loader.d.ts.map +1 -0
  65. package/dist/llm/pi/gondolin-loader.js +195 -0
  66. package/dist/llm/pi/gondolin-loader.js.map +1 -0
  67. package/dist/llm/pi/index.d.ts +28 -0
  68. package/dist/llm/pi/index.d.ts.map +1 -0
  69. package/dist/llm/pi/index.js +27 -0
  70. package/dist/llm/pi/index.js.map +1 -0
  71. package/dist/llm/pi/pi-agent-adapter.d.ts +135 -0
  72. package/dist/llm/pi/pi-agent-adapter.d.ts.map +1 -0
  73. package/dist/llm/pi/pi-agent-adapter.js +329 -0
  74. package/dist/llm/pi/pi-agent-adapter.js.map +1 -0
  75. package/dist/llm/pi/pi-errors.d.ts +161 -0
  76. package/dist/llm/pi/pi-errors.d.ts.map +1 -0
  77. package/dist/llm/pi/pi-errors.js +296 -0
  78. package/dist/llm/pi/pi-errors.js.map +1 -0
  79. package/dist/llm/pi/pi-execution-env.d.ts +286 -0
  80. package/dist/llm/pi/pi-execution-env.d.ts.map +1 -0
  81. package/dist/llm/pi/pi-execution-env.js +406 -0
  82. package/dist/llm/pi/pi-execution-env.js.map +1 -0
  83. package/dist/llm/pi/pi-gondolin-env.d.ts +227 -0
  84. package/dist/llm/pi/pi-gondolin-env.d.ts.map +1 -0
  85. package/dist/llm/pi/pi-gondolin-env.js +541 -0
  86. package/dist/llm/pi/pi-gondolin-env.js.map +1 -0
  87. package/dist/llm/pi/pi-session-storage.d.ts +154 -0
  88. package/dist/llm/pi/pi-session-storage.d.ts.map +1 -0
  89. package/dist/llm/pi/pi-session-storage.js +314 -0
  90. package/dist/llm/pi/pi-session-storage.js.map +1 -0
  91. package/dist/llm/pi/pi-stream-fn.d.ts +124 -0
  92. package/dist/llm/pi/pi-stream-fn.d.ts.map +1 -0
  93. package/dist/llm/pi/pi-stream-fn.js +504 -0
  94. package/dist/llm/pi/pi-stream-fn.js.map +1 -0
  95. package/dist/llm/pi/pi-tool-bridge.d.ts +99 -0
  96. package/dist/llm/pi/pi-tool-bridge.d.ts.map +1 -0
  97. package/dist/llm/pi/pi-tool-bridge.js +117 -0
  98. package/dist/llm/pi/pi-tool-bridge.js.map +1 -0
  99. package/dist/llm/pi/pi-types.d.ts +56 -0
  100. package/dist/llm/pi/pi-types.d.ts.map +1 -0
  101. package/dist/llm/pi/pi-types.js +16 -0
  102. package/dist/llm/pi/pi-types.js.map +1 -0
  103. package/dist/llm/pi/resolve-execution-env.d.ts +194 -0
  104. package/dist/llm/pi/resolve-execution-env.d.ts.map +1 -0
  105. package/dist/llm/pi/resolve-execution-env.js +132 -0
  106. package/dist/llm/pi/resolve-execution-env.js.map +1 -0
  107. package/dist/llm/plugin-facade.js +2253 -1151
  108. package/dist/llm/plugin-facade.js.map +3 -3
  109. package/dist/llm/role-executor.d.ts.map +1 -1
  110. package/dist/llm/role-executor.js +8 -5
  111. package/dist/llm/role-executor.js.map +1 -1
  112. package/dist/llm/role-resolver.d.ts +46 -14
  113. package/dist/llm/role-resolver.d.ts.map +1 -1
  114. package/dist/llm/role-resolver.js +178 -20
  115. package/dist/llm/role-resolver.js.map +1 -1
  116. package/dist/llm/sealed-credential.d.ts +125 -0
  117. package/dist/llm/sealed-credential.d.ts.map +1 -0
  118. package/dist/llm/sealed-credential.js +133 -0
  119. package/dist/llm/sealed-credential.js.map +1 -0
  120. package/dist/llm/session-factory.d.ts.map +1 -1
  121. package/dist/llm/session-factory.js +6 -2
  122. package/dist/llm/session-factory.js.map +1 -1
  123. package/dist/llm/system-key.d.ts +67 -0
  124. package/dist/llm/system-key.d.ts.map +1 -0
  125. package/dist/llm/system-key.js +87 -0
  126. package/dist/llm/system-key.js.map +1 -0
  127. package/dist/llm/system-of-use-registry.d.ts +119 -0
  128. package/dist/llm/system-of-use-registry.d.ts.map +1 -0
  129. package/dist/llm/system-of-use-registry.js +200 -0
  130. package/dist/llm/system-of-use-registry.js.map +1 -0
  131. package/dist/llm/system-resolver.d.ts +32 -10
  132. package/dist/llm/system-resolver.d.ts.map +1 -1
  133. package/dist/llm/system-resolver.js +70 -18
  134. package/dist/llm/system-resolver.js.map +1 -1
  135. package/dist/memory/brain-writer-thread.d.ts.map +1 -1
  136. package/dist/memory/brain-writer-thread.js +116 -11
  137. package/dist/memory/brain-writer-thread.js.map +1 -1
  138. package/dist/memory/claude-mem-migration.d.ts.map +1 -1
  139. package/dist/memory/claude-mem-migration.js +21 -0
  140. package/dist/memory/claude-mem-migration.js.map +1 -1
  141. package/dist/memory/graph-memory-bridge.d.ts.map +1 -1
  142. package/dist/memory/graph-memory-bridge.js +32 -25
  143. package/dist/memory/graph-memory-bridge.js.map +1 -1
  144. package/dist/memory/llm-backend-resolver.js +23 -5
  145. package/dist/memory/llm-backend-resolver.js.map +1 -1
  146. package/dist/nexus/migrations/M-split-graph.d.ts.map +1 -1
  147. package/dist/nexus/migrations/M-split-graph.js +60 -53
  148. package/dist/nexus/migrations/M-split-graph.js.map +1 -1
  149. package/dist/orchestrate/pivot.d.ts.map +1 -1
  150. package/dist/orchestrate/pivot.js +20 -2
  151. package/dist/orchestrate/pivot.js.map +1 -1
  152. package/dist/release/engine-ops.js +2 -2
  153. package/dist/release/engine-ops.js.map +1 -1
  154. package/dist/release/plan.d.ts +4 -6
  155. package/dist/release/plan.d.ts.map +1 -1
  156. package/dist/release/plan.js +10 -23
  157. package/dist/release/plan.js.map +1 -1
  158. package/dist/release/reconcile.d.ts +0 -2
  159. package/dist/release/reconcile.d.ts.map +1 -1
  160. package/dist/release/reconcile.js +43 -50
  161. package/dist/release/reconcile.js.map +1 -1
  162. package/dist/release/release-manifest.d.ts.map +1 -1
  163. package/dist/release/release-manifest.js +4 -1
  164. package/dist/release/release-manifest.js.map +1 -1
  165. package/dist/release/verify-provenance.js +20 -20
  166. package/dist/release/verify-provenance.js.map +1 -1
  167. package/dist/routing/capability-matrix.d.ts.map +1 -1
  168. package/dist/routing/capability-matrix.js +0 -57
  169. package/dist/routing/capability-matrix.js.map +1 -1
  170. package/dist/selfimprove/budget.d.ts +206 -0
  171. package/dist/selfimprove/budget.d.ts.map +1 -0
  172. package/dist/selfimprove/budget.js +203 -0
  173. package/dist/selfimprove/budget.js.map +1 -0
  174. package/dist/selfimprove/dhq-adapter.d.ts +105 -0
  175. package/dist/selfimprove/dhq-adapter.d.ts.map +1 -0
  176. package/dist/selfimprove/dhq-adapter.js +95 -0
  177. package/dist/selfimprove/dhq-adapter.js.map +1 -0
  178. package/dist/selfimprove/draft-pr.d.ts +129 -0
  179. package/dist/selfimprove/draft-pr.d.ts.map +1 -0
  180. package/dist/selfimprove/draft-pr.js +158 -0
  181. package/dist/selfimprove/draft-pr.js.map +1 -0
  182. package/dist/selfimprove/envelope-diff.d.ts +162 -0
  183. package/dist/selfimprove/envelope-diff.d.ts.map +1 -0
  184. package/dist/selfimprove/envelope-diff.js +321 -0
  185. package/dist/selfimprove/envelope-diff.js.map +1 -0
  186. package/dist/selfimprove/replay.d.ts +121 -0
  187. package/dist/selfimprove/replay.d.ts.map +1 -0
  188. package/dist/selfimprove/replay.js +109 -0
  189. package/dist/selfimprove/replay.js.map +1 -0
  190. package/dist/selfimprove/run-loop.d.ts +148 -0
  191. package/dist/selfimprove/run-loop.d.ts.map +1 -0
  192. package/dist/selfimprove/run-loop.js +240 -0
  193. package/dist/selfimprove/run-loop.js.map +1 -0
  194. package/dist/selfimprove/scenario.d.ts +145 -0
  195. package/dist/selfimprove/scenario.d.ts.map +1 -0
  196. package/dist/selfimprove/scenario.js +243 -0
  197. package/dist/selfimprove/scenario.js.map +1 -0
  198. package/dist/sentient/daemon-entry.js +5 -0
  199. package/dist/sentient/daemon-entry.js.map +1 -1
  200. package/dist/sentient/daemon.d.ts.map +1 -1
  201. package/dist/sentient/daemon.js +19 -0
  202. package/dist/sentient/daemon.js.map +1 -1
  203. package/dist/sentient/hygiene-scan.d.ts.map +1 -1
  204. package/dist/sentient/hygiene-scan.js +14 -6
  205. package/dist/sentient/hygiene-scan.js.map +1 -1
  206. package/dist/sessions/briefing.d.ts.map +1 -1
  207. package/dist/sessions/briefing.js +13 -9
  208. package/dist/sessions/briefing.js.map +1 -1
  209. package/dist/sessions/connection-session-handle.d.ts +161 -0
  210. package/dist/sessions/connection-session-handle.d.ts.map +1 -0
  211. package/dist/sessions/connection-session-handle.js +168 -0
  212. package/dist/sessions/connection-session-handle.js.map +1 -0
  213. package/dist/sessions/handoff.d.ts.map +1 -1
  214. package/dist/sessions/handoff.js +9 -0
  215. package/dist/sessions/handoff.js.map +1 -1
  216. package/dist/sessions/index.d.ts +4 -1
  217. package/dist/sessions/index.d.ts.map +1 -1
  218. package/dist/sessions/index.js +31 -1
  219. package/dist/sessions/index.js.map +1 -1
  220. package/dist/sessions/session-id.d.ts +34 -0
  221. package/dist/sessions/session-id.d.ts.map +1 -1
  222. package/dist/sessions/session-id.js +37 -0
  223. package/dist/sessions/session-id.js.map +1 -1
  224. package/dist/sessions/session-manifest-mirror.d.ts +115 -0
  225. package/dist/sessions/session-manifest-mirror.d.ts.map +1 -0
  226. package/dist/sessions/session-manifest-mirror.js +250 -0
  227. package/dist/sessions/session-manifest-mirror.js.map +1 -0
  228. package/dist/sessions/session-switch.d.ts.map +1 -1
  229. package/dist/sessions/session-switch.js +5 -2
  230. package/dist/sessions/session-switch.js.map +1 -1
  231. package/dist/store/converters.d.ts.map +1 -1
  232. package/dist/store/converters.js +2 -0
  233. package/dist/store/converters.js.map +1 -1
  234. package/dist/store/db-helpers.d.ts.map +1 -1
  235. package/dist/store/db-helpers.js +2 -0
  236. package/dist/store/db-helpers.js.map +1 -1
  237. package/dist/store/dual-scope-db.d.ts.map +1 -1
  238. package/dist/store/dual-scope-db.js +87 -47
  239. package/dist/store/dual-scope-db.js.map +1 -1
  240. package/dist/store/pi-session-store.d.ts +151 -0
  241. package/dist/store/pi-session-store.d.ts.map +1 -0
  242. package/dist/store/pi-session-store.js +166 -0
  243. package/dist/store/pi-session-store.js.map +1 -0
  244. package/dist/store/safety-data-accessor.d.ts +1 -0
  245. package/dist/store/safety-data-accessor.d.ts.map +1 -1
  246. package/dist/store/safety-data-accessor.js +5 -0
  247. package/dist/store/safety-data-accessor.js.map +1 -1
  248. package/dist/store/schema/cleo-global/accounts.d.ts +357 -0
  249. package/dist/store/schema/cleo-global/accounts.d.ts.map +1 -0
  250. package/dist/store/schema/cleo-global/accounts.js +136 -0
  251. package/dist/store/schema/cleo-global/accounts.js.map +1 -0
  252. package/dist/store/schema/cleo-global/index.d.ts +2 -0
  253. package/dist/store/schema/cleo-global/index.d.ts.map +1 -1
  254. package/dist/store/schema/cleo-global/index.js +2 -0
  255. package/dist/store/schema/cleo-global/index.js.map +1 -1
  256. package/dist/store/schema/cleo-global/session-manifest.d.ts +217 -0
  257. package/dist/store/schema/cleo-global/session-manifest.d.ts.map +1 -0
  258. package/dist/store/schema/cleo-global/session-manifest.js +99 -0
  259. package/dist/store/schema/cleo-global/session-manifest.js.map +1 -0
  260. package/dist/store/schema/cleo-project/tasks-core.d.ts +16 -0
  261. package/dist/store/schema/cleo-project/tasks-core.d.ts.map +1 -1
  262. package/dist/store/schema/cleo-project/tasks-core.js +14 -0
  263. package/dist/store/schema/cleo-project/tasks-core.js.map +1 -1
  264. package/dist/store/schema/tasks.d.ts +16 -0
  265. package/dist/store/schema/tasks.d.ts.map +1 -1
  266. package/dist/store/schema/tasks.js +10 -0
  267. package/dist/store/schema/tasks.js.map +1 -1
  268. package/dist/store/selfimprove-dhq-schema.d.ts +284 -0
  269. package/dist/store/selfimprove-dhq-schema.d.ts.map +1 -0
  270. package/dist/store/selfimprove-dhq-schema.js +128 -0
  271. package/dist/store/selfimprove-dhq-schema.js.map +1 -0
  272. package/dist/store/selfimprove-dhq-store.d.ts +175 -0
  273. package/dist/store/selfimprove-dhq-store.d.ts.map +1 -0
  274. package/dist/store/selfimprove-dhq-store.js +182 -0
  275. package/dist/store/selfimprove-dhq-store.js.map +1 -0
  276. package/dist/store/session-store.d.ts +52 -13
  277. package/dist/store/session-store.d.ts.map +1 -1
  278. package/dist/store/session-store.js +71 -13
  279. package/dist/store/session-store.js.map +1 -1
  280. package/dist/store/sqlite-data-accessor.d.ts.map +1 -1
  281. package/dist/store/sqlite-data-accessor.js +7 -0
  282. package/dist/store/sqlite-data-accessor.js.map +1 -1
  283. package/dist/store/tasks-schema.d.ts +4 -0
  284. package/dist/store/tasks-schema.d.ts.map +1 -1
  285. package/dist/store/tasks-schema.js +14 -0
  286. package/dist/store/tasks-schema.js.map +1 -1
  287. package/dist/store/umbrella-data-accessor.d.ts +1 -0
  288. package/dist/store/umbrella-data-accessor.d.ts.map +1 -1
  289. package/dist/store/umbrella-data-accessor.js +5 -0
  290. package/dist/store/umbrella-data-accessor.js.map +1 -1
  291. package/dist/store/validation-schemas.d.ts +94 -62
  292. package/dist/store/validation-schemas.d.ts.map +1 -1
  293. package/dist/store/writer-lease-schema.d.ts +392 -0
  294. package/dist/store/writer-lease-schema.d.ts.map +1 -0
  295. package/dist/store/writer-lease-schema.js +142 -0
  296. package/dist/store/writer-lease-schema.js.map +1 -0
  297. package/dist/store/writer-lease.d.ts +368 -0
  298. package/dist/store/writer-lease.d.ts.map +1 -0
  299. package/dist/store/writer-lease.js +1002 -0
  300. package/dist/store/writer-lease.js.map +1 -0
  301. package/dist/task-tools/describe-schema.d.ts +4 -2
  302. package/dist/task-tools/describe-schema.d.ts.map +1 -1
  303. package/dist/task-tools/describe-schema.js +9 -3
  304. package/dist/task-tools/describe-schema.js.map +1 -1
  305. package/dist/tasks/backfill-child-projections.d.ts.map +1 -1
  306. package/dist/tasks/backfill-child-projections.js +14 -9
  307. package/dist/tasks/backfill-child-projections.js.map +1 -1
  308. package/dist/tasks/complete.d.ts.map +1 -1
  309. package/dist/tasks/complete.js +7 -10
  310. package/dist/tasks/complete.js.map +1 -1
  311. package/dist/tasks/duplicate-detector.d.ts.map +1 -1
  312. package/dist/tasks/duplicate-detector.js +14 -7
  313. package/dist/tasks/duplicate-detector.js.map +1 -1
  314. package/dist/telemetry/index.d.ts.map +1 -1
  315. package/dist/telemetry/index.js +10 -4
  316. package/dist/telemetry/index.js.map +1 -1
  317. package/dist/tools/agent-registry.d.ts +250 -0
  318. package/dist/tools/agent-registry.d.ts.map +1 -0
  319. package/dist/tools/agent-registry.js +292 -0
  320. package/dist/tools/agent-registry.js.map +1 -0
  321. package/dist/tools/agent-tool-families.d.ts +107 -0
  322. package/dist/tools/agent-tool-families.d.ts.map +1 -0
  323. package/dist/tools/agent-tool-families.js +527 -0
  324. package/dist/tools/agent-tool-families.js.map +1 -0
  325. package/dist/tools/browser-driver.d.ts +183 -0
  326. package/dist/tools/browser-driver.d.ts.map +1 -0
  327. package/dist/tools/browser-driver.js +242 -0
  328. package/dist/tools/browser-driver.js.map +1 -0
  329. package/dist/tools/builtin-agent-tools.d.ts +36 -0
  330. package/dist/tools/builtin-agent-tools.d.ts.map +1 -0
  331. package/dist/tools/builtin-agent-tools.js +150 -0
  332. package/dist/tools/builtin-agent-tools.js.map +1 -0
  333. package/dist/tools/dispatch.d.ts +370 -0
  334. package/dist/tools/dispatch.d.ts.map +1 -0
  335. package/dist/tools/dispatch.js +505 -0
  336. package/dist/tools/dispatch.js.map +1 -0
  337. package/dist/tools/env-scrub.d.ts +93 -0
  338. package/dist/tools/env-scrub.d.ts.map +1 -0
  339. package/dist/tools/env-scrub.js +176 -0
  340. package/dist/tools/env-scrub.js.map +1 -0
  341. package/dist/tools/fs.d.ts +30 -0
  342. package/dist/tools/fs.d.ts.map +1 -1
  343. package/dist/tools/fs.js +55 -2
  344. package/dist/tools/fs.js.map +1 -1
  345. package/dist/tools/guard.d.ts +15 -0
  346. package/dist/tools/guard.d.ts.map +1 -1
  347. package/dist/tools/guard.js +49 -12
  348. package/dist/tools/guard.js.map +1 -1
  349. package/dist/tools/index.d.ts +10 -0
  350. package/dist/tools/index.d.ts.map +1 -1
  351. package/dist/tools/index.js +37 -0
  352. package/dist/tools/index.js.map +1 -1
  353. package/dist/tools/pty.d.ts +45 -0
  354. package/dist/tools/pty.d.ts.map +1 -0
  355. package/dist/tools/pty.js +166 -0
  356. package/dist/tools/pty.js.map +1 -0
  357. package/dist/tools/schema-gen.d.ts +57 -0
  358. package/dist/tools/schema-gen.d.ts.map +1 -0
  359. package/dist/tools/schema-gen.js +52 -0
  360. package/dist/tools/schema-gen.js.map +1 -0
  361. package/dist/tools/shell.d.ts +12 -0
  362. package/dist/tools/shell.d.ts.map +1 -1
  363. package/dist/tools/shell.js +14 -1
  364. package/dist/tools/shell.js.map +1 -1
  365. package/dist/tools/web-agent-tools.d.ts +72 -0
  366. package/dist/tools/web-agent-tools.d.ts.map +1 -0
  367. package/dist/tools/web-agent-tools.js +393 -0
  368. package/dist/tools/web-agent-tools.js.map +1 -0
  369. package/dist/tools/web-search-backends.d.ts +156 -0
  370. package/dist/tools/web-search-backends.d.ts.map +1 -0
  371. package/dist/tools/web-search-backends.js +290 -0
  372. package/dist/tools/web-search-backends.js.map +1 -0
  373. package/dist/validation/ops.d.ts +1 -15
  374. package/dist/validation/ops.d.ts.map +1 -1
  375. package/dist/validation/ops.js +0 -20
  376. package/dist/validation/ops.js.map +1 -1
  377. package/migrations/drizzle-cleo-global/20260607000000_t11891-writer-leases/migration.sql +55 -0
  378. package/migrations/drizzle-cleo-global/20260607010000_t11639-session-manifest/migration.sql +43 -0
  379. package/migrations/drizzle-cleo-global/20260608000000_t11899-pi-session-tree/migration.sql +52 -0
  380. package/migrations/drizzle-cleo-global/20260608010000_t11709-accounts-credential-pool/migration.sql +72 -0
  381. package/migrations/drizzle-cleo-global/20260608020000_t11889-selfimprove-dhq/migration.sql +64 -0
  382. package/migrations/drizzle-cleo-project/20260606000000_t11884-restore-prefixed-task-triggers/migration.sql +272 -0
  383. package/migrations/drizzle-cleo-project/20260606000000_t11884-restore-prefixed-task-triggers/revert.sql +29 -0
  384. package/migrations/drizzle-cleo-project/20260606000100_t11883-tasks-releases-version-unique/migration.sql +21 -0
  385. package/migrations/drizzle-cleo-project/20260606000100_t11883-tasks-releases-version-unique/revert.sql +4 -0
  386. package/migrations/drizzle-cleo-project/20260607000000_t11891-writer-leases/migration.sql +55 -0
  387. package/migrations/drizzle-cleo-project/20260607010000_t11639-session-parent/migration.sql +22 -0
  388. package/migrations/drizzle-cleo-project/20260608000000_t11899-pi-session-tree/migration.sql +52 -0
  389. package/migrations/drizzle-cleo-project/20260608020000_t11889-selfimprove-dhq/migration.sql +64 -0
  390. package/package.json +15 -13
  391. package/dist/lifecycle/chain-composition.d.ts +0 -30
  392. package/dist/lifecycle/chain-composition.d.ts.map +0 -1
  393. package/dist/lifecycle/chain-composition.js +0 -152
  394. package/dist/lifecycle/chain-composition.js.map +0 -1
  395. package/dist/lifecycle/chain-store.d.ts +0 -70
  396. package/dist/lifecycle/chain-store.d.ts.map +0 -1
  397. package/dist/lifecycle/chain-store.js +0 -246
  398. package/dist/lifecycle/chain-store.js.map +0 -1
  399. package/dist/lifecycle/default-chain.d.ts +0 -39
  400. package/dist/lifecycle/default-chain.d.ts.map +0 -1
  401. package/dist/lifecycle/default-chain.js +0 -176
  402. package/dist/lifecycle/default-chain.js.map +0 -1
  403. package/dist/lifecycle/tessera-engine.d.ts +0 -48
  404. package/dist/lifecycle/tessera-engine.d.ts.map +0 -1
  405. package/dist/lifecycle/tessera-engine.js +0 -249
  406. package/dist/lifecycle/tessera-engine.js.map +0 -1
  407. package/dist/release/provenance-fk.d.ts +0 -74
  408. package/dist/release/provenance-fk.d.ts.map +0 -1
  409. package/dist/release/provenance-fk.js +0 -122
  410. package/dist/release/provenance-fk.js.map +0 -1
  411. package/dist/validation/chain-validation.d.ts +0 -43
  412. package/dist/validation/chain-validation.d.ts.map +0 -1
  413. package/dist/validation/chain-validation.js +0 -146
  414. package/dist/validation/chain-validation.js.map +0 -1
@@ -1,20 +1,25 @@
1
1
  /**
2
- * IVTR Orchestration Loop — State Machine
3
- *
4
- * Implements the Implement → Validate → Test → Release phase state machine
5
- * for per-task multi-agent enforcement. State is persisted as JSON in the
6
- * `ivtr_state` column on the `tasks` table.
7
- *
8
- * State machine transitions:
9
- *
10
- * (none) ──startIvtr──► implement
11
- * implement ──advanceIvtr──► validate
12
- * validate ──advanceIvtr──► test
13
- * test ──advanceIvtr──► released
14
- *
15
- * implement | validate | test ──loopBackIvtr──► implement | validate | test
16
- *
17
- * released ──releaseIvtr──► marks task status=done
2
+ * IVTR `ivtr_state` record — read + cantbook-mirror surface.
3
+ *
4
+ * The Implement → Validate → Audit → Test → Release phase loop now runs on the
5
+ * cantbook runtime (the survivor state machine after the T11764 collapse). The
6
+ * hand-rolled phase-walk functions (`startIvtr`/`advanceIvtr`/`loopBackIvtr`/
7
+ * `releaseIvtr`) plus the per-phase prompt/auto-gate helpers were deleted in
8
+ * T11896 once `cleo go` (default) drives `executePlaybook(ivtr.cantbook)` and
9
+ * the manual `cleo orchestrate ivtr` mutate ops were deprecated.
10
+ *
11
+ * This module now owns the RETAINED `ivtr_state` surface (one deprecation
12
+ * cycle):
13
+ * - {@link IvtrState} / {@link IvtrPhase} / {@link IvtrPhaseEntry} — the JSON
14
+ * shape persisted in the `ivtr_state` column on `tasks`.
15
+ * - {@link getIvtrState} — the read path backing `cleo show --ivtr-history`
16
+ * and the strict `E_IVTR_INCOMPLETE` completion gate (`tasks/complete.ts`).
17
+ * - {@link seedIvtrForPlaybook} / {@link finalizeIvtrFromPlaybook} — the
18
+ * `cleo go` cantbook seam (T11805): seed the column at `implement` and
19
+ * mirror the run's terminal status back so the completion gate stays
20
+ * load-bearing.
21
+ * - {@link MAX_LOOP_BACKS_PER_PHASE} — read by `classify-readiness.ts`.
22
+ * - {@link validateSpawnRequest} — Lead authorship-bypass guard (ADR-070).
18
23
  *
19
24
  * Evidence refs are sha256 hashes of attachment blobs stored under
20
25
  * .cleo/attachments (see ADR T796 attachment store).
@@ -22,32 +27,17 @@
22
27
  * @epic T810
23
28
  * @task T811
24
29
  * @task T813
30
+ * @task T11805 — cantbook seam (seed + finalize mirror)
31
+ * @task T11896 — phase-walk functions deleted; this is the read/mirror surface
25
32
  */
26
33
  import { createHash } from 'node:crypto';
27
34
  import { eq } from 'drizzle-orm';
28
35
  import { getLogger } from '../logger.js';
29
- import { getProjectRoot } from '../paths.js';
30
36
  import { createAttachmentStore } from '../store/attachment-store.js';
31
37
  import { getDb } from '../store/sqlite.js';
32
38
  import * as schema from '../store/tasks-schema.js';
33
- import { extractTypedGates, runGates } from '../tasks/gate-runner.js';
34
- import { buildBlastRadiusTestScopeSection, detectInfrastructureTouch } from './infra-touch.js';
35
39
  const log = getLogger('lifecycle:ivtr');
36
40
  // =============================================================================
37
- // PHASE ORDER
38
- // =============================================================================
39
- /** @task T9216 — 'audit' inserted between validate and test */
40
- const PHASE_ORDER = ['implement', 'validate', 'audit', 'test', 'released'];
41
- /**
42
- * Return the next phase after `current`, or null if already at `released`.
43
- */
44
- function nextPhase(current) {
45
- const idx = PHASE_ORDER.indexOf(current);
46
- if (idx === -1 || idx >= PHASE_ORDER.length - 1)
47
- return null;
48
- return PHASE_ORDER[idx + 1] ?? null;
49
- }
50
- // =============================================================================
51
41
  // PERSISTENCE HELPERS
52
42
  // =============================================================================
53
43
  /**
@@ -101,32 +91,29 @@ async function writeIvtrState(state, cwd) {
101
91
  // PUBLIC API
102
92
  // =============================================================================
103
93
  /**
104
- * Start the IVTR loop for a task.
94
+ * Build the canonical fresh {@link IvtrState} seeded at the `implement` phase.
105
95
  *
106
- * Creates a fresh IvtrState with `currentPhase = 'implement'` and persists
107
- * it to the task row. Idempotent: calling again on a task that already has
108
- * IVTR state returns the existing state without mutation.
96
+ * The historical manual walk (`startIvtr`) was deleted in T11896 when the IVTR
97
+ * loop was collapsed onto the cantbook runtime; {@link seedIvtrForPlaybook}
98
+ * (the `cleo go` seam, T11805) is now the sole producer of a fresh IvtrState
99
+ * and delegates here so the seeded state is byte-identical to the retired walk.
109
100
  *
110
- * @param taskId - Task ID to start the IVTR loop for.
111
- * @param options - Optional cwd and agent identity.
112
- * @returns The current (possibly new) IvtrState.
101
+ * @param taskId - Task the IVTR loop is seeded for.
102
+ * @param agentIdentity - Agent identity string for the first phase entry, or
103
+ * `null` when unknown.
104
+ * @returns A fresh schema-v2 {@link IvtrState} at `currentPhase: 'implement'`.
113
105
  */
114
- export async function startIvtr(taskId, options) {
115
- const existing = await readIvtrStateRaw(taskId, options?.cwd);
116
- if (existing) {
117
- log.info({ taskId }, 'IVTR already started; returning existing state');
118
- return existing;
119
- }
106
+ function buildInitialIvtrState(taskId, agentIdentity) {
120
107
  const now = new Date().toISOString();
121
108
  const entry = {
122
109
  phase: 'implement',
123
- agentIdentity: options?.agentIdentity ?? null,
110
+ agentIdentity,
124
111
  startedAt: now,
125
112
  completedAt: null,
126
113
  passed: null,
127
114
  evidenceRefs: [],
128
115
  };
129
- const state = {
116
+ return {
130
117
  taskId,
131
118
  schemaVersion: 2,
132
119
  currentPhase: 'implement',
@@ -134,493 +121,191 @@ export async function startIvtr(taskId, options) {
134
121
  startedAt: now,
135
122
  loopBackCount: { implement: 0, validate: 0, audit: 0, test: 0, released: 0 },
136
123
  };
137
- await writeIvtrState(state, options?.cwd);
138
- log.info({ taskId }, 'IVTR loop started at implement phase');
139
- return state;
140
124
  }
141
125
  /**
142
- * Advance the IVTR loop from the current phase to the next.
143
- *
144
- * Closes the current in-progress phase entry (marks it `passed: true`,
145
- * records evidence), opens a new entry for the next phase.
146
- *
147
- * Throws if:
148
- * - No IVTR state exists (call startIvtr first).
149
- * - Already at `released` (use releaseIvtr to finalise).
150
- *
151
- * @param taskId - Task to advance.
152
- * @param evidence - sha256 hashes of evidence attachments from this phase.
153
- * @param options - Optional cwd and agent identity for the next phase entry.
154
- * @returns Updated IvtrState.
126
+ * Seed the `tasks.ivtr_state` mirror for a task whose IVTR loop is now driven
127
+ * by `executePlaybook(ivtr.cantbook)` rather than the hand-rolled phase walk
128
+ * (T11805 · collapse-plan §3 item 4).
129
+ *
130
+ * The strict completion gate `E_IVTR_INCOMPLETE` (`tasks/complete.ts`) fires
131
+ * **only when `ivtr_state !== null`**. The `cleo go` seam removed `startIvtr`
132
+ * — the historical sole writer of that column — from the autopilot path; this
133
+ * helper restores the writer so the gate stays load-bearing while the column
134
+ * is retained for one deprecation cycle. It is intentionally **not**
135
+ * `startIvtr`: AC4 of T11805 requires the go path to no longer call
136
+ * `startIvtr`, but the seeded state must remain identical, so both share
137
+ * {@link buildInitialIvtrState}.
138
+ *
139
+ * Idempotent: a task that already has IVTR state is left untouched and its
140
+ * existing state is returned.
141
+ *
142
+ * @param taskId - Task to seed `ivtr_state` for.
143
+ * @param options - Optional cwd and agent identity for the first phase entry.
144
+ * @returns The current (possibly newly seeded) {@link IvtrState}.
155
145
  */
156
- export async function advanceIvtr(taskId, evidence, options) {
157
- const state = await readIvtrStateRaw(taskId, options?.cwd);
158
- if (!state) {
159
- throw new Error(`No IVTR state for task ${taskId}. Call startIvtr first.`);
160
- }
161
- if (state.currentPhase === 'released') {
162
- throw new Error(`Task ${taskId} is already released. Use releaseIvtr to finalise.`);
163
- }
164
- const now = new Date().toISOString();
165
- // Close the current active phase entry.
166
- const activeEntry = state.phaseHistory.findLast((e) => e.completedAt === null);
167
- if (activeEntry) {
168
- activeEntry.completedAt = now;
169
- activeEntry.passed = true;
170
- activeEntry.evidenceRefs = [...activeEntry.evidenceRefs, ...evidence];
171
- }
172
- const next = nextPhase(state.currentPhase);
173
- if (!next) {
174
- throw new Error(`Cannot advance beyond released phase for task ${taskId}`);
175
- }
176
- state.currentPhase = next;
177
- if (next !== 'released') {
178
- const nextEntry = {
179
- phase: next,
180
- agentIdentity: options?.agentIdentity ?? null,
181
- startedAt: now,
182
- completedAt: null,
183
- passed: null,
184
- evidenceRefs: [],
185
- };
186
- state.phaseHistory.push(nextEntry);
146
+ export async function seedIvtrForPlaybook(taskId, options) {
147
+ const existing = await readIvtrStateRaw(taskId, options?.cwd);
148
+ if (existing) {
149
+ log.info({ taskId }, 'IVTR state already present; seam seed is a no-op');
150
+ return existing;
187
151
  }
152
+ const state = buildInitialIvtrState(taskId, options?.agentIdentity ?? null);
188
153
  await writeIvtrState(state, options?.cwd);
189
- log.info({ taskId, from: state.currentPhase === next ? 'unknown' : next, to: next }, 'IVTR advanced');
154
+ log.info({ taskId }, 'IVTR state mirror seeded for cantbook-driven run');
190
155
  return state;
191
156
  }
192
157
  /**
193
- * Maximum number of loop-backs allowed per phase before HITL escalation.
194
- *
195
- * After `MAX_LOOP_BACKS_PER_PHASE` loop-backs to the same phase, the next
196
- * attempt is rejected with `E_IVTR_MAX_RETRIES` so that a human can
197
- * intervene rather than the loop spinning indefinitely.
198
- */
199
- export const MAX_LOOP_BACKS_PER_PHASE = 2;
200
- /**
201
- * Error code emitted when a phase has exceeded its maximum loop-back count.
202
- *
203
- * Callers (domain handlers, orchestrators) should surface this to the operator
204
- * as a HITL escalation prompt — the task cannot self-heal and needs review.
205
- */
206
- export const E_IVTR_MAX_RETRIES = 'E_IVTR_MAX_RETRIES';
207
- /**
208
- * Loop back to an earlier phase due to failure.
209
- *
210
- * Closes the current active phase entry as failed, appends a failure note
211
- * to the history, then opens a new entry for the target phase.
212
- *
213
- * Increments the `loopBackCount` for the target phase. After
214
- * `MAX_LOOP_BACKS_PER_PHASE` loop-backs to the same phase, subsequent
215
- * calls throw an error with code `E_IVTR_MAX_RETRIES`.
216
- *
217
- * @param taskId - Task to loop back.
218
- * @param toPhase - Phase to rewind to. Must be 'implement', 'validate', or 'test'.
219
- * @param reason - Human-readable explanation of the failure.
220
- * @param evidence - sha256 hashes of failure evidence attachments.
221
- * @param options - Optional cwd and agent identity.
222
- * @returns Updated IvtrState.
223
- * @throws Error with message starting with `E_IVTR_MAX_RETRIES` when the
224
- * per-phase loop-back limit is exceeded.
158
+ * Mirror the terminal status of a cantbook-driven IVTR run back into
159
+ * `tasks.ivtr_state` (T11805 · collapse-plan §3 item 4 + Risk #2).
160
+ *
161
+ * The `cleo go` seam seeds `ivtr_state` at the `implement` phase via
162
+ * {@link seedIvtrForPlaybook} but the cantbook runtime (`executePlaybook`)
163
+ * only writes `playbook_runs` — it never touches `ivtr_state`. Without this
164
+ * mirror a fully-successful autonomous run leaves `ivtr_state.currentPhase`
165
+ * frozen at `'implement'`, so the strict `E_IVTR_INCOMPLETE` completion gate
166
+ * (`tasks/complete.ts`) permanently rejects `cleo complete`. This function
167
+ * closes that gap by translating the runtime's terminal status into the
168
+ * equivalent `ivtr_state` transition:
169
+ *
170
+ * - **`completed`** → walk every required phase to a passing
171
+ * {@link IvtrPhaseEntry} and set `currentPhase = 'released'`, so the gate
172
+ * passes exactly as the legacy `advanceIvtr`→`releaseIvtr` walk did. A
173
+ * content-addressed provenance blob (runId + terminalStatus + a bounded
174
+ * `finalContext` snapshot) is written to the attachment store and its
175
+ * sha256 recorded on the released entry's `evidenceRefs`, reproducing the
176
+ * per-phase evidence write the old walk produced (collapse-plan §3
177
+ * "evidence refs (sha256 attachments)").
178
+ * - **`failed` / `exceeded_iteration_cap`** → mark the active phase entry
179
+ * `passed: false` with the runtime error as the `reason`, leaving
180
+ * `currentPhase` un-advanced so the gate correctly blocks completion.
181
+ * - **`pending_approval`** → no-op (the run is awaiting a HITL gate; a later
182
+ * resume turn finalizes it).
183
+ *
184
+ * Idempotent: a state already at `'released'` is returned untouched.
185
+ *
186
+ * @param taskId - Task whose `ivtr_state` mirror is being finalized.
187
+ * @param terminalStatus - Terminal status from the cantbook run.
188
+ * @param options - Optional cwd, agent identity, runId, error reason, and a
189
+ * bounded `finalContext` snapshot for the provenance blob.
190
+ * @returns The finalized state + optional provenance evidence ref.
191
+ *
192
+ * @task T11805 — E-ORCH-STATE-MACHINE-COLLAPSE / T11764
225
193
  */
226
- export async function loopBackIvtr(taskId, toPhase, reason, evidence, options) {
227
- if (toPhase === 'released') {
228
- throw new Error(`Cannot loop back to 'released'. Use releaseIvtr to finalise.`);
229
- }
194
+ export async function finalizeIvtrFromPlaybook(taskId, terminalStatus, options) {
230
195
  const state = await readIvtrStateRaw(taskId, options?.cwd);
231
196
  if (!state) {
232
- throw new Error(`No IVTR state for task ${taskId}. Call startIvtr first.`);
197
+ log.warn({ taskId, terminalStatus }, 'finalizeIvtrFromPlaybook: no ivtr_state to mirror (seed step skipped?)');
198
+ return { state: null };
233
199
  }
200
+ // Already released — nothing to do (idempotent re-finalization).
234
201
  if (state.currentPhase === 'released') {
235
- throw new Error(`Task ${taskId} is already released. Cannot loop back.`);
236
- }
237
- // Backward-compat: legacy states may not have loopBackCount or audit field.
238
- if (!state.loopBackCount) {
239
- state.loopBackCount = { implement: 0, validate: 0, audit: 0, test: 0, released: 0 };
240
- }
241
- // Defensive: legacy rows predating T9216 won't have loopBackCount.audit.
242
- state.loopBackCount.audit = state.loopBackCount.audit ?? 0;
243
- // Check max BEFORE any mutation so the state stays clean on reject.
244
- const currentCount = state.loopBackCount[toPhase] ?? 0;
245
- if (currentCount >= MAX_LOOP_BACKS_PER_PHASE) {
246
- throw new Error(`${E_IVTR_MAX_RETRIES}: Task ${taskId} has reached the maximum of ${MAX_LOOP_BACKS_PER_PHASE} loop-backs to phase '${toPhase}'. ` +
247
- `HITL escalation required — review the loop-back history and resolve the root cause manually before retrying.`);
202
+ return { state };
248
203
  }
249
204
  const now = new Date().toISOString();
250
- // Close the current active phase entry as failed.
251
- const activeEntry = state.phaseHistory.findLast((e) => e.completedAt === null);
252
- if (activeEntry) {
253
- activeEntry.completedAt = now;
254
- activeEntry.passed = false;
255
- activeEntry.evidenceRefs = [...activeEntry.evidenceRefs, ...evidence];
256
- activeEntry.reason = reason;
205
+ const agentIdentity = options?.agentIdentity ?? null;
206
+ if (terminalStatus === 'pending_approval') {
207
+ // The run paused on a HITL gate; a later resume turn finalizes it.
208
+ log.info({ taskId }, 'finalizeIvtrFromPlaybook: run pending approval — leaving ivtr_state as-is');
209
+ return { state };
257
210
  }
258
- // Open a new entry for the target phase.
259
- const loopEntry = {
260
- phase: toPhase,
261
- agentIdentity: options?.agentIdentity ?? null,
262
- startedAt: now,
263
- completedAt: null,
264
- passed: null,
265
- evidenceRefs: [],
266
- reason: `Loop-back from ${state.currentPhase}: ${reason}`,
267
- };
268
- state.currentPhase = toPhase;
269
- state.phaseHistory.push(loopEntry);
270
- state.loopBackCount[toPhase] = currentCount + 1;
271
- await writeIvtrState(state, options?.cwd);
272
- log.info({ taskId, toPhase, reason, loopBackCount: state.loopBackCount[toPhase] }, 'IVTR loop-back recorded');
273
- return state;
274
- }
275
- /**
276
- * Attempt to release a task after all three phases have passed.
277
- *
278
- * Validates that implement, validate, and test all have at least one passing
279
- * phase entry. If validation passes, marks the task status = 'done' and
280
- * sets `currentPhase = 'released'`.
281
- *
282
- * @param taskId - Task to release.
283
- * @param options - Optional cwd.
284
- * @returns `{ released: true }` on success, or `{ released: false, failures }` listing missing phases.
285
- */
286
- export async function releaseIvtr(taskId, options) {
287
- const state = await readIvtrStateRaw(taskId, options?.cwd);
288
- if (!state) {
289
- return { released: false, failures: [`No IVTR state for task ${taskId}`] };
211
+ if (terminalStatus === 'failed' || terminalStatus === 'exceeded_iteration_cap') {
212
+ // Mark the active phase entry as failed so the gate blocks completion and
213
+ // the failure is auditable; do NOT advance currentPhase.
214
+ const reason = options?.error ?? `cantbook run ${terminalStatus}`;
215
+ const activeEntry = state.phaseHistory.findLast((e) => e.completedAt === null);
216
+ if (activeEntry) {
217
+ activeEntry.completedAt = now;
218
+ activeEntry.passed = false;
219
+ activeEntry.reason = `Playbook ${terminalStatus}: ${reason}`;
220
+ }
221
+ await writeIvtrState(state, options?.cwd);
222
+ log.info({ taskId, terminalStatus, currentPhase: state.currentPhase }, 'finalizeIvtrFromPlaybook: marked active phase failed (gate stays blocking)');
223
+ return { state };
290
224
  }
291
- if (state.currentPhase === 'released') {
292
- return { released: true };
225
+ // terminalStatus === 'completed' — write the provenance evidence blob first
226
+ // so its sha256 can be recorded on the released phase history (reproduces the
227
+ // legacy attachment-store write). Best-effort: a store failure must not block
228
+ // the terminal mirror, since the gate-passability fix is the load-bearing
229
+ // half — but we surface the failure in logs.
230
+ let evidenceRef;
231
+ try {
232
+ evidenceRef = await writeIvtrPlaybookProvenance(taskId, terminalStatus, options?.runId, options?.finalContext, agentIdentity, options?.cwd);
233
+ }
234
+ catch (err) {
235
+ log.warn({ taskId, err: err instanceof Error ? err.message : String(err) }, 'finalizeIvtrFromPlaybook: provenance attachment write failed (non-fatal)');
293
236
  }
294
- const failures = [];
295
- // T9216: 'audit' added as required phase
237
+ // Walk every required phase to a passing entry, then mark released. The
238
+ // E_IVTR_INCOMPLETE gate (complete.ts) requires implement/validate/test to
239
+ // each have a passing entry AND currentPhase === 'released'.
296
240
  const required = [
297
241
  'implement',
298
242
  'validate',
299
243
  'audit',
300
244
  'test',
301
245
  ];
302
- for (const phase of required) {
303
- const passed = state.phaseHistory.some((e) => e.phase === phase && e.passed === true);
304
- if (!passed) {
305
- failures.push(`Phase '${phase}' has no passing entry`);
306
- }
307
- }
308
- if (failures.length > 0) {
309
- return { released: false, failures };
310
- }
311
- // Close the active test entry if still open.
312
- const now = new Date().toISOString();
246
+ // Close any in-progress entry as passed (the active implement seed).
313
247
  const activeEntry = state.phaseHistory.findLast((e) => e.completedAt === null);
314
248
  if (activeEntry) {
315
249
  activeEntry.completedAt = now;
316
250
  activeEntry.passed = true;
251
+ if (evidenceRef)
252
+ activeEntry.evidenceRefs = [...activeEntry.evidenceRefs, evidenceRef];
253
+ }
254
+ // Ensure every required phase has at least one passing entry. Append a
255
+ // synthetic passing entry for any phase the seeded state lacks (the cantbook
256
+ // seed only writes the implement entry).
257
+ for (const phase of required) {
258
+ const hasPassed = state.phaseHistory.some((e) => e.phase === phase && e.passed === true);
259
+ if (!hasPassed) {
260
+ const entry = {
261
+ phase,
262
+ agentIdentity,
263
+ startedAt: now,
264
+ completedAt: now,
265
+ passed: true,
266
+ evidenceRefs: evidenceRef ? [evidenceRef] : [],
267
+ reason: `Cantbook run ${options?.runId ?? '(unknown run)'} completed — phase mirrored from playbook terminal status`,
268
+ };
269
+ state.phaseHistory.push(entry);
270
+ }
317
271
  }
318
272
  state.currentPhase = 'released';
319
273
  await writeIvtrState(state, options?.cwd);
320
- // Mark the task done.
321
- const db = await getDb(options?.cwd);
322
- await db
323
- .update(schema.tasks)
324
- .set({ status: 'done', completedAt: now, updatedAt: now })
325
- .where(eq(schema.tasks.id, taskId))
326
- .all();
327
- log.info({ taskId }, 'IVTR released --- task marked done');
328
- return { released: true };
329
- }
330
- /**
331
- * Retrieve the current IVTR state for a task, or null if the loop has not
332
- * been started.
333
- *
334
- * @param taskId - Task ID to inspect.
335
- * @param options - Optional cwd.
336
- * @returns IvtrState or null.
337
- */
338
- export async function getIvtrState(taskId, options) {
339
- return readIvtrStateRaw(taskId, options?.cwd);
340
- }
341
- /**
342
- * Build the validate-phase evidence bundle section (T812 §2).
343
- *
344
- * Renders a structured Markdown table when enriched summaries are provided,
345
- * or falls back to listing raw sha256 refs from the passed phase entries.
346
- *
347
- * @param implEntries - Implement phase entries with `passed === true`.
348
- * @param evidenceBundle - Optional enriched summaries from the attachment store.
349
- */
350
- function buildValidateEvidenceBundle(implEntries, evidenceBundle) {
351
- if (evidenceBundle.length > 0) {
352
- const rows = evidenceBundle.map((e) => {
353
- const files = e.filesChanged && e.filesChanged.length > 0 ? e.filesChanged.join(', ') : '(unknown)';
354
- const added = e.linesAdded !== undefined ? `+${e.linesAdded}` : '?';
355
- const removed = e.linesRemoved !== undefined ? `-${e.linesRemoved}` : '?';
356
- const duration = e.durationMs !== undefined ? `${e.durationMs}ms` : '?';
357
- return `| \`${e.attachmentSha256.slice(0, 16)}...\` | ${e.kind} | ${files} | ${added}/${removed} | ${duration} |`;
358
- });
359
- return `## Implement-Phase Evidence Bundle
360
-
361
- | sha256 (prefix) | kind | filesChanged | linesAdded/Removed | duration |
362
- |---|---|---|---|---|
363
- ${rows.join('\n')}
364
-
365
- > Retrieve full diff: \`cleo docs show <sha256>\``;
366
- }
367
- // Fallback: list raw refs from phase history.
368
- const allRefs = implEntries.flatMap((e) => e.evidenceRefs);
369
- if (allRefs.length === 0) {
370
- return '## Implement-Phase Evidence Bundle\n(none recorded — impl agent may not have produced attachments)';
371
- }
372
- return `## Implement-Phase Evidence Bundle (sha256 refs)
373
- ${allRefs.map((r) => `- \`${r}\``).join('\n')}
374
-
375
- > Retrieve diff content: \`cleo docs show <sha256>\``;
376
- }
377
- /**
378
- * Build the validate-phase instruction block + REJECT criteria (T812 §§3–4).
379
- *
380
- * @param taskId - Task ID for CLI command references.
381
- * @param state - Current IvtrState (currentPhase === 'validate').
382
- * @param evidenceBundle - Pre-fetched implement evidence summaries (may be empty).
383
- */
384
- function buildValidatePhaseInstruction(taskId, state, evidenceBundle) {
385
- const loopCount = state.loopBackCount?.validate ?? 0;
386
- const escalationNote = loopCount >= 2
387
- ? '\n> WARNING: This is loop-back attempt 3+. HITL escalation is required if this validate phase fails again.\n'
388
- : '';
389
- const implRefHint = evidenceBundle.length > 0
390
- ? evidenceBundle
391
- .map((e) => `- \`${e.attachmentSha256.slice(0, 16)}...\` (${e.kind}${e.filesChanged ? ', ' + e.filesChanged.length + ' file(s)' : ''})`)
392
- .join('\n')
393
- : '(enumerate REQ-IDs from the task specification above and cross-reference the impl-diff sha256 refs in the evidence bundle)';
394
- // T9842 — Blast-radius infrastructure-touch detection. Aggregate every
395
- // `filesChanged` array from the impl-phase evidence bundle and feed it to
396
- // the detector. When the impl touched an infrastructure path, the rendered
397
- // section instructs the Lead to run full per-package tests rather than the
398
- // targeted subset called out in the task spec.
399
- const allFilesChanged = evidenceBundle.flatMap((e) => e.filesChanged ?? []);
400
- const infraTouch = detectInfrastructureTouch(allFilesChanged);
401
- const blastRadiusSection = buildBlastRadiusTestScopeSection(infraTouch);
402
- const blastRadiusBlock = blastRadiusSection ? `\n\n${blastRadiusSection}\n` : '';
403
- const blastRadiusRejectLine = infraTouch.affected
404
- ? '\n- **Infra-test-scope violation (T9842)**: infrastructure paths were touched (see the Blast-Radius Test Scope section above) but no full per-package vitest run was attached. Loop-back reason: `infra-test-scope-violation`.'
405
- : '';
406
- return `## Phase: Validate
407
- You are the Validate agent for task ${taskId}. Read the impl diff + evidence listed in the Implement-Phase Evidence Bundle above. Check spec↔code alignment per each acceptance criterion and REQ-ID.${escalationNote}
408
-
409
- ### Your responsibilities
410
-
411
- 1. Read the task spec and each evidence attachment in the Implement-Phase Evidence Bundle above.
412
- 2. Retrieve each diff blob: \`cleo docs show <sha256>\`
413
- 3. For every acceptance criterion and REQ-ID in the task spec, verify it is traceable to a concrete code change in the impl diff.
414
- 4. Produce a \`ValidateSpecCheckRecord\` (\`kind: 'validate-spec-check'\`) and write it to a JSON file:
415
- \`\`\`json
416
- {
417
- "kind": "validate-spec-check",
418
- "phase": "validate",
419
- "agentIdentity": "<your-agent-id>",
420
- "attachmentSha256": "<sha256-of-this-report>",
421
- "reqIdsChecked": ["<REQ-ID-1>", "<REQ-ID-2>"],
422
- "passed": true,
423
- "details": "<per-REQ-ID verdict, one sentence each>",
424
- "ranAt": "<ISO-8601-timestamp>",
425
- "durationMs": 0
426
- }
427
- \`\`\`
428
- 5. Attach the report: \`cleo docs add <file> --task ${taskId}\`
429
- 6. Pass the returned sha256 to \`--next\`:
430
- - **PASS**: \`cleo orchestrate ivtr ${taskId} --next --evidence <sha256>\`
431
- - **FAIL**: \`cleo orchestrate ivtr ${taskId} --loop-back --phase implement --reason "<details>"\`
432
-
433
- ### Impl-diff attachment refs to review
434
-
435
- ${implRefHint}${blastRadiusBlock}
436
- ### REJECT criteria — trigger loop-back if ANY of the following are true
437
-
438
- - **Spec-code mismatch**: an acceptance criterion or REQ-ID has no traceable code change in the impl diff.
439
- - **Missing test**: an acceptance criterion that requires test coverage has no corresponding test added or updated in the diff.
440
- - **Undocumented deviation**: the implementation deviates from the task spec without a documented reason (comment, ADR reference, or inline note in the diff).
441
- - **Quality gate not run**: the impl-phase evidence does not include proof that \`pnpm biome check\` and \`pnpm run build\` both passed (lint-report or command-output attachment with exit code 0).${blastRadiusRejectLine}`;
274
+ log.info({ taskId, runId: options?.runId, evidenceRef }, 'finalizeIvtrFromPlaybook: ivtr_state mirrored to released (gate now passes)');
275
+ const result = { state };
276
+ if (evidenceRef !== undefined)
277
+ result.evidenceRef = evidenceRef;
278
+ return result;
442
279
  }
443
280
  /**
444
- * Build a resolved prompt string for the current phase's assigned agent.
445
- *
446
- * When advancing to the `validate` phase the prompt is enriched with four
447
- * additional sections required by T812:
448
- *
449
- * 1. **Original task spec** — always included.
450
- * 2. **Implement-phase evidence bundle** — all `IvtrPhaseEntry` records where
451
- * `phase === 'implement'` and `passed === true`, rendered with attachment
452
- * metadata (sha256, kind, filesChanged, linesAdded/Removed, duration).
453
- * Callers pass the optional `evidenceBundle` to supply pre-fetched metadata
454
- * from the attachment store; the function falls back to raw sha256 refs if
455
- * the bundle is empty.
456
- * 3. **Validate-agent instructions** — how to produce a `ValidateSpecCheckRecord`
457
- * (`kind: 'validate-spec-check'`) and attach it via `cleo docs add`.
458
- * 4. **Explicit REJECT criteria** — conditions under which the validate agent
459
- * MUST trigger a loop-back to implement.
281
+ * Write a content-addressed provenance blob for a completed cantbook IVTR run
282
+ * to the attachment store and return its sha256.
460
283
  *
461
- * When the target phase is `implement` and prior failures exist, a loop-back
462
- * context section is injected with the triggering reason and history.
284
+ * This reproduces the attachment-store write the legacy `autoRunGatesAndRecord`
285
+ * / `advanceIvtr` walk performed (collapse-plan §3 mapping row "evidence refs
286
+ * (sha256 attachments)"), so downstream observers (`cleo show --ivtr-history`,
287
+ * release observation reads) still find content-addressed evidence for
288
+ * autonomously-driven tasks.
463
289
  *
464
- * For the `test` phase, the prompt instructs the agent to run
465
- * `cleo verify <id> --run` and produce a `TestOutputRecord`.
290
+ * The `finalContext` snapshot is bounded to its top-level keys' JSON to avoid
291
+ * persisting an unbounded agent context.
466
292
  *
467
- * @param taskId - Task ID (used to label the prompt).
468
- * @param state - Current IvtrState (after the transition to the target phase).
469
- * @param taskTitle - Short task title (from cleo show).
470
- * @param taskDesc - Full task description / spec including REQ-IDs.
471
- * @param acceptanceGates - Optional typed AcceptanceGate objects (used by the test phase).
472
- * @param evidenceBundle - Optional pre-fetched implement-phase evidence summaries
473
- * (used by the validate phase; ignored for other phases).
474
- * @returns Prompt string for the phase's assigned agent.
293
+ * @internal
475
294
  */
476
- export function resolvePhasePrompt(taskId, state, taskTitle, taskDesc, acceptanceGates, evidenceBundle = []) {
477
- // ── Validate phase: structured 4-section prompt (T812) ───────────────────
478
- if (state.currentPhase === 'validate') {
479
- const implEntries = state.phaseHistory.filter((e) => e.phase === 'implement' && e.passed === true);
480
- const bundleSection = buildValidateEvidenceBundle(implEntries, evidenceBundle);
481
- const instructionSection = buildValidatePhaseInstruction(taskId, state, evidenceBundle);
482
- return `# IVTR Agent Prompt — ${taskId}: ${taskTitle}
483
- Phase: **VALIDATE**
484
-
485
- ## Task Specification
486
- ${taskDesc}
487
-
488
- ${bundleSection}
489
-
490
- ${instructionSection}
491
- `;
492
- }
493
- // ── Generic evidence refs section (implement / test / released) ───────────
494
- const priorEvidence = state.phaseHistory
495
- .filter((e) => e.passed === true)
496
- .flatMap((e) => e.evidenceRefs);
497
- const evidenceSection = priorEvidence.length > 0
498
- ? `## Prior Phase Evidence (sha256 attachment refs)\n${priorEvidence.map((r) => `- ${r}`).join('\n')}`
499
- : '## Prior Phase Evidence\n(none — first phase)';
500
- // Build loop-back context section when re-spawning Implement after a failure (T814).
501
- const failedEntries = state.phaseHistory.filter((e) => e.passed === false);
502
- let loopBackSection = '';
503
- if (state.currentPhase === 'implement' && failedEntries.length > 0) {
504
- const triggeringFailure = failedEntries[failedEntries.length - 1];
505
- const failureEvidenceLines = triggeringFailure.evidenceRefs.length > 0
506
- ? triggeringFailure.evidenceRefs.map((r) => `- ${r}`).join('\n')
507
- : '(no attachment refs --- check the reason text above for details)';
508
- const historyLines = failedEntries
509
- .map((e, idx) => `${idx + 1}. Phase: ${e.phase.toUpperCase()} | Reason: ${e.reason ?? '(none)'} | CompletedAt: ${e.completedAt ?? 'unknown'}`)
510
- .join('\n');
511
- loopBackSection = `
512
- ## LOOP-BACK CONTEXT --- READ THIS CAREFULLY
513
-
514
- **Previous attempt failed at phase: ${triggeringFailure.phase.toUpperCase()}**
515
- **Failure reason**: ${triggeringFailure.reason ?? '(none)'}
516
-
517
- ### Failure Evidence (sha256 refs from the failing phase)
518
- ${failureEvidenceLines}
519
-
520
- ### Loop-back History (all prior failures for this task)
521
- ${historyLines}
522
-
523
- **CRITICAL INSTRUCTION**: Previous attempt(s) failed. Read the failure evidence above.
524
- Fix the ROOT CAUSE --- do NOT retry the same approach.
525
- If the test phase failed, check what tests broke and WHY.
526
- If the validate phase failed, check which acceptance criteria were not met and ensure they are addressed.
527
- `;
528
- }
529
- // Build the typed gates section for the test phase prompt.
530
- const gatesSection = acceptanceGates && acceptanceGates.length > 0
531
- ? `\n## Typed AcceptanceGates (programmatic --- run via cleo verify --run)\n${acceptanceGates
532
- .map((g, i) => {
533
- const label = 'command' in g
534
- ? g.command
535
- : 'url' in g
536
- ? g.url
537
- : g.kind;
538
- return `${i + 1}. [${g.kind}] ${g.req ?? '(no req)'} --- ${label}`;
539
- })
540
- .join('\n')}`
541
- : '';
542
- const phaseInstructions = {
543
- implement: `## Phase: Implement
544
- You are the Implementation agent for task ${taskId}.
545
-
546
- Your responsibilities:
547
- 1. Read the task spec below in full.
548
- 2. Write, modify, or extend code to satisfy the acceptance criteria.
549
- 3. Run quality gates: pnpm biome check --write . then pnpm run build.
550
- 4. Produce a git diff or file list as evidence.
551
- 5. Report your sha256 attachment refs as evidence when you call cleo orchestrate ivtr ${taskId} --next.`,
552
- validate: '', // handled above — this branch is unreachable when currentPhase === 'validate'
553
- audit: `## Phase: Audit
554
- You are the independent Auditor agent for task ${taskId}.
555
-
556
- Your responsibilities:
557
- 1. Run cleo verify ${taskId} --explain to re-validate every ADR-051 evidence atom (commit reachable, file sha256, test-run hash, tool exit code) against the live git/fs/toolchain.
558
- 2. Read the captured evidence atoms from prior phases — do NOT trust the agent's prose claims, only the re-validated atom set.
559
- 3. If every required gate is backed by a passing atom: call cleo orchestrate ivtr ${taskId} --next.
560
- 4. If any atom fails re-validation (E_EVIDENCE_STALE, E_EVIDENCE_TESTS_FAILED, E_EVIDENCE_TOOL_FAILED) or any required gate is unbacked: call cleo orchestrate ivtr ${taskId} --loop-back --phase implement --reason "<atom diagnostic>".
561
- The Pre-Complete Gate Ritual (ADR-051) is the only enforcement surface — atoms re-validate against external state, so the Implementer cannot fake them.`,
562
- test: `## Phase: Test
563
- You are the Testing agent for task ${taskId}.
564
-
565
- Your responsibilities:
566
- 1. Read the task spec and all prior-phase evidence refs listed above (impl + validate).
567
- 2. Run cleo verify ${taskId} --run to execute all programmatic AcceptanceGates.
568
- 3. Attach the full gate-run output via cleo docs add --labels test-output.
569
- 4. Compute or capture the sha256 of the attached output.
570
- 5. Pass the sha256 + gate-pass-count + gate-fail-count back in your --next call as:
571
- EvidenceRecord{kind:'test-output', command:'cleo verify ${taskId} --run', exitCode, testsPassed, testsFailed}
572
- 6. If all gates pass, call cleo orchestrate ivtr ${taskId} --next --evidence <sha256>.
573
- 7. If any gate fails, call cleo orchestrate ivtr ${taskId} --loop-back --phase implement --reason "<failure summary>".
574
- ${gatesSection}`,
575
- released: `## Phase: Released
576
- Task ${taskId} has been released. No further agent action required.`,
295
+ async function writeIvtrPlaybookProvenance(taskId, terminalStatus, runId, finalContext, agentIdentity, cwd) {
296
+ const provenance = {
297
+ kind: 'ivtr-playbook-provenance',
298
+ taskId,
299
+ runId: runId ?? null,
300
+ terminalStatus,
301
+ finalizedAt: new Date().toISOString(),
302
+ // Snapshot only the bindings the cantbook nodes emitted (bounded). Internal
303
+ // bookkeeping keys (prefixed `__`) are stripped to keep the blob auditable.
304
+ bindings: finalContext
305
+ ? Object.fromEntries(Object.entries(finalContext).filter(([k]) => !k.startsWith('__')))
306
+ : {},
577
307
  };
578
- return `# IVTR Agent Prompt --- ${taskId}: ${taskTitle}
579
- Phase: **${state.currentPhase.toUpperCase()}**
580
-
581
- ## Task Specification
582
- ${taskDesc}
583
-
584
- ${evidenceSection}
585
- ${loopBackSection}
586
- ${phaseInstructions[state.currentPhase]}
587
- `;
588
- }
589
- /**
590
- * Execute all typed AcceptanceGates for a task atomically during an IVTR
591
- * --next transition with --auto-run-tests set.
592
- *
593
- * Steps performed in a single atomic operation:
594
- * 1. Accept the typed gates array (strings already filtered by caller).
595
- * 2. Run each gate via runGates().
596
- * 3. Serialise the results to JSON and store via AttachmentStore.
597
- * 4. Synthesise a TestOutputRecord carrying the sha256, pass/fail counts,
598
- * and exit code.
599
- * 5. Append the sha256 to the active phaseHistory entry's evidenceRefs and
600
- * persist the updated IvtrState.
601
- *
602
- * @param taskId - Task ID being tested.
603
- * @param acceptanceItems - Mixed acceptance array from the task record (strings
604
- * are silently ignored; only typed gates are executed).
605
- * @param agentIdentity - Optional agent identity string for provenance.
606
- * @param cwd - Optional working directory.
607
- * @returns AutoRunGatesResult with the attachment sha256 and counts.
608
- */
609
- export async function autoRunGatesAndRecord(taskId, acceptanceItems, agentIdentity, cwd) {
610
- const projectRoot = getProjectRoot(cwd);
611
- const ranAt = new Date().toISOString();
612
- const startMs = Date.now();
613
- // 1. Filter to typed gates only (strings are silently skipped).
614
- const typedGateEntries = extractTypedGates(acceptanceItems);
615
- const gates = typedGateEntries.map((e) => e.gate);
616
- // 2. Execute gates.
617
- const results = await runGates(gates, { projectRoot, skipManual: true });
618
- const testsPassed = results.filter((r) => r.result === 'pass').length;
619
- const testsFailed = results.filter((r) => r.result === 'fail' || r.result === 'error').length;
620
- const exitCode = testsFailed > 0 ? 1 : 0;
621
- const durationMs = Date.now() - startMs;
622
- // 3. Serialise gate results as JSON and store as an attachment.
623
- const outputJson = JSON.stringify({ taskId, gates: results, testsPassed, testsFailed }, null, 2);
308
+ const outputJson = JSON.stringify(provenance, null, 2);
624
309
  const attachmentSha256 = createHash('sha256').update(outputJson).digest('hex');
625
310
  const store = createAttachmentStore();
626
311
  await store.put(outputJson, {
@@ -628,31 +313,31 @@ export async function autoRunGatesAndRecord(taskId, acceptanceItems, agentIdenti
628
313
  storageKey: '',
629
314
  mime: 'application/json',
630
315
  size: Buffer.byteLength(outputJson),
631
- }, 'task', taskId, agentIdentity ?? 'ivtr-auto-run', cwd);
632
- // 4. Build the TestOutputRecord.
633
- const evidenceRecord = {
634
- kind: 'test-output',
635
- phase: 'test',
636
- agentIdentity: agentIdentity ?? 'ivtr-auto-run',
637
- attachmentSha256,
638
- command: `cleo verify ${taskId} --run`,
639
- exitCode,
640
- testsPassed,
641
- testsFailed,
642
- ranAt,
643
- durationMs,
644
- };
645
- // 5. Append sha256 to the active phase entry's evidenceRefs and persist.
646
- const state = await readIvtrStateRaw(taskId, cwd);
647
- if (state) {
648
- const activeEntry = state.phaseHistory.findLast((e) => e.completedAt === null);
649
- if (activeEntry) {
650
- activeEntry.evidenceRefs = [...activeEntry.evidenceRefs, attachmentSha256];
651
- }
652
- await writeIvtrState(state, cwd);
653
- }
654
- log.info({ taskId, testsPassed, testsFailed, exitCode, attachmentSha256 }, 'IVTR auto-run gates complete');
655
- return { attachmentSha256, testsPassed, testsFailed, exitCode, evidenceRecord };
316
+ }, 'task', taskId, agentIdentity ?? 'ivtr-playbook-seam', cwd);
317
+ return attachmentSha256;
318
+ }
319
+ /**
320
+ * Maximum number of loop-backs allowed per phase before HITL escalation.
321
+ *
322
+ * The hand-rolled loop-back walk (`loopBackIvtr`) that enforced this cap was
323
+ * deleted in T11896 (the IVTR loop now runs on the cantbook runtime). The
324
+ * constant is RETAINED because {@link classifyReadiness} still reads it to
325
+ * detect tasks whose `ivtr_state.loopBackCount` has reached the monotonic
326
+ * per-target cap (the audit's "Gap A" parity check) and must escalate to HITL.
327
+ *
328
+ * @see packages/core/src/orchestration/classify-readiness.ts
329
+ */
330
+ export const MAX_LOOP_BACKS_PER_PHASE = 2;
331
+ /**
332
+ * Retrieve the current IVTR state for a task, or null if the loop has not
333
+ * been started.
334
+ *
335
+ * @param taskId - Task ID to inspect.
336
+ * @param options - Optional cwd.
337
+ * @returns IvtrState or null.
338
+ */
339
+ export async function getIvtrState(taskId, options) {
340
+ return readIvtrStateRaw(taskId, options?.cwd);
656
341
  }
657
342
  /**
658
343
  * Validate whether a Lead agent is permitted to write the `implemented` gate