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
@@ -20,23 +20,24 @@ import {fileURLToPath} from 'node:url';
20
20
  * This module locates + reads that template and STRUCTURALLY VALIDATES it. The
21
21
  * package depends on NO YAML library (see `frontmatter.ts` for the same
22
22
  * constraint), so {@link validateAdvanceCiTemplate} checks the small set of
23
- * invariants the task's acceptance criteria require directly:
23
+ * invariants the acceptance criteria require directly:
24
24
  *
25
- * - triggers on a CRON schedule AND on-answer-committed (a push touching
26
- * `work/questions/**`);
27
- * - `propose` mode → a MATRIX of independent jobs enumerated via the
28
- * mirror-side pool scan (`dorfl scan --json`), one `advance … --propose`
29
- * per item (the `--propose` flag TIES the integration mode to the matrix shape,
30
- * so a leg can never merge to main);
31
- * - `merge` mode → a MATRIX of independent jobs (one per item), each leg
32
- * running `dorfl advance <item> --merge` so build/gate/review run
33
- * concurrently across siblings; the LAND TAIL is serialised by the engine's
34
- * `mergeRetries` CAS-retry loop (the git-alone floor), NOT by this
35
- * workflow's job shape — a host-specific `concurrency:` group would be
36
- * load-bearing for safety, which the floor framing forbids;
37
- * - the dispatch input is `integrationMode` (ONE word, ONE meaning): it drives
38
- * BOTH the integration flag the legs pass AND the job shape, so they cannot
39
- * desync;
25
+ * - triggers on a CRON schedule AND on-answer-committed (a push to `main`
26
+ * touching `work/questions/**`);
27
+ * - THE SPLIT (spec `ci-agent-job-without-write-token`, ADR
28
+ * `ci-agent-job-holds-no-write-token`, task `ci-split-generate-workflows`):
29
+ * the tick runs NO agent. `enumerate` lists the items via the pool scan
30
+ * (`dorfl scan --json`), and a `dispatch` job holding `actions: write` ONLY
31
+ * (no checkout, no setup) starts one `dorfl-item-dispatch.yml` run per item,
32
+ * which calls `dorfl-item.yml` (lock, agent, apply). No matrix: one item per
33
+ * workflow run, so no item shares another's artifact namespace;
34
+ * - the dispatch input is `integrationMode` (ONE word, ONE meaning): the
35
+ * `dispatch` job forwards it to every item run, which passes it to
36
+ * `advance` as `--propose`/`--merge`, so they cannot desync. In merge mode
37
+ * the LAND tail is serialised by the engine's `mergeRetries` CAS-retry loop
38
+ * in the item's apply job (the git-alone floor), NOT by a workflow
39
+ * `concurrency:` group; a lost CAS re-runs the rebase and the push only,
40
+ * never the gate (decision 2), and the apply phase reports it;
40
41
  * - it references the EXISTING `advance` driver only (no new execution model);
41
42
  * - it is a `.template` (so it never self-triggers in THIS repo).
42
43
  *
@@ -125,87 +126,85 @@ export function validateAdvanceCiTemplate(
125
126
  text,
126
127
  ), 'must trigger on-answer-committed (a push touching `work/questions/**`).');
127
128
 
