dorfl 0.14.2 → 0.15.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 (418) hide show
  1. package/dist/advance-ci-template.d.ts +17 -16
  2. package/dist/advance-ci-template.d.ts.map +1 -1
  3. package/dist/advance-ci-template.js +42 -53
  4. package/dist/advance-ci-template.js.map +1 -1
  5. package/dist/advance-drivers.d.ts +8 -0
  6. package/dist/advance-drivers.d.ts.map +1 -1
  7. package/dist/advance-drivers.js +28 -4
  8. package/dist/advance-drivers.js.map +1 -1
  9. package/dist/advance-isolated.d.ts.map +1 -1
  10. package/dist/advance-isolated.js +3 -2
  11. package/dist/advance-isolated.js.map +1 -1
  12. package/dist/advance-lifecycle-template.d.ts +41 -40
  13. package/dist/advance-lifecycle-template.d.ts.map +1 -1
  14. package/dist/advance-lifecycle-template.js +309 -489
  15. package/dist/advance-lifecycle-template.js.map +1 -1
  16. package/dist/advance-loop-driver.d.ts.map +1 -1
  17. package/dist/advance-loop-driver.js +3 -2
  18. package/dist/advance-loop-driver.js.map +1 -1
  19. package/dist/advance-treeless-publish.d.ts +31 -0
  20. package/dist/advance-treeless-publish.d.ts.map +1 -1
  21. package/dist/advance-treeless-publish.js +40 -0
  22. package/dist/advance-treeless-publish.js.map +1 -1
  23. package/dist/advance.d.ts +63 -3
  24. package/dist/advance.d.ts.map +1 -1
  25. package/dist/advance.js +80 -12
  26. package/dist/advance.js.map +1 -1
  27. package/dist/advancing-lock.d.ts +9 -0
  28. package/dist/advancing-lock.d.ts.map +1 -1
  29. package/dist/advancing-lock.js +21 -1
  30. package/dist/advancing-lock.js.map +1 -1
  31. package/dist/agent-env.d.ts +61 -0
  32. package/dist/agent-env.d.ts.map +1 -0
  33. package/dist/agent-env.js +144 -0
  34. package/dist/agent-env.js.map +1 -0
  35. package/dist/agent-stop.d.ts +35 -0
  36. package/dist/agent-stop.d.ts.map +1 -1
  37. package/dist/agent-stop.js +62 -0
  38. package/dist/agent-stop.js.map +1 -1
  39. package/dist/apply-merge-action.d.ts +76 -34
  40. package/dist/apply-merge-action.d.ts.map +1 -1
  41. package/dist/apply-merge-action.js +339 -129
  42. package/dist/apply-merge-action.js.map +1 -1
  43. package/dist/apply-stuck-action.js +2 -2
  44. package/dist/apply-stuck-action.js.map +1 -1
  45. package/dist/ci-agent-result.d.ts +151 -0
  46. package/dist/ci-agent-result.d.ts.map +1 -0
  47. package/dist/ci-agent-result.js +314 -0
  48. package/dist/ci-agent-result.js.map +1 -0
  49. package/dist/ci-handoff-apply.d.ts +162 -0
  50. package/dist/ci-handoff-apply.d.ts.map +1 -0
  51. package/dist/ci-handoff-apply.js +497 -0
  52. package/dist/ci-handoff-apply.js.map +1 -0
  53. package/dist/ci-handoff-format.d.ts +369 -0
  54. package/dist/ci-handoff-format.d.ts.map +1 -0
  55. package/dist/ci-handoff-format.js +646 -0
  56. package/dist/ci-handoff-format.js.map +1 -0
  57. package/dist/ci-handoff-lfs.d.ts +146 -0
  58. package/dist/ci-handoff-lfs.d.ts.map +1 -0
  59. package/dist/ci-handoff-lfs.js +397 -0
  60. package/dist/ci-handoff-lfs.js.map +1 -0
  61. package/dist/ci-handoff.d.ts +99 -0
  62. package/dist/ci-handoff.d.ts.map +1 -0
  63. package/dist/ci-handoff.js +277 -0
  64. package/dist/ci-handoff.js.map +1 -0
  65. package/dist/ci-lock-outputs.d.ts +93 -0
  66. package/dist/ci-lock-outputs.d.ts.map +1 -0
  67. package/dist/ci-lock-outputs.js +223 -0
  68. package/dist/ci-lock-outputs.js.map +1 -0
  69. package/dist/ci-phase-build.d.ts +178 -0
  70. package/dist/ci-phase-build.d.ts.map +1 -0
  71. package/dist/ci-phase-build.js +989 -0
  72. package/dist/ci-phase-build.js.map +1 -0
  73. package/dist/ci-phase-driver.d.ts +247 -0
  74. package/dist/ci-phase-driver.d.ts.map +1 -0
  75. package/dist/ci-phase-driver.js +370 -0
  76. package/dist/ci-phase-driver.js.map +1 -0
  77. package/dist/ci-phase-intake.d.ts +172 -0
  78. package/dist/ci-phase-intake.d.ts.map +1 -0
  79. package/dist/ci-phase-intake.js +555 -0
  80. package/dist/ci-phase-intake.js.map +1 -0
  81. package/dist/ci-phase-tasking.d.ts +205 -0
  82. package/dist/ci-phase-tasking.d.ts.map +1 -0
  83. package/dist/ci-phase-tasking.js +906 -0
  84. package/dist/ci-phase-tasking.js.map +1 -0
  85. package/dist/ci-phase-treeless.d.ts +224 -0
  86. package/dist/ci-phase-treeless.d.ts.map +1 -0
  87. package/dist/ci-phase-treeless.js +1482 -0
  88. package/dist/ci-phase-treeless.js.map +1 -0
  89. package/dist/ci-read-token.d.ts +47 -0
  90. package/dist/ci-read-token.d.ts.map +1 -0
  91. package/dist/ci-read-token.js +80 -0
  92. package/dist/ci-read-token.js.map +1 -0
  93. package/dist/cli.d.ts.map +1 -1
  94. package/dist/cli.js +447 -22
  95. package/dist/cli.js.map +1 -1
  96. package/dist/close-job-template.d.ts +10 -1
  97. package/dist/close-job-template.d.ts.map +1 -1
  98. package/dist/close-job-template.js +46 -14
  99. package/dist/close-job-template.js.map +1 -1
  100. package/dist/close-job.d.ts +20 -5
  101. package/dist/close-job.d.ts.map +1 -1
  102. package/dist/close-job.js +65 -12
  103. package/dist/close-job.js.map +1 -1
  104. package/dist/complete.d.ts.map +1 -1
  105. package/dist/complete.js +20 -1
  106. package/dist/complete.js.map +1 -1
  107. package/dist/config.d.ts +41 -44
  108. package/dist/config.d.ts.map +1 -1
  109. package/dist/config.js +2 -4
  110. package/dist/config.js.map +1 -1
  111. package/dist/continue-branch.d.ts +63 -15
  112. package/dist/continue-branch.d.ts.map +1 -1
  113. package/dist/continue-branch.js +75 -8
  114. package/dist/continue-branch.js.map +1 -1
  115. package/dist/crashed-run-save.d.ts +73 -0
  116. package/dist/crashed-run-save.d.ts.map +1 -0
  117. package/dist/crashed-run-save.js +86 -0
  118. package/dist/crashed-run-save.js.map +1 -0
  119. package/dist/cwd-section.d.ts.map +1 -1
  120. package/dist/cwd-section.js +10 -2
  121. package/dist/cwd-section.js.map +1 -1
  122. package/dist/decision-engine.d.ts +10 -0
  123. package/dist/decision-engine.d.ts.map +1 -1
  124. package/dist/decision-engine.js.map +1 -1
  125. package/dist/do-config.d.ts +2 -24
  126. package/dist/do-config.d.ts.map +1 -1
  127. package/dist/do-config.js +1 -33
  128. package/dist/do-config.js.map +1 -1
  129. package/dist/do.d.ts +149 -1
  130. package/dist/do.d.ts.map +1 -1
  131. package/dist/do.js +115 -25
  132. package/dist/do.js.map +1 -1
  133. package/dist/dorfl-item-template.d.ts +98 -0
  134. package/dist/dorfl-item-template.d.ts.map +1 -0
  135. package/dist/dorfl-item-template.js +504 -0
  136. package/dist/dorfl-item-template.js.map +1 -0
  137. package/dist/env-config.d.ts.map +1 -1
  138. package/dist/env-config.js +7 -5
  139. package/dist/env-config.js.map +1 -1
  140. package/dist/frontmatter.d.ts +52 -0
  141. package/dist/frontmatter.d.ts.map +1 -1
  142. package/dist/frontmatter.js +136 -2
  143. package/dist/frontmatter.js.map +1 -1
  144. package/dist/gc.d.ts +13 -0
  145. package/dist/gc.d.ts.map +1 -1
  146. package/dist/gc.js +16 -2
  147. package/dist/gc.js.map +1 -1
  148. package/dist/git.d.ts +18 -1
  149. package/dist/git.d.ts.map +1 -1
  150. package/dist/git.js +70 -5
  151. package/dist/git.js.map +1 -1
  152. package/dist/harness.d.ts +44 -5
  153. package/dist/harness.d.ts.map +1 -1
  154. package/dist/harness.js +24 -1
  155. package/dist/harness.js.map +1 -1
  156. package/dist/index.d.ts +11 -4
  157. package/dist/index.d.ts.map +1 -1
  158. package/dist/index.js +7 -3
  159. package/dist/index.js.map +1 -1
  160. package/dist/install-ci-action-pins.d.ts +123 -0
  161. package/dist/install-ci-action-pins.d.ts.map +1 -0
  162. package/dist/install-ci-action-pins.js +190 -0
  163. package/dist/install-ci-action-pins.js.map +1 -0
  164. package/dist/install-ci-actions-pr-creation.d.ts +70 -0
  165. package/dist/install-ci-actions-pr-creation.d.ts.map +1 -0
  166. package/dist/install-ci-actions-pr-creation.js +106 -0
  167. package/dist/install-ci-actions-pr-creation.js.map +1 -0
  168. package/dist/install-ci-capabilities/dorfl-item.d.ts +12 -0
  169. package/dist/install-ci-capabilities/dorfl-item.d.ts.map +1 -0
  170. package/dist/install-ci-capabilities/dorfl-item.js +26 -0
  171. package/dist/install-ci-capabilities/dorfl-item.js.map +1 -0
  172. package/dist/install-ci-core.d.ts +155 -37
  173. package/dist/install-ci-core.d.ts.map +1 -1
  174. package/dist/install-ci-core.js +304 -200
  175. package/dist/install-ci-core.js.map +1 -1
  176. package/dist/install-ci-github.d.ts +47 -2
  177. package/dist/install-ci-github.d.ts.map +1 -1
  178. package/dist/install-ci-github.js +113 -1
  179. package/dist/install-ci-github.js.map +1 -1
  180. package/dist/install-ci.d.ts +25 -6
  181. package/dist/install-ci.d.ts.map +1 -1
  182. package/dist/install-ci.js +72 -36
  183. package/dist/install-ci.js.map +1 -1
  184. package/dist/intake-marker.d.ts +6 -1
  185. package/dist/intake-marker.d.ts.map +1 -1
  186. package/dist/intake-marker.js.map +1 -1
  187. package/dist/intake-triage.d.ts.map +1 -1
  188. package/dist/intake-triage.js +6 -2
  189. package/dist/intake-triage.js.map +1 -1
  190. package/dist/intake-trigger-template.d.ts +31 -25
  191. package/dist/intake-trigger-template.d.ts.map +1 -1
  192. package/dist/intake-trigger-template.js +107 -292
  193. package/dist/intake-trigger-template.js.map +1 -1
  194. package/dist/intake.d.ts +186 -4
  195. package/dist/intake.d.ts.map +1 -1
  196. package/dist/intake.js +533 -416
  197. package/dist/intake.js.map +1 -1
  198. package/dist/integration-core.d.ts +154 -1
  199. package/dist/integration-core.d.ts.map +1 -1
  200. package/dist/integration-core.js +759 -486
  201. package/dist/integration-core.js.map +1 -1
  202. package/dist/integrator.d.ts +12 -0
  203. package/dist/integrator.d.ts.map +1 -1
  204. package/dist/integrator.js +21 -0
  205. package/dist/integrator.js.map +1 -1
  206. package/dist/isolation.d.ts +12 -2
  207. package/dist/isolation.d.ts.map +1 -1
  208. package/dist/isolation.js +19 -8
  209. package/dist/isolation.js.map +1 -1
  210. package/dist/item-lock.d.ts +93 -11
  211. package/dist/item-lock.d.ts.map +1 -1
  212. package/dist/item-lock.js +233 -65
  213. package/dist/item-lock.js.map +1 -1
  214. package/dist/land-question-residue.d.ts +58 -0
  215. package/dist/land-question-residue.d.ts.map +1 -0
  216. package/dist/land-question-residue.js +95 -0
  217. package/dist/land-question-residue.js.map +1 -0
  218. package/dist/lifecycle-gather.d.ts +16 -0
  219. package/dist/lifecycle-gather.d.ts.map +1 -1
  220. package/dist/lifecycle-gather.js +54 -6
  221. package/dist/lifecycle-gather.js.map +1 -1
  222. package/dist/merge-answer.d.ts +41 -0
  223. package/dist/merge-answer.d.ts.map +1 -0
  224. package/dist/merge-answer.js +60 -0
  225. package/dist/merge-answer.js.map +1 -0
  226. package/dist/merge-question-surfacer.d.ts +105 -30
  227. package/dist/merge-question-surfacer.d.ts.map +1 -1
  228. package/dist/merge-question-surfacer.js +202 -91
  229. package/dist/merge-question-surfacer.js.map +1 -1
  230. package/dist/merge-question-tick.d.ts +64 -0
  231. package/dist/merge-question-tick.d.ts.map +1 -0
  232. package/dist/merge-question-tick.js +96 -0
  233. package/dist/merge-question-tick.js.map +1 -0
  234. package/dist/mint-adr.d.ts.map +1 -1
  235. package/dist/mint-adr.js +20 -2
  236. package/dist/mint-adr.js.map +1 -1
  237. package/dist/needs-attention.d.ts +72 -2
  238. package/dist/needs-attention.d.ts.map +1 -1
  239. package/dist/needs-attention.js +275 -38
  240. package/dist/needs-attention.js.map +1 -1
  241. package/dist/phase-recorder.d.ts +168 -0
  242. package/dist/phase-recorder.d.ts.map +1 -0
  243. package/dist/phase-recorder.js +218 -0
  244. package/dist/phase-recorder.js.map +1 -0
  245. package/dist/phase.d.ts +94 -0
  246. package/dist/phase.d.ts.map +1 -0
  247. package/dist/phase.js +148 -0
  248. package/dist/phase.js.map +1 -0
  249. package/dist/pi-harness.d.ts.map +1 -1
  250. package/dist/pi-harness.js +19 -6
  251. package/dist/pi-harness.js.map +1 -1
  252. package/dist/prepare.d.ts.map +1 -1
  253. package/dist/prepare.js +4 -0
  254. package/dist/prepare.js.map +1 -1
  255. package/dist/prompt.d.ts +4 -0
  256. package/dist/prompt.d.ts.map +1 -1
  257. package/dist/prompt.js +48 -1
  258. package/dist/prompt.js.map +1 -1
  259. package/dist/protocol/CLAIM-PROTOCOL.md +3 -1
  260. package/dist/protocol/WORK-CONTRACT.md +1 -1
  261. package/dist/reap-branches.d.ts +48 -0
  262. package/dist/reap-branches.d.ts.map +1 -1
  263. package/dist/reap-branches.js +64 -0
  264. package/dist/reap-branches.js.map +1 -1
  265. package/dist/ref-write.d.ts +198 -0
  266. package/dist/ref-write.d.ts.map +1 -0
  267. package/dist/ref-write.js +79 -0
  268. package/dist/ref-write.js.map +1 -0
  269. package/dist/repo-config.js +8 -8
  270. package/dist/repo-config.js.map +1 -1
  271. package/dist/repo-mirror.d.ts +36 -0
  272. package/dist/repo-mirror.d.ts.map +1 -1
  273. package/dist/repo-mirror.js +91 -1
  274. package/dist/repo-mirror.js.map +1 -1
  275. package/dist/review-verdict.d.ts +1 -1
  276. package/dist/review-verdict.js +1 -1
  277. package/dist/run.d.ts +7 -1
  278. package/dist/run.d.ts.map +1 -1
  279. package/dist/run.js +28 -4
  280. package/dist/run.js.map +1 -1
  281. package/dist/scan.d.ts +19 -1
  282. package/dist/scan.d.ts.map +1 -1
  283. package/dist/scan.js +21 -8
  284. package/dist/scan.js.map +1 -1
  285. package/dist/sidecar.d.ts +14 -0
  286. package/dist/sidecar.d.ts.map +1 -1
  287. package/dist/sidecar.js +21 -0
  288. package/dist/sidecar.js.map +1 -1
  289. package/dist/single-job-warning.d.ts +63 -0
  290. package/dist/single-job-warning.d.ts.map +1 -0
  291. package/dist/single-job-warning.js +110 -0
  292. package/dist/single-job-warning.js.map +1 -0
  293. package/dist/skills/setup/protocol/CLAIM-PROTOCOL.md +3 -1
  294. package/dist/skills/setup/protocol/WORK-CONTRACT.md +1 -1
  295. package/dist/spec-complete.d.ts +13 -6
  296. package/dist/spec-complete.d.ts.map +1 -1
  297. package/dist/spec-complete.js +23 -11
  298. package/dist/spec-complete.js.map +1 -1
  299. package/dist/start.d.ts.map +1 -1
  300. package/dist/start.js +47 -14
  301. package/dist/start.js.map +1 -1
  302. package/dist/status.d.ts +12 -0
  303. package/dist/status.d.ts.map +1 -1
  304. package/dist/status.js +11 -3
  305. package/dist/status.js.map +1 -1
  306. package/dist/tasking.d.ts +246 -1
  307. package/dist/tasking.d.ts.map +1 -1
  308. package/dist/tasking.js +452 -358
  309. package/dist/tasking.js.map +1 -1
  310. package/dist/triage-persist.d.ts.map +1 -1
  311. package/dist/triage-persist.js +21 -2
  312. package/dist/triage-persist.js.map +1 -1
  313. package/dist/verify-workflow-template.d.ts.map +1 -1
  314. package/dist/verify-workflow-template.js +8 -4
  315. package/dist/verify-workflow-template.js.map +1 -1
  316. package/dist/verify.d.ts.map +1 -1
  317. package/dist/verify.js +4 -0
  318. package/dist/verify.js.map +1 -1
  319. package/dist/watch-session.d.ts +42 -13
  320. package/dist/watch-session.d.ts.map +1 -1
  321. package/dist/watch-session.js +52 -23
  322. package/dist/watch-session.js.map +1 -1
  323. package/dist/work-layout.d.ts +10 -4
  324. package/dist/work-layout.d.ts.map +1 -1
  325. package/dist/work-layout.js +11 -3
  326. package/dist/work-layout.js.map +1 -1
  327. package/dist/workspace.d.ts +65 -4
  328. package/dist/workspace.d.ts.map +1 -1
  329. package/dist/workspace.js +159 -11
  330. package/dist/workspace.js.map +1 -1
  331. package/package.json +1 -1
  332. package/src/advance-ci-template.ts +80 -81
  333. package/src/advance-drivers.ts +45 -6
  334. package/src/advance-isolated.ts +3 -5
  335. package/src/advance-lifecycle-template.ts +375 -538
  336. package/src/advance-loop-driver.ts +3 -5
  337. package/src/advance-treeless-publish.ts +61 -0
  338. package/src/advance.ts +145 -15
  339. package/src/advancing-lock.ts +36 -1
  340. package/src/agent-env.ts +174 -0
  341. package/src/agent-stop.ts +81 -0
  342. package/src/apply-merge-action.ts +401 -154
  343. package/src/apply-stuck-action.ts +2 -2
  344. package/src/ci-agent-result.ts +421 -0
  345. package/src/ci-handoff-apply.ts +737 -0
  346. package/src/ci-handoff-format.ts +926 -0
  347. package/src/ci-handoff-lfs.ts +519 -0
  348. package/src/ci-handoff.ts +392 -0
  349. package/src/ci-lock-outputs.ts +273 -0
  350. package/src/ci-phase-build.ts +1328 -0
  351. package/src/ci-phase-driver.ts +548 -0
  352. package/src/ci-phase-intake.ts +861 -0
  353. package/src/ci-phase-tasking.ts +1255 -0
  354. package/src/ci-phase-treeless.ts +2028 -0
  355. package/src/ci-read-token.ts +90 -0
  356. package/src/cli.ts +591 -29
  357. package/src/close-job-template.ts +52 -15
  358. package/src/close-job.ts +77 -12
  359. package/src/complete.ts +19 -1
  360. package/src/config.ts +43 -48
  361. package/src/continue-branch.ts +121 -16
  362. package/src/crashed-run-save.ts +162 -0
  363. package/src/cwd-section.ts +10 -0
  364. package/src/decision-engine.ts +10 -0
  365. package/src/do-config.ts +2 -57
  366. package/src/do.ts +170 -28
  367. package/src/dorfl-item-template.ts +556 -0
  368. package/src/env-config.ts +7 -5
  369. package/src/frontmatter.ts +155 -2
  370. package/src/gc.ts +27 -2
  371. package/src/git.ts +83 -5
  372. package/src/harness.ts +58 -6
  373. package/src/index.ts +50 -1
  374. package/src/install-ci-action-pins.ts +209 -0
  375. package/src/install-ci-actions-pr-creation.ts +186 -0
  376. package/src/install-ci-capabilities/dorfl-item.ts +33 -0
  377. package/src/install-ci-core.ts +388 -233
  378. package/src/install-ci-github.ts +149 -1
  379. package/src/install-ci.ts +83 -37
  380. package/src/intake-marker.ts +6 -1
  381. package/src/intake-triage.ts +7 -3
  382. package/src/intake-trigger-template.ts +126 -327
  383. package/src/intake.ts +725 -544
  384. package/src/integration-core.ts +975 -523
  385. package/src/integrator.ts +28 -0
  386. package/src/isolation.ts +29 -10
  387. package/src/item-lock.ts +308 -92
  388. package/src/land-question-residue.ts +122 -0
  389. package/src/lifecycle-gather.ts +82 -10
  390. package/src/merge-answer.ts +82 -0
  391. package/src/merge-question-surfacer.ts +320 -112
  392. package/src/merge-question-tick.ts +182 -0
  393. package/src/mint-adr.ts +28 -2
  394. package/src/needs-attention.ts +350 -42
  395. package/src/phase-recorder.ts +350 -0
  396. package/src/phase.ts +177 -0
  397. package/src/pi-harness.ts +25 -5
  398. package/src/prepare.ts +4 -0
  399. package/src/prompt.ts +68 -1
  400. package/src/reap-branches.ts +107 -0
  401. package/src/ref-write.ts +324 -0
  402. package/src/repo-config.ts +8 -8
  403. package/src/repo-mirror.ts +107 -1
  404. package/src/review-verdict.ts +1 -1
  405. package/src/run.ts +47 -6
  406. package/src/scan.ts +37 -7
  407. package/src/sidecar.ts +36 -0
  408. package/src/single-job-warning.ts +135 -0
  409. package/src/spec-complete.ts +36 -14
  410. package/src/start.ts +55 -16
  411. package/src/status.ts +29 -3
  412. package/src/tasking.ts +593 -378
  413. package/src/triage-persist.ts +24 -2
  414. package/src/verify-workflow-template.ts +8 -4
  415. package/src/verify.ts +4 -0
  416. package/src/watch-session.ts +86 -28
  417. package/src/work-layout.ts +11 -3
  418. package/src/workspace.ts +210 -14
