@tacuchi/agent-workflow-cli 25.8.0 → 25.9.0

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 (502) hide show
  1. package/CHANGELOG.md +80 -0
  2. package/README.md +5 -1
  3. package/dist/adapters/git-cli.js +225 -17
  4. package/dist/adapters/git-cli.js.map +1 -1
  5. package/dist/adapters/node-file-system.js +48 -0
  6. package/dist/adapters/node-file-system.js.map +1 -1
  7. package/dist/application/amend-service.js +51 -14
  8. package/dist/application/amend-service.js.map +1 -1
  9. package/dist/application/branch-resolver.js +6 -3
  10. package/dist/application/branch-resolver.js.map +1 -1
  11. package/dist/application/capability/design-handler.js +124 -43
  12. package/dist/application/capability/design-handler.js.map +1 -1
  13. package/dist/application/capability/dispatcher.js +4 -1
  14. package/dist/application/capability/dispatcher.js.map +1 -1
  15. package/dist/application/capability/durable-effect.js +3 -0
  16. package/dist/application/capability/durable-effect.js.map +1 -1
  17. package/dist/application/check-branch-service.js +158 -19
  18. package/dist/application/check-branch-service.js.map +1 -1
  19. package/dist/application/checkpoint/markdown.js +2 -2
  20. package/dist/application/checkpoint/markdown.js.map +1 -1
  21. package/dist/application/checkpoint/state-reader.js +12 -0
  22. package/dist/application/checkpoint/state-reader.js.map +1 -1
  23. package/dist/application/checkpoint-service.js +12 -4
  24. package/dist/application/checkpoint-service.js.map +1 -1
  25. package/dist/application/checkpoint-write-service.js +91 -17
  26. package/dist/application/checkpoint-write-service.js.map +1 -1
  27. package/dist/application/claims-ledger.js +137 -11
  28. package/dist/application/claims-ledger.js.map +1 -1
  29. package/dist/application/claims-recovery.js +85 -44
  30. package/dist/application/claims-recovery.js.map +1 -1
  31. package/dist/application/database-tool-catalog.js +33 -0
  32. package/dist/application/database-tool-catalog.js.map +1 -1
  33. package/dist/application/design/consumer-document.js +2 -2
  34. package/dist/application/design/consumer-document.js.map +1 -1
  35. package/dist/application/design/design-content-gate-service.js +20 -2
  36. package/dist/application/design/design-content-gate-service.js.map +1 -1
  37. package/dist/application/design/design-gate-service.js +2 -0
  38. package/dist/application/design/design-gate-service.js.map +1 -1
  39. package/dist/application/design/design-index-service.js +4 -0
  40. package/dist/application/design/design-index-service.js.map +1 -1
  41. package/dist/application/design/design-publish-service.js +1 -4
  42. package/dist/application/design/design-publish-service.js.map +1 -1
  43. package/dist/application/design/design-record-service.js +13 -7
  44. package/dist/application/design/design-record-service.js.map +1 -1
  45. package/dist/application/design/design-resolver-service.js +22 -3
  46. package/dist/application/design/design-resolver-service.js.map +1 -1
  47. package/dist/application/design/design-simple-service.js +24 -5
  48. package/dist/application/design/design-simple-service.js.map +1 -1
  49. package/dist/application/design/digest.js +41 -0
  50. package/dist/application/design/digest.js.map +1 -0
  51. package/dist/application/dev-only-services.js +166 -20
  52. package/dist/application/dev-only-services.js.map +1 -1
  53. package/dist/application/doc-branch-ledger.js +145 -0
  54. package/dist/application/doc-branch-ledger.js.map +1 -0
  55. package/dist/application/docs-canon-service.js +1 -1
  56. package/dist/application/docs-canon-service.js.map +1 -1
  57. package/dist/application/doctor/dist-integrity.js +113 -0
  58. package/dist/application/doctor/dist-integrity.js.map +1 -0
  59. package/dist/application/doctor/hosts.js +5 -2
  60. package/dist/application/doctor/hosts.js.map +1 -1
  61. package/dist/application/doctor/prepare.js +4 -1
  62. package/dist/application/doctor/prepare.js.map +1 -1
  63. package/dist/application/doctor/provider-installation.js +39 -19
  64. package/dist/application/doctor/provider-installation.js.map +1 -1
  65. package/dist/application/doctor/provider-mcps.js +9 -1
  66. package/dist/application/doctor/provider-mcps.js.map +1 -1
  67. package/dist/application/doctor/provider-skills.js +25 -0
  68. package/dist/application/doctor/provider-skills.js.map +1 -1
  69. package/dist/application/doctor/provider-visibility.js +76 -3
  70. package/dist/application/doctor/provider-visibility.js.map +1 -1
  71. package/dist/application/doctor/provider-workspace-block.js +156 -0
  72. package/dist/application/doctor/provider-workspace-block.js.map +1 -0
  73. package/dist/application/doctor/repair-runner.js +47 -3
  74. package/dist/application/doctor/repair-runner.js.map +1 -1
  75. package/dist/application/doctor/report.js +24 -4
  76. package/dist/application/doctor/report.js.map +1 -1
  77. package/dist/application/doctor/skills-toml-migrate.js +76 -0
  78. package/dist/application/doctor/skills-toml-migrate.js.map +1 -0
  79. package/dist/application/export-catalog-check.js +200 -0
  80. package/dist/application/export-catalog-check.js.map +1 -0
  81. package/dist/application/export-service.js +716 -79
  82. package/dist/application/export-service.js.map +1 -1
  83. package/dist/application/fix-git-service.js +285 -64
  84. package/dist/application/fix-git-service.js.map +1 -1
  85. package/dist/application/flow/advance.js +202 -25
  86. package/dist/application/flow/advance.js.map +1 -1
  87. package/dist/application/flow/annul-service.js +3 -1
  88. package/dist/application/flow/annul-service.js.map +1 -1
  89. package/dist/application/flow/batch-commit.js +189 -0
  90. package/dist/application/flow/batch-commit.js.map +1 -0
  91. package/dist/application/flow/checkout-observation.js +63 -10
  92. package/dist/application/flow/checkout-observation.js.map +1 -1
  93. package/dist/application/flow/close-artifacts.js +105 -0
  94. package/dist/application/flow/close-artifacts.js.map +1 -0
  95. package/dist/application/flow/close-at-boundary.js +25 -14
  96. package/dist/application/flow/close-at-boundary.js.map +1 -1
  97. package/dist/application/flow/close-document-guidance.js +70 -0
  98. package/dist/application/flow/close-document-guidance.js.map +1 -0
  99. package/dist/application/flow/flow-service.js +46 -3
  100. package/dist/application/flow/flow-service.js.map +1 -1
  101. package/dist/application/flow/internal-actions.js +300 -82
  102. package/dist/application/flow/internal-actions.js.map +1 -1
  103. package/dist/application/flow/internal-drive.js +24 -1
  104. package/dist/application/flow/internal-drive.js.map +1 -1
  105. package/dist/application/flow/plan-entry.js +82 -0
  106. package/dist/application/flow/plan-entry.js.map +1 -0
  107. package/dist/application/flow/prove.js +32 -1
  108. package/dist/application/flow/prove.js.map +1 -1
  109. package/dist/application/flow/quick-checkouts.js +48 -0
  110. package/dist/application/flow/quick-checkouts.js.map +1 -0
  111. package/dist/application/flow/reinfer-batch.js +177 -0
  112. package/dist/application/flow/reinfer-batch.js.map +1 -0
  113. package/dist/application/flow/reopen-run.js +12 -5
  114. package/dist/application/flow/reopen-run.js.map +1 -1
  115. package/dist/application/flow/run-state-service.js +2 -0
  116. package/dist/application/flow/run-state-service.js.map +1 -1
  117. package/dist/application/flow/submit.js +583 -116
  118. package/dist/application/flow/submit.js.map +1 -1
  119. package/dist/application/generate-launch-service.js +16 -6
  120. package/dist/application/generate-launch-service.js.map +1 -1
  121. package/dist/application/git-flow-service.js +34 -3
  122. package/dist/application/git-flow-service.js.map +1 -1
  123. package/dist/application/history-publications.js +24 -0
  124. package/dist/application/history-publications.js.map +1 -1
  125. package/dist/application/history-reconcile-service.js +45 -0
  126. package/dist/application/history-reconcile-service.js.map +1 -0
  127. package/dist/application/history-table.js +61 -12
  128. package/dist/application/history-table.js.map +1 -1
  129. package/dist/application/history-update-service.js +25 -4
  130. package/dist/application/history-update-service.js.map +1 -1
  131. package/dist/application/hook-branch-check.js +25 -3
  132. package/dist/application/hook-branch-check.js.map +1 -1
  133. package/dist/application/hook-git-commit-advisor.js +3 -4
  134. package/dist/application/hook-git-commit-advisor.js.map +1 -1
  135. package/dist/application/hook-turn-start.js +51 -0
  136. package/dist/application/hook-turn-start.js.map +1 -0
  137. package/dist/application/host-memory/codex.js +1 -1
  138. package/dist/application/host-memory/codex.js.map +1 -1
  139. package/dist/application/hub-registry.js +135 -0
  140. package/dist/application/hub-registry.js.map +1 -0
  141. package/dist/application/local-proposal.js +72 -19
  142. package/dist/application/local-proposal.js.map +1 -1
  143. package/dist/application/mcp-host-reader.js +1 -1
  144. package/dist/application/mcp-host-reader.js.map +1 -1
  145. package/dist/application/mcp-host-writer.js +16 -10
  146. package/dist/application/mcp-host-writer.js.map +1 -1
  147. package/dist/application/merge-state-service.js +150 -34
  148. package/dist/application/merge-state-service.js.map +1 -1
  149. package/dist/application/multiroot/claude.js +17 -10
  150. package/dist/application/multiroot/claude.js.map +1 -1
  151. package/dist/application/multiroot/codex.js +17 -11
  152. package/dist/application/multiroot/codex.js.map +1 -1
  153. package/dist/application/multiroot-service.js +52 -28
  154. package/dist/application/multiroot-service.js.map +1 -1
  155. package/dist/application/parsers/execution-batches.js +64 -0
  156. package/dist/application/parsers/execution-batches.js.map +1 -0
  157. package/dist/application/parsers/phases.js +23 -2
  158. package/dist/application/parsers/phases.js.map +1 -1
  159. package/dist/application/parsers/project-block.js +146 -17
  160. package/dist/application/parsers/project-block.js.map +1 -1
  161. package/dist/application/parsers/tasks.js +16 -2
  162. package/dist/application/parsers/tasks.js.map +1 -1
  163. package/dist/application/parsers/toml.js +19 -0
  164. package/dist/application/parsers/toml.js.map +1 -0
  165. package/dist/application/paths-service.js +13 -16
  166. package/dist/application/paths-service.js.map +1 -1
  167. package/dist/application/persist-service.js +118 -5
  168. package/dist/application/persist-service.js.map +1 -1
  169. package/dist/application/plan-exec-batch-service.js +162 -22
  170. package/dist/application/plan-exec-batch-service.js.map +1 -1
  171. package/dist/application/plan-exec-decision-service.js +61 -12
  172. package/dist/application/plan-exec-decision-service.js.map +1 -1
  173. package/dist/application/plan-exec-plan-diff.js +105 -0
  174. package/dist/application/plan-exec-plan-diff.js.map +1 -0
  175. package/dist/application/plan-lint-service.js +2 -0
  176. package/dist/application/plan-lint-service.js.map +1 -1
  177. package/dist/application/plan-passes.js +41 -0
  178. package/dist/application/plan-passes.js.map +1 -0
  179. package/dist/application/preparation-receipts.js +58 -0
  180. package/dist/application/preparation-receipts.js.map +1 -0
  181. package/dist/application/project-md-upsert-service.js +191 -52
  182. package/dist/application/project-md-upsert-service.js.map +1 -1
  183. package/dist/application/project-tab-data.js +40 -10
  184. package/dist/application/project-tab-data.js.map +1 -1
  185. package/dist/application/release-data/artifacts.js +15 -7
  186. package/dist/application/release-data/artifacts.js.map +1 -1
  187. package/dist/application/release-data/bundles.js +52 -6
  188. package/dist/application/release-data/bundles.js.map +1 -1
  189. package/dist/application/release-data/common.js +2 -2
  190. package/dist/application/release-data/common.js.map +1 -1
  191. package/dist/application/release-data/rollback.js +7 -0
  192. package/dist/application/release-data/rollback.js.map +1 -0
  193. package/dist/application/release-data/sessions.js +2 -2
  194. package/dist/application/release-data/sessions.js.map +1 -1
  195. package/dist/application/release-pass-ledger.js +1 -1
  196. package/dist/application/render/history-row.js +2 -0
  197. package/dist/application/render/history-row.js.map +1 -1
  198. package/dist/application/render/project-block.js +28 -11
  199. package/dist/application/render/project-block.js.map +1 -1
  200. package/dist/application/reseal-service.js +1 -0
  201. package/dist/application/reseal-service.js.map +1 -1
  202. package/dist/application/resume-service.js +55 -8
  203. package/dist/application/resume-service.js.map +1 -1
  204. package/dist/application/retirement/apply.js +25 -7
  205. package/dist/application/retirement/apply.js.map +1 -1
  206. package/dist/application/retirement/attribution.js +121 -48
  207. package/dist/application/retirement/attribution.js.map +1 -1
  208. package/dist/application/retirement/prepare.js +17 -11
  209. package/dist/application/retirement/prepare.js.map +1 -1
  210. package/dist/application/retirement/preview.js +2 -1
  211. package/dist/application/retirement/preview.js.map +1 -1
  212. package/dist/application/self/codex-plugin.js +1 -1
  213. package/dist/application/self/codex-plugin.js.map +1 -1
  214. package/dist/application/self/host-states.js +3 -3
  215. package/dist/application/self/host-states.js.map +1 -1
  216. package/dist/application/self/install-hooks.js +1 -1
  217. package/dist/application/self/install-hooks.js.map +1 -1
  218. package/dist/application/self/mcp-config.js +19 -11
  219. package/dist/application/self/mcp-config.js.map +1 -1
  220. package/dist/application/self/opencode-plugin.js +1 -0
  221. package/dist/application/self/opencode-plugin.js.map +1 -1
  222. package/dist/application/self/uninstall.js +1 -1
  223. package/dist/application/self/uninstall.js.map +1 -1
  224. package/dist/application/semantic-operation/protocol.js +66 -5
  225. package/dist/application/semantic-operation/protocol.js.map +1 -1
  226. package/dist/application/session-archive-service.js +113 -0
  227. package/dist/application/session-archive-service.js.map +1 -0
  228. package/dist/application/session-binding-service.js +35 -0
  229. package/dist/application/session-binding-service.js.map +1 -1
  230. package/dist/application/session-close-service.js +390 -54
  231. package/dist/application/session-close-service.js.map +1 -1
  232. package/dist/application/session-create-service.js +97 -5
  233. package/dist/application/session-create-service.js.map +1 -1
  234. package/dist/application/session-custody-recorder.js +15 -12
  235. package/dist/application/session-custody-recorder.js.map +1 -1
  236. package/dist/application/session-custody-service.js +1 -0
  237. package/dist/application/session-custody-service.js.map +1 -1
  238. package/dist/application/session-narrative.js +42 -12
  239. package/dist/application/session-narrative.js.map +1 -1
  240. package/dist/application/session-pause-service.js +46 -0
  241. package/dist/application/session-pause-service.js.map +1 -0
  242. package/dist/application/session-resolver.js +36 -11
  243. package/dist/application/session-resolver.js.map +1 -1
  244. package/dist/application/session-resume-service.js +134 -13
  245. package/dist/application/session-resume-service.js.map +1 -1
  246. package/dist/application/sessions-service.js +4 -0
  247. package/dist/application/sessions-service.js.map +1 -1
  248. package/dist/application/sessions-sweep-service.js +77 -0
  249. package/dist/application/sessions-sweep-service.js.map +1 -0
  250. package/dist/application/settle-service.js +3 -1
  251. package/dist/application/settle-service.js.map +1 -1
  252. package/dist/application/skills-resolver-service.js +1 -1
  253. package/dist/application/skills-resolver-service.js.map +1 -1
  254. package/dist/application/source-add-service.js +37 -0
  255. package/dist/application/source-add-service.js.map +1 -0
  256. package/dist/application/source-boundary-policy.js +97 -8
  257. package/dist/application/source-boundary-policy.js.map +1 -1
  258. package/dist/application/source-pipeline.js +68 -0
  259. package/dist/application/source-pipeline.js.map +1 -0
  260. package/dist/application/source-remove-service.js +15 -3
  261. package/dist/application/source-remove-service.js.map +1 -1
  262. package/dist/application/sources-service.js +71 -16
  263. package/dist/application/sources-service.js.map +1 -1
  264. package/dist/application/status-service.js +55 -5
  265. package/dist/application/status-service.js.map +1 -1
  266. package/dist/application/unit-dependencies.js +100 -0
  267. package/dist/application/unit-dependencies.js.map +1 -0
  268. package/dist/application/unit-membership.js +37 -0
  269. package/dist/application/unit-membership.js.map +1 -0
  270. package/dist/application/unit-residue.js +72 -0
  271. package/dist/application/unit-residue.js.map +1 -0
  272. package/dist/application/visibility-doctor-service.js +66 -4
  273. package/dist/application/visibility-doctor-service.js.map +1 -1
  274. package/dist/application/working-branch-service.js +6 -0
  275. package/dist/application/working-branch-service.js.map +1 -1
  276. package/dist/application/workline-graph.js +1 -1
  277. package/dist/application/workline-graph.js.map +1 -1
  278. package/dist/application/workline-index-service.js +118 -17
  279. package/dist/application/workline-index-service.js.map +1 -1
  280. package/dist/application/workspace-commit-service.js +218 -0
  281. package/dist/application/workspace-commit-service.js.map +1 -0
  282. package/dist/application/workspace-init-service.js +64 -34
  283. package/dist/application/workspace-init-service.js.map +1 -1
  284. package/dist/application/workspace-local-config.js +90 -0
  285. package/dist/application/workspace-local-config.js.map +1 -0
  286. package/dist/application/workspace-materialization-service.js +52 -3
  287. package/dist/application/workspace-materialization-service.js.map +1 -1
  288. package/dist/application/workspace-migrate/apply.js +525 -4
  289. package/dist/application/workspace-migrate/apply.js.map +1 -1
  290. package/dist/application/workspace-migrate/markers.js +9 -6
  291. package/dist/application/workspace-migrate/markers.js.map +1 -1
  292. package/dist/application/workspace-migrate/plan.js +97 -5
  293. package/dist/application/workspace-migrate/plan.js.map +1 -1
  294. package/dist/application/workspace-move-service.js +270 -0
  295. package/dist/application/workspace-move-service.js.map +1 -0
  296. package/dist/application/workspace-untrack-service.js +28 -0
  297. package/dist/application/workspace-untrack-service.js.map +1 -0
  298. package/dist/application/worktree-service.js +654 -105
  299. package/dist/application/worktree-service.js.map +1 -1
  300. package/dist/cli/ascii.js +2 -0
  301. package/dist/cli/ascii.js.map +1 -1
  302. package/dist/cli/commands/add-source.js +38 -0
  303. package/dist/cli/commands/add-source.js.map +1 -0
  304. package/dist/cli/commands/amend.js +14 -3
  305. package/dist/cli/commands/amend.js.map +1 -1
  306. package/dist/cli/commands/capability.js +11 -0
  307. package/dist/cli/commands/capability.js.map +1 -1
  308. package/dist/cli/commands/designs.js +14 -5
  309. package/dist/cli/commands/designs.js.map +1 -1
  310. package/dist/cli/commands/dev-only.js +19 -6
  311. package/dist/cli/commands/dev-only.js.map +1 -1
  312. package/dist/cli/commands/doc-branch.js +184 -0
  313. package/dist/cli/commands/doc-branch.js.map +1 -0
  314. package/dist/cli/commands/doctor.js +5 -1
  315. package/dist/cli/commands/doctor.js.map +1 -1
  316. package/dist/cli/commands/export.js +78 -18
  317. package/dist/cli/commands/export.js.map +1 -1
  318. package/dist/cli/commands/fix-git.js +89 -14
  319. package/dist/cli/commands/fix-git.js.map +1 -1
  320. package/dist/cli/commands/flow.js +120 -15
  321. package/dist/cli/commands/flow.js.map +1 -1
  322. package/dist/cli/commands/generate-launch.js +14 -2
  323. package/dist/cli/commands/generate-launch.js.map +1 -1
  324. package/dist/cli/commands/history-update.js +1 -1
  325. package/dist/cli/commands/history-update.js.map +1 -1
  326. package/dist/cli/commands/history.js +14 -0
  327. package/dist/cli/commands/history.js.map +1 -0
  328. package/dist/cli/commands/hook.js +15 -2
  329. package/dist/cli/commands/hook.js.map +1 -1
  330. package/dist/cli/commands/index.js +18 -1
  331. package/dist/cli/commands/index.js.map +1 -1
  332. package/dist/cli/commands/merge-state.js +2 -2
  333. package/dist/cli/commands/merge-state.js.map +1 -1
  334. package/dist/cli/commands/persist.js +6 -5
  335. package/dist/cli/commands/persist.js.map +1 -1
  336. package/dist/cli/commands/project-md-upsert.js +5 -3
  337. package/dist/cli/commands/project-md-upsert.js.map +1 -1
  338. package/dist/cli/commands/release-pass.js +3 -3
  339. package/dist/cli/commands/release-pass.js.map +1 -1
  340. package/dist/cli/commands/resume.js +12 -3
  341. package/dist/cli/commands/resume.js.map +1 -1
  342. package/dist/cli/commands/self.js +7 -2
  343. package/dist/cli/commands/self.js.map +1 -1
  344. package/dist/cli/commands/session-close.js +64 -9
  345. package/dist/cli/commands/session-close.js.map +1 -1
  346. package/dist/cli/commands/session-create.js +4 -2
  347. package/dist/cli/commands/session-create.js.map +1 -1
  348. package/dist/cli/commands/session-pause.js +14 -0
  349. package/dist/cli/commands/session-pause.js.map +1 -0
  350. package/dist/cli/commands/sessions.js +16 -3
  351. package/dist/cli/commands/sessions.js.map +1 -1
  352. package/dist/cli/commands/set-branch.js +28 -4
  353. package/dist/cli/commands/set-branch.js.map +1 -1
  354. package/dist/cli/commands/set-edit-mode.js +20 -0
  355. package/dist/cli/commands/set-edit-mode.js.map +1 -0
  356. package/dist/cli/commands/set-pipeline.js +35 -0
  357. package/dist/cli/commands/set-pipeline.js.map +1 -0
  358. package/dist/cli/commands/sources.js +4 -0
  359. package/dist/cli/commands/sources.js.map +1 -1
  360. package/dist/cli/commands/status.js +35 -2
  361. package/dist/cli/commands/status.js.map +1 -1
  362. package/dist/cli/commands/unknown-flags.js +1 -0
  363. package/dist/cli/commands/unknown-flags.js.map +1 -1
  364. package/dist/cli/commands/visibility.js +1 -0
  365. package/dist/cli/commands/visibility.js.map +1 -1
  366. package/dist/cli/commands/workspace-commit.js +62 -0
  367. package/dist/cli/commands/workspace-commit.js.map +1 -0
  368. package/dist/cli/commands/workspace-init.js +39 -2
  369. package/dist/cli/commands/workspace-init.js.map +1 -1
  370. package/dist/cli/commands/workspace-migrate.js +31 -3
  371. package/dist/cli/commands/workspace-migrate.js.map +1 -1
  372. package/dist/cli/commands/workspace-move.js +42 -0
  373. package/dist/cli/commands/workspace-move.js.map +1 -0
  374. package/dist/cli/commands/worktree.js +4 -4
  375. package/dist/cli/commands/worktree.js.map +1 -1
  376. package/dist/cli/context-id.js +6 -0
  377. package/dist/cli/context-id.js.map +1 -1
  378. package/dist/cli/full-cli.js +555 -0
  379. package/dist/cli/full-cli.js.map +1 -0
  380. package/dist/cli/help-groups.js +75 -16
  381. package/dist/cli/help-groups.js.map +1 -1
  382. package/dist/cli/hook-stdin-cache.js +12 -0
  383. package/dist/cli/hook-stdin-cache.js.map +1 -0
  384. package/dist/cli/main.js +47 -453
  385. package/dist/cli/main.js.map +1 -1
  386. package/dist/cli/parser.js +4 -0
  387. package/dist/cli/parser.js.map +1 -1
  388. package/dist/cli/tui/app.js +1 -1
  389. package/dist/cli/tui/app.js.map +1 -1
  390. package/dist/cli/tui/components/workspace-init-form.js +4 -1
  391. package/dist/cli/tui/components/workspace-init-form.js.map +1 -1
  392. package/dist/cli/tui/data/recommended-skills.js +2 -2
  393. package/dist/cli/tui/data/recommended-skills.js.map +1 -1
  394. package/dist/cli/tui/data/workflow-content.js +6 -1
  395. package/dist/cli/tui/data/workflow-content.js.map +1 -1
  396. package/dist/cli/tui/tabs/mcp-tab.js +4 -3
  397. package/dist/cli/tui/tabs/mcp-tab.js.map +1 -1
  398. package/dist/cli/tui/tabs/project-tab.js +7 -2
  399. package/dist/cli/tui/tabs/project-tab.js.map +1 -1
  400. package/dist/dist-manifest.json +4117 -0
  401. package/dist/domain/capability/protocol.js.map +1 -1
  402. package/dist/domain/decision-note.js +13 -0
  403. package/dist/domain/decision-note.js.map +1 -1
  404. package/dist/domain/design/artifact.js +22 -3
  405. package/dist/domain/design/artifact.js.map +1 -1
  406. package/dist/domain/design/capability.js +1 -0
  407. package/dist/domain/design/capability.js.map +1 -1
  408. package/dist/domain/design/expansion.js +1 -1
  409. package/dist/domain/design/expansion.js.map +1 -1
  410. package/dist/domain/design/maturity.js +16 -0
  411. package/dist/domain/design/maturity.js.map +1 -1
  412. package/dist/domain/design/reference.js +5 -0
  413. package/dist/domain/design/reference.js.map +1 -1
  414. package/dist/domain/doctor/operations.js +28 -2
  415. package/dist/domain/doctor/operations.js.map +1 -1
  416. package/dist/domain/effective-contract.js +3 -1
  417. package/dist/domain/effective-contract.js.map +1 -1
  418. package/dist/domain/elicitation.js +1 -1
  419. package/dist/domain/flow/answer.js +265 -130
  420. package/dist/domain/flow/answer.js.map +1 -1
  421. package/dist/domain/flow/authority.js +193 -34
  422. package/dist/domain/flow/authority.js.map +1 -1
  423. package/dist/domain/flow/batch-review.js +65 -0
  424. package/dist/domain/flow/batch-review.js.map +1 -0
  425. package/dist/domain/flow/decision-schema.js +47 -0
  426. package/dist/domain/flow/decision-schema.js.map +1 -0
  427. package/dist/domain/flow/directive.js +16 -0
  428. package/dist/domain/flow/directive.js.map +1 -1
  429. package/dist/domain/flow/execution-result.js +91 -2
  430. package/dist/domain/flow/execution-result.js.map +1 -1
  431. package/dist/domain/flow/run-state.js +352 -24
  432. package/dist/domain/flow/run-state.js.map +1 -1
  433. package/dist/domain/flow/test-run-evidence.js +285 -0
  434. package/dist/domain/flow/test-run-evidence.js.map +1 -0
  435. package/dist/domain/flow/unchanged-phase.js +15 -0
  436. package/dist/domain/flow/unchanged-phase.js.map +1 -0
  437. package/dist/domain/harnesses.js +14 -5
  438. package/dist/domain/harnesses.js.map +1 -1
  439. package/dist/domain/isolation-unit.js +2 -2
  440. package/dist/domain/isolation-unit.js.map +1 -1
  441. package/dist/domain/lineage.js +7 -2
  442. package/dist/domain/lineage.js.map +1 -1
  443. package/dist/domain/obligation-correspondence.js +4 -2
  444. package/dist/domain/obligation-correspondence.js.map +1 -1
  445. package/dist/domain/plan-handoff.js +5 -0
  446. package/dist/domain/plan-handoff.js.map +1 -0
  447. package/dist/domain/proposal.js +18 -7
  448. package/dist/domain/proposal.js.map +1 -1
  449. package/dist/domain/reservation.js +5 -3
  450. package/dist/domain/reservation.js.map +1 -1
  451. package/dist/domain/retirement/proposal.js +1 -0
  452. package/dist/domain/retirement/proposal.js.map +1 -1
  453. package/dist/domain/session/custody.js +10 -6
  454. package/dist/domain/session/custody.js.map +1 -1
  455. package/dist/domain/session/narrative.js +4 -1
  456. package/dist/domain/session/narrative.js.map +1 -1
  457. package/dist/domain/skills.js +2 -0
  458. package/dist/domain/skills.js.map +1 -1
  459. package/dist/domain/sql-lexer.js +1 -1
  460. package/dist/domain/sql-lexer.js.map +1 -1
  461. package/dist/runtime/namespace-resolver.js +4 -0
  462. package/dist/runtime/namespace-resolver.js.map +1 -1
  463. package/dist/runtime/workline-marker.js +35 -8
  464. package/dist/runtime/workline-marker.js.map +1 -1
  465. package/dist/runtime/workspace-resolution.js +123 -0
  466. package/dist/runtime/workspace-resolution.js.map +1 -0
  467. package/package.json +5 -4
  468. package/skills/w/SKILL.md +3 -1
  469. package/skills/w/artifacts/artifacts-core/CHECKPOINT.md +1 -1
  470. package/skills/w/artifacts/artifacts-core/SCRIPTS.rollback.sql +8 -0
  471. package/skills/w/artifacts/artifacts-core/SCRIPTS.sql +4 -8
  472. package/skills/w/commands/export-diagrams.md +3 -3
  473. package/skills/w/commands/export-manuals.md +6 -6
  474. package/skills/w/commands/export-reports.md +3 -3
  475. package/skills/w/commands/export-scripts.md +5 -5
  476. package/skills/w/commands/fix-git.md +12 -13
  477. package/skills/w/commands/persist.md +2 -2
  478. package/skills/w/commands/plan-exec.md +4 -2
  479. package/skills/w/commands/spec-new.md +1 -1
  480. package/skills/w/commands/workspace-init.md +2 -0
  481. package/skills/w/context/MANIFEST.json +1 -1
  482. package/skills/w/exports/export-diagrams/EXPORT.md +3 -3
  483. package/skills/w/exports/export-manuals/EXPORT.md +14 -16
  484. package/skills/w/exports/export-reports/EXPORT.md +3 -3
  485. package/skills/w/exports/export-scripts/EXPORT.md +45 -21
  486. package/skills/w/harness/HARNESS.md +2 -2
  487. package/skills/w/hooks/hooks.template.json +6 -4
  488. package/skills/w/loops/CHASSIS.md +11 -5
  489. package/skills/w/loops/CODE-POLICIES.md +7 -4
  490. package/skills/w/loops/plan-exec-loop/LOOP.md +23 -22
  491. package/skills/w/loops/plan-new-loop/LOOP.md +23 -31
  492. package/skills/w/loops/plan-refine-loop/LOOP.md +8 -2
  493. package/skills/w/loops/quick-loop/LOOP.md +6 -5
  494. package/skills/w/modules/DESIGN-REFERENCES.md +9 -11
  495. package/skills/w/modules/PLAN-EXECUTION-BATCHES.md +4 -4
  496. package/skills/w/modules/SESSION-NUMBERING.md +2 -0
  497. package/skills/w/roles/design/CONTRACT.md +6 -4
  498. package/skills/w/roles/design/ROLE.md +4 -2
  499. package/skills/w/roles/git/ROLE.md +16 -9
  500. package/skills/w/roles/research/ROLE.md +1 -1
  501. package/skills/w/roles/sql/ROLE.md +16 -14
  502. package/skills/w/schemas/design/ui-screen.v1.schema.json +9 -0