128
- // --- propose ⇒ a MATRIX enumerated via the mirror-side pool scan -------------
129
- require('propose-matrix', /strategy:\s*[\s\S]*?matrix:/.test(
129
+ // --- The pool scan enumerates the items ------------------------------------
130
+ require('enumerates-via-scan', /dorfl scan --json/.test(
130
131
  text,
131
- ), '`propose` mode must emit a MATRIX of jobs (`strategy.matrix`).');
132
- require('propose-enumerates-via-scan', /dorfl scan --json/.test(
133
- text,
134
- ), 'the matrix items must be ENUMERATED via the mirror-side pool scan ' +
132
+ ), 'the items must be ENUMERATED via the mirror-side pool scan ' +
135
133
  '(`dorfl scan --json`).');
136
- // The `enumerate` `jq` must UNION taskable prds into the matrix
134
+ // The `enumerate` `jq` must UNION taskable prds into the item list
137
135
  // (`ci-propose-matrix-must-enumerate-sliceable-prds-not-only-slices`): a
138
- // task-only `jq` would render `DORFL_AUTO_TASK` dead on the hourly
139
- // cron — a ready ungated SPEC would never become a matrix leg. The `jq` must
140
- // read `scan --json`'s taskable-SPEC pool (`repos[].specs[]` + `cwd.repo.specs[]`)
141
- // and emit `spec:<slug>` legs alongside the `task:<slug>` legs.
136
+ // task-only `jq` would render `DORFL_AUTO_TASK` dead on the hourly cron.
142
137
  require('propose-enumerates-taskable-specs', /"spec:" \+ \.slug/.test(text) &&
143
138
  /\.specs\[\]/.test(
144
139
  text,
145
- ), 'the propose-mode `enumerate` `jq` must union taskable specs into the ' +
146
- "matrix as `spec:<slug>` legs (read from `scan --json`'s `repos[].specs[]` " +
140
+ ), 'the `enumerate` `jq` must union taskable specs into the item list as ' +
141
+ "`spec:<slug>` ids (read from `scan --json`'s `repos[].specs[]` " +
147
142
  '+ `cwd.repo.specs[]` pools), so a ready ungated SPEC becomes one auto-task ' +
148
- 'matrix leg alongside the eligible-task legs ' +
143
+ 'item run alongside the eligible-task items ' +
149
144
  '(`ci-propose-matrix-must-enumerate-sliceable-prds-not-only-slices`).');
