@tacuchi/agent-workflow-cli 25.7.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 (580) hide show
  1. package/CHANGELOG.md +110 -0
  2. package/README.md +5 -1
  3. package/dist/adapters/git-cli.js +311 -24
  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/capability/readiness.js +26 -10
  18. package/dist/application/capability/readiness.js.map +1 -1
  19. package/dist/application/capability/wrapper.js +10 -3
  20. package/dist/application/capability/wrapper.js.map +1 -1
  21. package/dist/application/check-branch-service.js +158 -19
  22. package/dist/application/check-branch-service.js.map +1 -1
  23. package/dist/application/checkpoint/markdown.js +2 -2
  24. package/dist/application/checkpoint/markdown.js.map +1 -1
  25. package/dist/application/checkpoint/state-reader.js +12 -0
  26. package/dist/application/checkpoint/state-reader.js.map +1 -1
  27. package/dist/application/checkpoint-service.js +12 -4
  28. package/dist/application/checkpoint-service.js.map +1 -1
  29. package/dist/application/checkpoint-write-service.js +91 -17
  30. package/dist/application/checkpoint-write-service.js.map +1 -1
  31. package/dist/application/claims-ledger.js +137 -11
  32. package/dist/application/claims-ledger.js.map +1 -1
  33. package/dist/application/claims-recovery.js +85 -44
  34. package/dist/application/claims-recovery.js.map +1 -1
  35. package/dist/application/database-tool-catalog.js +33 -0
  36. package/dist/application/database-tool-catalog.js.map +1 -1
  37. package/dist/application/design/consumer-document.js +2 -2
  38. package/dist/application/design/consumer-document.js.map +1 -1
  39. package/dist/application/design/design-content-gate-service.js +20 -2
  40. package/dist/application/design/design-content-gate-service.js.map +1 -1
  41. package/dist/application/design/design-gate-service.js +2 -0
  42. package/dist/application/design/design-gate-service.js.map +1 -1
  43. package/dist/application/design/design-index-service.js +4 -0
  44. package/dist/application/design/design-index-service.js.map +1 -1
  45. package/dist/application/design/design-publish-service.js +1 -4
  46. package/dist/application/design/design-publish-service.js.map +1 -1
  47. package/dist/application/design/design-record-service.js +13 -7
  48. package/dist/application/design/design-record-service.js.map +1 -1
  49. package/dist/application/design/design-resolver-service.js +22 -3
  50. package/dist/application/design/design-resolver-service.js.map +1 -1
  51. package/dist/application/design/design-simple-service.js +24 -5
  52. package/dist/application/design/design-simple-service.js.map +1 -1
  53. package/dist/application/design/digest.js +41 -0
  54. package/dist/application/design/digest.js.map +1 -0
  55. package/dist/application/dev-only-services.js +171 -27
  56. package/dist/application/dev-only-services.js.map +1 -1
  57. package/dist/application/doc-branch-ledger.js +145 -0
  58. package/dist/application/doc-branch-ledger.js.map +1 -0
  59. package/dist/application/docs-canon-service.js +1 -1
  60. package/dist/application/docs-canon-service.js.map +1 -1
  61. package/dist/application/doctor/dist-integrity.js +113 -0
  62. package/dist/application/doctor/dist-integrity.js.map +1 -0
  63. package/dist/application/doctor/hosts.js +5 -2
  64. package/dist/application/doctor/hosts.js.map +1 -1
  65. package/dist/application/doctor/prepare.js +4 -1
  66. package/dist/application/doctor/prepare.js.map +1 -1
  67. package/dist/application/doctor/provider-installation.js +39 -19
  68. package/dist/application/doctor/provider-installation.js.map +1 -1
  69. package/dist/application/doctor/provider-mcps.js +10 -2
  70. package/dist/application/doctor/provider-mcps.js.map +1 -1
  71. package/dist/application/doctor/provider-skills.js +25 -0
  72. package/dist/application/doctor/provider-skills.js.map +1 -1
  73. package/dist/application/doctor/provider-visibility.js +76 -3
  74. package/dist/application/doctor/provider-visibility.js.map +1 -1
  75. package/dist/application/doctor/provider-workspace-block.js +156 -0
  76. package/dist/application/doctor/provider-workspace-block.js.map +1 -0
  77. package/dist/application/doctor/repair-runner.js +47 -3
  78. package/dist/application/doctor/repair-runner.js.map +1 -1
  79. package/dist/application/doctor/report.js +24 -4
  80. package/dist/application/doctor/report.js.map +1 -1
  81. package/dist/application/doctor/skills-toml-migrate.js +76 -0
  82. package/dist/application/doctor/skills-toml-migrate.js.map +1 -0
  83. package/dist/application/export-catalog-check.js +200 -0
  84. package/dist/application/export-catalog-check.js.map +1 -0
  85. package/dist/application/export-service.js +716 -79
  86. package/dist/application/export-service.js.map +1 -1
  87. package/dist/application/fix-git-service.js +285 -64
  88. package/dist/application/fix-git-service.js.map +1 -1
  89. package/dist/application/flow/advance.js +241 -30
  90. package/dist/application/flow/advance.js.map +1 -1
  91. package/dist/application/flow/annul-service.js +3 -1
  92. package/dist/application/flow/annul-service.js.map +1 -1
  93. package/dist/application/flow/batch-commit.js +189 -0
  94. package/dist/application/flow/batch-commit.js.map +1 -0
  95. package/dist/application/flow/checkout-observation.js +110 -8
  96. package/dist/application/flow/checkout-observation.js.map +1 -1
  97. package/dist/application/flow/close-artifacts.js +105 -0
  98. package/dist/application/flow/close-artifacts.js.map +1 -0
  99. package/dist/application/flow/close-at-boundary.js +155 -0
  100. package/dist/application/flow/close-at-boundary.js.map +1 -0
  101. package/dist/application/flow/close-document-guidance.js +70 -0
  102. package/dist/application/flow/close-document-guidance.js.map +1 -0
  103. package/dist/application/flow/flow-service.js +49 -5
  104. package/dist/application/flow/flow-service.js.map +1 -1
  105. package/dist/application/flow/internal-actions.js +361 -80
  106. package/dist/application/flow/internal-actions.js.map +1 -1
  107. package/dist/application/flow/internal-drive.js +47 -19
  108. package/dist/application/flow/internal-drive.js.map +1 -1
  109. package/dist/application/flow/plan-entry.js +82 -0
  110. package/dist/application/flow/plan-entry.js.map +1 -0
  111. package/dist/application/flow/prove.js +32 -1
  112. package/dist/application/flow/prove.js.map +1 -1
  113. package/dist/application/flow/quick-checkouts.js +48 -0
  114. package/dist/application/flow/quick-checkouts.js.map +1 -0
  115. package/dist/application/flow/reinfer-batch.js +177 -0
  116. package/dist/application/flow/reinfer-batch.js.map +1 -0
  117. package/dist/application/flow/reopen-run.js +159 -0
  118. package/dist/application/flow/reopen-run.js.map +1 -0
  119. package/dist/application/flow/run-journey.js +11 -8
  120. package/dist/application/flow/run-journey.js.map +1 -1
  121. package/dist/application/flow/run-projection.js +16 -5
  122. package/dist/application/flow/run-projection.js.map +1 -1
  123. package/dist/application/flow/run-state-service.js +3 -1
  124. package/dist/application/flow/run-state-service.js.map +1 -1
  125. package/dist/application/flow/submit.js +731 -154
  126. package/dist/application/flow/submit.js.map +1 -1
  127. package/dist/application/generate-launch-service.js +16 -6
  128. package/dist/application/generate-launch-service.js.map +1 -1
  129. package/dist/application/git-flow-service.js +34 -3
  130. package/dist/application/git-flow-service.js.map +1 -1
  131. package/dist/application/history-publications.js +24 -0
  132. package/dist/application/history-publications.js.map +1 -1
  133. package/dist/application/history-reconcile-service.js +45 -0
  134. package/dist/application/history-reconcile-service.js.map +1 -0
  135. package/dist/application/history-table.js +61 -12
  136. package/dist/application/history-table.js.map +1 -1
  137. package/dist/application/history-update-service.js +25 -4
  138. package/dist/application/history-update-service.js.map +1 -1
  139. package/dist/application/hook-branch-check.js +25 -3
  140. package/dist/application/hook-branch-check.js.map +1 -1
  141. package/dist/application/hook-git-commit-advisor.js +3 -4
  142. package/dist/application/hook-git-commit-advisor.js.map +1 -1
  143. package/dist/application/hook-sql-mutation-guard.js +147 -12
  144. package/dist/application/hook-sql-mutation-guard.js.map +1 -1
  145. package/dist/application/hook-turn-start.js +51 -0
  146. package/dist/application/hook-turn-start.js.map +1 -0
  147. package/dist/application/host-memory/codex.js +1 -1
  148. package/dist/application/host-memory/codex.js.map +1 -1
  149. package/dist/application/hub-registry.js +135 -0
  150. package/dist/application/hub-registry.js.map +1 -0
  151. package/dist/application/local-proposal.js +72 -19
  152. package/dist/application/local-proposal.js.map +1 -1
  153. package/dist/application/mcp-host-reader.js +1 -1
  154. package/dist/application/mcp-host-reader.js.map +1 -1
  155. package/dist/application/mcp-host-writer.js +16 -10
  156. package/dist/application/mcp-host-writer.js.map +1 -1
  157. package/dist/application/merge-state-service.js +150 -34
  158. package/dist/application/merge-state-service.js.map +1 -1
  159. package/dist/application/multiroot/claude.js +17 -10
  160. package/dist/application/multiroot/claude.js.map +1 -1
  161. package/dist/application/multiroot/codex.js +17 -11
  162. package/dist/application/multiroot/codex.js.map +1 -1
  163. package/dist/application/multiroot-service.js +52 -28
  164. package/dist/application/multiroot-service.js.map +1 -1
  165. package/dist/application/parsers/execution-batches.js +64 -0
  166. package/dist/application/parsers/execution-batches.js.map +1 -0
  167. package/dist/application/parsers/phases.js +23 -2
  168. package/dist/application/parsers/phases.js.map +1 -1
  169. package/dist/application/parsers/project-block.js +146 -17
  170. package/dist/application/parsers/project-block.js.map +1 -1
  171. package/dist/application/parsers/tasks.js +16 -2
  172. package/dist/application/parsers/tasks.js.map +1 -1
  173. package/dist/application/parsers/toml.js +19 -0
  174. package/dist/application/parsers/toml.js.map +1 -0
  175. package/dist/application/paths-service.js +13 -16
  176. package/dist/application/paths-service.js.map +1 -1
  177. package/dist/application/persist-service.js +118 -5
  178. package/dist/application/persist-service.js.map +1 -1
  179. package/dist/application/plan-exec-batch-service.js +162 -22
  180. package/dist/application/plan-exec-batch-service.js.map +1 -1
  181. package/dist/application/plan-exec-decision-service.js +61 -12
  182. package/dist/application/plan-exec-decision-service.js.map +1 -1
  183. package/dist/application/plan-exec-plan-diff.js +105 -0
  184. package/dist/application/plan-exec-plan-diff.js.map +1 -0
  185. package/dist/application/plan-lint-service.js +2 -0
  186. package/dist/application/plan-lint-service.js.map +1 -1
  187. package/dist/application/plan-passes.js +41 -0
  188. package/dist/application/plan-passes.js.map +1 -0
  189. package/dist/application/preparation-receipts.js +58 -0
  190. package/dist/application/preparation-receipts.js.map +1 -0
  191. package/dist/application/project-md-upsert-service.js +191 -52
  192. package/dist/application/project-md-upsert-service.js.map +1 -1
  193. package/dist/application/project-tab-data.js +40 -10
  194. package/dist/application/project-tab-data.js.map +1 -1
  195. package/dist/application/release-data/artifacts.js +15 -7
  196. package/dist/application/release-data/artifacts.js.map +1 -1
  197. package/dist/application/release-data/bundles.js +52 -6
  198. package/dist/application/release-data/bundles.js.map +1 -1
  199. package/dist/application/release-data/common.js +2 -2
  200. package/dist/application/release-data/common.js.map +1 -1
  201. package/dist/application/release-data/rollback.js +7 -0
  202. package/dist/application/release-data/rollback.js.map +1 -0
  203. package/dist/application/release-data/sessions.js +2 -2
  204. package/dist/application/release-data/sessions.js.map +1 -1
  205. package/dist/application/release-pass-ledger.js +1 -1
  206. package/dist/application/render/history-row.js +2 -0
  207. package/dist/application/render/history-row.js.map +1 -1
  208. package/dist/application/render/project-block.js +28 -11
  209. package/dist/application/render/project-block.js.map +1 -1
  210. package/dist/application/reseal-service.js +1 -0
  211. package/dist/application/reseal-service.js.map +1 -1
  212. package/dist/application/resume-service.js +55 -8
  213. package/dist/application/resume-service.js.map +1 -1
  214. package/dist/application/retirement/apply.js +25 -7
  215. package/dist/application/retirement/apply.js.map +1 -1
  216. package/dist/application/retirement/attribution.js +121 -48
  217. package/dist/application/retirement/attribution.js.map +1 -1
  218. package/dist/application/retirement/prepare.js +17 -11
  219. package/dist/application/retirement/prepare.js.map +1 -1
  220. package/dist/application/retirement/preview.js +2 -1
  221. package/dist/application/retirement/preview.js.map +1 -1
  222. package/dist/application/self/codex-plugin.js +1 -1
  223. package/dist/application/self/codex-plugin.js.map +1 -1
  224. package/dist/application/self/host-states.js +3 -3
  225. package/dist/application/self/host-states.js.map +1 -1
  226. package/dist/application/self/install-hooks.js +1 -1
  227. package/dist/application/self/install-hooks.js.map +1 -1
  228. package/dist/application/self/install-skill.js +35 -11
  229. package/dist/application/self/install-skill.js.map +1 -1
  230. package/dist/application/self/install-targets.js +73 -2
  231. package/dist/application/self/install-targets.js.map +1 -1
  232. package/dist/application/self/mcp-config.js +19 -11
  233. package/dist/application/self/mcp-config.js.map +1 -1
  234. package/dist/application/self/opencode-plugin.js +1 -0
  235. package/dist/application/self/opencode-plugin.js.map +1 -1
  236. package/dist/application/self/uninstall.js +22 -8
  237. package/dist/application/self/uninstall.js.map +1 -1
  238. package/dist/application/semantic-operation/protocol.js +66 -5
  239. package/dist/application/semantic-operation/protocol.js.map +1 -1
  240. package/dist/application/session-archive-service.js +113 -0
  241. package/dist/application/session-archive-service.js.map +1 -0
  242. package/dist/application/session-binding-service.js +35 -0
  243. package/dist/application/session-binding-service.js.map +1 -1
  244. package/dist/application/session-close-service.js +390 -54
  245. package/dist/application/session-close-service.js.map +1 -1
  246. package/dist/application/session-create-service.js +97 -5
  247. package/dist/application/session-create-service.js.map +1 -1
  248. package/dist/application/session-custody-recorder.js +15 -12
  249. package/dist/application/session-custody-recorder.js.map +1 -1
  250. package/dist/application/session-custody-service.js +1 -0
  251. package/dist/application/session-custody-service.js.map +1 -1
  252. package/dist/application/session-narrative.js +51 -12
  253. package/dist/application/session-narrative.js.map +1 -1
  254. package/dist/application/session-pause-service.js +46 -0
  255. package/dist/application/session-pause-service.js.map +1 -0
  256. package/dist/application/session-resolver.js +36 -11
  257. package/dist/application/session-resolver.js.map +1 -1
  258. package/dist/application/session-resume-service.js +190 -20
  259. package/dist/application/session-resume-service.js.map +1 -1
  260. package/dist/application/sessions-service.js +4 -0
  261. package/dist/application/sessions-service.js.map +1 -1
  262. package/dist/application/sessions-sweep-service.js +77 -0
  263. package/dist/application/sessions-sweep-service.js.map +1 -0
  264. package/dist/application/settle-service.js +3 -1
  265. package/dist/application/settle-service.js.map +1 -1
  266. package/dist/application/skills-resolver-service.js +1 -1
  267. package/dist/application/skills-resolver-service.js.map +1 -1
  268. package/dist/application/source-add-service.js +37 -0
  269. package/dist/application/source-add-service.js.map +1 -0
  270. package/dist/application/source-boundary-policy.js +97 -8
  271. package/dist/application/source-boundary-policy.js.map +1 -1
  272. package/dist/application/source-pipeline.js +68 -0
  273. package/dist/application/source-pipeline.js.map +1 -0
  274. package/dist/application/source-remove-service.js +15 -3
  275. package/dist/application/source-remove-service.js.map +1 -1
  276. package/dist/application/sources-service.js +71 -16
  277. package/dist/application/sources-service.js.map +1 -1
  278. package/dist/application/status-service.js +55 -5
  279. package/dist/application/status-service.js.map +1 -1
  280. package/dist/application/unit-dependencies.js +100 -0
  281. package/dist/application/unit-dependencies.js.map +1 -0
  282. package/dist/application/unit-membership.js +37 -0
  283. package/dist/application/unit-membership.js.map +1 -0
  284. package/dist/application/unit-residue.js +72 -0
  285. package/dist/application/unit-residue.js.map +1 -0
  286. package/dist/application/visibility-doctor-service.js +66 -4
  287. package/dist/application/visibility-doctor-service.js.map +1 -1
  288. package/dist/application/working-branch-service.js +6 -0
  289. package/dist/application/working-branch-service.js.map +1 -1
  290. package/dist/application/workline-graph.js +1 -1
  291. package/dist/application/workline-graph.js.map +1 -1
  292. package/dist/application/workline-index-service.js +118 -17
  293. package/dist/application/workline-index-service.js.map +1 -1
  294. package/dist/application/workspace-commit-service.js +218 -0
  295. package/dist/application/workspace-commit-service.js.map +1 -0
  296. package/dist/application/workspace-init-service.js +64 -34
  297. package/dist/application/workspace-init-service.js.map +1 -1
  298. package/dist/application/workspace-local-config.js +90 -0
  299. package/dist/application/workspace-local-config.js.map +1 -0
  300. package/dist/application/workspace-materialization-service.js +52 -3
  301. package/dist/application/workspace-materialization-service.js.map +1 -1
  302. package/dist/application/workspace-migrate/apply.js +525 -4
  303. package/dist/application/workspace-migrate/apply.js.map +1 -1
  304. package/dist/application/workspace-migrate/markers.js +9 -6
  305. package/dist/application/workspace-migrate/markers.js.map +1 -1
  306. package/dist/application/workspace-migrate/plan.js +97 -5
  307. package/dist/application/workspace-migrate/plan.js.map +1 -1
  308. package/dist/application/workspace-move-service.js +270 -0
  309. package/dist/application/workspace-move-service.js.map +1 -0
  310. package/dist/application/workspace-untrack-service.js +28 -0
  311. package/dist/application/workspace-untrack-service.js.map +1 -0
  312. package/dist/application/worktree-service.js +654 -105
  313. package/dist/application/worktree-service.js.map +1 -1
  314. package/dist/cli/ascii.js +86 -0
  315. package/dist/cli/ascii.js.map +1 -0
  316. package/dist/cli/commands/add-source.js +38 -0
  317. package/dist/cli/commands/add-source.js.map +1 -0
  318. package/dist/cli/commands/amend.js +14 -2
  319. package/dist/cli/commands/amend.js.map +1 -1
  320. package/dist/cli/commands/capability.js +26 -0
  321. package/dist/cli/commands/capability.js.map +1 -1
  322. package/dist/cli/commands/check-branch.js +1 -0
  323. package/dist/cli/commands/check-branch.js.map +1 -1
  324. package/dist/cli/commands/checkpoint-read.js +1 -0
  325. package/dist/cli/commands/checkpoint-read.js.map +1 -1
  326. package/dist/cli/commands/checkpoint-write.js +4 -1
  327. package/dist/cli/commands/checkpoint-write.js.map +1 -1
  328. package/dist/cli/commands/claims.js +1 -0
  329. package/dist/cli/commands/claims.js.map +1 -1
  330. package/dist/cli/commands/code-scan.js +1 -0
  331. package/dist/cli/commands/code-scan.js.map +1 -1
  332. package/dist/cli/commands/context-budget.js +1 -0
  333. package/dist/cli/commands/context-budget.js.map +1 -1
  334. package/dist/cli/commands/context-plan.js +1 -0
  335. package/dist/cli/commands/context-plan.js.map +1 -1
  336. package/dist/cli/commands/cut-intent.js +1 -0
  337. package/dist/cli/commands/cut-intent.js.map +1 -1
  338. package/dist/cli/commands/designs.js +15 -5
  339. package/dist/cli/commands/designs.js.map +1 -1
  340. package/dist/cli/commands/dev-only.js +22 -5
  341. package/dist/cli/commands/dev-only.js.map +1 -1
  342. package/dist/cli/commands/doc-branch.js +184 -0
  343. package/dist/cli/commands/doc-branch.js.map +1 -0
  344. package/dist/cli/commands/doctor.js +9 -0
  345. package/dist/cli/commands/doctor.js.map +1 -1
  346. package/dist/cli/commands/export.js +89 -16
  347. package/dist/cli/commands/export.js.map +1 -1
  348. package/dist/cli/commands/fix-git.js +89 -13
  349. package/dist/cli/commands/fix-git.js.map +1 -1
  350. package/dist/cli/commands/flow.js +129 -13
  351. package/dist/cli/commands/flow.js.map +1 -1
  352. package/dist/cli/commands/generate-launch.js +15 -2
  353. package/dist/cli/commands/generate-launch.js.map +1 -1
  354. package/dist/cli/commands/git-flow.js +1 -0
  355. package/dist/cli/commands/git-flow.js.map +1 -1
  356. package/dist/cli/commands/history-update.js +7 -9
  357. package/dist/cli/commands/history-update.js.map +1 -1
  358. package/dist/cli/commands/history.js +14 -0
  359. package/dist/cli/commands/history.js.map +1 -0
  360. package/dist/cli/commands/hook.js +26 -5
  361. package/dist/cli/commands/hook.js.map +1 -1
  362. package/dist/cli/commands/host-doctor.js +1 -0
  363. package/dist/cli/commands/host-doctor.js.map +1 -1
  364. package/dist/cli/commands/host-memory.js +2 -9
  365. package/dist/cli/commands/host-memory.js.map +1 -1
  366. package/dist/cli/commands/index.js +18 -1
  367. package/dist/cli/commands/index.js.map +1 -1
  368. package/dist/cli/commands/mcp.js +30 -4
  369. package/dist/cli/commands/mcp.js.map +1 -1
  370. package/dist/cli/commands/merge-state.js +3 -2
  371. package/dist/cli/commands/merge-state.js.map +1 -1
  372. package/dist/cli/commands/multiroot.js +16 -0
  373. package/dist/cli/commands/multiroot.js.map +1 -1
  374. package/dist/cli/commands/persist.js +7 -5
  375. package/dist/cli/commands/persist.js.map +1 -1
  376. package/dist/cli/commands/plan.js +1 -0
  377. package/dist/cli/commands/plan.js.map +1 -1
  378. package/dist/cli/commands/plugin-cache.js +4 -0
  379. package/dist/cli/commands/plugin-cache.js.map +1 -1
  380. package/dist/cli/commands/plugin-doctor.js +3 -0
  381. package/dist/cli/commands/plugin-doctor.js.map +1 -1
  382. package/dist/cli/commands/project-md-upsert.js +8 -3
  383. package/dist/cli/commands/project-md-upsert.js.map +1 -1
  384. package/dist/cli/commands/release-data.js +12 -0
  385. package/dist/cli/commands/release-data.js.map +1 -1
  386. package/dist/cli/commands/release-pass.js +13 -3
  387. package/dist/cli/commands/release-pass.js.map +1 -1
  388. package/dist/cli/commands/remove-source.js +1 -0
  389. package/dist/cli/commands/remove-source.js.map +1 -1
  390. package/dist/cli/commands/reseal.js +1 -0
  391. package/dist/cli/commands/reseal.js.map +1 -1
  392. package/dist/cli/commands/resume-summary.js +5 -0
  393. package/dist/cli/commands/resume-summary.js.map +1 -1
  394. package/dist/cli/commands/resume.js +13 -3
  395. package/dist/cli/commands/resume.js.map +1 -1
  396. package/dist/cli/commands/retirement.js +1 -0
  397. package/dist/cli/commands/retirement.js.map +1 -1
  398. package/dist/cli/commands/self.js +39 -1
  399. package/dist/cli/commands/self.js.map +1 -1
  400. package/dist/cli/commands/session-artifacts.js +1 -0
  401. package/dist/cli/commands/session-artifacts.js.map +1 -1
  402. package/dist/cli/commands/session-close.js +185 -31
  403. package/dist/cli/commands/session-close.js.map +1 -1
  404. package/dist/cli/commands/session-create.js +4 -1
  405. package/dist/cli/commands/session-create.js.map +1 -1
  406. package/dist/cli/commands/session-pause.js +14 -0
  407. package/dist/cli/commands/session-pause.js.map +1 -0
  408. package/dist/cli/commands/session-resume.js +1 -0
  409. package/dist/cli/commands/session-resume.js.map +1 -1
  410. package/dist/cli/commands/sessions.js +16 -2
  411. package/dist/cli/commands/sessions.js.map +1 -1
  412. package/dist/cli/commands/set-branch.js +29 -4
  413. package/dist/cli/commands/set-branch.js.map +1 -1
  414. package/dist/cli/commands/set-edit-mode.js +20 -0
  415. package/dist/cli/commands/set-edit-mode.js.map +1 -0
  416. package/dist/cli/commands/set-pipeline.js +35 -0
  417. package/dist/cli/commands/set-pipeline.js.map +1 -0
  418. package/dist/cli/commands/settle.js +1 -0
  419. package/dist/cli/commands/settle.js.map +1 -1
  420. package/dist/cli/commands/skill-index.js +1 -0
  421. package/dist/cli/commands/skill-index.js.map +1 -1
  422. package/dist/cli/commands/skills.js +1 -0
  423. package/dist/cli/commands/skills.js.map +1 -1
  424. package/dist/cli/commands/sources.js +5 -0
  425. package/dist/cli/commands/sources.js.map +1 -1
  426. package/dist/cli/commands/stack.js +1 -0
  427. package/dist/cli/commands/stack.js.map +1 -1
  428. package/dist/cli/commands/status.js +36 -2
  429. package/dist/cli/commands/status.js.map +1 -1
  430. package/dist/cli/commands/tool.js +5 -21
  431. package/dist/cli/commands/tool.js.map +1 -1
  432. package/dist/cli/commands/unknown-flags.js +68 -16
  433. package/dist/cli/commands/unknown-flags.js.map +1 -1
  434. package/dist/cli/commands/visibility.js +2 -0
  435. package/dist/cli/commands/visibility.js.map +1 -1
  436. package/dist/cli/commands/workspace-commit.js +62 -0
  437. package/dist/cli/commands/workspace-commit.js.map +1 -0
  438. package/dist/cli/commands/workspace-init.js +51 -2
  439. package/dist/cli/commands/workspace-init.js.map +1 -1
  440. package/dist/cli/commands/workspace-migrate.js +31 -14
  441. package/dist/cli/commands/workspace-migrate.js.map +1 -1
  442. package/dist/cli/commands/workspace-move.js +42 -0
  443. package/dist/cli/commands/workspace-move.js.map +1 -0
  444. package/dist/cli/commands/worktree.js +5 -4
  445. package/dist/cli/commands/worktree.js.map +1 -1
  446. package/dist/cli/context-id.js +6 -0
  447. package/dist/cli/context-id.js.map +1 -1
  448. package/dist/cli/full-cli.js +555 -0
  449. package/dist/cli/full-cli.js.map +1 -0
  450. package/dist/cli/help-groups.js +108 -14
  451. package/dist/cli/help-groups.js.map +1 -1
  452. package/dist/cli/hook-stdin-cache.js +12 -0
  453. package/dist/cli/hook-stdin-cache.js.map +1 -0
  454. package/dist/cli/main.js +47 -471
  455. package/dist/cli/main.js.map +1 -1
  456. package/dist/cli/output-mode.js +11 -2
  457. package/dist/cli/output-mode.js.map +1 -1
  458. package/dist/cli/parser.js +18 -5
  459. package/dist/cli/parser.js.map +1 -1
  460. package/dist/cli/registry.js.map +1 -1
  461. package/dist/cli/render.js +30 -1
  462. package/dist/cli/render.js.map +1 -1
  463. package/dist/cli/tui/app.js +1 -1
  464. package/dist/cli/tui/app.js.map +1 -1
  465. package/dist/cli/tui/components/workspace-init-form.js +4 -1
  466. package/dist/cli/tui/components/workspace-init-form.js.map +1 -1
  467. package/dist/cli/tui/data/recommended-skills.js +2 -2
  468. package/dist/cli/tui/data/recommended-skills.js.map +1 -1
  469. package/dist/cli/tui/data/workflow-content.js +6 -1
  470. package/dist/cli/tui/data/workflow-content.js.map +1 -1
  471. package/dist/cli/tui/tabs/mcp-tab.js +4 -3
  472. package/dist/cli/tui/tabs/mcp-tab.js.map +1 -1
  473. package/dist/cli/tui/tabs/project-tab.js +7 -2
  474. package/dist/cli/tui/tabs/project-tab.js.map +1 -1
  475. package/dist/dist-manifest.json +4117 -0
  476. package/dist/domain/capability/protocol.js.map +1 -1
  477. package/dist/domain/decision-note.js +13 -0
  478. package/dist/domain/decision-note.js.map +1 -1
  479. package/dist/domain/design/artifact.js +22 -3
  480. package/dist/domain/design/artifact.js.map +1 -1
  481. package/dist/domain/design/capability.js +1 -0
  482. package/dist/domain/design/capability.js.map +1 -1
  483. package/dist/domain/design/expansion.js +1 -1
  484. package/dist/domain/design/expansion.js.map +1 -1
  485. package/dist/domain/design/maturity.js +16 -0
  486. package/dist/domain/design/maturity.js.map +1 -1
  487. package/dist/domain/design/reference.js +5 -0
  488. package/dist/domain/design/reference.js.map +1 -1
  489. package/dist/domain/doctor/operations.js +28 -2
  490. package/dist/domain/doctor/operations.js.map +1 -1
  491. package/dist/domain/effective-contract.js +3 -1
  492. package/dist/domain/effective-contract.js.map +1 -1
  493. package/dist/domain/elicitation.js +1 -1
  494. package/dist/domain/flow/answer.js +273 -130
  495. package/dist/domain/flow/answer.js.map +1 -1
  496. package/dist/domain/flow/authority.js +330 -44
  497. package/dist/domain/flow/authority.js.map +1 -1
  498. package/dist/domain/flow/batch-review.js +65 -0
  499. package/dist/domain/flow/batch-review.js.map +1 -0
  500. package/dist/domain/flow/decision-schema.js +47 -0
  501. package/dist/domain/flow/decision-schema.js.map +1 -0
  502. package/dist/domain/flow/directive.js +16 -0
  503. package/dist/domain/flow/directive.js.map +1 -1
  504. package/dist/domain/flow/execution-result.js +169 -9
  505. package/dist/domain/flow/execution-result.js.map +1 -1
  506. package/dist/domain/flow/route.js.map +1 -1
  507. package/dist/domain/flow/rules.js +5 -6
  508. package/dist/domain/flow/rules.js.map +1 -1
  509. package/dist/domain/flow/run-state.js +531 -47
  510. package/dist/domain/flow/run-state.js.map +1 -1
  511. package/dist/domain/flow/test-run-evidence.js +285 -0
  512. package/dist/domain/flow/test-run-evidence.js.map +1 -0
  513. package/dist/domain/flow/unchanged-phase.js +15 -0
  514. package/dist/domain/flow/unchanged-phase.js.map +1 -0
  515. package/dist/domain/harnesses.js +22 -6
  516. package/dist/domain/harnesses.js.map +1 -1
  517. package/dist/domain/isolation-unit.js +2 -2
  518. package/dist/domain/isolation-unit.js.map +1 -1
  519. package/dist/domain/lineage.js +7 -2
  520. package/dist/domain/lineage.js.map +1 -1
  521. package/dist/domain/obligation-correspondence.js +4 -2
  522. package/dist/domain/obligation-correspondence.js.map +1 -1
  523. package/dist/domain/plan-handoff.js +5 -0
  524. package/dist/domain/plan-handoff.js.map +1 -0
  525. package/dist/domain/proposal.js +18 -7
  526. package/dist/domain/proposal.js.map +1 -1
  527. package/dist/domain/reservation.js +5 -3
  528. package/dist/domain/reservation.js.map +1 -1
  529. package/dist/domain/retirement/proposal.js +1 -0
  530. package/dist/domain/retirement/proposal.js.map +1 -1
  531. package/dist/domain/session/custody.js +10 -6
  532. package/dist/domain/session/custody.js.map +1 -1
  533. package/dist/domain/session/narrative.js +4 -1
  534. package/dist/domain/session/narrative.js.map +1 -1
  535. package/dist/domain/skills.js +2 -0
  536. package/dist/domain/skills.js.map +1 -1
  537. package/dist/domain/sql-lexer.js +15 -2
  538. package/dist/domain/sql-lexer.js.map +1 -1
  539. package/dist/runtime/namespace-resolver.js +4 -0
  540. package/dist/runtime/namespace-resolver.js.map +1 -1
  541. package/dist/runtime/workline-marker.js +35 -8
  542. package/dist/runtime/workline-marker.js.map +1 -1
  543. package/dist/runtime/workspace-resolution.js +123 -0
  544. package/dist/runtime/workspace-resolution.js.map +1 -0
  545. package/package.json +5 -4
  546. package/skills/w/SKILL.md +3 -1
  547. package/skills/w/artifacts/artifacts-core/CHECKPOINT.md +1 -1
  548. package/skills/w/artifacts/artifacts-core/SCRIPTS.rollback.sql +8 -0
  549. package/skills/w/artifacts/artifacts-core/SCRIPTS.sql +4 -8
  550. package/skills/w/commands/export-diagrams.md +3 -3
  551. package/skills/w/commands/export-manuals.md +6 -6
  552. package/skills/w/commands/export-reports.md +3 -3
  553. package/skills/w/commands/export-scripts.md +5 -5
  554. package/skills/w/commands/fix-git.md +12 -13
  555. package/skills/w/commands/persist.md +2 -2
  556. package/skills/w/commands/plan-exec.md +4 -2
  557. package/skills/w/commands/spec-new.md +1 -1
  558. package/skills/w/commands/workspace-init.md +2 -0
  559. package/skills/w/context/MANIFEST.json +1 -1
  560. package/skills/w/exports/export-diagrams/EXPORT.md +3 -3
  561. package/skills/w/exports/export-manuals/EXPORT.md +14 -16
  562. package/skills/w/exports/export-reports/EXPORT.md +3 -3
  563. package/skills/w/exports/export-scripts/EXPORT.md +45 -21
  564. package/skills/w/harness/HARNESS.md +5 -3
  565. package/skills/w/hooks/hooks.template.json +6 -4
  566. package/skills/w/loops/CHASSIS.md +12 -6
  567. package/skills/w/loops/CODE-POLICIES.md +7 -4
  568. package/skills/w/loops/plan-exec-loop/LOOP.md +23 -22
  569. package/skills/w/loops/plan-new-loop/LOOP.md +23 -31
  570. package/skills/w/loops/plan-refine-loop/LOOP.md +8 -2
  571. package/skills/w/loops/quick-loop/LOOP.md +6 -5
  572. package/skills/w/modules/DESIGN-REFERENCES.md +9 -11
  573. package/skills/w/modules/PLAN-EXECUTION-BATCHES.md +4 -4
  574. package/skills/w/modules/SESSION-NUMBERING.md +2 -0
  575. package/skills/w/roles/design/CONTRACT.md +16 -7
  576. package/skills/w/roles/design/ROLE.md +4 -2
  577. package/skills/w/roles/git/ROLE.md +16 -9
  578. package/skills/w/roles/research/ROLE.md +1 -1
  579. package/skills/w/roles/sql/ROLE.md +16 -14
  580. package/skills/w/schemas/design/ui-screen.v1.schema.json +9 -0