@@ -27,6 +27,7 @@ import { isEffectClass, touchesTheWorld } from "../capability/effects.js";
27
27
  import { AttemptLedger } from "../capability/protocol.js";
28
28
  import { normalizeObligations, validateDecisionNote } from "../decision-note.js";
29
29
  import { expandJourney, journeyOfFlow, } from "./authority.js";
30
+ import { isBatchReview } from "./batch-review.js";
30
31
  import { V11_JOURNEY_BASE } from "./journey-baseline.js";
31
32
  import { assuranceForRoute, isAssuranceStatus, isRouteDisposition, } from "./route.js";
32
33
  /**
@@ -40,7 +41,7 @@ import { assuranceForRoute, isAssuranceStatus, isRouteDisposition, } from "./rou
40
41
  * turning the cap off in silence while somebody alternates CLI versions over one
41
42
  * run. Failing with a cause is the requirement; failing silently is the defect.
42
43
  */
43
- export const FLOW_RUN_STATE_VERSION = 13;
44
+ export const FLOW_RUN_STATE_VERSION = 15;
44
45
  /**
45
46
  * The versions this CLI CONTINUES without adoption, newest first.
46
47
  *
@@ -58,7 +59,15 @@ export const FLOW_RUN_STATE_VERSION = 13;
58
59
  * and the `route-refused` trace kind. A v12 run has none of them either, and a
59
60
  * batch without `base` is read as the one that was in flight when the CLI updated.
60
61
  */