150
- require('propose-one-advance-per-item', /WORK_ITEM:\s*\$\{\{\s*matrix\.item\s*\}\}[\s\S]*?dorfl advance "\$\{WORK_ITEM\}"/.test(
145
+
146
+ // --- THE SPLIT: one dorfl-item run per item, dispatched, never a matrix -----
147
+ require('no-matrix', !/\bstrategy:\s*[\s\S]*?matrix:/.test(
151
148
  text,
152
- ), 'each matrix leg must run one `dorfl advance <matrix item>` ' +
153
- '(one PR per item), reading the item from the step env (`WORK_ITEM`).');
154
- // The item id is a slug that may be hand-written, so it must reach the shell
155
- // as DATA through `env:`, never as `${{ }}` text spliced into the `run:` script
156
- // (GitHub Actions script injection).
157
- require('matrix-item-not-spliced-into-run', !/dorfl advance "?\$\{\{/.test(
149
+ ), 'no job may use a `strategy.matrix`: one item per workflow run (a matrix ' +
150
+ 'shares one artifact namespace across items; decision 1 of ADR ' +
151
+ 'ci-agent-job-holds-no-write-token).');
152
+ require('dispatches-item-runs', /gh workflow run dorfl-item-dispatch\.yml\b/.test(
158
153
  text,
159
- ), 'the matrix item must NOT be interpolated into the `run:` script as ' +
160
- '`${{ matrix.item }}` (script injection): pass it through the step `env:` ' +
161
- 'as `WORK_ITEM` and quote it as `"${WORK_ITEM}"`.');
162
- // The matrix leg must carry `--propose` so the integration mode is TIED to the
163
- // matrix shape (it cannot desync from the dispatch `integrationMode` input nor
164
- // fall back to a repo config default of `merge`). Scoped to the `advance-propose`
165
- // job so it is the LEG that carries it, not merely the file somewhere.
166
- require('propose-leg-carries-propose-flag', /advance-propose:[\s\S]*?dorfl advance "\$\{WORK_ITEM\}"[^\n]*--propose\b/.test(
154
+ ), 'the `dispatch` job must start one `dorfl-item-dispatch.yml` run per item ' +
155
+ '(which calls dorfl-item.yml: lock, agent, apply).');
156
+ require('dispatch-actions-write-only', /\n {2}dispatch:[\s\S]*?\n {4}permissions:\s*\n {6}actions: write\s*\n {4}steps:/.test(
167
157
  text,
168
- ), 'each `propose` matrix leg must pass `--propose` so the integration mode is ' +
169
- 'TIED to the matrix shape (a leg can never merge to main / desync from the ' +
170
- 'dispatch mode).');
171
-
172
- // --- merge ⇒ a MATRIX per item (parallel build/gate/review, serialised land) -
173
- // The engine's `integrateLock` + `mergeRetries` CAS-retry loop is what makes
174
- // concurrent merge jobs LAND-SAFE (`land-time-reverify-and-parallel-merge-ceiling`):
175
- // build/gate/review fan out across siblings, and a non-fast-forward push
176
- // triggers re-rebase + re-gate + retry up to the resolved `mergeRetries` cap.
177
- // The cross-job serialiser is the CAS-retry loop itself — the git-alone floor.
178
- require('merge-matrix', /advance-merge:[\s\S]*?strategy:\s*[\s\S]*?matrix:/.test(
158
+ ), 'the `dispatch` job must hold `actions: write` and nothing else.');
159
+ const dispatchJob =
160
+ /\n {2}dispatch:[\s\S]*?(?=\n {2}[#\w]|$)/.exec(text)?.[0] ?? '';
161
+ require('dispatch-no-checkout-no-setup', dispatchJob !== '' &&
162
+ !/uses:/.test(
163
+ dispatchJob,
164
+ ), 'the `dispatch` job must have NO checkout and NO setup (no repository ' +
165
+ 'code runs next to `actions: write`).');
166
+ // ONE word: the dispatch job forwards `integrationMode` to every item run,
167
+ // which passes it to `advance` as `--propose`/`--merge`.
168
+ require('dispatch-forwards-integration-mode', /-f "integrationMode=\$\{INTEGRATION_MODE\}"/.test(
169
+ text,
170
+ ) &&
171
+ /INTEGRATION_MODE: \$\{\{ github\.event\.inputs\.integrationMode \|\| 'propose' \}\}/.test(
172
+ text,
173
+ ), 'the `dispatch` job must forward the `integrationMode` dispatch input ' +
174
+ "(default `propose`) to each item run, so the items' integration mode is " +
175
+ 'TIED to the tick.');
176
+ require('dispatch-slot', /-f "slot=\$\{slot\}"/.test(
179
177
  text,
180
- ), 'the `merge` job must use a MATRIX (parallel build/gate/review per item; ' +
181
- "the land tail is serialised by the engine's `mergeRetries` CAS-retry " +
182
- "loop, not by the workflow's job shape).");
183
- // Each merge matrix leg must run one `dorfl advance <matrix.item> --merge`,
184
- // scoped to the `advance-merge:` job so the `--merge` flag is TIED to its leg
185
- // (cannot desync from the dispatch `integrationMode` input nor fall back to a
186
- // repo config default of `propose`).
187
- require('merge-leg-carries-merge-flag', /advance-merge:[\s\S]*?dorfl advance "\$\{WORK_ITEM\}"[^\n]*--merge\b/.test(
178
+ ), 'the `dispatch` job must give each item run a parallelism slot.');
179
+ require('dispatch-skips-active-runs', /gh run list[^\n]*--workflow dorfl-item-dispatch\.yml[^\n]*displayTitle,status/.test(
188
180
  text,
189
- ), 'each `merge` matrix leg must pass `--merge` so the integration mode is ' +
190
- 'TIED to the matrix shape (a leg can never propose-only / desync from the ' +
191
- 'dispatch mode).');
192
- // The merge fan-out is the SAFETY-FLOOR shape: no `concurrency:` group on the
193
- // `advance-merge:` job, because a GitHub Actions `concurrency:` serialiser
194
- // would be load-bearing for cross-job land safety, and the floor must work on
195
- // a bare arbiter with no host (Applied Answer q1: scaled CAS-retry is the
196
- // floor; the portable cross-job ref-lock is the planned accelerator; GitHub
197
- // `concurrency:` is OPTIONAL host sugar only, deliberately not used here).
198
- require('merge-no-host-concurrency-serialiser', !/advance-merge:[\s\S]*?\n\s{4}concurrency:/.test(
181
+ ), 'the `dispatch` job must skip an item whose `dorfl-item <item>` run is ' +
182
+ 'not completed yet.');
183
+ // The item id may be hand-written, so it must reach the shell as DATA through
184
+ // `env:`, never as `${{ }}` text spliced into the `run:` script.
185
+ require('items-not-spliced-into-run', !/gh workflow run[^\n]*\$\{\{/.test(
199
186
  text,
200
- ), 'the `merge` job must NOT carry a `concurrency:` group: a host-specific ' +
201
- 'serialiser would make the cross-job land safety depend on a GitHub Actions ' +
202
- "feature; the engine's `mergeRetries` CAS-retry loop is the git-alone " +
203
- 'floor.');
187
+ ), 'the items must reach the dispatch script through `env:`, never as ' +
188
+ '`${{ }}` text in the `run:` script (script injection).');
189
+ // No host-specific serialiser on the land: a workflow-level `concurrency:`
190
+ // group keyed on main would be load-bearing for cross-run land safety, which
191
+ // the git-alone floor forbids (the slot groups live on the item runs and
192
+ // only cap the parallelism).
193
+ require('permissions-empty', /^permissions: \{\}$/m.test(
194
+ text,
195
+ ), 'the workflow must grant nothing at workflow level (`permissions: {}`).');
196
+ require('push-pinned-to-main', /\bpush:\s*\n\s+(?:#[^\n]*\n\s+)*branches:\s*\n\s+-\s*main\b/.test(
197
+ text,
198
+ ), 'the on-answer-committed `push` trigger must be pinned to `main`.');
204
199
 
205
200
  // --- It only INVOKES the existing `advance` driver (no new execution model) --
206
- require('invokes-advance-driver', /dorfl advance\b/.test(
207
- text,
208
- ), 'the workflow must INVOKE the existing `advance` driver.');
201
+ // The driver runs inside the per-item workflow: the template names it in the
202
+ // comments and must not run any agent verb itself.
203
+ require('invokes-advance-driver', /\badvance\b/.test(text) &&
204
+ !/^\s*[^#\n]*dorfl (?:advance|do|intake|run)\b/m.test(
205
+ text,
206
+ ), 'the workflow must reach the existing `advance` driver through the ' +
207
+ 'per-item workflow, and run no agent verb itself.');
209
208
 
210
209
  return {ok: problems.length === 0, problems};
211
210
  }
@@ -5,12 +5,14 @@ import {
5
5
  type AdvanceExitCode,
6
6
  type AdvanceOutcome,
7
7
  } from './advance.js';
8
- import {
9
- pushTreelessResult,
10
- TREELESS_RUNGS,
11
- } from './advance-treeless-publish.js';
8
+ import {TREELESS_RUNGS} from './advance-treeless-publish.js';
9
+ import {refWrite} from './ref-write.js';
12
10
  import {scanRepoPaths} from './scan.js';
13
- import {heldTaskSlugs, heldSpecSlugs} from './item-lock.js';
11
+ import {
12
+ heldTaskSlugs,
13
+ heldSpecSlugs,
14
+ proposeKeptTaskSlugs,
15
+ } from './item-lock.js';
14
16
  import {ledgerRead, type LedgerReadStrategy} from './ledger-read.js';
15
17
  import {
16
18
  selectPrioritised,
@@ -20,6 +22,11 @@ import {
20
22
  } from './select-priority.js';
21
23
  import {gatherLifecycleInPlace} from './lifecycle-gather.js';
22
24
  import type {LifecyclePoolGates} from './lifecycle-pools.js';
25
+ import {
26
+ runMergeQuestionTick,
27
+ type MergeQuestionTickOptions,
28
+ type MergeQuestionTickResult,
29
+ } from './merge-question-tick.js';
23
30
  import type {Config} from './config.js';
24
31
  import type {ConfigOverrideMap} from './config-override.js';
25
32
 
@@ -120,6 +127,15 @@ export interface PerformAdvanceMultiOptions extends SharedAdvanceContext {
120
127
  * this same hook to exercise the triage/surface paths.
121
128
  */
122
129
  lifecycleGates?: LifecyclePoolGates;
130
+ /**
131
+ * The merge-question pass the bare/`-n` form runs BEFORE it selects (task
132
+ * `wire-merge-questions-into-the-advance-tick`), gated by
133
+ * `config.mergeQuestions`. Defaults to {@link runMergeQuestionTick}; tests
134
+ * inject a stub, or `false` to skip it.
135
+ */
136
+ mergeQuestionTick?:
137
+ | ((options: MergeQuestionTickOptions) => Promise<MergeQuestionTickResult>)
138
+ | false;
123
139
  }
124
140
 
125
141
  /** The aggregate result of a multi-item `advance` invocation. */
@@ -169,6 +185,24 @@ export async function performAdvanceAuto(
169
185
  const cwd = options.cwd;
170
186
  const count = options.count ?? 1;
171
187
 
188
+ // The MERGE-QUESTION pass (task `wire-merge-questions-into-the-advance-tick`):
189
+ // ask about every unmerged work branch with no open PR and no live build,
190
+ // behind `mergeQuestions` (`off` skips it). Deterministic, no agent. It runs
191
+ // BEFORE selection so an answer committed since the last tick is not raced
192
+ // by a fresh question, and it publishes like a tree-less rung (only with an
193
+ // arbiter configured; a no-arbiter checkout sits on the real `main`).
194
+ if (options.mergeQuestionTick !== false) {
195
+ const tick = options.mergeQuestionTick ?? runMergeQuestionTick;
196
+ const pass = await tick({
197
+ cwd,
198
+ arbiter: options.arbiter ?? 'origin',
199
+ mergeQuestions: options.config.mergeQuestions,
200
+ publish: options.arbiter !== undefined,
201
+ note,
202
+ });
203
+ if (pass.ran || pass.failed) note(pass.message);
204
+ }
205
+
172
206
  // Held-slug subtraction (task
173
207
  // `in-place-scan-subtracts-held-locked-slugs-from-propose-matrix`): read the
174
208
  // coordination arbiter's held task-lock refs and pass them into `scanRepoPaths`
@@ -228,6 +262,9 @@ export async function performAdvanceAuto(
228
262
  // Subtract held task slugs from the triage/surface/apply candidate inputs,
229
263
  // symmetric to Pool 1's `scoreItems` subtraction above.
230
264
  heldSlugs,
265
+ // ...except an answered `merge` on a lock a finished propose build keeps,
266
+ // whose apply takes that lock over (decision 6).
267
+ proposeKeptSlugs: await proposeKeptTaskSlugs(cwd, options.arbiter),
231
268
  });
232
269
 
233
270
  // Order across the (up to) FIVE pools per the resolved `selectionOrder` (apply
@@ -359,7 +396,7 @@ export async function runAdvanceTickWithTreelessPublish(
359
396
  TREELESS_RUNGS.has(result.rung) &&
360
397
  options.arbiter !== undefined
361
398
  ) {
362
- await pushTreelessResult({
399
+ await refWrite.publishTreelessResult({
363
400
  cwd: options.cwd,
364
401
  arbiter: options.arbiter,
365
402
  // Large liveness ceiling — see `pushTreelessResult`'s C2 docs (task
@@ -409,8 +446,10 @@ function sharedAdvanceContext(
409
446
  run: _run,
410
447
  read: _read,
411
448
  lifecycleGates: _lifecycleGates,
449
+ mergeQuestionTick: _mergeQuestionTick,
412
450
  ...rest
413
451
  } = options;
452
+ void _mergeQuestionTick;
414
453
  void _config;
415
454
  void _count;
416
455
  void _run;
@@ -3,10 +3,8 @@ import {dirname, join} from 'node:path';
3
3
  import {git} from './git.js';
4
4
  import {ensureMirror, encodeRepoKey} from './repo-mirror.js';
5
5
  import {jobWorktreeDoDriver} from './do.js';
6
- import {
7
- pushTreelessResult,
8
- TREELESS_RUNGS,
9
- } from './advance-treeless-publish.js';
6
+ import {TREELESS_RUNGS} from './advance-treeless-publish.js';
7
+ import {refWrite} from './ref-write.js';
10
8
  import {
11
9
  performAdvance,
12
10
  type AdvanceContext,
@@ -196,7 +194,7 @@ export async function performAdvanceIsolated(
196
194
  result.rung !== undefined &&
197
195
  TREELESS_RUNGS.has(result.rung)
198
196
  ) {
199
- await pushTreelessResult({
197
+ await refWrite.publishTreelessResult({
200
198
  cwd: cloneDir,
201
199
  arbiter: arbiterRemoteName,
202
200
  // Large liveness ceiling (C2, task `c2-rebase-until-real-on-durable-main-