package/CHANGELOG.md CHANGED
@@ -12,6 +12,116 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
12
12
  - `### Migration` sigue como notas libres.
13
13
  - Las versiones hasta la 25.6.1 sólo traen la sección donde se registró una ruptura conocida, y ahí no pretende ser completa.
14
14
 
15
+ ## [25.9.0] — 2026-09-27
16
+
17
+ La ejecución acredita revisiones, pruebas y commits por lote. Las fuentes tienen rutas locales, pipeline versionado y ramas por documento. Los exports conservan el número aprobado. Las sesiones y unidades se cierran con evidencia; cada comando resuelve el workspace que le corresponde.
18
+
19
+ ### Contrato
20
+
21
+ - **Deja de valer:** omitir `plan-exec.review-findings` o cerrar un lote sin revisar sus correcciones. **Lo reemplaza:** revisión registrada por alguien distinto de los implementadores; sin subagentes, relectura limpia declarada. `batch-close` exige el registro. **Qué hacer:** entregá la revisión y volvé a revisar las correcciones.
22
+ - **Deja de valer:** acreditar una fase o la validación final con pruebas que no corrieron, no cargaron o introdujeron fallos. **Lo reemplaza:** el veredicto exige ejecución real y sólo admite rojos previos declarados. **Qué hacer:** corregí fallos nuevos y declará los preexistentes en el plan.
23
+ - **Deja de valer:** bloquear fases sin tareas abiertas o acreditar cualquier lote sin cambios. **Lo reemplaza:** la fase de sólo validación exige aprobación expresa y prueba real; las demás exigen cambios propios. **Qué hacer:** aprobá el lote de sólo validación antes de acreditarlo.
24
+ - **Deja de valer:** omitir `plan-exec.final-validation` o acreditarla con `aw status --json`. **Lo reemplaza:** build y tests reales por fuente de código, resueltos desde `## Validations` o el pipeline versionado. `plan-done` exige evidencia. **Qué hacer:** declará build y test con `aw set-pipeline` o en el plan y entregá sus salidas.
25
+ - **Deja de valer:** inferir siempre un lote por fase y diferir todos los commits al final. **Lo reemplaza:** `## Execution batches` delimita lotes; cada lote acreditado propone commits por fuente y los crea tras aprobación. Las corridas abiertas con la cola anterior la conservan. **Qué hacer:** revisá y aprobá las rutas y mensajes de cada lote.
26
+ - **Deja de valer:** descontar un intento por aprobar una integración o un commit. **Lo reemplaza:** la concesión queda registrada sin gastar un intento de respuesta. **Qué hacer:** distinguí aprobaciones de rechazos al leer el contador.
27
+ - **Deja de valer:** gastar intentos en formato inválido, digest erróneo, plan inválido o prueba vencida y mostrar sólo el primer defecto. **Lo reemplaza:** `error.violations` reúne defectos detectables y `aw flow submit --check` comprueba sin escribir ni gastar intento. La directiva declara efectos, aprobación, tipos, esquema y fuentes en `expects`. **Qué hacer:** corregí las violaciones y comprobá con `--check`.
28
+ - **Deja de valer:** una prueba sin raíz observada o perder `Compactar` y `Cerrar` tras un rechazo. **Lo reemplaza:** `proof` distingue otra raíz de un checkout cambiado y muestra el stderr de git; los controles siguen disponibles en la directiva de rechazo. **Qué hacer:** medí otra vez con `aw flow prove` en el checkout indicado.
29
+ - **Deja de valer:** exigir `schema` y `date` al autor de una nota o cobrar dos veces un reenvío idéntico. **Lo reemplaza:** el CLI completa ambos campos, avisa de campos desconocidos y reconoce el reenvío. **Qué hacer:** entregá los campos de autor y corregí los faltantes indicados.
30
+ - **Deja de valer:** invalidar sellos de texto por LF/CRLF o rechazar en `batch-close` las marcas que el propio CLI escribió. **Lo reemplaza:** se admiten ambos finales de línea y los digests anteriores; otras ediciones muestran diff. `PLAN_EXEC_BATCH_STALE` no cobra intento. **Qué hacer:** ante cambios de contenido, prepará `aw flow recover --reinfer-batch` y confirmá con `--approval <digest>`; repetí pruebas y revisión.
31
+ - **Deja de valer:** escribir el estado de corrida v13. **Lo reemplaza:** v15; v14 sumó revisiones, retiro de señales y observaciones de quick, y v15 añade aislamiento al alcance. Se continúan v11–v14 y se actualizan al escribir; v7–v10 sólo se leen para diagnóstico y recuperación. **Qué hacer:** avanzá una corrida v11–v14; para v7–v10 usá `aw flow restart`. No abras v15 con un CLI anterior.
32
+ - **Deja de valer:** una rama esperada única por fuente. **Lo reemplaza:** `aw doc-branch show|set` registra la rama por documento y fuente, hereda la de spec al plan y permite integrar unidades sin mover el checkout. **Qué hacer:** consultá con `--code` o `--doc` y registrá la rama con `set --source <alias> --rama <rama>`.
33
+ - **Deja de valer:** reescribir siempre rutas absolutas en `## Fuentes` o podar fuentes omitidas por `workspace-init --source`. **Lo reemplaza:** `.workflow/local.json` guarda rutas de este host; `aw add-source` y `workspace-init --source` son aditivos. **Qué hacer:** registrá cada checkout con `aw add-source <alias>:<ruta>:<rama>`.
34
+ - **Deja de valer:** estampar `Última actividad` en WORKSPACE y mostrar `Histórico:` sin archivo. **Lo reemplaza:** la actividad sale en `aw status`, la rama de trabajo figura en Fuentes y CLAUDE.md/AGENTS.md se escriben juntos. **Qué hacer:** consultá la actividad en `aw status`.
35
+ - **Deja de valer:** descargar tres versiones completas en `fix-git prepare` o resolver conflictos sólo con texto; informar `any_merging: false` al no poder leer una fuente. **Lo reemplaza:** `--show` y `--adapt` detallan rutas pedidas; `resolutions` acepta `ours`, `theirs` y `delete`, incluso binarios. `merge-state` informa `unreadable`, `any_merging: null` y sale con 1. **Qué hacer:** pedí las rutas necesarias y tratá `unreadable` como lectura incompleta.
36
+ - **Deja de valer:** confirmar `aw fix-git commit` sin comprobar el build. **Lo reemplaza:** la vista previa sin `--confirm` incluye build, rutas y `left_out`; confirmar ejecuta el build declarado o rechaza con `FIX_GIT_BUILD_UNDECLARED`/`FIX_GIT_BUILD_FAILED`. **Qué hacer:** declará build con `aw set-pipeline` o justificá la omisión con `--skip-build <motivo>`.
37
+ - **Deja de valer:** cambiar en `export-* apply` el número aprobado, admitir `--overwrite` fuera de manuals o reutilizar correlativos publicados tras borrar su carpeta. **Lo reemplaza:** `EXPORT_NUMBER_TAKEN` bloquea la colisión y la numeración consulta HISTORY y pases. **Qué hacer:** prepará otra propuesta si el número quedó ocupado.
38
+ - **Deja de valer:** sellar sólo el inventario de `export-scripts` o publicar forwards y rollbacks planos. **Lo reemplaza:** SQL y `scope.seal` entran al sello; bundles nuevos organizan forwards en 01–05, rollbacks en `rollback/` y generan `bundle.json`. Los bundles planos antiguos siguen legibles. **Qué hacer:** prepará otra vez si cambió SQL o scope y publicá con el manifiesto generado.
39
+ - **Deja de valer:** duplicar publicaciones de `next-number --publish`, materializar un workspace ausente, admitir sólo texto en `persist` o exigir siempre dossier en manuals. **Lo reemplaza:** publicación idempotente con `--dry-run`, adjuntos binarios y manuals de canon plano o `complement` con `INDEX.md`. **Qué hacer:** usá el número reservado y la forma de manuals que corresponde a tus archivos.
40
+ - **Deja de valer:** forzar una tercera revisión simple de design por package o aceptar revisiones editadas. **Lo reemplaza:** `update` conserva el modo simple, `screen_refs` declara citas y `aw designs`/`capability validate` verifican digests; sólo cambiar LF/CRLF avisa sin bloquear. **Qué hacer:** publicá otra revisión en lugar de editar una ya publicada.
41
+ - **Deja de valer:** que `Cerrar` sólo pause, que `quick.db-touched` incluya lecturas o que una señal errónea no se pueda retirar. **Lo reemplaza:** `Cerrar` finaliza los cinco flujos y conserva lo pendiente; `quick.db-touched` significa mutación y `aw flow retract` retira señales no consumidas. **Qué hacer:** reabrí con `aw session-resume --reopen` si seguís; retirá una señal de mera lectura antes del gate.
42
+ - **Deja de valer:** exigir scripts por mera lectura o commit por quick sin archivos, y dejar abierta la quick al cambiar a SPEC. **Lo reemplaza:** scripts sólo por mutación, fix vacío sin commit y escalamiento con cierre y handoff a `/w:spec-new`. **Qué hacer:** guardá DDL/DML en `SCRIPTS.sql` o `scripts/*.sql`; indicá análisis cuando corresponda.
43
+ - **Deja de valer:** escribir para averiguar si `aw amend apply` toca contrato, contar casillas de `## Handoff operativo` como tareas o arrancar `plan-refine` sin plan. **Lo reemplaza:** `--check` consulta sin escribir; el pase se declara `- Pase a cert|prod: <corte>` y `plan-refine` exige plan existente. **Qué hacer:** comprobá con `--check` y pasá `--input docs/plans/PPP-plan-<slug>.md` si falta el plan.
44
+ - **Deja de valer:** exigir unidad aunque el workspace elija editar en su checkout. **Lo reemplaza:** `aw set-edit-mode in-place|unit`; `> Aislamiento: unidad` prevalece. In-place prueba y commitea sólo rutas aprobadas, conserva cambios ajenos y rechaza otra rama o HEAD. **Qué hacer:** elegí `in-place` expresamente y aprobá sólo las rutas propias.
45
+ - **Deja de valer:** fallar en `aw reset` o `aw discard` por una unidad integrada cuya carpeta ya no existe. **Lo reemplaza:** el retiro verifica recibo, inventario git y rama destino antes de revertir el rango atribuible. **Qué hacer:** ejecutalo desde el destino limpio y atendé la negativa si la atribución no es única.
46
+ - **Deja de valer:** cargar todo el CLI en hooks fuera de un workspace o necesitar un hook `prompt` extra para `PostCompact`. **Lo reemplaza:** entrada ligera y reanudación en `resume-summary`; `sql-mutation-guard` conserva su alcance. **Qué hacer:** reinstalá hooks gestionados con `aw self install-hooks`.
47
+ - **Deja de valer:** que `aw doctor` dé por sana la ausencia de hosts o falle sólo por un host `ready` sin binario. **Lo reemplaza:** distingue ausencia, contradicción y cobertura omitida; avisa de `dist/` alterado y upstream a PROD. **Qué hacer:** consultá sus avisos y el remedio de upstream indicado.
48
+ - **Deja de valer:** cerrar con CHECKPOINT incompleto, `## Origin` vacío o criterios sin marcar y sin razón. **Lo reemplaza:** el cierre se niega salvo `--force` o `--abandon`; el CHECKPOINT registra el estado git real por fuente y el Recorrido termina en «Siguiente paso: ninguno». **Qué hacer:** completá origen, criterios y checkpoint; usá `--abandon` sólo para abandonar.
49
+ - **Deja de valer:** crear HISTORY sólo al cerrar, desordenar sus filas o volver a usar un número tras `discard`. **Lo reemplaza:** la fila nace al crear, se ordena por código y se conserva al retirar; `aw history reconcile` muestra discrepancias y `aw workspace-migrate --renumber` resuelve colisiones. **Qué hacer:** reconciliá HISTORY y renumerá la sesión local si comparte número.
50
+ - **Deja de valer:** inferir que toda sesión sin `.closed` está activa. **Lo reemplaza:** `aw session-pause --code <NNN>` y `session-close --abandon` marcan estados propios; retomar reactiva una pausada y una abandonada exige `--reopen`. **Qué hacer:** marcá el estado expresamente y usá `--reopen` para una abandonada.
51
+ - **Deja de valer:** que el cierre deje todo el mínimo sólo en la carpeta efímera o commitee el índice ajeno. **Lo reemplaza:** archiva CHECKPOINT, DECISION, BACKLOG, SQL y evidencia consentida en `.workflow/archive/`; `aw workspace-commit` prepara y aplica con aprobación un commit por rutas, sin push. **Qué hacer:** inspeccioná la propuesta de cierre o export y aprobá el digest si querés el commit; para evidencia temporal usá `--with-evidence`.
52
+ - **Deja de valer:** resolver un workspace por el cwd o por un marcador de `$HOME` dentro de una fuente. **Lo reemplaza:** el registro de hubs en `~/.workflow/hubs.json` resuelve al hub dueño; con varios exige `--workspace <ruta>`. La fuente no recibe `.workflow/` ni cambios de `.gitignore`. **Qué hacer:** corré una vez `aw` en el hub o indicá `--workspace` cuando haya ambigüedad.
53
+ - **Deja de valer:** preparar una operación en un workspace y aplicarla en otro con el mismo contenido. **Lo reemplaza:** las propuestas de dos tiempos sellan la raíz real; `--workspace` selecciona la carpeta exacta y un cambio de raíz se rechaza. **Qué hacer:** aplicá desde el mismo hub o especificá su ruta con `--workspace`.
54
+ - **Deja de valer:** compartir la rama `aw/<sesión>` entre hubs o perder unidades al mover el hub. **Lo reemplaza:** las unidades nuevas usan `aw/<hash8>/<carpeta>`; custodia y claves previas reconocen las antiguas. `aw workspace-move` mueve o repara rutas. **Qué hacer:** mudá con `aw workspace-move <destino>` o repará un movimiento manual con `--repair`.
55
+ - **Deja de valer:** tomar `development` como rama de trabajo implícita para `worktree ensure`, `integrate` y git-flow. **Lo reemplaza:** se exige la rama del documento o una rama de trabajo declarada; `aw sources` informa si falta. **Qué hacer:** registrá la rama con `aw set-working-branch <alias> <rama>`.
56
+ - **Deja de valer:** dejar carpetas huérfanas recuperables y ramas `aw/*` integradas tras liberar, o exigir reabrir la sesión para liberar. **Lo reemplaza:** `release`/`reclaim` terminan removes partidos, retienen archivos propios y borran por CAS sólo ramas contenidas en su base. `release` e `integrate` aceptan sesiones cerradas. **Qué hacer:** usá `aw worktree reclaim` para restos y resolvé por separado lo retenido.
57
+ - **Deja de valer:** que una unidad con dependencias idénticas deba reinstalarlas o que el retiro borre indiscriminadamente `node_modules`. **Lo reemplaza:** la unidad enlaza las dependencias de la fuente si coinciden manifiesto y lockfile; libera sólo ese enlace verificado. **Qué hacer:** no ejecutes `npm ci` en una unidad enlazada: modificaría las dependencias de la fuente.
58
+ - **Deja de valer:** tratar unidades vivas de multiroot como sobrantes o bloquear el cierre final por unidades vacías o preservadas. **Lo reemplaza:** la reparación quita sólo rutas sobrantes; el cierre final libera unidades vacías y preservadas y retiene las que tienen trabajo no acreditado. **Qué hacer:** consultá el motivo de retención antes de integrar o liberar.
59
+ - **Deja de valer:** mostrar ayuda del padre para todo subverbo, ofrecer `--overwrite` en exportaciones que no lo aceptan o admitir juntos `project-md-upsert --read --init`. **Lo reemplaza:** ayuda por subverbo desde el contrato de flags, con `Usage` y opciones excluyentes; la ayuda global anuncia `--workspace`. **Qué hacer:** consultá `<comando> <subverbo> --help` y elegí sólo `--read` o `--init`.
60
+
61
+ ### Added
62
+
63
+ - **`aw doc-branch show|set`, `aw add-source` y `aw set-pipeline`.** Registran ramas por documento, rutas locales y build/test por fuente.
64
+ - **`aw flow submit --check`, `aw flow retract` y `aw flow recover --reinfer-batch`.** Comprueban sin gastar intento, retiran señales no consumidas y re-infieren un lote con aprobación.
65
+ - **`aw set-edit-mode in-place|unit` y `aw set-exception-branch`.** Declaran la edición del checkout y excepciones de rama.
66
+ - **`aw history reconcile`, `aw session-pause` y `aw sessions --sweep`.** Consultan discrepancias, pausan sesiones y limpian residuos del runtime.
67
+ - **`aw workspace-commit` y `aw workspace-init --untrack`.** Preparan commits acotados y dejan de trackear archivos excluidos sin borrarlos.
68
+ - **`aw workspace-move` y registro de hubs.** Resuelven fuentes compartidas y reparan rutas tras una mudanza.
69
+ - **`export-scripts --catalog` y bundles con `bundle.json`.** Contrastan el catálogo en sólo lectura y registran el origen del SQL.
70
+ - **Pases y specs reemplazadas.** `## Handoff operativo` admite `- Pase a cert|prod: <corte>`; `superseded` retira la spec de pendientes.
71
+
72
+ ### Changed
73
+
74
+ - **El estado de corrida escribe v15.** Continúa v11, v12, v13 y v14; v7–v10 sólo se leen y salen por `aw flow restart`.
75
+ - **El cierre acredita pruebas, revisiones y commits por lote.** La validación final toma build y tests del pipeline o del plan.
76
+ - **Los números y sellos de publicación permanecen estables.** `export-* apply` conserva el número aprobado; los sellos de texto toleran LF/CRLF.
77
+ - **La doctrina y la ayuda siguen el binario.** `> Cierre:` lleva evidencia, `> Assurance:` el veredicto; CHASSIS incluye reglas de host y las guías redirigen sobres desde archivos.
78
+ - **El CLI conserva su catálogo propio de skills recomendadas.** El marketplace contrasta una captura del catálogo; el CLI no carga su README.
79
+ - **`aw doctor` distingue cobertura omitida de fallo.** Comprueba integridad de `dist/` y avisa de upstreams a PROD.
80
+ - **Dependencias de mantenimiento.** Vitest 5.0.2 y Vite 8.3.1 son de desarrollo; smol-toml 1.9.0 normaliza tablas de prototipo nulo y ws 8.22.0 sigue transitiva.
81
+
82
+ ### Fixed
83
+
84
+ - **`aw reset` y `aw discard` reconocen unidades integradas y liberadas.** Comprueban recibo y destino antes de revertir.
85
+ - **`fix-git` resuelve bajas, binarios y archivos adaptados.** Aplica sólo las rutas propuestas y conserva los finales de línea de Windows.
86
+ - **`merge-state` informa fuentes ilegibles.** Devuelve `unreadable` y `any_merging: null` en vez de descartar merges sin certeza.
87
+ - **Design comprueba revisiones y renditions.** Una tercera revisión simple sigue la ruta simple y una revisión editada falla por digest.
88
+ - **El bloque compartido conserva fuentes.** Rutas locales quedan fuera del bloque versionado y sus dos espejos se actualizan juntos.
89
+ - **Las unidades se liberan sin arrastrar dependencias.** Se recuperan carpetas limpias de removes partidos y se conserva el trabajo propio.
90
+ - **El commit in-place se reconoce aunque queden cambios ajenos.** Tras una interrupción, sólo impiden reconocerlo cambios pendientes en rutas de la propuesta.
91
+ - **La ayuda conserva `Usage` y anuncia `--workspace`.** `context-budget` puede medir el bundle desde un checkout sin hub.
92
+ - **Una sesión pausada conserva sus reservas.** `aw claims` ya no ofrece recuperarlas; al retomarla, la reserva sigue suya. Las de una sesión abandonada siguen siendo recuperables.
93
+ - **El cierre puede copiar la evidencia y commitearla en la misma decisión.** La copia versionada entra en el commit final del workspace.
94
+
95
+ ## [25.8.0] — 2026-09-27
96
+
97
+ La guarda de SQL distingue los servidores PostgreSQL registrados en `aw self mcp` y revisa el SQL que ejecutan las funciones remotas. Las corridas acreditan cada lote con prueba de su propio checkout y dejan registrar su ciclo de vida completo. Los comandos rechazan los flags desconocidos, la salida humana puede ser ASCII y el wrapper instalado de design usa el protocolo real de `aw capability` en cada host.
98
+
99
+ ### Contrato
100
+
101
+ - **Deja de valer:** que la guarda `sql-mutation-guard` bloquee en todo servidor lo que MySQL leería distinto. Hoy bloquea un `#` fuera de un literal (los operadores `#>`, `#>>` y `#-` de jsonb y el XOR `#`), un backtick, una `\` pegada a una comilla (como `'\'`) y un `/*! … */`. **Lo reemplaza:** la guarda lee como PostgreSQL al servidor cuyo nombre está registrado en `aw self mcp`, porque lo sirve `aw mcp serve-db`. Ahí esas cuatro formas pasan y el dollar-quoting se reconoce como literal. El servidor no registrado, o uno cuyo registro no se puede leer, se sigue leyendo también como MySQL: siguen bloqueadas las cuatro formas y además se bloquea todo literal `$…$`, como `SELECT $$texto$$`, que MySQL no lee como literal. El mensaje de bloqueo suma la línea `Motor`. **Qué hacer:** contra un servidor de Workline no hace falta reescribir nada. Contra otro servidor, reemplazá el `$$…$$` por `'…'`, o registrá el servidor con `aw self mcp` si lo sirve `serve-db`.
102
+ - **Deja de valer:** que un `SELECT` que llama a `dblink_exec`, `dblink`, `dblink_send_query`, `dblink_open`, `query_to_xml`, `query_to_xmlschema` o `query_to_xml_and_xmlschema` pase sin mirar el SQL que esas funciones ejecutan. **Lo reemplaza:** la llamada pasa sólo si ese SQL es un único literal `'…'` o `$…$` que lee. Ese SQL es el primer argumento de `query_to_xml*` y, en `dblink*`, el último que no es `TRUE` ni `FALSE`. Se bloquea si ese literal no lee, si el SQL no es un literal (una concatenación, un cast, `E'…'`, un argumento con nombre) o si la función se llama con un nombre `U&"…"`. **Qué hacer:** pasá el SQL como un único literal. Lo que de verdad tenga que mutar va como script a `docs/scripts/`, o por la excepción que delega la persona (`AW_SQL_GUARD_ALLOW`).
103
+ - **Deja de valer:** acreditar con un resultado externo una acción que el CLI debe ejecutar, o cerrar un lote con una prueba reciclada o sin cambios propios de su checkout. **Lo reemplaza:** las acciones internas sólo se acreditan al correr `aw flow advance`. Cada lote exige prueba de checkout por cada fuente; la huella debe diferir de la base del lote (o del inicio de la corrida en el primero), y una prueba no puede acreditar dos lotes. La validación de fase no se puede omitir y `batch-close` no cierra sin acreditación. **Qué hacer:** corré la acción con `aw flow advance` y aportá una prueba propia de cada checkout del lote, tomada después de sus cambios.
104
+ - **Deja de valer:** que `Refinar` cierre la sesión, que `aw session-close` deje abierta la corrida en su frontera, y que `aw session-resume --reopen` sólo borre `.closed`. **Lo reemplaza:** `Refinar` vuelve a la frontera de redacción y mantiene abierta la sesión; `session-close` termina la corrida en la frontera donde estaba, y `--reopen` reabre también la corrida para retomarla desde esa frontera o desde la última frontera humana. El estado de corrida v13 es el formato de escritura; las versiones v11 y v12 se continúan y se suben al escribir. **Qué hacer:** después de `Refinar`, avanzá con `aw flow advance`; para retomar una corrida cerrada, usá `aw session-resume --reopen` y luego `aw flow advance`.
105
+ - **Deja de valer:** que un flag desconocido se ignore y el comando siga, incluso si después espera stdin. **Lo reemplaza:** los comandos lo rechazan con `UNKNOWN_FLAG` antes de ejecutarse. Los hooks avisan por stderr y siguen con su código de salida y stdout de siempre. **Qué hacer:** quitá el flag desconocido o usá el flag que declara el comando; `aw flow submit` recibe su sobre por stdin, no por `--file`.
106
+ - **Deja de valer:** que `aw session-resume --reopen` salga con 0 cuando no pudo reabrir la corrida y devuelve `run_error`. **Lo reemplaza:** el comando sale con un código distinto de 0 si la corrida no se pudo reabrir. **Qué hacer:** un consumidor que trataba el código 0 como reapertura exitosa debe comprobar el código de salida.
107
+ - **Deja de valer:** que el wrapper instalado de `design` instruya `aw capability continue` y `validate` con `--request`, y `apply` con `--plan`, o que una copia compartida fuerce el `--host` de otro agente. **Lo reemplaza:** el wrapper muestra las cuatro etapas `prepare`, `continue`, `validate` y `apply`, repitiendo `--capability design`, `--operation <op>` y todos los `--input` en cada una; la respuesta se transporta como un objeto JSON por stdin y `apply` recibe `--approval <plan.proposal.digest>`. En carpetas de HOME leídas por varios hosts el wrapper va sin binding y detecta el host al correr; Gemini/Antigravity conserva `.gemini/skills/design` con binding `gemini`, ya que no lee HOME/.agents/skills. Si `aw harness` responde `unknown`, se pasa `--host <id>` en cada etapa. **Qué hacer:** después de actualizar, reinstalá las skills con `aw self install-skill --target all --confirm-all --force` (`--confirm-all` es obligatorio para `all` y `--force` reemplaza las instalaciones existentes); consultá `aw capability --help` para el sobre completo.
108
+
109
+ ### Added
110
+
111
+ - **`--ascii` y `AW_ASCII=1` — salida humana sólo ASCII.** La transliteración se aplica a la salida humana, la ayuda y los avisos de hooks; no cambia JSON ni protocolos. `--ascii` se rechaza con `--format json` o `--json` explícitos, y `AW_ASCII=1` se ignora bajo JSON.
112
+ - **Prueba de checkout propia para acreditar lotes.** La validación de fase pide una prueba por fuente y compara su huella acotada con la base guardada en el inicio del lote. El digest acreditado queda asociado al lote, y las pruebas de otros lotes no se pueden reciclar.
113
+
114
+ ### Changed
115
+
116
+ - **El ciclo de vida vuelve a entrar por inserción de tramos, no rebobinando el cursor.** `Refinar` repite desde la frontera de redacción; cerrar termina el recorrido en la frontera vigente, y reabrir agrega el tramo que permite continuar sin repetir efectos ya aplicados.
117
+ - **Un flag desconocido se detecta según el contrato de cada comando.** Todos los comandos declaran sus flags por comando o acción; los tokens de un guion también se leen como flags, salvo `-h`, `-` y `--`.
118
+
119
+ ### Fixed
120
+
121
+ - **La guarda de SQL no distinguía el motor del servidor ni revisaba SQL ejecutado por funciones.** Ahora toma PostgreSQL del registro de `aw self mcp`, y clasifica recursivamente el literal que ejecutan `dblink*` y `query_to_xml*`. Las excepciones al clasificar bloquean con código 2, igual que cualquier SQL no permitido.
122
+ - **Una corrida podía cerrarse o reabrirse a medias.** `Refinar` ya no la finaliza, `session-close` registra el `finalize` en su frontera y `--reopen` reabre la corrida. Un fallo al reabrirla ya no se informa como éxito.
123
+ - **El wrapper de design y su diagnóstico no coincidían con los hosts ni con los flags de `aw capability`.** La instalación sitúa un wrapper sin binding en raíces HOME compartidas, mantiene la copia nativa con binding `gemini` para Gemini/Antigravity y retira sólo las copias antiguas propias cuando sus lectores quedan cubiertos. `aw skills` y `aw doctor` consultan las carpetas HOME reales que lee cada host, sin contar raíces legadas o sólo de proyecto; la detección de host prioriza las marcas del agente sobre la terminal Warp.
124
+
15
125
  ## [25.7.0] — 2026-09-26
