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
@@ -0,0 +1,162 @@
1
+ import {existsSync} from 'node:fs';
2
+ import {run} from './git.js';
3
+ import {evaluateDeletionSafety, RETAIN_REASON_TEXT} from './gc.js';
4
+ import {resolveHarness} from './harness.js';
5
+ // Import for the registration side-effect: ensures the `pi` adapter is in the
6
+ // harness registry so a pi job's liveness is answered by the pi adapter (the
7
+ // same reason `status.ts` imports it).
8
+ import './pi-harness.js';
9
+ import {jobWorktreePath, readJobRecord} from './workspace.js';
10
+ import {workBranchRef} from './slug-namespace.js';
11
+ import {refWrite} from './ref-write.js';
12
+ import type {BackoffOptions, Sleep} from './retry-backoff.js';
13
+
14
+ /**
15
+ * **Save a CRASHED run's local-only work before its lock is released** (task
16
+ * `a-crashed-runs-local-work-is-saved-before-its-lock-is-released`).
17
+ *
18
+ * A `do --isolated` run that is killed mid-agent (a host restart, an OOM kill)
19
+ * leaves its per-item lock `active` and its job worktree RETAINED under
20
+ * `<workspacesDir>/work/<work-id>/`. The runner's own abort handler may already
21
+ * have made the usual wip commit there, but the process died before pushing it,
22
+ * so the work exists ONLY in that worktree. A plain `requeue` then released the
23
+ * lock without saving it, and the next claim (or `gc --force`) cut the worktree
24
+ * away: the work was lost.
25
+ *
26
+ * This is the SAVE step `requeue` runs before it releases a held lock. It
27
+ * locates the slug's retained job worktree by the SAME arbiter-URL + slug naming
28
+ * `do --isolated` created it with (`jobWorktreePath`, as `complete --isolated`
29
+ * locates it), and:
30
+ *
31
+ * - no retained worktree (or one that belongs to a same-slug SPEC run)
32
+ * ⇒ `no-worktree`: nothing to do, requeue behaves as before;
33
+ * - the run is still ALIVE per its harness (PID/session, never mtime, ADR §5)
34
+ * ⇒ `alive`: we never write into a live agent's tree;
35
+ * - the gc deletion-safety predicate already holds (clean tree AND tip on the
36
+ * arbiter) ⇒ `nothing-unsaved`: requeue behaves as before;
37
+ * - otherwise commit any uncommitted residue as the usual wip commit and push
38
+ * the work branch through `refWrite.saveWorkBranch` (the SAME save half
39
+ * `routeToNeedsAttention` and the deadline checkpoint use: plain push, never
40
+ * `--force`, bounded backoff), then RE-CHECK the predicate: holds ⇒ `saved`,
41
+ * else `not-saved` with why (the caller keeps the lock and the worktree).
42
+ *
43
+ * A worktree whose HEAD is not on its work branch (e.g. a run killed mid-rebase,
44
+ * detached HEAD) is `not-saved` WITHOUT touching it: committing onto a detached
45
+ * HEAD would strand the commit, so the human resolves it by hand.
46
+ */
47
+ export type CrashedRunSaveOutcome =
48
+ | {kind: 'no-worktree'}
49
+ | {kind: 'alive'; dir: string; branch: string}
50
+ | {kind: 'nothing-unsaved'; dir: string; branch: string}
51
+ | {kind: 'saved'; dir: string; branch: string; committedResidue: boolean}
52
+ | {kind: 'not-saved'; dir: string; branch: string; detail: string};
53
+
54
+ export interface SaveCrashedRunWorkOptions {
55
+ /** The operator's checkout; its `arbiter` remote names the repo. */
56
+ cwd: string;
57
+ /** The arbiter remote NAME in {@link cwd}. */
58
+ arbiter: string;
59
+ /** The task slug (the branch is `work/task-<slug>`). */
60
+ slug: string;
61
+ /** The execution working area (config `workspacesDir`). */
62
+ workspacesDir: string;
63
+ env?: NodeJS.ProcessEnv;
64
+ note?: (message: string) => void;
65
+ /** Backoff bounds for the save push (tests pass a no-wait `sleep`). */
66
+ backoff?: BackoffOptions;
67
+ sleep?: Sleep;
68
+ }
69
+
70
+ /** The arbiter remote name valid INSIDE a job worktree (cut from the bare hub mirror). */
71
+ const WORKTREE_ARBITER_REMOTE = 'origin';
72
+
73
+ export async function saveCrashedRunWork(
74
+ options: SaveCrashedRunWorkOptions,
75
+ ): Promise<CrashedRunSaveOutcome> {
76
+ const note = options.note ?? (() => {});
77
+ const {cwd, arbiter, slug, workspacesDir, env} = options;
78
+
79
+ const url = run('git', ['remote', 'get-url', arbiter], cwd, {env});
80
+ if (url.status !== 0 || url.stdout.trim() === '') {
81
+ return {kind: 'no-worktree'};
82
+ }
83
+ const dir = jobWorktreePath(workspacesDir, url.stdout.trim(), slug);
84
+ if (!existsSync(dir)) {
85
+ return {kind: 'no-worktree'};
86
+ }
87
+ const branch = workBranchRef('task', slug);
88
+ const record = readJobRecord(dir);
89
+ if (record !== undefined && record.branch !== branch) {
90
+ // A same-slug SPEC (tasking) run shares the work-id; it is not this task's.
91
+ return {kind: 'no-worktree'};
92
+ }
93
+
94
+ if (
95
+ record !== undefined &&
96
+ record.state === 'running' &&
97
+ resolveHarness(record.harness).isAlive(record.harness)
98
+ ) {
99
+ note(
100
+ `'${slug}': its run in ${dir} is still ALIVE (per its harness), so ` +
101
+ 'requeue does not touch its worktree.',
102
+ );
103
+ return {kind: 'alive', dir, branch};
104
+ }
105
+
106
+ const before = evaluateDeletionSafety({dir, branch, env});
107
+ if (before.safe) {
108
+ return {kind: 'nothing-unsaved', dir, branch};
109
+ }
110
+
111
+ const head = run('git', ['symbolic-ref', '-q', '--short', 'HEAD'], dir, {
112
+ env,
113
+ });
114
+ if (head.status !== 0 || head.stdout.trim() !== branch) {
115
+ return {
116
+ kind: 'not-saved',
117
+ dir,
118
+ branch,
119
+ detail:
120
+ `its worktree is not on ${branch} (HEAD: ` +
121
+ `${head.status === 0 ? head.stdout.trim() : 'detached, e.g. killed mid-rebase'}), ` +
122
+ 'so it cannot be saved automatically',
123
+ };
124
+ }
125
+
126
+ note(
127
+ `'${slug}': its crashed run left unsaved work in ${dir} ` +
128
+ `(${RETAIN_REASON_TEXT[before.reason ?? 'unmerged-commits']}); saving it ` +
129
+ `to ${branch} on the arbiter before releasing the lock.`,
130
+ );
131
+ const saved = await refWrite.saveWorkBranch({
132
+ cwd: dir,
133
+ slug,
134
+ reason: `save a crashed run's local work before requeue`,
135
+ arbiter: WORKTREE_ARBITER_REMOTE,
136
+ branch,
137
+ env,
138
+ // The save half's own notes speak of a bounce; this is a requeue, so we
139
+ // report from the outcome instead.
140
+ note: () => {},
141
+ ...(options.backoff !== undefined ? {backoff: options.backoff} : {}),
142
+ ...(options.sleep !== undefined ? {sleep: options.sleep} : {}),
143
+ });
144
+ const committedResidue = saved.moveCommit !== undefined;
145
+
146
+ const after = evaluateDeletionSafety({dir, branch, env});
147
+ if (after.safe) {
148
+ note(
149
+ `Saved the crashed run's work: pushed ${branch}` +
150
+ (committedResidue
151
+ ? ' (with a wip commit of its uncommitted files)'
152
+ : '') +
153
+ '.',
154
+ );
155
+ return {kind: 'saved', dir, branch, committedResidue};
156
+ }
157
+ const detail =
158
+ saved.branchPush === 'failed'
159
+ ? `the push of ${branch} failed (${saved.pushError ?? 'unknown error'})`
160
+ : `it is still ${RETAIN_REASON_TEXT[after.reason ?? 'unmerged-commits']}`;
161
+ return {kind: 'not-saved', dir, branch, detail};
162
+ }
@@ -6,6 +6,7 @@ import {listMirrors} from './registry.js';
6
6
  import {encodeRepoKey, mirrorPath} from './repo-mirror.js';