61
- export const FLOW_RUN_STATE_CONTINUABLE = [FLOW_RUN_STATE_VERSION, 12, 11];
62
+ // v14 adds batch reviews, signal retractions and QUICK checkout observations.
63
+ // Older observations and events remain unchanged.
64
+ export const FLOW_RUN_STATE_CONTINUABLE = [
65
+ FLOW_RUN_STATE_VERSION,
66
+ 14,
67
+ 13,
68
+ 12,
69
+ 11,
70
+ ];
62
71
  /**
63
72
  * The versions this CLI READS, newest first.
64
73
  *
@@ -83,6 +92,13 @@ export const FLOW_RUN_STATE_READABLE = [
83
92
  const CONTINUABLE_UPGRADES = {
84
93
  11: (state) => ({ ...state, version: 12, journey_base: [...V11_JOURNEY_BASE[state.flow]] }),
85
94
  12: (state) => ({ ...state, version: 13 }),
95
+ // Historical reviews are never fabricated. A still-open batch must supply one.
96
+ 13: (state) => ({ ...state, version: 14 }),
97
+ 14: (state) => ({
98
+ ...state,
99
+ version: 15,
100
+ ...(state.scope ? { scope: { isolation: "unit", ...state.scope } } : {}),
101
+ }),
86
102
  };
87
103
  /** The CLI-owned run state inside the session folder. Machine-local, dotted. */