16
126
 
17
127
  La primera versión que declara sus contratos, y la que cierra la primera ola del lote de specs 048-058, nacido del consolidado de incidencias del 2026-09-25 sobre la 25.6.1. Entran ocho planes juntos. Una corrida de `aw flow` sobrevive a actualizar el CLI y a una escritura fallida, y sale de cualquier estado trabado por un verbo propio (`aw flow restart`, `aw flow annul`). Publicar en PROD pasa a ser un acto de la persona, git-flow deja de usar `git pull` y `fix-git` deja de cerrar un merge que trae desarrollo a una rama de trabajo. La guarda de SQL deja pasar sólo lecturas. Una escritura sin `--code` ni asociación ya no cae en la sesión de otra conversación. La gramática del plan juzga las cláusulas por lo que nombran, y ningún plan se publica sin sello en silencio. `aw self update` pasa a avisar los cambios de contrato antes de instalar, aunque no en este salto: el aviso lo ejecuta la versión instalada, y la 25.6.1 no lo trae. Suma además la memoria compartida entre hosts, `aw host-memory` y `/w:recall`, y la doctrina que admite subagentes por etapa. **Diez archivos de `skills/` cambian, uno de ellos nuevo**, así que el bundle instalado ya no es el de 25.6.0. **Ningún recorrido cambia**: los cinco son idénticos a los de la 25.6.1.