7
7
  import {
8
8
  heldTaskSlugsStrict,
9
+ proposeKeptTaskSlugs,
9
10
  heldSpecSlugsStrict,
10
11
  listItemLockEntries,
11
12
  classifyTerminalItemLocks,
@@ -421,12 +422,21 @@ export async function resolveCwdSection(
421
422
  // with the arbiter-read held set SUBTRACTED so in-flight (lock-held) items are
422
423
  // not reported eligible. Thread the per-machine override so the cwd section's
423
424
  // eligibility matches what `do`/`advance` autopick will actually select.
425
+ // The held tasks whose lock a finished propose build keeps (the `propose-pr`
426
+ // marker): an answered `merge` on one of them is still enumerated, because
427
+ // its apply takes that lock over (task
428
+ // `wire-merge-questions-into-the-advance-tick`, decision 6). GRACEFUL: a read
429
+ // fault yields an empty set, so every held lock keeps excluding its item.
430
+ const proposeKeptSlugs = hasLockRemote
431
+ ? await proposeKeptTaskSlugs(cwd, lockRemote, env)
432
+ : new Set<string>();
424
433
  const localReport = scanRepoPaths(
425
434
  [cwd],
426
435
  config,
427
436
  heldSlugs,
428
437
  options.override,
429
438
  heldSpecSlugs,
439
+ proposeKeptSlugs,
430
440
  );
431
441
  const repo = localReport.repos[0];
432
442
 
@@ -138,6 +138,16 @@ export interface DecisionVerdict {
138
138
  * append/re-pause loop).
139
139
  */
140
140
  question?: string;
141
+ /**
142
+ * The follow-up questions as SEPARATE questions (`ask` outcome); when
143
+ * non-empty it takes precedence over {@link question}, and each becomes its
144
+ * own sidecar entry. The decision agent's contract emits the single
145
+ * `question` ({@link parseDecisionVerdict} does not read this field); the CI
146
+ * apply phase sets it when it replays a handed-over `ask`, so a handoff's
147
+ * questions are never joined into one (task
148
+ * `ci-surface-questions-keep-their-context-and-default`).
149
+ */
150
+ questions?: string[];
141
151
  }
142
152
 
143
153
  /**
package/src/do-config.ts CHANGED
@@ -1,7 +1,6 @@
1
1
  import type {
2
2
  Config,
3
3
  IntegrationMode,
4
- MergeQuestions,
5
4
  ObservationTriage,
6
5
  PartialConfig,
7
6
  } from './config.js';
@@ -79,7 +78,6 @@ export function doFlagOverrides(
79
78
  SelectionOrderFlags &
80
79
  ObservationTriageFlags &
81
80
  SurfaceBlockersFlags &
82
- MergeQuestionsFlags &
83
81
  StrictMergeApprovalFlags &
84
82
  NoPRFlags &
85
83
  MergeRetriesFlags,
@@ -94,17 +92,10 @@ export function doFlagOverrides(
94
92
  // boolean gate over DECLARED blocked work (the orthogonal peer of
95
93
  // `--observation-triage`).
96
94
  ...surfaceBlockersFlagOverrides(flags),
97
- // `--merge-questions <off|ask|auto>` rides the SAME flag-override chain
98
- // (flag > env > per-repo > global > default `ask`): the 3-state gate over
99
- // the merge-question SURFACER (spec `land-time-reverify-and-parallel-
100
- // merge-ceiling` Story 17 / task `merge-questions-gate-axis`). SEPARATE
101
- // axis from `--observation-triage` with a HIGHER default — NEVER rides
102
- // `--observation-triage`.
103
- ...mergeQuestionsFlagOverrides(flags),
104
95
  // `--strict-merge-approval`/`--no-strict-merge-approval` rides the SAME
105
96
  // flag-override chain (flag > env > per-repo > global > default `false`):
106
97
  // the OPT-IN strictness layered on the OQ6 stale-approval default. SEPARATE
107
- // axis from `--merge-questions` — the re-surface vs. land branch is
98
+ // axis from `mergeQuestions`: the re-surface vs. land branch is
108
99
  // `apply-rung-merge-disposition`'s consumer; this only resolves the boolean.
109
100
  ...strictMergeApprovalFlagOverrides(flags),
110
101
  // `--selection-order <order>` rides the SAME flag-override chain (flag > env >
@@ -450,51 +441,6 @@ export function mergeRetriesFlagOverrides(
450
441
  return overrides;
451
442
  }
452
443
 
453
- /**
454
- * The merge-questions CLI flag (`advance`): `--merge-questions <off|ask|auto>`,
455
- * the 3-state gate over the MERGE-QUESTION SURFACER (spec
456
- * `land-time-reverify-and-parallel-merge-ceiling` Story 17 / task
457
- * `merge-questions-gate-axis`). MIRRORS `--observation-triage`'s SHAPE but is a
458
- * SEPARATE axis with a HIGHER default (`ask`, never `off` — a dropped merge-
459
- * question means pushed work never lands). Resolved through the SAME
460
- * `flag > env > per-repo > global > default` chain as the other gate flags.
461
- */
462
- export interface MergeQuestionsFlags {
463
- /** `--merge-questions <off|ask|auto>` — the merge-question surfacer gate. */
464
- mergeQuestions?: string;
465
- }
466
-
467
- /** The valid `--merge-questions` values (mirrors the env enum coercion). */
468
- const MERGE_QUESTIONS_VALUES: readonly MergeQuestions[] = [
469
- 'off',
470
- 'ask',
471
- 'auto',
472
- ];
473
-
474
- /**
475
- * Map the `--merge-questions` flag into a {@link PartialConfig} override. Only a
476
- * present flag contributes (absent ⇒ absent key). An INVALID value FAILS LOUDLY
477
- * (the same loud-failure contract `--observation-triage` enforces) rather than
478
- * silently falling through — a typo on a question-surfacing gate must never be
479
- * quietly ignored.
480
- */
481
- export function mergeQuestionsFlagOverrides(
482
- flags: MergeQuestionsFlags,
483
- ): PartialConfig {
484
- const overrides: PartialConfig = {};
485
- if (flags.mergeQuestions !== undefined) {
486
- const raw = flags.mergeQuestions;
487
- if (!MERGE_QUESTIONS_VALUES.includes(raw as MergeQuestions)) {
488
- throw new Error(
489
- `Invalid value for --merge-questions: '${raw}'. ` +
490
- `Expected one of: ${MERGE_QUESTIONS_VALUES.join(', ')}.`,
491
- );
492
- }
493
- overrides.mergeQuestions = raw as MergeQuestions;
494
- }
495
- return overrides;
496
- }
497
-
498
444
  /**
499
445
  * **The strict-merge-approval CLI flag** (`--strict-merge-approval` /
500
446
  * `--no-strict-merge-approval`) — spec
@@ -504,8 +450,7 @@ export function mergeQuestionsFlagOverrides(
504
450
  * change instead of auto-landing on a green re-verify (the host-agnostic
505
451
  * analogue of GitHub's "dismiss stale approvals when the base changes"); OFF
506
452
  * (default) honours the prior answer + lands when the rebased tip re-verifies
507
- * GREEN. Offered alongside `--merge-questions` on `advance` (the apply rung is
508
- * the consumer). Resolved through the SAME `flag > env > per-repo > global >
453
+ * GREEN. Offered on `advance` (the apply rung is the consumer). Resolved through the SAME `flag > env > per-repo > global >
509
454
  * default` chain as the other gate-family members. A negatable boolean
510
455
  * (mirrors `--fresh-worktree-gate`).
511
456
  */