88
104
  export const FLOW_RUN_STATE_FILE = ".flow-run.json";
@@ -171,11 +187,27 @@ export function currentReentryIteration(state, transition) {
171
187
  */
172
188
  function spendAt(state, transition) {
173
189
  const iteration = iterationOf(state, transition);
174
- const rows = state.attempts.filter((attempt) => attempt.transition === transition && sameIteration(attempt, iteration));
190
+ const recorded = state.attempts.filter((attempt) => attempt.transition === transition && sameIteration(attempt, iteration));
191
+ const seen = new Set();
192
+ const rows = recorded.filter((attempt) => {
193
+ const key = `${attempt.invocation_id}:${attempt.attempt}:${attempt.request_digest}`;
194
+ if (seen.has(key))
195
+ return false;
196
+ seen.add(key);
197
+ return true;
198
+ });
175
199
  const key = attemptCounterKey(state, transition);
176
- const floor = state.attempt_floor?.[key] ?? 0;
200
+ // Old runs may hold a twin row and a counter raised over that twin. Removing
201
+ // both copies of the same resend from the reading preserves the anti-rollback
202
+ // excess, which is the portion the monotone floor still has to protect.
203
+ const floor = Math.max(0, (state.attempt_floor?.[key] ?? 0) - (recorded.length - rows.length));
177
204
  const granted = state.attempt_grants?.[key] ?? 0;
178
- return { rows, floor, granted, spent: Math.max(0, Math.max(rows.length, floor) - granted) };
205
+ return {
206
+ rows,
207
+ floor,
208
+ granted,
209
+ spent: Math.max(0, Math.max(rows.filter((row) => row.approval !== true).length, floor) - granted),
210
+ };
179
211
  }
180
212
  /**
181
213
  * The whole accounting of one transition, conflicts named and answerability read.
@@ -190,23 +222,24 @@ export function attemptAccountingAt(state, transition) {
190
222
  // — and a projection that disagrees with the state it describes is the very
191
223
  // thing this reading exists to stop. It cannot mask a real divergence: a
192
224
  // counter that runs AHEAD of the rows stays ahead of this maximum.
193
- const floor = Math.max(read, rows.length);
225
+ const paid = rows.filter((row) => row.approval !== true).length;
226
+ const floor = Math.max(read, paid);
194
227
  const ordinals = rows.map((attempt) => attempt.attempt);
195
228
  const conflicts = [];
196
- if (floor > rows.length) {
229
+ if (floor > paid) {
197
230
  conflicts.push({
198
231
  between: [
199
232
  { name: "attempt_floor", value: floor },
200
- { name: "attempts", value: rows.length },
233
+ { name: "attempts", value: paid },
201
234
  ],
202
235
  cause: "el contador monótono declara más intentos que las filas persistidas: o se restauró una copia anterior del ledger, o una escritura murió entre el contador y el estado",
203
236
  });
204
237
  }
205
- if (granted > Math.max(rows.length, floor)) {
238
+ if (granted > Math.max(paid, floor)) {
206
239
  conflicts.push({
207
240
  between: [
208
241
  { name: "attempt_grants", value: granted },
209
- { name: "attempts", value: Math.max(rows.length, floor) },
242
+ { name: "attempts", value: Math.max(paid, floor) },
210
243
  ],
211
244
  cause: "se perdonan más intentos de los que esta transición llegó a registrar",
212
245
  });
@@ -268,7 +301,8 @@ export function reconcileAttemptsAt(state, transition) {
268
301
  };
269
302
  }
270
303
  const { rows, floor: read, granted, spent } = spendAt(state, transition);
271
- const floor = Math.max(read, rows.length);
304
+ const paid = rows.filter((row) => row.approval !== true).length;
305
+ const floor = Math.max(read, paid);
272
306
  const accounting = attemptAccountingAt(state, transition);
273
307
  const repairs = [];
274
308
  // What is repaired is the EFFECTIVE spend, not the raw difference between the
@@ -277,7 +311,7 @@ export function reconcileAttemptsAt(state, transition) {
277
311
  // against that difference would forgive it again on every single advance and
278
312
  // quietly remove the cap. Written against the spend, the second reading finds
279
313
  // `spent === rows` and has nothing to do.
280
- const unforgiven = spent - rows.length;
314
+ const unforgiven = spent - paid;
281
315
  if (unforgiven > 0) {
282
316
  repairs.push({
283
317
  rule: "forgive-counter-excess",
@@ -287,7 +321,7 @@ export function reconcileAttemptsAt(state, transition) {
287
321
  after: granted + unforgiven,
288
322
  });
289
323
  }
290
- const recorded = Math.max(rows.length, floor);
324
+ const recorded = Math.max(paid, floor);
291
325
  if (granted > recorded) {
292
326
  repairs.push({
293
327
  rule: "clamp-grants",
@@ -327,10 +361,11 @@ function conflictCause(accounting, field) {
327
361
  function repeatedOrdinal(state) {
328
362
  const seen = new Map();
329
363
  for (const row of state.attempts) {
330
- const ordinals = seen.get(row.invocation_id) ?? new Set();
331
- if (ordinals.has(row.attempt))
364
+ const ordinals = seen.get(row.invocation_id) ?? new Map();
365
+ const previous = ordinals.get(row.attempt);
366
+ if (previous !== undefined && previous !== row.request_digest)
332
367
  return row.attempt;
333
- ordinals.add(row.attempt);
368
+ ordinals.set(row.attempt, row.request_digest);
334
369
  seen.set(row.invocation_id, ordinals);
335
370
  }
336
371
  return null;
@@ -388,8 +423,7 @@ function unanswerableAt(state) {
388
423
  }
389
424
  return null;
390
425
  }
391
- export function recoveryBlockedAt(state, transition) {
392
- const iteration = iterationOf(state, transition);
426
+ export function recoveryBlockedAt(state, transition, iteration = iterationOf(state, transition)) {
393
427
  const trace = state.events.filter((event) => event.transition === transition && sameIteration(event, iteration));
394
428
  const material = [...trace].reverse().find(declaresMaterialEffect);
395
429
  if (material !== undefined)
@@ -415,6 +449,7 @@ function declaresMaterialEffect(event) {
415
449
  event.kind === "aligned" ||
416
450
  event.kind === "route-refused" ||
417
451
  event.kind === "restarted" ||
452
+ event.kind === "retracted" ||
418
453
  event.kind === "annulled") {
419
454
  return false;
420
455
  }
@@ -454,6 +489,7 @@ export const PLAN_EXEC_BATCH_STAGES = [
454
489
  "deviation",
455
490
  "validating",
456
491
  "reviewing",
492
+ "batch-committing",
457
493
  "closed",
458
494
  "committing",
459
495
  "integrating",
@@ -708,9 +744,64 @@ export function withPlanExecBatchCredit(state, batchId, credit) {
708
744
  return state;
709
745
  return sealRunState({
710
746
  ...withoutSeal(state),
711
- batches: batches.map((batch) => (batch.id === batchId ? { ...batch, credit } : batch)),
747
+ batches: batches.map((batch) => batch.id === batchId ? { ...batch, credit, credit_phases: [...batch.phases] } : batch),
748
+ });
749
+ }
750
+ export function withPlanExecBatchUpdate(state, id, update) {
751
+ return sealRunState({
752
+ ...withoutSeal(state),
753
+ batches: (state.batches ?? []).map((batch) => (batch.id === id ? update(batch) : batch)),
754
+ });
755
+ }
756
+ /** Re-seal the SAME unpublished batch; old validation/review cannot credit a new base. */
757
+ export function withReinferredPlanExecBatch(state, batchId, planDigest, anchor) {
758
+ const replaced = withPlanExecBatchUpdate(state, batchId, (batch) => {
759
+ const { credit: _credit, credit_phases: _phases, review: _review, commit_proposal: _proposal, ...rest } = batch;
760
+ return { ...rest, plan_digest: planDigest, stage: "inferred" };
761
+ });
762
+ const traced = withPlanExecBatchStage(replaced, batchId, "inferred", "plan-exec.batch-inference", "entered");
763
+ if (anchor === null)
764
+ return traced;
765
+ const reentered = withReentry(traced, {
766
+ kind: "reinfer",
767
+ transition: anchor,
768
+ occurrence: state.applied.filter((id) => id === anchor).length + 1,
769
+ from: "plan-exec.validation-execution",
770
+ });
771
+ return withPendingAction(withBoundary(reentered, "plan-exec.validation-execution"), null);
772
+ }
773
+ /** Old runs that closed even one batch without a commit result stay on the old tail. */
774
+ export function legacyPlanExecCommits(state) {
775
+ if (state.skipped.includes("plan-exec.batch-commit-proposal"))
776
+ return true;
777
+ const acquired = state.applied.filter((transition) => transition === "plan-exec.unit-acquisition").length;
778
+ return (state.batches ?? []).some((batch) => (batch.published_plan_digest !== undefined && batch.commit_result === undefined) ||
779
+ (batch.iteration === state.batch_loop?.iteration &&
780
+ batch.snapshot === undefined &&
781
+ acquired >= batch.iteration));
782
+ }
783
+ /** Record only the current iteration's review, never borrowing one from a prior batch. */
784
+ export function withPlanExecBatchReview(state, review) {
785
+ return sealRunState({
786
+ ...withoutSeal(state),
787
+ batches: (state.batches ?? []).map((batch) => batch.iteration === state.batch_loop?.iteration ? { ...batch, review } : batch),
712
788
  });
713
789
  }
790
+ /** A legacy close may have passed the old untyped review. Insert a fresh, answerable copy. */
791
+ export function withPendingBatchReview(state) {
792
+ const review = "plan-exec.review-findings";
793
+ if (state.flow !== "plan-exec" || state.boundary !== "plan-exec.batch-close")
794
+ return state;
795
+ const batch = (state.batches ?? []).find((entry) => entry.published_plan_digest === undefined);
796
+ if (batch === undefined || batch.review !== undefined)
797
+ return state;
798
+ return withBoundary(withReentry(state, {
799
+ kind: "review",
800
+ transition: "plan-exec.batch-close",
801
+ from: review,
802
+ occurrence: state.applied.filter((id) => id === "plan-exec.batch-close").length + 1,
803
+ }), review);
804
+ }
714
805
  /** Record one inferred or declared batch, refusing duplicate ids at the caller's boundary. */
715
806
  export function withPlanExecBatch(state, batch) {
716
807
  const batches = state.batches ?? [];
@@ -774,6 +865,7 @@ const PLAN_EXEC_BATCH_STAGE_BY_TRANSITION = {
774
865
  "plan-exec.deviation-recognition": "deviation",
775
866
  "plan-exec.validation-execution": "validating",
776
867
  "plan-exec.review-findings": "reviewing",
868
+ "plan-exec.batch-commit": "batch-committing",
777
869
  // These only occur after the final batch publication. They therefore extend
778
870
  // the last closed batch's trace instead of fabricating a new one for Git/done.
779
871
  "plan-exec.final-validation": "validating",
@@ -849,6 +941,9 @@ export const PLAN_EXEC_BATCH_LOOP_TRANSITIONS = new Set([
849
941
  "plan-exec.validation-execution",
850
942
  "plan-exec.deferred-check",
851
943
  "plan-exec.review-findings",
944
+ "plan-exec.batch-commit-proposal",
945
+ "plan-exec.batch-commit-authorization",
946
+ "plan-exec.batch-commit",
852
947
  "plan-exec.batch-close",
853
948
  ]);
854
949
  /** Seal the plan bytes the batch publication actually produced. */
@@ -894,6 +989,33 @@ export function withPlanExecBatchPublicationPrepared(state, batchId, publication
894
989
  export function withHandoff(state, handoff) {
895
990
  return sealRunState({ ...withoutSeal(state), handoff });
896
991
  }
992
+ export function withPlanExecEntry(state, entry) {
993
+ return sealRunState({ ...withoutSeal(state), plan_exec_entry: entry });
994
+ }
995
+ export function withDecisionDate(state, date) {
996
+ return state.decision_date === date
997
+ ? state
998
+ : sealRunState({ ...withoutSeal(state), decision_date: date });
999
+ }
1000
+ /** Both the human exit and the structural rule deliver the same recoverable destination. */
1001
+ export function planRefineHandoff(state, decisions, selection) {
1002
+ const plan = state.scope?.plan ?? state.plan_exec_entry?.plan ?? null;
1003
+ const packageBody = {
1004
+ plan,
1005
+ observations: state.observations.filter((observation) => observation.transition.startsWith("plan-exec.entry-") ||
1006
+ observation.transition.startsWith("plan-exec.deviation-")),
1007
+ decisions: plan === null
1008
+ ? { ...decisions, recovery: "nombrá el plan que debe refinar /w:plan-refine <plan>" }
1009
+ : decisions,
1010
+ selection,
1011
+ };
1012
+ return {
1013
+ destination: "plan-refine",
1014
+ command: plan === null ? "/w:plan-refine <plan>" : `/w:plan-refine ${plan}`,
1015
+ package: packageBody,
1016
+ package_digest: semanticDigest(packageBody),
1017
+ };
1018
+ }
897
1019
  /** Persist the gate's executable consequence before the run leaves that boundary. */
898
1020
  export function withSelectedChoice(state, selected) {
899
1021
  return sealRunState({ ...withoutSeal(state), selected_choice: selected });
@@ -914,6 +1036,72 @@ export function withDecisionPreparation(state, preparation) {
914
1036
  export function withFixPreview(state, preview) {
915
1037
  return sealRunState({ ...withoutSeal(state), fix_preview: preview });
916
1038
  }
1039
+ export function withQuickCheckouts(state, checkouts) {
1040
+ if (checkouts === null && state.quick_checkouts === undefined)
1041
+ return state;
1042
+ return state.flow === "quick"
1043
+ ? sealRunState({ ...withoutSeal(state), quick_checkouts: checkouts })
1044
+ : state;
1045
+ }
1046
+ /** Remove a mistaken signal only before any of its consumers has used it. */
1047
+ export function retractSignal(state, journey, signal) {
1048
+ const producers = journey.filter((row) => row.signals?.includes(signal)).map((row) => row.id);
1049
+ const consumers = journey.filter((row) => {
1050
+ const rule = row.condition?.threshold;
1051
+ return (rule !== undefined &&
1052
+ producers.includes(rule.observed) &&
1053
+ (rule.of === undefined || rule.of.includes(signal)));
1054
+ });
1055
+ if (producers.length === 0 || consumers.length === 0) {
1056
+ return {
1057
+ ok: false,
1058
+ failure: {
1059
+ code: "FLOW_RETRACT_SIGNAL_UNKNOWN",
1060
+ message: `la señal '${signal}' no tiene un consumidor retirable en este recorrido`,
1061
+ action: "usá una señal declarada por el recorrido y consumida por una condición pendiente",
1062
+ },
1063
+ };
1064
+ }
1065
+ const removed = state.observations.filter((item) => item.signals.includes(signal) && sameIteration(item, iterationOf(state, item.transition)));
1066
+ if (removed.length === 0)
1067
+ return { ok: true, state };
1068
+ const consumed = consumers.find((row) => removed.some((observation) => signalWasConsumed(state, row, observation)));
1069
+ if (consumed !== undefined) {
1070
+ return {
1071
+ ok: false,
1072
+ failure: {
1073
+ code: "FLOW_RETRACT_ALREADY_CONSUMED",
1074
+ message: `'${consumed.id}' ya aplicó o dejó una ejecución sin resolver; no se retira '${signal}'`,
1075
+ action: "conservá la señal: retirar no revierte decisiones ni efectos ya ejercidos",
1076
+ },
1077
+ };
1078
+ }
1079
+ const updated = sealRunState({
1080
+ ...withoutSeal(state),
1081
+ observations: state.observations.map((item) => removed.includes(item)
1082
+ ? { ...item, signals: item.signals.filter((value) => value !== signal) }
1083
+ : item),
1084
+ });
1085
+ return {
1086
+ ok: true,
1087
+ state: withEvent(updated, {
1088
+ kind: "retracted",
1089
+ transition: state.boundary ?? producers[0] ?? "",
1090
+ ...iterationOf(state, state.boundary ?? producers[0] ?? ""),
1091
+ operation: "flow.retract",
1092
+ signal,
1093
+ observations: removed,
1094
+ }),
1095
+ };
1096
+ }
1097
+ function signalWasConsumed(state, consumer, observation) {
1098
+ if (consumer.condition?.threshold.observed !== observation.transition)
1099
+ return false;
1100
+ // Only a consumer after THIS producer occurrence can have consumed its signal.
1101
+ const producer = state.applied.lastIndexOf(observation.transition);
1102
+ const consumed = state.applied.slice(producer + 1).includes(consumer.id);
1103
+ return consumed || recoveryBlockedAt(state, consumer.id, observation) !== null;
1104
+ }
917
1105
  /**
918
1106
  * Record what the closure owes — written once, when the batch loop ends.
919
1107
  *
@@ -1433,8 +1621,44 @@ function checkCommonRecordShape(parsed, invalid) {
1433
1621
  if (!isInheritedBaseArray(parsed.inherited_bases)) {
1434
1622
  return invalid("hereda una base de batch sin sus fases o sin sus fuentes");
1435
1623
  }
1624
+ if (!isPlanExecEntry(parsed.plan_exec_entry)) {
1625
+ return invalid("declara una entrada de plan-exec sin plan o con fases inválidas");
1626
+ }
1627
+ if (parsed.decision_date !== undefined &&
1628
+ (typeof parsed.decision_date !== "string" || !/^\d{4}-\d{2}-\d{2}$/.test(parsed.decision_date))) {
1629
+ return invalid("declara una fecha de decisión inválida");
1630
+ }
1436
1631
  return null;
1437
1632
  }
1633
+ function isPlanExecEntry(value) {
1634
+ if (value === undefined)
1635
+ return true;
1636
+ if (!isRecord(value) || !(value.plan === null || isNonEmptyString(value.plan)))
1637
+ return false;
1638
+ if (value.sources !== undefined &&
1639
+ (value.plan === null || !Array.isArray(value.sources) || !value.sources.every(isNonEmptyString)))
1640
+ return false;
1641
+ if (value.grammar_failure !== undefined &&
1642
+ (!isRecord(value.grammar_failure) ||
1643
+ !isNonEmptyString(value.grammar_failure.code) ||
1644
+ !isNonEmptyString(value.grammar_failure.message) ||
1645
+ !isNonEmptyString(value.grammar_failure.action)))
1646
+ return false;
1647
+ const phases = value.phases_without_open_tasks;
1648
+ const approval = value.approved_without_changes;
1649
+ if (approval !== undefined &&
1650
+ (value.plan === null ||
1651
+ !Array.isArray(phases) ||
1652
+ !Array.isArray(approval) ||
1653
+ approval.length === 0 ||
1654
+ new Set(approval).size !== approval.length ||
1655
+ !approval.every((phase) => phases.includes(phase))))
1656
+ return false;
1657
+ return (phases === null ||
1658
+ (Array.isArray(phases) &&
1659
+ phases.every((phase) => Number.isInteger(phase) && phase > 0) &&
1660
+ new Set(phases).size === phases.length));
1661
+ }
1438
1662
  function isInheritedBaseArray(value) {
1439
1663
  if (value === undefined)
1440
1664
  return true;
@@ -1499,7 +1723,7 @@ function checkV10RecordShape(parsed, invalid) {
1499
1723
  if (!isDecisionPreparation(parsed.decision_preparation)) {
1500
1724
  return invalid("declara una vista de decisión sin nota, preview o linaje sellados");
1501
1725
  }
1502
- if (!isFixPreview(parsed.fix_preview)) {
1726
+ if (!isFixPreview(parsed.fix_preview) || !isQuickCheckouts(parsed.quick_checkouts)) {
1503
1727
  return invalid("declara un preview de arreglo sin archivos, intención o forma del diff");
1504
1728
  }
1505
1729
  if (!isSettlement(parsed.settlement)) {
@@ -1636,6 +1860,17 @@ function isScope(value) {
1636
1860
  return false;
1637
1861
  if (!isStringArray(value.sources) || value.sources.length === 0)
1638
1862
  return false;
1863
+ if (value.isolation !== undefined && value.isolation !== "unit" && value.isolation !== "in-place")
1864
+ return false;
1865
+ if (value.final_validation !== undefined &&
1866
+ (!Array.isArray(value.final_validation) ||
1867
+ !value.final_validation.every((entry) => isRecord(entry) &&
1868
+ typeof entry.alias === "string" &&
1869
+ [entry.build, entry.test].every((item) => isRecord(item) &&
1870
+ (item.command === null || typeof item.command === "string") &&
1871
+ (item.origin === null || item.origin === "plan" || item.origin === "source") &&
1872
+ (item.action === undefined || typeof item.action === "string")))))
1873
+ return false;
1639
1874
  return value.sources.every((alias) => alias.trim().length > 0);
1640
1875
  }
1641
1876
  function isPlanExecBatchArray(value) {
@@ -1658,7 +1893,11 @@ function isPlanExecBatchArray(value) {
1658
1893
  entry.phases.length === 0 ||
1659
1894
  !entry.phases.every((phase) => typeof phase === "number" && Number.isInteger(phase) && phase > 0) ||
1660
1895
  !isStringArray(entry.tasks) ||
1661
- entry.tasks.length === 0 ||
1896
+ (entry.validation_only !== undefined && typeof entry.validation_only !== "boolean") ||
1897
+ (entry.validation_only === true && entry.tasks.length !== 0) ||
1898
+ (entry.validation_only === false && entry.kind === "validation-only") ||
1899
+ (entry.kind === "validation-only" ? entry.tasks.length !== 0 : entry.tasks.length === 0) ||
1900
+ (entry.kind !== undefined && entry.kind !== "validation-only") ||
1662
1901
  new Set(entry.tasks).size !== entry.tasks.length ||
1663
1902
  typeof entry.plan_digest !== "string" ||
1664
1903
  entry.plan_digest.length === 0 ||
@@ -1671,7 +1910,14 @@ function isPlanExecBatchArray(value) {
1671
1910
  entry.published_plan_digest !== entry.publication.after_plan_digest) ||
1672
1911
  !PLAN_EXEC_BATCH_STAGES.includes(entry.stage) ||
1673
1912
  !isSourceMap(entry.base, true) ||
1674
- !isSourceMap(entry.credit, false)) {
1913
+ !isSourceMap(entry.credit, false) ||
1914
+ !isBatchPartition(entry.partition, entry.phases, entry.mode) ||
1915
+ !isBatchSnapshot(entry.snapshot) ||
1916
+ !isBatchCommitProposal(entry.commit_proposal) ||
1917
+ !isBatchCommitResult(entry.commit_result) ||
1918
+ (entry.credit_phases !== undefined &&
1919
+ (entry.credit === undefined || !samePhaseRange(entry.credit_phases, entry.phases))) ||
1920
+ (entry.review !== undefined && !isBatchReview(entry.review))) {
1675
1921
  return false;
1676
1922
  }
1677
1923
  ids.add(entry.id);
@@ -1679,6 +1925,67 @@ function isPlanExecBatchArray(value) {
1679
1925
  return true;
1680
1926
  });
1681
1927
  }
1928
+ function isBatchSnapshot(value) {
1929
+ if (value === undefined)
1930
+ return true;
1931
+ return (isRecord(value) &&
1932
+ Object.values(value).every((entry) => isRecord(entry) &&
1933
+ isNonEmptyString(entry.head) &&
1934
+ isNonEmptyString(entry.branch) &&
1935
+ Array.isArray(entry.dirty) &&
1936
+ entry.dirty.every((path) => isRecord(path) && isNonEmptyString(path.path) && isNonEmptyString(path.digest))));
1937
+ }
1938
+ function isBatchCommitProposal(value) {
1939
+ if (value === undefined)
1940
+ return true;
1941
+ return (isRecord(value) &&
1942
+ isNonEmptyString(value.digest) &&
1943
+ (value.approved_digest === undefined || isNonEmptyString(value.approved_digest)) &&
1944
+ Array.isArray(value.sources) &&
1945
+ value.sources.every((item) => isRecord(item) &&
1946
+ isNonEmptyString(item.alias) &&
1947
+ isNonEmptyString(item.message) &&
1948
+ isStringArray(item.paths) &&
1949
+ (item.foreign_paths === undefined || isStringArray(item.foreign_paths)) &&
1950
+ item.paths.length > 0 &&
1951
+ Array.isArray(item.dirty) &&
1952
+ item.dirty.length === item.paths.length &&
1953
+ item.dirty.every((path) => isRecord(path) && isNonEmptyString(path.path) && isNonEmptyString(path.digest))));
1954
+ }
1955
+ function isBatchCommitResult(value) {
1956
+ if (value === undefined)
1957
+ return true;
1958
+ return (isRecord(value) &&
1959
+ Object.values(value).every((receipt) => isRecord(receipt) &&
1960
+ isNonEmptyString(receipt.after) &&
1961
+ (receipt.before === null || isNonEmptyString(receipt.before)) &&
1962
+ (receipt.branch === null || isNonEmptyString(receipt.branch)) &&
1963
+ isStringArray(receipt.parents)));
1964
+ }
1965
+ function samePhaseRange(value, phases) {
1966
+ return (Array.isArray(value) &&
1967
+ value.length === phases.length &&
1968
+ value.every((phase, index) => phase === phases[index]));
1969
+ }
1970
+ function isBatchPartition(value, phases, mode) {
1971
+ if (value === undefined)
1972
+ return true;
1973
+ if (!isRecord(value) ||
1974
+ !isNonEmptyString(value.reason) ||
1975
+ !isRecord(value.effective) ||
1976
+ value.effective.mode !== mode ||
1977
+ !samePhaseRange(value.effective.phases, phases))
1978
+ return false;
1979
+ return (value.declared === null ||
1980
+ (Array.isArray(value.declared) &&
1981
+ value.declared.length > 0 &&
1982
+ value.declared.every((row) => isRecord(row) &&
1983
+ isNonEmptyString(row.id) &&
1984
+ (row.mode === "continuous" || row.mode === "isolated") &&
1985
+ Array.isArray(row.phases) &&
1986
+ row.phases.length > 0 &&
1987
+ row.phases.every((phase) => Number.isSafeInteger(phase) && phase > 0))));
1988
+ }
1682
1989
  /** Absent, or a non-empty alias → digest map; `nullable` admits an unobserved source. */
1683
1990
  function isSourceMap(value, nullable) {
1684
1991
  if (value === undefined)
@@ -1724,6 +2031,7 @@ function isPlanExecBatchTraceArray(value, batches) {
1724
2031
  typeof entry.iteration === "number" &&
1725
2032
  Number.isInteger(entry.iteration) &&
1726
2033
  typeof entry.transition === "string" &&
2034
+ (entry.approval === undefined || entry.approval === true) &&
1727
2035
  entry.transition.length > 0 &&
1728
2036
  PLAN_EXEC_BATCH_STAGES.includes(entry.stage) &&
1729
2037
  (entry.kind === "entered" || entry.kind === "completed" || entry.kind === "blocked"));
@@ -1881,7 +2189,13 @@ function isFixPreview(value) {
1881
2189
  return (typeof value.intent === "string" &&
1882
2190
  value.intent.trim().length > 0 &&
1883
2191
  typeof value.diff === "string" &&
1884
- value.diff.trim().length > 0);
2192
+ value.diff.trim().length > 0 &&
2193
+ isQuickCheckouts(value.checkouts));
2194
+ }
2195
+ function isQuickCheckouts(value) {
2196
+ return (value === null ||
2197
+ value === undefined ||
2198
+ (isRecord(value) && Object.values(value).every(nonEmpty)));
1885
2199
  }
1886
2200
  function isDecisionPreview(value, baseline) {
1887
2201
  if (!isRecord(value) ||
@@ -2015,6 +2329,9 @@ const EVENT_BODIES = new Map(Object.entries({
2015
2329
  isEffectClassArray(entry.effects) &&
2016
2330
  isStringArray(entry.evidence),
2017
2331
  reconciled: (entry) => isRepairArray(entry.repairs),
2332
+ retracted: (entry) => nonEmpty(entry.signal) &&
2333
+ isObservationArray(entry.observations) &&
2334
+ entry.observations.length > 0,
2018
2335
  restarted: (entry) => nonEmpty(entry.archive) && nonEmpty(entry.cause),
2019
2336
  annulled: (entry) => isStringArray(entry.batches) &&
2020
2337
  entry.batches.length > 0 &&
@@ -2051,7 +2368,7 @@ function isObservationArray(value) {
2051
2368
  isStringArray(entry.signals) &&
2052
2369
  isIterationRecord(entry));
2053
2370
  }
2054
- const REENTRY_KINDS = ["refine", "close", "reopen"];
2371
+ const REENTRY_KINDS = ["refine", "close", "reopen", "review", "reinfer"];
2055
2372
  /** Absent, or reentries each with its kind, its boundary, its occurrence and its origin. */
2056
2373
  function isReentryArray(value) {
2057
2374
  if (value === undefined)
@@ -2060,6 +2377,17 @@ function isReentryArray(value) {
2060
2377
  return false;
2061
2378
  return value.every((entry) => isRecord(entry) &&
2062
2379
  REENTRY_KINDS.includes(entry.kind) &&
2380
+ (entry.kind !== "review" ||
2381
+ (entry.transition === "plan-exec.batch-close" &&
2382
+ entry.from === "plan-exec.review-findings")) &&
2383
+ (entry.kind !== "reinfer" ||
2384
+ (entry.from === "plan-exec.validation-execution" &&
2385
+ [
2386
+ "plan-exec.deferred-check",
2387
+ "plan-exec.review-findings",
2388
+ "plan-exec.batch-commit-proposal",
2389
+ "plan-exec.batch-close",
2390
+ ].includes(entry.transition))) &&
2063
2391
  nonEmpty(entry.transition) &&
2064
2392
  Number.isInteger(entry.occurrence) &&
2065
2393
  entry.occurrence >= 1 &&