package/README.md CHANGED
@@ -93,6 +93,8 @@ The bundle's internal manuals (`loops/*/LOOP.md`, `roles/*/ROLE.md`, `exports/*/
93
93
 
94
94
  Opt-out flags: `--skill-only`, `--no-commands`, `--no-hooks`. Override the source with `--from /path/to/skills/w`. Other flags: `--confirm-all` (required with `--target all`), `--keep-cache`, `--force`, `--dry-run`.
95
95
 
96
+ To add the `UserPromptSubmit` branch advisory to an existing Claude or Kimi installation, rerun `aw self install-hooks --target claude` or `--target kimi`; updating the CLI alone does not reinstall hooks. Editing remains protected by `branch-check` on all managed hosts.
97
+
96
98
  **What `--target all` means.** Every **host** — never the shared skills dirs, which are install destinations rather than hosts and are reached explicitly (`--target agents`). `install` and `uninstall` use the same set, so the round trip matches: what `all` installs is what `all` removes. (`oz` installs into `~/.agents/skills`, so that directory is still covered under `all` through its host.)
97
99
 
98
100
  ### Support levels and how long a verification is worth
@@ -181,7 +183,9 @@ Workspace artifacts live under `.<namespace>/`. Resolution order (first match wi
181
183
  - `sessions` / `session-create --type <research|refine|exec|quick>` / `session-close` / `session-resume` / `session-artifacts` — internal session lifecycle (used by the loops).
182
184
  - `checkpoint-read` / `checkpoint-write` — `CHECKPOINT.md` handling.
183
185
  - `flow <advance|submit>` — the direction engine: `advance` applies every consecutive `cli`-owned transition of a flow run and returns the directive of the first non-deterministic frontier; `submit` takes the response as JSON via stdin (`--approval <digest>` for effects) and keeps advancing.
184
- - `sources` / `check-branch` / `set-working-branch` / `set-qa-branch` — multi-source git-safety (per-source base / working / QA branches).
186
+ - `sources` / `check-branch` / `set-working-branch` / `set-qa-branch` / `set-exception-branch` — multi-source git-safety (per-source base / working / QA / exception branches).
187
+ - `set-edit-mode in-place|unit` — declares checkout editing or isolated units in the WORKSPACE block; plans can require `> Aislamiento: unidad`.
188
+ - `doc-branch show|set` — propone y asocia una rama de trabajo por documento y fuente, heredada por sus planes; `show` no modifica nada.
185
189
  - `git-flow <sync|to-dev|to-qa|to-prod> [--source|--all] [--target] [--dry-run]` — run the per-source branch flows (sync working ← base, promote to dev/QA/prod) with conflict-pause; `--all` processes every source and reports each one. Also surfaced as Project-tab actions.
186
190
  - `release-data` — corpus reader backing the `export-*` skills.
187
191
  - `self install-skill` / `self doctor` / `self update` / `mcp` — CLI maintenance.
@@ -1,6 +1,7 @@
1
1
  import { createHash } from "node:crypto";
2
- import { readFile } from "node:fs/promises";
2
+ import { appendFile, lstat, readFile, readlink } from "node:fs/promises";
3
3
  import { resolve } from "node:path";
4
+ import { checkSafeRelativePath } from "../domain/safe-path.js";
4
5
  /**
5
6
  * Non-interactive git env: `GIT_TERMINAL_PROMPT=0` makes git FAIL FAST instead of
6
7
  * blocking on a terminal credential prompt (a push against a repo needing creds
@@ -9,6 +10,24 @@ import { resolve } from "node:path";
9
10
  */
10
11
  /** Stands in for the blob id of an untracked path git cannot hash; never a real one. */
11
12
  const UNHASHABLE_BLOB = "unhashable";
13
+ const DELETED_BLOB = "deleted";
14
+ /** `ls-files -s` entries of mode 160000, by path: the commit each submodule is pinned at. */
15
+ function gitlinksOf(staged) {
16
+ const gitlinks = new Map();
17
+ for (const entry of nulSeparated(staged)) {
18
+ const tab = entry.indexOf("\t");
19
+ const [mode, object] = entry.slice(0, tab).split(" ");
20
+ if (mode === "160000" && object !== undefined)
21
+ gitlinks.set(entry.slice(tab + 1), object);
22
+ }
23
+ return gitlinks;
24
+ }
25
+ function nulSeparated(bytes) {
26
+ return bytes
27
+ .toString("utf8")
28
+ .split("\0")
29
+ .filter((entry) => entry.length > 0);
30
+ }
12
31
  function nonInteractiveGitEnv() {
13
32
  const env = {};
14
33
  for (const [key, value] of Object.entries(process.env)) {
@@ -31,8 +50,8 @@ export class GitCliAdapter {
31
50
  return new Error(`git ${label} failed in ${repoPath}: ${stderr.trim()}`);
32
51
  }
33
52
  /** Run git, throwing `git <label> failed in <repo>: <stderr>` on non-zero exit. */
34
- async mustRun(label, args, repoPath) {
35
- const result = await this.process.run("git", args, this.opts(repoPath));
53
+ async mustRun(label, args, repoPath, extra = {}) {
54
+ const result = await this.process.run("git", args, this.opts(repoPath, extra));
36
55
  if (result.code !== 0) {
37
56
  throw this.failed(label, repoPath, result.stderr);
38
57
  }
@@ -48,7 +67,22 @@ export class GitCliAdapter {
48
67
  }
49
68
  async isGitRepo(repoPath) {
50
69
  const result = await this.process.run("git", ["rev-parse", "--git-dir"], this.opts(repoPath));
51
- return result.code === 0;
70
+ if (result.code === 0)
71
+ return true;
72
+ if (/not a git repository/i.test(result.stderr))
73
+ return false;
74
+ throw this.failed("rev-parse", repoPath, result.stderr);
75
+ }
76
+ async readConfig(repoPath, key) {
77
+ const result = await this.process.run("git", ["config", "--get", key], this.opts(repoPath));
78
+ if (result.code === 1)
79
+ return null;
80
+ if (result.code !== 0)
81
+ throw this.failed(`config --get ${key}`, repoPath, result.stderr);
82
+ return result.stdout.trim();
83
+ }
84
+ async writeLocalConfig(repoPath, key, value) {
85
+ await this.mustRun(`config --local ${key}`, ["config", "--local", key, value], repoPath);
52
86
  }
53
87
  async currentBranch(repoPath) {
54
88
  const result = await this.process.run("git", ["rev-parse", "--abbrev-ref", "HEAD"], this.opts(repoPath));
@@ -91,24 +125,103 @@ export class GitCliAdapter {
91
125
  * Git's output is hashed as BYTES and never decoded: a digest that has to be
92
126
  * reproducible cannot depend on a text encoding it does not need.
93
127
  */
94
- async checkoutFingerprint(repoPath) {
128
+ async checkoutFingerprint(repoPath, excluded) {
129
+ const scope = excluded === undefined ? [] : [".", ...excluded.map((p) => `:(exclude)${p}`)];
95
130
  const [patch, status, untracked] = await Promise.all([
96
- this.mustRunBinary("diff for checkout fingerprint", ["diff", "--binary", "--full-index", "--no-ext-diff", "HEAD", "--"], repoPath),
97
- this.mustRunBinary("status for checkout fingerprint", ["status", "--porcelain=v2", "-z"], repoPath),
98
- this.mustRunBinary("untracked files for checkout fingerprint", ["ls-files", "--others", "--exclude-standard", "-z"], repoPath),
131
+ this.mustRunBinary("diff for checkout fingerprint", ["diff", "--binary", "--full-index", "--no-ext-diff", "HEAD", "--", ...scope], repoPath),
132
+ this.mustRunBinary("status for checkout fingerprint", ["status", "--porcelain=v2", "-z", ...(excluded === undefined ? [] : ["--", ...scope])], repoPath),
133
+ this.mustRunBinary("untracked files for checkout fingerprint", [
134
+ "ls-files",
135
+ "--others",
136
+ "--exclude-standard",
137
+ "-z",
138
+ ...(excluded === undefined ? [] : ["--", ...scope]),
139
+ ], repoPath),
99
140
  ]);
100
141
  const hash = createHash("sha256");
101
142
  hash.update("patch\0", "utf8");
102
143
  hash.update(patch.stdout);
103
144
  hash.update("status\0", "utf8");
104
145
  hash.update(status.stdout);
105
- const paths = untracked.stdout
106
- .toString("utf8")
107
- .split("\0")
108
- .filter((path) => path.length > 0)
109
- .sort();
146
+ await this.hashUntracked(hash, repoPath, untracked.stdout);
147
+ if (excluded !== undefined) {
148
+ // hash-object alone follows symlinks and omits execute bits. A no-index
149
+ // patch includes both Git's file mode and a symlink's destination.
150
+ for (const path of nulSeparated(untracked.stdout).sort()) {
151
+ const patch = await this.process.runBinary("git", ["diff", "--no-index", "--binary", "--no-ext-diff", "--", "/dev/null", path], this.opts(repoPath));
152
+ if (patch.code !== 0 && patch.code !== 1)
153
+ throw this.failed("untracked state", repoPath, patch.stderr.toString());
154
+ hash.update(patch.stdout);
155
+ }
156
+ }
157
+ return `sha256:${hash.digest("hex")}`;
158
+ }
159
+ /**
160
+ * The content of the tree under `root` alone, without the excluded subpaths.
161
+ *
162
+ * `checkoutFingerprint` measures the whole repository relative to HEAD, so in a
163
+ * hub a neighbouring project moves it, and so does a commit or a `git add` that
164
+ * changes no byte under `root`. This one is what a batch is compared against:
165
+ * every path under `root` git tracks or would track, each with the blob id of
166
+ * its bytes on disk — so only what the files hold decides whether they changed.
167
+ */
168
+ async scopedFingerprint(root, excluded) {
169
+ const pathspec = ["--", ".", ...excluded.map((path) => `:(exclude)${path}`)];
170
+ const [listed, removed, staged] = await Promise.all([
171
+ this.mustRunBinary("paths for scoped fingerprint", ["ls-files", "-z", "--cached", "--others", "--exclude-standard", ...pathspec], root),
172
+ this.mustRunBinary("deleted paths for scoped fingerprint", ["ls-files", "-z", "--deleted", ...pathspec], root),
173
+ this.mustRunBinary("index for scoped fingerprint", ["ls-files", "-z", "-s", ...pathspec], root),
174
+ ]);
175
+ const deleted = new Set(nulSeparated(removed.stdout));
176
+ const paths = [...new Set(nulSeparated(listed.stdout))].sort();
177
+ // A submodule is a directory git records by commit: its entry stands for its
178
+ // content, and handing it to `hash-object` would fail the whole batch. It is
179
+ // the commit STAGED in this repository, so work inside the submodule counts
180
+ // once the parent records it.
181
+ const gitlinks = gitlinksOf(staged.stdout);
182
+ const present = paths.filter((path) => !deleted.has(path) && !gitlinks.has(path));
183
+ const blobs = await this.blobsOf(root, present);
184
+ for (const [path, commit] of gitlinks)
185
+ blobs.set(path, `gitlink:${commit}`);
186
+ const hash = createHash("sha256");
110
187
  for (const path of paths) {
111
- const blob = await this.process.run("git", ["hash-object", "--no-filters", "--", path], this.opts(repoPath));
188
+ hash.update(path, "utf8");
189
+ hash.update("\0", "utf8");
190
+ hash.update(deleted.has(path) ? DELETED_BLOB : (blobs.get(path) ?? UNHASHABLE_BLOB), "utf8");
191
+ hash.update("\0", "utf8");
192
+ }
193
+ return `sha256:${hash.digest("hex")}`;
194
+ }
195
+ /**
196
+ * The blob id of each path's bytes, in one `hash-object` when it can.
197
+ *
198
+ * A path git cannot hash, or one whose name breaks the line protocol, sends the
199
+ * batch to the per-path fallback, where an unhashable entry is recorded as such
200
+ * instead of taking the whole tree down.
201
+ */
202
+ async blobsOf(cwd, paths) {
203
+ const blobs = new Map();
204
+ if (paths.length === 0)
205
+ return blobs;
206
+ const batch = paths.some((path) => path.includes("\n"))
207
+ ? null
208
+ : await this.process.run("git", ["hash-object", "--no-filters", "--stdin-paths"], this.opts(cwd, { stdin: `${paths.join("\n")}\n` }));
209
+ const ids = batch?.code === 0 ? batch.stdout.trim().split("\n") : [];
210
+ if (ids.length === paths.length) {
211
+ paths.forEach((path, index) => blobs.set(path, ids[index]));
212
+ return blobs;
213
+ }
214
+ for (const path of paths) {
215
+ const blob = await this.process.run("git", ["hash-object", "--no-filters", "--", path], this.opts(cwd));
216
+ if (blob.code === 0)
217
+ blobs.set(path, blob.stdout.trim());
218
+ }
219
+ return blobs;
220
+ }
221
+ /** Each untracked path with its blob id, in a stable order. */
222
+ async hashUntracked(hash, cwd, listing) {
223
+ for (const path of nulSeparated(listing).sort()) {
224
+ const blob = await this.process.run("git", ["hash-object", "--no-filters", "--", path], this.opts(cwd));
112
225
  hash.update("untracked\0", "utf8");
113
226
  hash.update(path, "utf8");
114
227
  hash.update("\0", "utf8");
@@ -119,7 +232,6 @@ export class GitCliAdapter {
119
232
  hash.update(blob.code === 0 ? blob.stdout.trim() : UNHASHABLE_BLOB, "utf8");
120
233
  hash.update("\0", "utf8");
121
234
  }
122
- return `sha256:${hash.digest("hex")}`;
123
235
  }
124
236
  async repoPrefix(repoPath) {
125
237
  const result = await this.process.run("git", ["rev-parse", "--show-prefix"], this.opts(repoPath));
@@ -250,6 +362,17 @@ export class GitCliAdapter {
250
362
  throw err;
251
363
  }
252
364
  }
365
+ async mergeBases(repoPath) {
366
+ const result = await this.process.run("git", ["merge-base", "--all", "HEAD", "MERGE_HEAD"], this.opts(repoPath));
367
+ if (result.code === 1)
368
+ return [];
369
+ if (result.code !== 0)
370
+ throw this.failed("merge-base --all", repoPath, result.stderr);
371
+ return result.stdout
372
+ .split("\n")
373
+ .map((line) => line.trim())
374
+ .filter(Boolean);
375
+ }
253
376
  async conflictedFiles(repoPath) {
254
377
  const result = await this.process.run("git", ["diff", "--name-only", "--diff-filter=U"], this.opts(repoPath));
255
378
  if (result.code !== 0) {
@@ -277,9 +400,9 @@ export class GitCliAdapter {
277
400
  const hashes = new Map();
278
401
  if (listed.code === 0) {
279
402
  for (const line of listed.stdout.split("\n")) {
280
- const match = /^\d+ ([0-9a-f]{40}) ([123])\t/.exec(line);
281
- if (match?.[1] && match[2])
282
- hashes.set(match[2], match[1]);
403
+ const match = /^(\d{6}) ([0-9a-f]{40}|[0-9a-f]{64}) ([123])\t/.exec(line);
404
+ if (match?.[1] && match[2] && match[3])
405
+ hashes.set(match[3], { mode: match[1], hash: match[2] });
283
406
  }
284
407
  }
285
408
  const base = await this.readStage(repoPath, hashes.get("1"));
@@ -294,12 +417,41 @@ export class GitCliAdapter {
294
417
  binary: present.some((s) => s.content === null),
295
418
  };
296
419
  }
297
- async readStage(repoPath, hash) {
298
- if (hash === undefined)
299
- return { hash: null, content: null, bytes: 0 };
420
+ async indexEntry(repoPath, path) {
421
+ const listed = await this.mustRun(`ls-files -s ${path}`, ["ls-files", "-s", "--", path], repoPath);
422
+ const match = /^(\d{6}) ([0-9a-f]{40}|[0-9a-f]{64}) 0\t/.exec(listed.stdout);
423
+ return match?.[1] && match[2] ? { mode: match[1], hash: match[2] } : null;
424
+ }
425
+ async isWorktreeCleanPath(repoPath, path) {
426
+ const result = await this.process.run("git", ["diff", "--quiet", "--", path], this.opts(repoPath));
427
+ if (result.code === 0)
428
+ return true;
429
+ if (result.code === 1)
430
+ return false;
431
+ throw this.failed(`diff --quiet ${path}`, repoPath, result.stderr);
432
+ }
433
+ async readBlob(repoPath, hash) {
434
+ const stage = await this.readStage(repoPath, { hash, mode: "100644" });
435
+ return { content: stage.content, bytes: stage.bytes };
436
+ }
437
+ async hashBlob(repoPath, content) {
438
+ const result = await this.mustRun("hash-object", ["hash-object", "-w", "--no-filters", "--stdin"], repoPath, { stdin: content });
439
+ return result.stdout.trim();
440
+ }
441
+ async setIndexEntry(repoPath, path, mode, hash) {
442
+ await this.mustRun(`update-index ${path}`, ["update-index", "--add", "--cacheinfo", `${mode},${hash},${path}`], repoPath);
443
+ await this.mustRun(`checkout-index ${path}`, ["checkout-index", "-f", "--", path], repoPath);
444
+ }
445
+ async removeIndexEntry(repoPath, path) {
446
+ await this.mustRun(`update-index --force-remove ${path}`, ["update-index", "--force-remove", "--", path], repoPath);
447
+ }
448
+ async readStage(repoPath, entry) {
449
+ if (entry === undefined)
450
+ return { hash: null, content: null, bytes: 0, mode: null };
451
+ const { hash, mode } = entry;
300
452
  const result = await this.process.runBinary("git", ["cat-file", "-p", hash], this.opts(repoPath));
301
453
  if (result.code !== 0)
302
- return { hash, content: null, bytes: 0 };
454
+ return { hash, content: null, bytes: 0, mode };
303
455
  // A NUL byte is the same heuristic git itself uses to call a blob binary.
304
456
  const binary = result.stdout.includes(0);
305
457
  // The size is the bytes git stored, which a decoded blob no longer measures.
@@ -307,6 +459,7 @@ export class GitCliAdapter {
307
459
  hash,
308
460
  content: binary ? null : result.stdout.toString("utf8"),
309
461
  bytes: result.stdout.length,
462
+ mode,
310
463
  };
311
464
  }
312
465
  async stagePath(repoPath, path) {
@@ -329,6 +482,71 @@ export class GitCliAdapter {
329
482
  parents: await this.parentsOf(repoPath, after),
330
483
  };
331
484
  }
485
+ async commitPaths(repoPath, message, paths) {
486
+ if (paths.length === 0 ||
487
+ paths.some((path) => path.length === 0 ||
488
+ path.startsWith("-") ||
489
+ path.includes("\0") ||
490
+ !checkSafeRelativePath(path).ok)) {
491
+ throw new Error("git commitPaths exige rutas relativas explícitas no vacías");
492
+ }
493
+ const before = await this.headSha(repoPath);
494
+ await this.mustRun("add -- paths", ["add", "--", ...paths], repoPath);
495
+ await this.mustRun("commit --only -- paths", ["commit", "--only", "-m", message, "--", ...paths], repoPath);
496
+ const after = await this.headSha(repoPath);
497
+ if (after === null || after === before)
498
+ throw new Error(`git commitPaths no movió HEAD en ${repoPath}`);
499
+ return {
500
+ branch: (await this.currentBranch(repoPath)) ?? null,
501
+ before,
502
+ after,
503
+ parents: await this.parentsOf(repoPath, after),
504
+ };
505
+ }
506
+ async dirtyPaths(repoPath) {
507
+ const changes = await this.localChanges(repoPath);
508
+ const byPath = new Map();
509
+ for (const change of changes) {
510
+ const files = [change.path, ...(change.from === null ? [] : [change.from])];
511
+ for (const path of files) {
512
+ const absolute = resolve(repoPath, path);
513
+ let bytes = "deleted";
514
+ try {
515
+ const stats = await lstat(absolute);
516
+ bytes = stats.isSymbolicLink() ? await readlink(absolute) : await readFile(absolute);
517
+ }
518
+ catch (error) {
519
+ if (error.code !== "ENOENT")
520
+ throw error;
521
+ }
522
+ const digest = createHash("sha256")
523
+ .update(change.code)
524
+ .update("\0")
525
+ .update(change.head_mode ?? "")
526
+ .update("\0")
527
+ .update(change.worktree_mode ?? "")
528
+ .update("\0")
529
+ .update(bytes)
530
+ .digest("hex");
531
+ byPath.set(path, digest);
532
+ }
533
+ }
534
+ return [...byPath]
535
+ .sort(([left], [right]) => left.localeCompare(right))
536
+ .map(([path, digest]) => ({ path, digest }));
537
+ }
538
+ async commitInfo(repoPath, sha) {
539
+ const [message, changed, parents] = await Promise.all([
540
+ this.mustRun("show --format=%B", ["show", "-s", "--format=%B", sha], repoPath),
541
+ this.mustRun("diff-tree --name-only", ["diff-tree", "--root", "--no-commit-id", "-r", "-z", "--name-only", sha], repoPath),
542
+ this.parentsOf(repoPath, sha),
543
+ ]);
544
+ return {
545
+ message: message.stdout.trimEnd(),
546
+ paths: changed.stdout.split("\0").filter(Boolean).sort(),
547
+ parents,
548
+ };
549
+ }
332
550
  async head(repoPath) {
333
551
  return this.headSha(repoPath);
334
552
  }
@@ -376,6 +594,65 @@ export class GitCliAdapter {
376
594
  return [];
377
595
  return result.stdout.split("\0").filter((p) => p.length > 0);
378
596
  }
597
+ async treeEntries(repoPath, rev) {
598
+ const result = await this.mustRun("ls-tree", ["ls-tree", "-r", "-z", rev], repoPath);
599
+ return result.stdout
600
+ .split("\0")
601
+ .filter(Boolean)
602
+ .map((item) => {
603
+ const match = /^(\d+) blob ([0-9a-f]+)\t(.+)$/s.exec(item);
604
+ if (!match?.[1] || !match[2] || !match[3])
605
+ throw new Error(`entrada ls-tree ilegible en ${repoPath}`);
606
+ return { mode: match[1], hash: match[2], path: match[3] };
607
+ });
608
+ }
609
+ async hashWorktreePath(repoPath, path, symlink) {
610
+ if (symlink) {
611
+ const target = await readlink(path);
612
+ return (await this.mustRun("hash-object", ["hash-object", "--stdin"], repoPath, { stdin: target })).stdout.trim();
613
+ }
614
+ return (await this.mustRun("hash-object", ["hash-object", "--no-filters", path], repoPath)).stdout.trim();
615
+ }
616
+ async worktreeFileMode(path) {
617
+ const stat = await lstat(path);
618
+ if (stat.isSymbolicLink())
619
+ return "120000";
620
+ if (!stat.isFile())
621
+ throw new Error(`no es un archivo recuperable: ${path}`);
622
+ return stat.mode & 0o111 ? "100755" : "100644";
623
+ }
624
+ async ignoredOutsideIndex(repoPath, treePath, relativePath) {
625
+ const gitDir = (await this.mustRun("rev-parse --absolute-git-dir", ["rev-parse", "--absolute-git-dir"], repoPath)).stdout.trim();
626
+ const result = await this.process.run("git", [
627
+ `--git-dir=${gitDir}`,
628
+ `--work-tree=${treePath}`,
629
+ "check-ignore",
630
+ "--no-index",
631
+ "-q",
632
+ "--",
633
+ relativePath,
634
+ ], this.opts(repoPath));
635
+ if (result.code !== 0 && result.code !== 1)
636
+ throw this.failed("check-ignore", repoPath, result.stderr);
637
+ return result.code === 0;
638
+ }
639
+ async ignoredInSource(repoPath, relativePath) {
640
+ const result = await this.process.run("git", ["check-ignore", "--no-index", "-q", "--", relativePath], this.opts(repoPath));
641
+ if (result.code !== 0 && result.code !== 1)
642
+ throw this.failed("check-ignore", repoPath, result.stderr);
643
+ return result.code === 0;
644
+ }
645
+ async excludePattern(repoPath, pattern) {
646
+ const exclude = (await this.mustRun("rev-parse --git-path", ["rev-parse", "--git-path", "info/exclude"], repoPath)).stdout.trim();
647
+ const path = resolve(repoPath, exclude);
648
+ const existing = await readFile(path, "utf8").catch((err) => {
649
+ if (err.code === "ENOENT")
650
+ return "";
651
+ throw err;
652
+ });
653
+ if (!existing.split(/\r?\n/).includes(pattern))
654
+ await appendFile(path, `${existing.length > 0 && !existing.endsWith("\n") ? "\n" : ""}${pattern}\n`);
655
+ }
379
656
  async operationState(repoPath) {
380
657
  // git's own pseudo-refs are the record of an interrupted operation, and asking
381
658
  // git for them keeps this adapter needing only one binary: a `test -d` on
@@ -428,8 +705,8 @@ export class GitCliAdapter {
428
705
  async setRef(repoPath, ref, sha) {
429
706
  return this.attempt("update-ref", ["update-ref", ref, sha], repoPath);
430
707
  }
431
- async deleteRef(repoPath, ref) {
432
- return this.attempt("update-ref -d", ["update-ref", "-d", ref], repoPath);
708
+ async deleteRef(repoPath, ref, expectedOld) {
709
+ return this.attempt("update-ref -d", ["update-ref", "-d", ref, ...(expectedOld ? [expectedOld] : [])], repoPath);
433
710
  }
434
711
  /** Run git and report whether it agreed, with its own words when it did not. */
435
712
  async attempt(label, args, cwd) {
@@ -468,6 +745,16 @@ export class GitCliAdapter {
468
745
  .map((line) => line.trim())
469
746
  .filter((line) => line.length > 0);
470
747
  }
748
+ async upstreamBranch(repoPath, branch) {
749
+ const result = await this.mustRun("for-each-ref upstream", ["for-each-ref", "--format=%(upstream)", `refs/heads/${branch}`], repoPath);
750
+ return result.stdout.trim() || null;
751
+ }
752
+ async readAtRef(repoPath, ref, path) {
753
+ const result = await this.process.run("git", ["show", `${ref}:${path}`], this.opts(repoPath));
754
+ if (result.code !== 0)
755
+ return null;
756
+ return result.stdout;
757
+ }
471
758
  async originFetchRefspecs(repoPath) {
472
759
  const result = await this.process.run("git", ["config", "--get-all", "remote.origin.fetch"], this.opts(repoPath));
473
760
  // `config --get-all` exits 1 when the key is unset: no refspec, not a failure.