package/src/do.ts CHANGED
@@ -1,8 +1,10 @@
1
+ import type {Phase} from './phase.js';
2
+ import {continueRebaseSentence} from './continue-branch.js';
1
3
  import {existsSync, mkdirSync, readFileSync, rmSync} from 'node:fs';
2
4
  import {dirname, join} from 'node:path';
3
5
  import {performStart} from './start.js';
4
6
  import {performComplete} from './complete.js';
5
- import {performClaim} from './claim-cas.js';
7
+ import {performClaim, type ClaimCasResult} from './claim-cas.js';
6
8
  import {
7
9
  resolveSlug,
8
10
  SlugResolutionError,
@@ -20,6 +22,7 @@ import {
20
22
  import {
21
23
  NullHarness,
22
24
  type AgentTreeReap,
25
+ type CutOffTurn,
23
26
  type Harness,
24
27
  type HarnessRecord,
25
28
  } from './harness.js';
@@ -38,7 +41,11 @@ import {
38
41
  type IsolatedTree,
39
42
  } from './isolation.js';
40
43
  import {ensureMirror, encodeRepoKey, mirrorPath} from './repo-mirror.js';
41
- import {jobWorktreePath, updateJobRecord} from './workspace.js';
44
+ import {
45
+ jobWorktreePath,
46
+ RetainedWorktreeUnsavedWorkError,
47
+ updateJobRecord,
48
+ } from './workspace.js';
42
49
  import {reapJob} from './gc.js';
43
50
  import {isGitHubArbiterUrl, GitHubProvider} from './github.js';
44
51
  import type {ReviewProvider} from './integrator.js';
@@ -66,12 +73,12 @@ import {
66
73
  isWorkBranchDiffEmpty,
67
74
  emptyDiffStopReason,
68
75
  emptyDiffDisposeEnvelope,
76
+ resolveCutOffTurnFailure,
69
77
  type AgentStopClass,
70
78
  } from './agent-stop.js';
71
- import {
72
- surfaceStuckToNeedsAttention,
73
- routeToNeedsAttention,
74
- } from './needs-attention.js';
79
+ import {surfaceStuckToNeedsAttention} from './needs-attention.js';
80
+ import {refWrite} from './ref-write.js';
81
+ import {annotatePhaseBoundary} from './phase-recorder.js';
75
82
  import {resolveItemPathByIdentity} from './item-path.js';
76
83
  import {
77
84
  classifyFailureCause,
@@ -159,7 +166,7 @@ function deadlineAutoContinueReason(params: {
159
166
  `tick continues from the branch tip.`
160
167
  );
161
168
  }
162
- function deadlineSurfaceReason(params: {
169
+ export function deadlineSurfaceReason(params: {
163
170
  slug: string;
164
171
  kind: 'no-progress' | 'ceiling' | 'unreaped';
165
172
  count?: number;
@@ -278,8 +285,10 @@ async function saveDeadlineCheckpoint(params: {
278
285
  // Push the branch to the arbiter (best-effort). Reuse routeToNeedsAttention's
279
286
  // save-half exact contract: it commits any residue + pushes the branch with
280
287
  // bounded backoff. We already committed above; the wip commit inside
281
- // routeToNeedsAttention will be a no-op (clean tree) and the push runs.
282
- return routeToNeedsAttention({
288
+ // routeToNeedsAttention will be a no-op (clean tree) and the push runs. It
289
+ // is reached through the ref-write seam (`refWrite.saveWorkBranch`) so the
290
+ // branch push is visible to the CI phase mode.
291
+ return refWrite.saveWorkBranch({
283
292
  cwd,
284
293
  slug,
285
294
  reason: `deadline-checkpoint save for '${slug}' (see branch)`,
@@ -290,6 +299,26 @@ async function saveDeadlineCheckpoint(params: {
290
299
  });
291
300
  }
292
301
 
302
+ /**
303
+ * What a build's FIRST WRITE is, when the write seam call alone does not say
304
+ * (CI phase mode, task `ci-split-build-path-non-integrate-intents`): an agent
305
+ * failure, a deliberate STOP and a red gate all bounce through
306
+ * `ledgerWrite.applyNeedsAttentionTransition`, and the deadline checkpoint's
307
+ * first write is a plain branch save. The pipeline names it with
308
+ * `annotatePhaseBoundary` right before the write; the build phase driver
309
+ * (`ci-phase-build.ts`) maps it to a handoff intent. Without a phase it is
310
+ * never read.
311
+ */
312
+ export type BuildBoundary =
313
+ | {kind: 'agent-failed'; failureDetail: string}
314
+ | {kind: 'stop'; reason: string; stopKind: 'sentinel' | 'empty-diff'}
315
+ | {
316
+ kind: 'deadline-checkpoint';
317
+ /** Whether the checkpointed agent's process tree was verified gone. */
318
+ predecessorGone: boolean;
319
+ reapDetail?: string;
320
+ };
321
+
293
322
  /** The terminal status of one in-place `do` run. */
294
323
  export type DoOutcome =
295
324
  | 'completed' // claimed/onboarded → agent → gate green → integrated → exited
@@ -362,6 +391,14 @@ export type DoDorfl = (input: {
362
391
  * Absent ⇒ nothing was left running (the pre-existing behaviour).
363
392
  */
364
393
  reap?: AgentTreeReap;
394
+ /**
395
+ * **The agent's final model turn was CUT OFF** (`length` / `error` stop; the
396
+ * harness seam's `LaunchResult.cutOffTurn`, task
397
+ * `a-truncated-agent-turn-routes-as-agent-failed`). An empty diff with this
398
+ * set routes `agent-failed`, never the empty-diff STOP. Lets an injected agent
399
+ * drive that routing; production reads it off the pi session log.
400
+ */
401
+ cutOffTurn?: CutOffTurn;
365
402
  };
366
403
 
367
404
  export interface DoOptions {
@@ -602,6 +639,13 @@ export interface DoOptions {
602
639
  env?: NodeJS.ProcessEnv;
603
640
  /** Sink for human-readable progress notes. */
604
641
  note?: (message: string) => void;
642
+ /**
643
+ * The CI phase this run executes as (`--phase lock|agent|apply`, CI-only;
644
+ * see `phase.ts`). `undefined` ⇒ today's single process. Threaded next to
645
+ * `env` and `note` so the per-path phase splits can branch on it; the phase
646
+ * guards read the process-wide active phase.
647
+ */
648
+ phase?: Phase;
605
649
  /**
606
650
  * Sink for a pre-formatted block printed VERBATIM (forwarded to `complete`'s
607
651
  * propose-mode next-step block). Defaults to `note`.
@@ -1146,17 +1190,25 @@ export async function performDo(options: DoOptions): Promise<DoResult> {
1146
1190
  // fresh-main `work/<slug>` switch, incl. the §14 continue/rebase path)
1147
1191
  // WITHOUT re-claiming — the split the seam mandates (claim → driver,
1148
1192
  // onboarding → strategy).
1149
- const claim = await performClaim({
1150
- slug,
1151
- cwd,
1152
- arbiter,
1153
- // `--allow-backlog`: widen the claimable predicate to ALSO accept a
1154
- // `tasks/backlog/`-resident body. Claim stays a pure lock (writes nothing to
1155
- // `main`, moves nothing); default off ⇒ pool-only, exactly as today.
1156
- allowBacklog: options.allowBacklog === true,
1157
- env,
1158
- note,
1159
- });
1193
+ // CI AGENT PHASE (task `ci-split-build-path`): the lock phase already took
1194
+ // the claim in the job that holds the write token, and the build phase
1195
+ // driver (`ci-phase-build.ts`) checked the lock ref still equals its
1196
+ // `lockSha` before calling here. The agent job cannot write, so it skips
1197
+ // the claim and onboards directly; everything after is unchanged.
1198
+ const claim: ClaimCasResult =
1199
+ options.phase === 'agent'
1200
+ ? {exitCode: 0, outcome: 'claimed', message: 'claimed by the lock phase'}
1201
+ : await performClaim({
1202
+ slug,
1203
+ cwd,
1204
+ arbiter,
1205
+ // `--allow-backlog`: widen the claimable predicate to ALSO accept a
1206
+ // `tasks/backlog/`-resident body. Claim stays a pure lock (writes nothing to
1207
+ // `main`, moves nothing); default off ⇒ pool-only, exactly as today.
1208
+ allowBacklog: options.allowBacklog === true,
1209
+ env,
1210
+ note,
1211
+ });
1160
1212
  if (claim.outcome === 'lost') {
1161
1213
  return {exitCode: 2, outcome: 'lost', slug, message: claim.message};
1162
1214
  }
@@ -1204,8 +1256,9 @@ export async function performDo(options: DoOptions): Promise<DoResult> {
1204
1256
  // did NOT onboard; the runner owns the bounce.
1205
1257
  if (tree.continueRebaseConflict) {
1206
1258
  const reason =
1207
- `continuing the kept ${tree.branch}: rebase onto the latest main ` +
1208
- 'conflicted (aborted, never auto-resolved) — run `requeue --reconcile` ' +
1259
+ `continuing the kept ${tree.branch}: ` +
1260
+ `${continueRebaseSentence(tree.branch, tree.continueRebaseFailure)} — ` +
1261
+ 'run `requeue --reconcile` ' +
1209
1262
  'to non-destructively re-sync the mirror and retry the rebase (keeps ' +
1210
1263
  'the work). Last resort: `requeue --reset` DESTRUCTIVELY discards the ' +
1211
1264
  'branch and starts fresh.';
@@ -1318,6 +1371,7 @@ export async function performDo(options: DoOptions): Promise<DoResult> {
1318
1371
  cwd: tree.dir,
1319
1372
  continueContext,
1320
1373
  promptGuidance: itemGuidance,
1374
+ taskFolder: task.folder,
1321
1375
  });
1322
1376
  } catch (err) {
1323
1377
  if (err instanceof PromptError) {
@@ -1340,6 +1394,7 @@ export async function performDo(options: DoOptions): Promise<DoResult> {
1340
1394
  output?: string;
1341
1395
  timedOut?: boolean;
1342
1396
  reap?: AgentTreeReap;
1397
+ cutOffTurn?: CutOffTurn;
1343
1398
  };
1344
1399
  try {
1345
1400
  agent = await runDoAgent(options, tree.dir, prompt, slug);
@@ -1394,6 +1449,29 @@ export async function performDo(options: DoOptions): Promise<DoResult> {
1394
1449
  // deterministic empty-diff backstop. Either routes to needs-attention and
1395
1450
  // SKIPS the acceptance gate AND Gate-2 — a clean STOP is NOT "a build that
1396
1451
  // changed nothing".
1452
+ // A CUT-OFF final turn (`length`/`error`) with an empty diff is NOT a STOP:
1453
+ // it is a harness failure, routed `agent-failed` (WIP save, requeue-able)
1454
+ // BEFORE the empty-diff backstop can read it as "nothing to build" (task
1455
+ // `a-truncated-agent-turn-routes-as-agent-failed`).
1456
+ const cutOffDetail = await resolveCutOffTurnFailure({
1457
+ cutOffTurn: agent.cutOffTurn,
1458
+ output: agent.output,
1459
+ slug,
1460
+ cwd: tree.dir,
1461
+ arbiter: tree.arbiterRemote,
1462
+ env,
1463
+ });
1464
+ if (cutOffDetail !== undefined) {
1465
+ return await saveAgentFailure({
1466
+ slug,
1467
+ branch,
1468
+ cwd: tree.dir,
1469
+ arbiter: tree.arbiterRemote,
1470
+ detail: cutOffDetail,
1471
+ env,
1472
+ note,
1473
+ });
1474
+ }
1397
1475
  const stopReason = await resolveStopReason({
1398
1476
  output: agent.output,
1399
1477
  slug,
@@ -1726,16 +1804,27 @@ function routeReport(
1726
1804
  * `requeue` (continue) / `requeue --reconcile` (non-destructive retry) vs
1727
1805
  * `requeue --reset` (destructive last resort).
1728
1806
  */
1729
- async function saveAgentFailure(params: {
1807
+ export async function saveAgentFailure(params: {
1730
1808
  slug: string;
1731
1809
  branch: string | undefined;
1732
1810
  cwd: string;
1733
1811
  arbiter: string;
1734
1812
  detail: string;
1813
+ /**
1814
+ * `false`: surface only, push no work branch (the CI apply phase when the
1815
+ * handoff carried no bundle). Default: push, exactly as before.
1816
+ */
1817
+ pushBranch?: boolean;
1735
1818
  env: NodeJS.ProcessEnv | undefined;
1736
1819
  note: (message: string) => void;
1737
1820
  }): Promise<DoResult> {
1738
1821
  const {slug, cwd, arbiter, detail, env, note} = params;
1822
+ // CI agent phase: this bounce is the build's first write; name it so the
1823
+ // phase driver hands it over as `agent-failed` (a no-op without a phase).
1824
+ annotatePhaseBoundary({
1825
+ kind: 'agent-failed',
1826
+ failureDetail: detail,
1827
+ } satisfies BuildBoundary);
1739
1828
  // The work branch is the namespaced build branch (`work/task-<slug>`; the
1740
1829
  // onboarding switched the checkout to it before the agent ran); derive it from
1741
1830
  // the slug so the push target is always defined even when the caller's `branch`
@@ -1761,6 +1850,7 @@ async function saveAgentFailure(params: {
1761
1850
  slug,
1762
1851
  reason,
1763
1852
  arbiter,
1853
+ ...(params.pushBranch === false ? {pushBranch: false} : {}),
1764
1854
  env,
1765
1855
  note,
1766
1856
  });
@@ -1863,18 +1953,27 @@ async function resolveStopReason(params: {
1863
1953
  * rebase conflict). The agent's STOP reason is recorded VERBATIM as the
1864
1954
  * needs-attention reason. The acceptance gate AND Gate-2 are NEVER reached.
1865
1955
  */
1866
- async function saveAgentStop(params: {
1956
+ export async function saveAgentStop(params: {
1867
1957
  slug: string;
1868
1958
  branch: string | undefined;
1869
1959
  cwd: string;
1870
1960
  arbiter: string;
1871
1961
  reason: string;
1872
1962
  kind: 'sentinel' | 'empty-diff';
1963
+ /** As {@link saveAgentFailure}'s `pushBranch` (the sentinel branch only). */
1964
+ pushBranch?: boolean;
1873
1965
  env: NodeJS.ProcessEnv | undefined;
1874
1966
  note: (message: string) => void;
1875
1967
  }): Promise<DoResult> {
1876
1968
  const {slug, cwd, arbiter, reason, kind, env, note} = params;
1877
1969
  const branch = params.branch ?? workBranchRef('task', slug);
1970
+ // CI agent phase: name this first write so the phase driver hands it over as
1971
+ // `stop` (a no-op without a phase).
1972
+ annotatePhaseBoundary({
1973
+ kind: 'stop',
1974
+ reason,
1975
+ stopKind: kind,
1976
+ } satisfies BuildBoundary);
1878
1977
 
1879
1978
  // EMPTY-DIFF branch (spec resolved decision #2, task
1880
1979
  // `empty-diff-bounce-surfaces-dispose-defaulted-question`): surface a sidecar
@@ -1934,6 +2033,7 @@ async function saveAgentStop(params: {
1934
2033
  slug,
1935
2034
  reason,
1936
2035
  arbiter,
2036
+ ...(params.pushBranch === false ? {pushBranch: false} : {}),
1937
2037
  env,
1938
2038
  note,
1939
2039
  });
@@ -1997,6 +2097,8 @@ async function runDoAgent(
1997
2097
  * (observation `deadline-reap-lets-node-exit-0-before-the-checkpoint-runs`).
1998
2098
  */
1999
2099
  record?: HarnessRecord;
2100
+ /** The harness's cut-off-final-turn signal (`LaunchResult.cutOffTurn`). */
2101
+ cutOffTurn?: CutOffTurn;
2000
2102
  }> {
2001
2103
  if (options.dorfl) {
2002
2104
  return options.dorfl({cwd, prompt, slug, env: options.env});
@@ -2047,6 +2149,7 @@ async function launchAgentUnderWriterLock(params: {
2047
2149
  timedOut?: boolean;
2048
2150
  reap?: AgentTreeReap;
2049
2151
  record?: HarnessRecord;
2152
+ cutOffTurn?: CutOffTurn;
2050
2153
  }> {
2051
2154
  const {options, cwd, prompt, slug, harness} = params;
2052
2155
  // Convert the dorfl-internal deadline (minutes) into a wall-clock epoch-ms so
@@ -2091,6 +2194,9 @@ async function launchAgentUnderWriterLock(params: {
2091
2194
  // Threaded to {@link routeDeadlineCheckpoint}, which refuses to release the
2092
2195
  // item lock without it.
2093
2196
  reap: launched.reap,
2197
+ // How the final model turn ended: a `length`/`error` cut-off turns an
2198
+ // empty diff into an agent failure (see `resolveCutOffTurnFailure`).
2199
+ cutOffTurn: launched.cutOffTurn,
2094
2200
  };
2095
2201
  }
2096
2202
 
@@ -2102,7 +2208,7 @@ async function launchAgentUnderWriterLock(params: {
2102
2208
  * Shared by {@link performDo} and {@link runRemotePipeline} so the in-place
2103
2209
  * and remote forms route a deadline stop identically.
2104
2210
  */
2105
- async function routeDeadlineCheckpoint(params: {
2211
+ export async function routeDeadlineCheckpoint(params: {
2106
2212
  slug: string;
2107
2213
  branch: string;
2108
2214
  cwd: string;
@@ -2141,6 +2247,13 @@ async function routeDeadlineCheckpoint(params: {
2141
2247
  if (reap !== undefined && reap.escalatedToSigkill && reap.reaped) {
2142
2248
  note(`Deadline checkpoint for '${slug}': ${reap.detail}`);
2143
2249
  }
2250
+ // CI agent phase: the save below is the first write; name it so the phase
2251
+ // driver hands it over as `deadline-checkpoint` (a no-op without a phase).
2252
+ annotatePhaseBoundary({
2253
+ kind: 'deadline-checkpoint',
2254
+ predecessorGone,
2255
+ ...(reap?.detail === undefined ? {} : {reapDetail: reap.detail}),
2256
+ } satisfies BuildBoundary);
2144
2257
 
2145
2258
  // 1. ALWAYS save the WIP first: commit any residue + push the work branch.
2146
2259
  const savedReason = `deadline checkpoint save for '${slug}'`;
@@ -2625,7 +2738,12 @@ export async function performDoRemote(
2625
2738
  // build's fetch. Best-effort reap the deterministic worktree path for this
2626
2739
  // slug (it is reaped ONLY if its branch is reachable on the arbiter —
2627
2740
  // never lose work), then re-throw so the failure is still reported.
2628
- reapPreparedWorktreeLeak(mirror.url, slug, workspacesDir, env, note);
2741
+ // EXCEPT when `createJob` REFUSED over a retained worktree holding
2742
+ // unsaved work: that tree is the work being protected, not a leak, and
2743
+ // the reachable-only reap would discard its uncommitted changes.
2744
+ if (!(err instanceof RetainedWorktreeUnsavedWorkError)) {
2745
+ reapPreparedWorktreeLeak(mirror.url, slug, workspacesDir, env, note);
2746
+ }
2629
2747
  throw err;
2630
2748
  }
2631
2749
  result = await runRemotePipeline(options, tree, slug, note, env);
@@ -2772,8 +2890,9 @@ async function runRemotePipeline(
2772
2890
  // agent — the §10 path `run` uses.
2773
2891
  if (tree.continueRebaseConflict) {
2774
2892
  const reason =
2775
- `continuing the kept ${tree.branch}: rebase onto the latest main ` +
2776
- 'conflicted (aborted, never auto-resolved) — run `requeue --reconcile` ' +
2893
+ `continuing the kept ${tree.branch}: ` +
2894
+ `${continueRebaseSentence(tree.branch, tree.continueRebaseFailure)} — ` +
2895
+ 'run `requeue --reconcile` ' +
2777
2896
  'to non-destructively re-sync the mirror and retry the rebase (keeps ' +
2778
2897
  'the work). Last resort: `requeue --reset` DESTRUCTIVELY discards the ' +
2779
2898
  'branch and starts fresh.';
@@ -2932,6 +3051,7 @@ async function runRemotePipeline(
2932
3051
  cwd,
2933
3052
  continueContext,
2934
3053
  promptGuidance: itemGuidance,
3054
+ taskFolder: task.folder,
2935
3055
  });
2936
3056
  } catch (err) {
2937
3057
  if (err instanceof PromptError) {
@@ -2955,6 +3075,7 @@ async function runRemotePipeline(
2955
3075
  timedOut?: boolean;
2956
3076
  reap?: AgentTreeReap;
2957
3077
  record?: HarnessRecord;
3078
+ cutOffTurn?: CutOffTurn;
2958
3079
  };
2959
3080
  try {
2960
3081
  agent = await runDoAgent(options, cwd, prompt, slug);
@@ -3015,6 +3136,27 @@ async function runRemotePipeline(
3015
3136
  // sentinel STOP (verbatim reason) or an empty work-branch diff routes to
3016
3137
  // needs-attention (surfaced on the arbiter) and SKIPS the gate + Gate-2. The
3017
3138
  // diff base is the worktree's `origin` (arbiterRemote).
3139
+ // A cut-off final turn with an empty diff is an agent failure, not a STOP
3140
+ // (same guard as in-place `do`).
3141
+ const cutOffDetail = await resolveCutOffTurnFailure({
3142
+ cutOffTurn: agent.cutOffTurn,
3143
+ output: agent.output,
3144
+ slug,
3145
+ cwd,
3146
+ arbiter: arbiterRemote,
3147
+ env,
3148
+ });
3149
+ if (cutOffDetail !== undefined) {
3150
+ return await saveRemoteAgentFailure({
3151
+ slug,
3152
+ branch,
3153
+ cwd,
3154
+ arbiterRemote,
3155
+ detail: cutOffDetail,
3156
+ env,
3157
+ note,
3158
+ });
3159
+ }
3018
3160
  const stopReason = await resolveStopReason({
3019
3161
  output: agent.output,
3020
3162
  slug,