dorfl 0.0.0 → 0.1.1

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 (619) hide show
  1. package/dist/advance-ci-template.d.ts +73 -0
  2. package/dist/advance-ci-template.d.ts.map +1 -0
  3. package/dist/advance-ci-template.js +104 -0
  4. package/dist/advance-ci-template.js.map +1 -0
  5. package/dist/advance-classify.d.ts +132 -0
  6. package/dist/advance-classify.d.ts.map +1 -0
  7. package/dist/advance-classify.js +120 -0
  8. package/dist/advance-classify.js.map +1 -0
  9. package/dist/advance-drivers.d.ts +182 -0
  10. package/dist/advance-drivers.d.ts.map +1 -0
  11. package/dist/advance-drivers.js +231 -0
  12. package/dist/advance-drivers.js.map +1 -0
  13. package/dist/advance-isolated.d.ts +156 -0
  14. package/dist/advance-isolated.d.ts.map +1 -0
  15. package/dist/advance-isolated.js +256 -0
  16. package/dist/advance-isolated.js.map +1 -0
  17. package/dist/advance-lifecycle-template.d.ts +107 -0
  18. package/dist/advance-lifecycle-template.d.ts.map +1 -0
  19. package/dist/advance-lifecycle-template.js +668 -0
  20. package/dist/advance-lifecycle-template.js.map +1 -0
  21. package/dist/advance-loop-driver.d.ts +325 -0
  22. package/dist/advance-loop-driver.d.ts.map +1 -0
  23. package/dist/advance-loop-driver.js +437 -0
  24. package/dist/advance-loop-driver.js.map +1 -0
  25. package/dist/advance-treeless-publish.d.ts +108 -0
  26. package/dist/advance-treeless-publish.d.ts.map +1 -0
  27. package/dist/advance-treeless-publish.js +71 -0
  28. package/dist/advance-treeless-publish.js.map +1 -0
  29. package/dist/advance.d.ts +340 -0
  30. package/dist/advance.d.ts.map +1 -0
  31. package/dist/advance.js +1122 -0
  32. package/dist/advance.js.map +1 -0
  33. package/dist/advancing-lock.d.ts +294 -0
  34. package/dist/advancing-lock.d.ts.map +1 -0
  35. package/dist/advancing-lock.js +594 -0
  36. package/dist/advancing-lock.js.map +1 -0
  37. package/dist/agent-launch.d.ts +79 -0
  38. package/dist/agent-launch.d.ts.map +1 -0
  39. package/dist/agent-launch.js +61 -0
  40. package/dist/agent-launch.js.map +1 -0
  41. package/dist/agent-stop.d.ts +149 -0
  42. package/dist/agent-stop.d.ts.map +1 -0
  43. package/dist/agent-stop.js +307 -0
  44. package/dist/agent-stop.js.map +1 -0
  45. package/dist/apply-decide.d.ts +127 -0
  46. package/dist/apply-decide.d.ts.map +1 -0
  47. package/dist/apply-decide.js +176 -0
  48. package/dist/apply-decide.js.map +1 -0
  49. package/dist/apply-merge-action.d.ts +206 -0
  50. package/dist/apply-merge-action.d.ts.map +1 -0
  51. package/dist/apply-merge-action.js +307 -0
  52. package/dist/apply-merge-action.js.map +1 -0
  53. package/dist/apply-persist.d.ts +174 -0
  54. package/dist/apply-persist.d.ts.map +1 -0
  55. package/dist/apply-persist.js +359 -0
  56. package/dist/apply-persist.js.map +1 -0
  57. package/dist/arbiter.d.ts +120 -0
  58. package/dist/arbiter.d.ts.map +1 -0
  59. package/dist/arbiter.js +255 -0
  60. package/dist/arbiter.js.map +1 -0
  61. package/dist/brand.d.ts +70 -0
  62. package/dist/brand.d.ts.map +1 -0
  63. package/dist/brand.js +84 -0
  64. package/dist/brand.js.map +1 -0
  65. package/dist/buildable-body.d.ts +132 -0
  66. package/dist/buildable-body.d.ts.map +1 -0
  67. package/dist/buildable-body.js +131 -0
  68. package/dist/buildable-body.js.map +1 -0
  69. package/dist/categorise.d.ts +66 -0
  70. package/dist/categorise.d.ts.map +1 -0
  71. package/dist/categorise.js +106 -0
  72. package/dist/categorise.js.map +1 -0
  73. package/dist/claim-cas.d.ts +117 -0
  74. package/dist/claim-cas.d.ts.map +1 -0
  75. package/dist/claim-cas.js +312 -0
  76. package/dist/claim-cas.js.map +1 -0
  77. package/dist/cli-spinner.d.ts +112 -0
  78. package/dist/cli-spinner.d.ts.map +1 -0
  79. package/dist/cli-spinner.js +157 -0
  80. package/dist/cli-spinner.js.map +1 -0
  81. package/dist/cli.d.ts +11 -0
  82. package/dist/cli.d.ts.map +1 -0
  83. package/dist/cli.js +3100 -0
  84. package/dist/cli.js.map +1 -0
  85. package/dist/close-job-template.d.ts +70 -0
  86. package/dist/close-job-template.d.ts.map +1 -0
  87. package/dist/close-job-template.js +180 -0
  88. package/dist/close-job-template.js.map +1 -0
  89. package/dist/close-job.d.ts +95 -0
  90. package/dist/close-job.d.ts.map +1 -0
  91. package/dist/close-job.js +226 -0
  92. package/dist/close-job.js.map +1 -0
  93. package/dist/complete.d.ts +361 -0
  94. package/dist/complete.d.ts.map +1 -0
  95. package/dist/complete.js +885 -0
  96. package/dist/complete.js.map +1 -0
  97. package/dist/concurrency.d.ts +68 -0
  98. package/dist/concurrency.d.ts.map +1 -0
  99. package/dist/concurrency.js +112 -0
  100. package/dist/concurrency.js.map +1 -0
  101. package/dist/config-override.d.ts +76 -0
  102. package/dist/config-override.d.ts.map +1 -0
  103. package/dist/config-override.js +50 -0
  104. package/dist/config-override.js.map +1 -0
  105. package/dist/config.d.ts +668 -0
  106. package/dist/config.d.ts.map +1 -0
  107. package/dist/config.js +241 -0
  108. package/dist/config.js.map +1 -0
  109. package/dist/continue-branch.d.ts +249 -0
  110. package/dist/continue-branch.d.ts.map +1 -0
  111. package/dist/continue-branch.js +389 -0
  112. package/dist/continue-branch.js.map +1 -0
  113. package/dist/cwd-section.d.ts +186 -0
  114. package/dist/cwd-section.d.ts.map +1 -0
  115. package/dist/cwd-section.js +209 -0
  116. package/dist/cwd-section.js.map +1 -0
  117. package/dist/decision-engine.d.ts +170 -0
  118. package/dist/decision-engine.d.ts.map +1 -0
  119. package/dist/decision-engine.js +136 -0
  120. package/dist/decision-engine.js.map +1 -0
  121. package/dist/detect.d.ts +17 -0
  122. package/dist/detect.d.ts.map +1 -0
  123. package/dist/detect.js +118 -0
  124. package/dist/detect.js.map +1 -0
  125. package/dist/do-autopick.d.ts +85 -0
  126. package/dist/do-autopick.d.ts.map +1 -0
  127. package/dist/do-autopick.js +112 -0
  128. package/dist/do-autopick.js.map +1 -0
  129. package/dist/do-config.d.ts +312 -0
  130. package/dist/do-config.d.ts.map +1 -0
  131. package/dist/do-config.js +358 -0
  132. package/dist/do-config.js.map +1 -0
  133. package/dist/do-remote-auto.d.ts +75 -0
  134. package/dist/do-remote-auto.d.ts.map +1 -0
  135. package/dist/do-remote-auto.js +111 -0
  136. package/dist/do-remote-auto.js.map +1 -0
  137. package/dist/do.d.ts +621 -0
  138. package/dist/do.d.ts.map +1 -0
  139. package/dist/do.js +1882 -0
  140. package/dist/do.js.map +1 -0
  141. package/dist/drop-source.d.ts +96 -0
  142. package/dist/drop-source.d.ts.map +1 -0
  143. package/dist/drop-source.js +91 -0
  144. package/dist/drop-source.js.map +1 -0
  145. package/dist/eligibility.d.ts +46 -0
  146. package/dist/eligibility.d.ts.map +1 -0
  147. package/dist/eligibility.js +34 -0
  148. package/dist/eligibility.js.map +1 -0
  149. package/dist/env-config.d.ts +51 -0
  150. package/dist/env-config.d.ts.map +1 -0
  151. package/dist/env-config.js +272 -0
  152. package/dist/env-config.js.map +1 -0
  153. package/dist/failure-cause.d.ts +70 -0
  154. package/dist/failure-cause.d.ts.map +1 -0
  155. package/dist/failure-cause.js +126 -0
  156. package/dist/failure-cause.js.map +1 -0
  157. package/dist/format.d.ts +43 -0
  158. package/dist/format.d.ts.map +1 -0
  159. package/dist/format.js +256 -0
  160. package/dist/format.js.map +1 -0
  161. package/dist/frontmatter.d.ts +208 -0
  162. package/dist/frontmatter.d.ts.map +1 -0
  163. package/dist/frontmatter.js +344 -0
  164. package/dist/frontmatter.js.map +1 -0
  165. package/dist/gate-readiness.d.ts +84 -0
  166. package/dist/gate-readiness.d.ts.map +1 -0
  167. package/dist/gate-readiness.js +103 -0
  168. package/dist/gate-readiness.js.map +1 -0
  169. package/dist/gc.d.ts +165 -0
  170. package/dist/gc.d.ts.map +1 -0
  171. package/dist/gc.js +313 -0
  172. package/dist/gc.js.map +1 -0
  173. package/dist/gh-failure.d.ts +42 -0
  174. package/dist/gh-failure.d.ts.map +1 -0
  175. package/dist/gh-failure.js +49 -0
  176. package/dist/gh-failure.js.map +1 -0
  177. package/dist/git.d.ts +75 -0
  178. package/dist/git.d.ts.map +1 -0
  179. package/dist/git.js +130 -0
  180. package/dist/git.js.map +1 -0
  181. package/dist/github.d.ts +187 -0
  182. package/dist/github.d.ts.map +1 -0
  183. package/dist/github.js +343 -0
  184. package/dist/github.js.map +1 -0
  185. package/dist/harness.d.ts +242 -0
  186. package/dist/harness.d.ts.map +1 -0
  187. package/dist/harness.js +157 -0
  188. package/dist/harness.js.map +1 -0
  189. package/dist/identity.d.ts +167 -0
  190. package/dist/identity.d.ts.map +1 -0
  191. package/dist/identity.js +231 -0
  192. package/dist/identity.js.map +1 -0
  193. package/dist/index.d.ts +147 -0
  194. package/dist/index.d.ts.map +1 -0
  195. package/dist/index.js +76 -0
  196. package/dist/index.js.map +1 -0
  197. package/dist/install-ci-branch-protection.d.ts +147 -0
  198. package/dist/install-ci-branch-protection.d.ts.map +1 -0
  199. package/dist/install-ci-branch-protection.js +166 -0
  200. package/dist/install-ci-branch-protection.js.map +1 -0
  201. package/dist/install-ci-capabilities/advance-lifecycle.d.ts +15 -0
  202. package/dist/install-ci-capabilities/advance-lifecycle.d.ts.map +1 -0
  203. package/dist/install-ci-capabilities/advance-lifecycle.js +28 -0
  204. package/dist/install-ci-capabilities/advance-lifecycle.js.map +1 -0
  205. package/dist/install-ci-capabilities/close-job.d.ts +13 -0
  206. package/dist/install-ci-capabilities/close-job.d.ts.map +1 -0
  207. package/dist/install-ci-capabilities/close-job.js +26 -0
  208. package/dist/install-ci-capabilities/close-job.js.map +1 -0
  209. package/dist/install-ci-capabilities/example-noop.d.ts +16 -0
  210. package/dist/install-ci-capabilities/example-noop.d.ts.map +1 -0
  211. package/dist/install-ci-capabilities/example-noop.js +23 -0
  212. package/dist/install-ci-capabilities/example-noop.js.map +1 -0
  213. package/dist/install-ci-capabilities/intake.d.ts +15 -0
  214. package/dist/install-ci-capabilities/intake.d.ts.map +1 -0
  215. package/dist/install-ci-capabilities/intake.js +28 -0
  216. package/dist/install-ci-capabilities/intake.js.map +1 -0
  217. package/dist/install-ci-capabilities/verify.d.ts +14 -0
  218. package/dist/install-ci-capabilities/verify.d.ts.map +1 -0
  219. package/dist/install-ci-capabilities/verify.js +27 -0
  220. package/dist/install-ci-capabilities/verify.js.map +1 -0
  221. package/dist/install-ci-core.d.ts +446 -0
  222. package/dist/install-ci-core.d.ts.map +1 -0
  223. package/dist/install-ci-core.js +760 -0
  224. package/dist/install-ci-core.js.map +1 -0
  225. package/dist/install-ci-github.d.ts +167 -0
  226. package/dist/install-ci-github.d.ts.map +1 -0
  227. package/dist/install-ci-github.js +315 -0
  228. package/dist/install-ci-github.js.map +1 -0
  229. package/dist/install-ci.d.ts +105 -0
  230. package/dist/install-ci.d.ts.map +1 -0
  231. package/dist/install-ci.js +363 -0
  232. package/dist/install-ci.js.map +1 -0
  233. package/dist/intake-event.d.ts +88 -0
  234. package/dist/intake-event.d.ts.map +1 -0
  235. package/dist/intake-event.js +66 -0
  236. package/dist/intake-event.js.map +1 -0
  237. package/dist/intake-marker.d.ts +95 -0
  238. package/dist/intake-marker.d.ts.map +1 -0
  239. package/dist/intake-marker.js +127 -0
  240. package/dist/intake-marker.js.map +1 -0
  241. package/dist/intake-triage.d.ts +48 -0
  242. package/dist/intake-triage.d.ts.map +1 -0
  243. package/dist/intake-triage.js +95 -0
  244. package/dist/intake-triage.js.map +1 -0
  245. package/dist/intake-trigger-template.d.ts +185 -0
  246. package/dist/intake-trigger-template.d.ts.map +1 -0
  247. package/dist/intake-trigger-template.js +449 -0
  248. package/dist/intake-trigger-template.js.map +1 -0
  249. package/dist/intake.d.ts +569 -0
  250. package/dist/intake.d.ts.map +1 -0
  251. package/dist/intake.js +1628 -0
  252. package/dist/intake.js.map +1 -0
  253. package/dist/integration-core.d.ts +539 -0
  254. package/dist/integration-core.d.ts.map +1 -0
  255. package/dist/integration-core.js +2195 -0
  256. package/dist/integration-core.js.map +1 -0
  257. package/dist/integrator.d.ts +343 -0
  258. package/dist/integrator.d.ts.map +1 -0
  259. package/dist/integrator.js +400 -0
  260. package/dist/integrator.js.map +1 -0
  261. package/dist/isolation.d.ts +219 -0
  262. package/dist/isolation.d.ts.map +1 -0
  263. package/dist/isolation.js +261 -0
  264. package/dist/isolation.js.map +1 -0
  265. package/dist/issue-provider.d.ts +349 -0
  266. package/dist/issue-provider.d.ts.map +1 -0
  267. package/dist/issue-provider.js +360 -0
  268. package/dist/issue-provider.js.map +1 -0
  269. package/dist/item-lock.d.ts +626 -0
  270. package/dist/item-lock.d.ts.map +1 -0
  271. package/dist/item-lock.js +1381 -0
  272. package/dist/item-lock.js.map +1 -0
  273. package/dist/item-path.d.ts +49 -0
  274. package/dist/item-path.d.ts.map +1 -0
  275. package/dist/item-path.js +66 -0
  276. package/dist/item-path.js.map +1 -0
  277. package/dist/ledger-lint.d.ts +129 -0
  278. package/dist/ledger-lint.d.ts.map +1 -0
  279. package/dist/ledger-lint.js +249 -0
  280. package/dist/ledger-lint.js.map +1 -0
  281. package/dist/ledger-read.d.ts +357 -0
  282. package/dist/ledger-read.d.ts.map +1 -0
  283. package/dist/ledger-read.js +442 -0
  284. package/dist/ledger-read.js.map +1 -0
  285. package/dist/ledger-write.d.ts +330 -0
  286. package/dist/ledger-write.d.ts.map +1 -0
  287. package/dist/ledger-write.js +411 -0
  288. package/dist/ledger-write.js.map +1 -0
  289. package/dist/lifecycle-gather.d.ts +30 -0
  290. package/dist/lifecycle-gather.d.ts.map +1 -0
  291. package/dist/lifecycle-gather.js +205 -0
  292. package/dist/lifecycle-gather.js.map +1 -0
  293. package/dist/lifecycle-pools.d.ts +180 -0
  294. package/dist/lifecycle-pools.d.ts.map +1 -0
  295. package/dist/lifecycle-pools.js +78 -0
  296. package/dist/lifecycle-pools.js.map +1 -0
  297. package/dist/merge-question-surfacer.d.ts +166 -0
  298. package/dist/merge-question-surfacer.d.ts.map +1 -0
  299. package/dist/merge-question-surfacer.js +297 -0
  300. package/dist/merge-question-surfacer.js.map +1 -0
  301. package/dist/mint-adr.d.ts +126 -0
  302. package/dist/mint-adr.d.ts.map +1 -0
  303. package/dist/mint-adr.js +257 -0
  304. package/dist/mint-adr.js.map +1 -0
  305. package/dist/mirror-pool-scan.d.ts +125 -0
  306. package/dist/mirror-pool-scan.d.ts.map +1 -0
  307. package/dist/mirror-pool-scan.js +104 -0
  308. package/dist/mirror-pool-scan.js.map +1 -0
  309. package/dist/needs-attention.d.ts +341 -0
  310. package/dist/needs-attention.d.ts.map +1 -0
  311. package/dist/needs-attention.js +900 -0
  312. package/dist/needs-attention.js.map +1 -0
  313. package/dist/orphan-sidecar.d.ts +79 -0
  314. package/dist/orphan-sidecar.d.ts.map +1 -0
  315. package/dist/orphan-sidecar.js +71 -0
  316. package/dist/orphan-sidecar.js.map +1 -0
  317. package/dist/output.d.ts +48 -0
  318. package/dist/output.d.ts.map +1 -0
  319. package/dist/output.js +66 -0
  320. package/dist/output.js.map +1 -0
  321. package/dist/pi-harness.d.ts +179 -0
  322. package/dist/pi-harness.d.ts.map +1 -0
  323. package/dist/pi-harness.js +342 -0
  324. package/dist/pi-harness.js.map +1 -0
  325. package/dist/placement.d.ts +99 -0
  326. package/dist/placement.d.ts.map +1 -0
  327. package/dist/placement.js +67 -0
  328. package/dist/placement.js.map +1 -0
  329. package/dist/prd-to-spec.d.ts +329 -0
  330. package/dist/prd-to-spec.d.ts.map +1 -0
  331. package/dist/prd-to-spec.js +706 -0
  332. package/dist/prd-to-spec.js.map +1 -0
  333. package/dist/prepare.d.ts +121 -0
  334. package/dist/prepare.d.ts.map +1 -0
  335. package/dist/prepare.js +140 -0
  336. package/dist/prepare.js.map +1 -0
  337. package/dist/prompt.d.ts +363 -0
  338. package/dist/prompt.d.ts.map +1 -0
  339. package/dist/prompt.js +499 -0
  340. package/dist/prompt.js.map +1 -0
  341. package/dist/protocol/ADR-FORMAT.md +47 -0
  342. package/dist/protocol/CLAIM-PROTOCOL.md +217 -0
  343. package/dist/protocol/REVIEW-PROTOCOL.md +119 -0
  344. package/dist/protocol/SURFACE-PROTOCOL.md +121 -0
  345. package/dist/protocol/TASKING-PROTOCOL.md +122 -0
  346. package/dist/protocol/WORK-CONTRACT.md +276 -0
  347. package/dist/protocol/spec-template.md +71 -0
  348. package/dist/protocol/task-template.md +65 -0
  349. package/dist/readiness.d.ts +66 -0
  350. package/dist/readiness.d.ts.map +1 -0
  351. package/dist/readiness.js +36 -0
  352. package/dist/readiness.js.map +1 -0
  353. package/dist/reap-branches.d.ts +102 -0
  354. package/dist/reap-branches.d.ts.map +1 -0
  355. package/dist/reap-branches.js +149 -0
  356. package/dist/reap-branches.js.map +1 -0
  357. package/dist/recover-isolated.d.ts +72 -0
  358. package/dist/recover-isolated.d.ts.map +1 -0
  359. package/dist/recover-isolated.js +188 -0
  360. package/dist/recover-isolated.js.map +1 -0
  361. package/dist/registry.d.ts +172 -0
  362. package/dist/registry.d.ts.map +1 -0
  363. package/dist/registry.js +296 -0
  364. package/dist/registry.js.map +1 -0
  365. package/dist/repo-config.d.ts +201 -0
  366. package/dist/repo-config.d.ts.map +1 -0
  367. package/dist/repo-config.js +414 -0
  368. package/dist/repo-config.js.map +1 -0
  369. package/dist/repo-key.d.ts +20 -0
  370. package/dist/repo-key.d.ts.map +1 -0
  371. package/dist/repo-key.js +68 -0
  372. package/dist/repo-key.js.map +1 -0
  373. package/dist/repo-mirror.d.ts +177 -0
  374. package/dist/repo-mirror.d.ts.map +1 -0
  375. package/dist/repo-mirror.js +271 -0
  376. package/dist/repo-mirror.js.map +1 -0
  377. package/dist/retry-backoff.d.ts +90 -0
  378. package/dist/retry-backoff.d.ts.map +1 -0
  379. package/dist/retry-backoff.js +98 -0
  380. package/dist/retry-backoff.js.map +1 -0
  381. package/dist/review-gate.d.ts +173 -0
  382. package/dist/review-gate.d.ts.map +1 -0
  383. package/dist/review-gate.js +261 -0
  384. package/dist/review-gate.js.map +1 -0
  385. package/dist/review-verdict.d.ts +149 -0
  386. package/dist/review-verdict.d.ts.map +1 -0
  387. package/dist/review-verdict.js +332 -0
  388. package/dist/review-verdict.js.map +1 -0
  389. package/dist/run.d.ts +221 -0
  390. package/dist/run.d.ts.map +1 -0
  391. package/dist/run.js +963 -0
  392. package/dist/run.js.map +1 -0
  393. package/dist/scan.d.ts +308 -0
  394. package/dist/scan.d.ts.map +1 -0
  395. package/dist/scan.js +374 -0
  396. package/dist/scan.js.map +1 -0
  397. package/dist/select-order.d.ts +75 -0
  398. package/dist/select-order.d.ts.map +1 -0
  399. package/dist/select-order.js +108 -0
  400. package/dist/select-order.js.map +1 -0
  401. package/dist/select-priority.d.ts +188 -0
  402. package/dist/select-priority.d.ts.map +1 -0
  403. package/dist/select-priority.js +80 -0
  404. package/dist/select-priority.js.map +1 -0
  405. package/dist/select.d.ts +25 -0
  406. package/dist/select.d.ts.map +1 -0
  407. package/dist/select.js +43 -0
  408. package/dist/select.js.map +1 -0
  409. package/dist/session-path.d.ts +36 -0
  410. package/dist/session-path.d.ts.map +1 -0
  411. package/dist/session-path.js +129 -0
  412. package/dist/session-path.js.map +1 -0
  413. package/dist/sidecar-apply.d.ts +83 -0
  414. package/dist/sidecar-apply.d.ts.map +1 -0
  415. package/dist/sidecar-apply.js +111 -0
  416. package/dist/sidecar-apply.js.map +1 -0
  417. package/dist/sidecar.d.ts +245 -0
  418. package/dist/sidecar.d.ts.map +1 -0
  419. package/dist/sidecar.js +481 -0
  420. package/dist/sidecar.js.map +1 -0
  421. package/dist/slug-namespace.d.ts +204 -0
  422. package/dist/slug-namespace.d.ts.map +1 -0
  423. package/dist/slug-namespace.js +229 -0
  424. package/dist/slug-namespace.js.map +1 -0
  425. package/dist/spec-complete.d.ts +44 -0
  426. package/dist/spec-complete.d.ts.map +1 -0
  427. package/dist/spec-complete.js +69 -0
  428. package/dist/spec-complete.js.map +1 -0
  429. package/dist/start.d.ts +97 -0
  430. package/dist/start.d.ts.map +1 -0
  431. package/dist/start.js +633 -0
  432. package/dist/start.js.map +1 -0
  433. package/dist/status.d.ts +199 -0
  434. package/dist/status.d.ts.map +1 -0
  435. package/dist/status.js +228 -0
  436. package/dist/status.js.map +1 -0
  437. package/dist/surface-gate.d.ts +162 -0
  438. package/dist/surface-gate.d.ts.map +1 -0
  439. package/dist/surface-gate.js +206 -0
  440. package/dist/surface-gate.js.map +1 -0
  441. package/dist/surface-persist.d.ts +86 -0
  442. package/dist/surface-persist.d.ts.map +1 -0
  443. package/dist/surface-persist.js +129 -0
  444. package/dist/surface-persist.js.map +1 -0
  445. package/dist/tasker-review-loop.d.ts +249 -0
  446. package/dist/tasker-review-loop.d.ts.map +1 -0
  447. package/dist/tasker-review-loop.js +369 -0
  448. package/dist/tasker-review-loop.js.map +1 -0
  449. package/dist/tasking-eligibility.d.ts +74 -0
  450. package/dist/tasking-eligibility.d.ts.map +1 -0
  451. package/dist/tasking-eligibility.js +52 -0
  452. package/dist/tasking-eligibility.js.map +1 -0
  453. package/dist/tasking-lock.d.ts +111 -0
  454. package/dist/tasking-lock.d.ts.map +1 -0
  455. package/dist/tasking-lock.js +256 -0
  456. package/dist/tasking-lock.js.map +1 -0
  457. package/dist/tasking.d.ts +275 -0
  458. package/dist/tasking.d.ts.map +1 -0
  459. package/dist/tasking.js +951 -0
  460. package/dist/tasking.js.map +1 -0
  461. package/dist/triage-gate.d.ts +127 -0
  462. package/dist/triage-gate.d.ts.map +1 -0
  463. package/dist/triage-gate.js +139 -0
  464. package/dist/triage-gate.js.map +1 -0
  465. package/dist/triage-persist.d.ts +163 -0
  466. package/dist/triage-persist.d.ts.map +1 -0
  467. package/dist/triage-persist.js +387 -0
  468. package/dist/triage-persist.js.map +1 -0
  469. package/dist/verdict-json.d.ts +32 -0
  470. package/dist/verdict-json.d.ts.map +1 -0
  471. package/dist/verdict-json.js +74 -0
  472. package/dist/verdict-json.js.map +1 -0
  473. package/dist/verify-workflow-template.d.ts +60 -0
  474. package/dist/verify-workflow-template.d.ts.map +1 -0
  475. package/dist/verify-workflow-template.js +126 -0
  476. package/dist/verify-workflow-template.js.map +1 -0
  477. package/dist/verify.d.ts +60 -0
  478. package/dist/verify.d.ts.map +1 -0
  479. package/dist/verify.js +62 -0
  480. package/dist/verify.js.map +1 -0
  481. package/dist/watch-session.d.ts +112 -0
  482. package/dist/watch-session.d.ts.map +1 -0
  483. package/dist/watch-session.js +347 -0
  484. package/dist/watch-session.js.map +1 -0
  485. package/dist/work-layout.d.ts +198 -0
  486. package/dist/work-layout.d.ts.map +1 -0
  487. package/dist/work-layout.js +217 -0
  488. package/dist/work-layout.js.map +1 -0
  489. package/dist/work-on.d.ts +154 -0
  490. package/dist/work-on.d.ts.map +1 -0
  491. package/dist/work-on.js +387 -0
  492. package/dist/work-on.js.map +1 -0
  493. package/dist/workspace.d.ts +224 -0
  494. package/dist/workspace.d.ts.map +1 -0
  495. package/dist/workspace.js +325 -0
  496. package/dist/workspace.js.map +1 -0
  497. package/package.json +46 -2
  498. package/src/advance-ci-template.ts +203 -0
  499. package/src/advance-classify.ts +197 -0
  500. package/src/advance-drivers.ts +414 -0
  501. package/src/advance-isolated.ts +432 -0
  502. package/src/advance-lifecycle-template.ts +791 -0
  503. package/src/advance-loop-driver.ts +745 -0
  504. package/src/advance-treeless-publish.ts +177 -0
  505. package/src/advance.ts +1564 -0
  506. package/src/advancing-lock.ts +988 -0
  507. package/src/agent-launch.ts +137 -0
  508. package/src/agent-stop.ts +361 -0
  509. package/src/apply-decide.ts +242 -0
  510. package/src/apply-merge-action.ts +502 -0
  511. package/src/apply-persist.ts +518 -0
  512. package/src/arbiter.ts +372 -0
  513. package/src/brand.ts +111 -0
  514. package/src/buildable-body.ts +196 -0
  515. package/src/categorise.ts +158 -0
  516. package/src/claim-cas.ts +513 -0
  517. package/src/cli-spinner.ts +225 -0
  518. package/src/cli.ts +4379 -0
  519. package/src/close-job-template.ts +236 -0
  520. package/src/close-job.ts +319 -0
  521. package/src/complete.ts +1379 -0
  522. package/src/concurrency.ts +151 -0
  523. package/src/config-override.ts +116 -0
  524. package/src/config.ts +883 -0
  525. package/src/continue-branch.ts +542 -0
  526. package/src/cwd-section.ts +392 -0
  527. package/src/decision-engine.ts +272 -0
  528. package/src/detect.ts +124 -0
  529. package/src/do-autopick.ts +223 -0
  530. package/src/do-config.ts +589 -0
  531. package/src/do-remote-auto.ts +197 -0
  532. package/src/do.ts +2623 -0
  533. package/src/drop-source.ts +194 -0
  534. package/src/eligibility.ts +79 -0
  535. package/src/env-config.ts +305 -0
  536. package/src/failure-cause.ts +142 -0
  537. package/src/format.ts +313 -0
  538. package/src/frontmatter.ts +477 -0
  539. package/src/gate-readiness.ts +147 -0
  540. package/src/gc.ts +510 -0
  541. package/src/gh-failure.ts +53 -0
  542. package/src/git.ts +186 -0
  543. package/src/github.ts +468 -0
  544. package/src/harness.ts +355 -0
  545. package/src/identity.ts +322 -0
  546. package/src/index.ts +785 -0
  547. package/src/install-ci-branch-protection.ts +255 -0
  548. package/src/install-ci-capabilities/advance-lifecycle.ts +34 -0
  549. package/src/install-ci-capabilities/close-job.ts +32 -0
  550. package/src/install-ci-capabilities/example-noop.ts +24 -0
  551. package/src/install-ci-capabilities/intake.ts +34 -0
  552. package/src/install-ci-capabilities/verify.ts +33 -0
  553. package/src/install-ci-core.ts +1088 -0
  554. package/src/install-ci-github.ts +376 -0
  555. package/src/install-ci.ts +552 -0
  556. package/src/intake-event.ts +102 -0
  557. package/src/intake-marker.ts +195 -0
  558. package/src/intake-triage.ts +138 -0
  559. package/src/intake-trigger-template.ts +591 -0
  560. package/src/intake.ts +2445 -0
  561. package/src/integration-core.ts +3065 -0
  562. package/src/integrator.ts +771 -0
  563. package/src/isolation.ts +484 -0
  564. package/src/issue-provider.ts +733 -0
  565. package/src/item-lock.ts +1858 -0
  566. package/src/item-path.ts +75 -0
  567. package/src/ledger-lint.ts +332 -0
  568. package/src/ledger-read.ts +924 -0
  569. package/src/ledger-write.ts +865 -0
  570. package/src/lifecycle-gather.ts +298 -0
  571. package/src/lifecycle-pools.ts +250 -0
  572. package/src/merge-question-surfacer.ts +496 -0
  573. package/src/mint-adr.ts +362 -0
  574. package/src/mirror-pool-scan.ts +240 -0
  575. package/src/needs-attention.ts +1506 -0
  576. package/src/orphan-sidecar.ts +150 -0
  577. package/src/output.ts +89 -0
  578. package/src/pi-harness.ts +403 -0
  579. package/src/placement.ts +131 -0
  580. package/src/prd-to-spec.ts +1059 -0
  581. package/src/prepare.ts +230 -0
  582. package/src/prompt.ts +763 -0
  583. package/src/readiness.ts +98 -0
  584. package/src/reap-branches.ts +278 -0
  585. package/src/recover-isolated.ts +276 -0
  586. package/src/registry.ts +475 -0
  587. package/src/repo-config.ts +550 -0
  588. package/src/repo-key.ts +74 -0
  589. package/src/repo-mirror.ts +367 -0
  590. package/src/retry-backoff.ts +130 -0
  591. package/src/review-gate.ts +389 -0
  592. package/src/review-verdict.ts +422 -0
  593. package/src/run.ts +1430 -0
  594. package/src/scan.ts +611 -0
  595. package/src/select-order.ts +143 -0
  596. package/src/select-priority.ts +266 -0
  597. package/src/select.ts +62 -0
  598. package/src/session-path.ts +153 -0
  599. package/src/sidecar-apply.ts +216 -0
  600. package/src/sidecar.ts +700 -0
  601. package/src/slug-namespace.ts +367 -0
  602. package/src/spec-complete.ts +118 -0
  603. package/src/start.ts +974 -0
  604. package/src/status.ts +441 -0
  605. package/src/surface-gate.ts +337 -0
  606. package/src/surface-persist.ts +241 -0
  607. package/src/tasker-review-loop.ts +671 -0
  608. package/src/tasking-eligibility.ts +114 -0
  609. package/src/tasking-lock.ts +416 -0
  610. package/src/tasking.ts +1437 -0
  611. package/src/triage-gate.ts +248 -0
  612. package/src/triage-persist.ts +570 -0
  613. package/src/verdict-json.ts +73 -0
  614. package/src/verify-workflow-template.ts +159 -0
  615. package/src/verify.ts +123 -0
  616. package/src/watch-session.ts +397 -0
  617. package/src/work-layout.ts +262 -0
  618. package/src/work-on.ts +660 -0
  619. package/src/workspace.ts +502 -0
@@ -0,0 +1,791 @@
1
+ /**
2
+ * The `install-ci` ADVANCE-LIFECYCLE capability (prd `runner-in-ci`, task
3
+ * `install-ci-advance-lifecycle-workflow`; capability C: auto-triage observations
4
+ * + surface declared blockers + apply committed answers). This module GENERATES
5
+ * the advance-lifecycle workflow by ABSORBING and PARAMETERISING the existing seed
6
+ * `docs/ci/advance-loop.yml.template` (the advance-loop capability's output) — it
7
+ * does NOT hand-roll a competing advance workflow. It also STRUCTURALLY VALIDATES
8
+ * the emitted YAML, mirroring the snapshot-assertion style of
9
+ * `advance-ci-template.ts` (the package depends on
10
+ * NO YAML lib, so the checks are presence/shape assertions over the raw text).
11
+ *
12
+ * This is the "human is the clock" loop: CI drains the populated `work/` tree
13
+ * toward done while the human only answers committed question sidecars on their own
14
+ * time. Over the build/task tick (its sibling capability), the advance-lifecycle
15
+ * tick adds exactly three things — and they are the whole reason `advance` (not
16
+ * `do`) is the verb here:
17
+ *
18
+ * - the LIFECYCLE rungs (triage observations / surface declared blockers / apply
19
+ * a committed answer), gated by the two calm-default lifecycle gates below;
20
+ * - the on-answer-committed trigger `on: push work/questions/**`, which re-runs
21
+ * the loop promptly when a question sidecar is answered;
22
+ * - (already in the absorbed seed) capability F — the `reap-merged-branches` job
23
+ * (`gc --remote-branches`) on the same `schedule:` cron, opt-out via the
24
+ * `sweepMergedBranches` dispatch input.
25
+ *
26
+ * The discipline is VERBATIM from the seed:
27
+ *
28
+ * - CI ALWAYS invokes `advance` (ADR `ci-config-policy-and-gate-family` §1):
29
+ * `advance` is a strict superset of `do`, and with the lifecycle gates at their
30
+ * calm defaults it degrades to exactly `do`'s build/task behaviour. The verb
31
+ * is NEVER a user decision; the workflow tunes behaviour via the
32
+ * `DORFL_*` env block, not by swapping the verb. There is NO
33
+ * `autoAdvance` gate.
34
+ * - The two LIFECYCLE gates are ORTHOGONAL peers, both calm by default:
35
+ * `DORFL_OBSERVATION_TRIAGE` (`off`/`ask`/`auto`, calm `off`) governs the
36
+ * raw observation INBOX; `DORFL_SURFACE_BLOCKERS` (`true`/`false`, calm
37
+ * `false`) governs DECLARED `needsAnswers` work. "Groom my observations but
38
+ * leave my blocked work alone" = `OBSERVATION_TRIAGE: ask` + `SURFACE_BLOCKERS:
39
+ * false`. Applying a committed answer has NO gate.
40
+ * - ONE word `integrationMode` drives BOTH the job SHAPE AND the
41
+ * `--propose`/`--merge` flag (they can never desync): `propose` ⇒ a DYNAMIC
42
+ * matrix (`dorfl scan --json | jq` enumerates one leg per eligible id,
43
+ * each leg carries `--propose` so it can NEVER merge to `main`); `merge` ⇒ ALSO
44
+ * a MATRIX (one leg per item; build/gate/review fan out, the LAND tail is
45
+ * serialised by the engine's `mergeRetries` CAS-retry loop — the git-alone
46
+ * floor — NOT by the workflow shape; PRD
47
+ * `land-time-reverify-and-parallel-merge-ceiling`). This is integration-mode
48
+ * behaviour, IDENTICAL to the build tick (integration mode is
49
+ * verb-independent).
50
+ * - CI runs IN-PLACE (the CI container IS the isolation): no
51
+ * `--isolated`/`--remote`/registry. A CI concurrency group (per-ref) prevents
52
+ * overlapping ticks; the claim CAS is the real cross-run serialiser.
53
+ * - All invocations use explicit slug prefixes (`task:`/`spec:`), never bare
54
+ * (ADR `command-surface-and-journeys` §3a).
55
+ * - The running CI job NEVER edits `.github/workflows/**` (US #9): it requests
56
+ * NO `workflows` permission and cannot rewrite its own triggers.
57
+ *
58
+ * The structural validator is the dependency-free counterpart of "the workflow
59
+ * parses + carries the right discipline" the task's acceptance criteria require;
60
+ * the test generates this artifact under `--fake` and asserts every invariant.
61
+ */
62
+
63
+ import type {ResolvedCIConfig} from './install-ci-core.js';
64
+ import {providerSecretsWithBlock} from './install-ci-core.js';
65
+
66
+ /** The capability id (the registry key + the emitted workflow file stem). */
67
+ export const ADVANCE_LIFECYCLE_CAPABILITY_ID = 'advance-lifecycle';
68
+
69
+ /** The wizard-facing label for the advance-lifecycle capability. */
70
+ export const ADVANCE_LIFECYCLE_CAPABILITY_LABEL =
71
+ 'Auto-triage observations + surface declared blockers + apply committed answers (the advance lifecycle loop: cron + dispatch + on-answer-committed)';
72
+
73
+ /** The repo-relative path (under the output base) of the emitted workflow. */
74
+ export const ADVANCE_LIFECYCLE_WORKFLOW_PATH =
75
+ 'workflows/advance-lifecycle.yml';
76
+
77
+ /**
78
+ * Generate the advance-lifecycle workflow YAML by PARAMETERISING the seed
79
+ * `docs/ci/advance-loop.yml.template`. Deterministic: the same config produces
80
+ * byte-identical output. The workflow is a FIXED shell (ADR §6: all policy is
81
+ * env/config, so the artifact carries no config-derived policy beyond the env-block
82
+ * scaffolding) — `config` is accepted for parity with the `CapabilityEmitter` seam
83
+ * and future per-config wiring, but the advance-lifecycle shape itself is
84
+ * config-independent.
85
+ *
86
+ * This is the absorbed seed, with two parameterisations: (1) it wires the SHARED
87
+ * composite setup action (`./.github/actions/dorfl-setup`, emitted by the
88
+ * core task) into every job; (2) it surfaces the engine gate family — including
89
+ * the two calm-default LIFECYCLE gates — as the `DORFL_*` env block, so the
90
+ * out-of-the-box tick asks nothing until the user opts in. The seed's capability-F
91
+ * reap job + `sweepMergedBranches` input are PRESERVED verbatim (NOT stripped); no
92
+ * separate gc-sweep workflow is emitted.
93
+ */
94
+ export function generateAdvanceLifecycleWorkflow(
95
+ config: ResolvedCIConfig,
96
+ ): string {
97
+ // The agent-running jobs (propose / merge) pass the configured provider
98
+ // secret(s) to the setup action ONCE via `with:`; the action forwards them to
99
+ // `$GITHUB_ENV` so `pi` can authenticate (models-json mode). auth-json mode has
100
+ // no provider keys here (it uses auth.json), so the block is empty.
101
+ const setupWith = providerSecretsWithBlock(config);
102
+ return `\
103
+ # dorfl — the ADVANCE LIFECYCLE loop in CI (capability C: auto-triage
104
+ # observations + surface declared blockers + apply committed answers, prd
105
+ # runner-in-ci). EMITTED by \`dorfl install-ci\` by PARAMETERISING the seed
106
+ # \`docs/ci/advance-loop.yml.template\` (the advance-loop capability's output) — the
107
+ # human commits it. DO NOT hand-edit a copy — re-run install-ci to upgrade the
108
+ # shell, and edit the workflow SHAPE in the seed template, not here.
109
+ #
110
+ # THIS is the "human is the clock" loop: CI drains the populated work/ tree toward
111
+ # done while the human only answers committed question sidecars (work/questions/**)
112
+ # on their own time.
113
+ #
114
+ # CI ALWAYS invokes \`advance\` (NEVER a user-chosen verb): \`advance\` is a strict
115
+ # superset of \`do\`, and with the lifecycle gates at their calm defaults (below) it
116
+ # degrades to exactly \`do\`'s build/task behaviour (ADR
117
+ # ci-config-policy-and-gate-family §1). The triage/surface/apply rungs + the
118
+ # on-answer-committed trigger are EXACTLY what \`advance\` adds over the build/task
119
+ # tick. There is NO \`autoAdvance\` gate — the lifecycle decomposes into the gate
120
+ # family in the env block.
121
+ #
122
+ # ONE WORD, ONE MEANING — \`integrationMode\` drives BOTH the job SHAPE AND the
123
+ # \`--propose\`/\`--merge\` flag the legs pass, so they can NEVER desync:
124
+ # * propose ⇒ a DYNAMIC matrix (one leg per eligible id, enumerated via
125
+ # \`dorfl scan --json | jq\`), each leg \`advance --propose\`
126
+ # opening its OWN PR — a leg can NEVER merge to main.
127
+ # * merge ⇒ ALSO a MATRIX (one leg per item; build/gate/review fan out, the
128
+ # LAND tail — rebase + CAS push to \`main\` — is serialised by the
129
+ # engine's \`mergeRetries\` CAS-retry loop, NOT by the workflow shape.
130
+ # PRD \`land-time-reverify-and-parallel-merge-ceiling\`: a
131
+ # non-fast-forward push triggers re-rebase + re-gate + retry, never
132
+ # a \`--force\`. The cross-job serialiser is the CAS-retry FLOOR;
133
+ # there is NO host-specific \`concurrency:\` group on the merge job).
134
+ # This is integration-mode behaviour, IDENTICAL to the build/task tick
135
+ # (integration mode is verb-independent). The CLAIM CAS, not the matrix, is the
136
+ # real cross-run serialiser: a leg that loses the claim race exits clean.
137
+ #
138
+ # CI runs IN-PLACE (the CI container IS the isolation): NO --isolated/--remote/
139
+ # registry (laptop-only affordances). The concurrency group below stops
140
+ # overlapping ticks of the same ref from colliding.
141
+ #
142
+ # SAFETY (US #9): the running job is FORBIDDEN from editing the workflows tree
143
+ # under .github. It requests NO \`workflows\` permission, so it can never rewrite
144
+ # its own triggers.
145
+
146
+ name: advance-lifecycle
147
+
148
+ on:
149
+ schedule:
150
+ # Cron tick: drain whatever the human has answered/produced since the last run
151
+ # (triage / surface / apply + build / task). Adjust the cadence to taste
152
+ # (here: hourly).
153
+ - cron: '0 * * * *'
154
+ push:
155
+ # On-answer-committed: a push that touches an answered question sidecar
156
+ # (\`work/questions/**\`) re-runs the loop so the human's answer is applied
157
+ # promptly. This is the lifecycle-specific trigger \`do\` cannot provide.
158
+ paths:
159
+ - 'work/questions/**'
160
+ workflow_dispatch:
161
+ inputs:
162
+ integrationMode:
163
+ description: "Integration mode (drives BOTH the integration flag passed to \`advance\` AND the job shape): propose ⇒ a matrix, each leg \`advance --propose\` (one PR per item); merge ⇒ a matrix, each leg \`advance --merge\` (one item — build/gate/review fan out in parallel; the LAND tail is serialised by the engine's \`mergeRetries\` CAS-retry loop, not by the workflow shape)."
164
+ required: false
165
+ default: 'propose'
166
+ type: choice
167
+ options:
168
+ - propose
169
+ - merge
170
+ sweepMergedBranches:
171
+ description: 'Reap merged remote work/* branches on the scheduled tick (gc --remote-branches): delete only branches PROVABLY MERGED into <arbiter>/main, so out-of-band human/UI PR merges stop leaving their work/<slug> branches lingering on the arbiter. ON by default; set false to opt out. An in-flight (un-merged) branch is NEVER touched.'
172
+ required: false
173
+ default: true
174
+ type: boolean
175
+ # ── GATE-FAMILY one-shot overrides (dispatch only) ──────────────────────
176
+ # Override an engine gate for THIS manual run only, riding the env layer of
177
+ # flag > env > per-repo > global > default. Modelled as \`type: choice\` with a
178
+ # BLANK first option (not \`type: boolean\`, which cannot represent "unset"):
179
+ # blank ⇒ emit NOTHING (the committed .dorfl.json wins, today's
180
+ # behaviour); a non-blank choice ⇒ export the matching DORFL_* for this
181
+ # run. The blank is load-bearing: env-config coercion THROWS on an empty
182
+ # string, so the per-job step below only writes when the input is non-blank.
183
+ autoBuild:
184
+ description: 'One-shot override of the autoBuild gate (DORFL_AUTO_BUILD) for THIS dispatch run only. Blank ⇒ no override (config wins).'
185
+ required: false
186
+ default: ''
187
+ type: choice
188
+ options:
189
+ - ''
190
+ - 'true'
191
+ - 'false'
192
+ autoTask:
193
+ description: 'One-shot override of the autoTask gate (DORFL_AUTO_TASK) for THIS dispatch run only. Blank ⇒ no override (config wins).'
194
+ required: false
195
+ default: ''
196
+ type: choice
197
+ options:
198
+ - ''
199
+ - 'true'
200
+ - 'false'
201
+ observationTriage:
202
+ description: 'One-shot override of the observationTriage gate (DORFL_OBSERVATION_TRIAGE) for THIS dispatch run only. Blank ⇒ no override (config wins).'
203
+ required: false
204
+ default: ''
205
+ type: choice
206
+ options:
207
+ - ''
208
+ - 'off'
209
+ - 'ask'
210
+ - 'auto'
211
+ surfaceBlockers:
212
+ description: 'One-shot override of the surfaceBlockers gate (DORFL_SURFACE_BLOCKERS) for THIS dispatch run only. Blank ⇒ no override (config wins).'
213
+ required: false
214
+ default: ''
215
+ type: choice
216
+ options:
217
+ - ''
218
+ - 'true'
219
+ - 'false'
220
+
221
+ # Serialise overlapping ticks of the same ref; the claim CAS is the real
222
+ # cross-run serialiser, this just avoids redundant concurrent ticks.
223
+ concurrency:
224
+ group: advance-lifecycle-\${{ github.ref }}
225
+ cancel-in-progress: false
226
+
227
+ # NO \`workflows\` permission: the running job can NEVER edit the workflows tree
228
+ # under .github (US #9). \`contents: write\` + \`pull-requests: write\` are all this
229
+ # tick needs (commit work, open PRs); it never rewrites its triggers.
230
+ permissions:
231
+ contents: write
232
+ pull-requests: write
233
+
234
+ env:
235
+ # The resolved integration mode: the dispatch input when present, else \`propose\`
236
+ # (the conservative default — one PR per item, a human merges). This single value
237
+ # selects BOTH the job shape (via the \`if:\` guards below) AND the integration flag
238
+ # the \`advance\` legs pass (\`--propose\`/\`--merge\`), so they can never desync.
239
+ INTEGRATION_MODE: \${{ github.event.inputs.integrationMode || 'propose' }}
240
+ # Reap merged remote work/* branches on the scheduled tick (capability F). ON by
241
+ # default (the empty dispatch input on a \`schedule\`/\`push\` trigger reads as the
242
+ # default); set the \`sweepMergedBranches\` dispatch input to \`false\` to opt out.
243
+ # This is the provider-agnostic hygiene sweep (\`gc --remote-branches\`) for
244
+ # out-of-band human/UI PR merges, whose work/<slug> branch nothing else deletes.
245
+ SWEEP_MERGED_BRANCHES: \${{ github.event.inputs.sweepMergedBranches || 'true' }}
246
+
247
+ # ── The engine GATE FAMILY is resolved FROM CONFIG, not carried here ─────────
248
+ # CI is NOT a special policy surface (ADR ci-config-policy-and-gate-family §5):
249
+ # it runs the SAME engine gates, resolved through flag > env > per-repo > global
250
+ # > default. The SAME .dorfl.json the laptop uses applies here. This
251
+ # workflow emits NO DORFL_AUTO_BUILD / DORFL_AUTO_TASK /
252
+ # DORFL_OBSERVATION_TRIAGE / DORFL_SURFACE_BLOCKERS line on a
253
+ # SCHEDULE/PUSH tick, so the env layer carries NO defaults there — your committed
254
+ # .dorfl.json wins (then the global config, then the strict built-in
255
+ # defaults autoBuild:false / autoTask:false / observationTriage:'off' /
256
+ # surfaceBlockers:false). The ONE exception is a manual \`workflow_dispatch\` where
257
+ # you fill a gate override input (above): the per-job step then exports that ONE
258
+ # DORFL_* for that run only (blank input ⇒ still nothing). The override
259
+ # MUST be wired into every job that resolves the gate family — including the
260
+ # \`enumerate\` scan (it gates the matrix pools via observationTriage/surfaceBlockers
261
+ # /autoTask/autoBuild), not just the agent-running jobs — or the override is inert
262
+ # for the very pools it targets. To enable CI autonomy durably, set the gate(s) in
263
+ # .dorfl.json (applies everywhere) — NOT by re-running install-ci (ADR §6:
264
+ # install-ci is one-time).
265
+
266
+ jobs:
267
+ # ── ENUMERATE (propose only) ────────────────────────────────────────────────
268
+ # Build the DYNAMIC matrix from the eligible-pool scan. \`scan --json\` reports
269
+ # BOTH the registry/hub-mirror pool (\`repos[].items[]\`, \`repos[].specs[]\`,
270
+ # \`repos[].lifecycle\`) AND the in-place working checkout (\`cwd.repo.items[]\`,
271
+ # \`cwd.repo.specs[]\`, \`cwd.repo.lifecycle\`); CI runs IN-PLACE so the items live
272
+ # in the latter (a fresh runner has no registered mirror). \`jq\` unions + dedups
273
+ # the build/task pools AND the LIFECYCLE pools into a deduplicated GitHub
274
+ # Actions matrix list of explicit \`task:<slug>\` / \`spec:<slug>\` / \`obs:<slug>\`
275
+ # ids (CI MUST use explicit prefixes). The lifecycle legs run the WHOLE
276
+ # answer-loop in propose mode (not only merge): \`obs:\` (triage untriaged
277
+ # observations), surface \`task:\`/\`spec:\` (\`needsAnswers\`, no answered sidecar)
278
+ # AND apply \`task:\`/\`spec:\` (\`needsAnswers\`, answered sidecar — consume the
279
+ # committed answer, closing the on-answer \`push: work/questions/**\` loop). Each
280
+ # becomes one matrix leg → one independent \`advance --propose\`. Skipped in merge
281
+ # mode. Inert with calm-default gates (empty triage/surface pools).
282
+ enumerate:
283
+ runs-on: ubuntu-latest
284
+ outputs:
285
+ items: \${{ steps.scan.outputs.items }}
286
+ any: \${{ steps.scan.outputs.any }}
287
+ steps:
288
+ - uses: actions/checkout@v4
289
+ with:
290
+ fetch-depth: 0
291
+ - uses: ./.github/actions/dorfl-setup
292
+ - name: apply dispatch gate overrides (one-shot, this run only)
293
+ # MUST run BEFORE \`scan\`: scan's matrix pools are gated by the SAME engine
294
+ # gate family (autoTask/autoBuild + lifecycle observationTriage/
295
+ # surfaceBlockers), so an override that does not reach this job produces an
296
+ # empty matrix and is silently inert. \`if:\` + the inner \`[ -n ... ]\` guard
297
+ # keep schedule/push (and a blank dispatch field) exporting NOTHING — an
298
+ # empty DORFL_* would make env-config coercion throw.
299
+ if: \${{ github.event_name == 'workflow_dispatch' }}
300
+ run: |
301
+ [ -n "\${{ github.event.inputs.autoBuild }}" ] && echo "DORFL_AUTO_BUILD=\${{ github.event.inputs.autoBuild }}" >> "$GITHUB_ENV"
302
+ [ -n "\${{ github.event.inputs.autoTask }}" ] && echo "DORFL_AUTO_TASK=\${{ github.event.inputs.autoTask }}" >> "$GITHUB_ENV"
303
+ [ -n "\${{ github.event.inputs.observationTriage }}" ] && echo "DORFL_OBSERVATION_TRIAGE=\${{ github.event.inputs.observationTriage }}" >> "$GITHUB_ENV"
304
+ [ -n "\${{ github.event.inputs.surfaceBlockers }}" ] && echo "DORFL_SURFACE_BLOCKERS=\${{ github.event.inputs.surfaceBlockers }}" >> "$GITHUB_ENV"
305
+ true
306
+ - id: scan
307
+ # Enumerate eligible items as namespaced ids, one matrix leg per id. CI
308
+ # uses explicit \`task:\` / \`spec:\` / \`obs:\` prefixes, never bare (ADR
309
+ # command-surface §3a). Eligible TASKS ⇒ \`task:<slug>\` legs (\`advance\`
310
+ # builds them); TASKABLE SPECS ⇒ \`spec:<slug>\` legs (\`advance\` auto-tasks
311
+ # them, capability B — \`DORFL_AUTO_TASK\` above). LIFECYCLE pools:
312
+ # \`lifecycle.triage[]\` ⇒ \`obs:<slug>\` (the \`obs:\` prefix is fixed here),
313
+ # \`lifecycle.surface[]\` + \`lifecycle.apply[]\` ⇒ \`.namespace + ":" + .slug\`
314
+ # (surface: \`task:\`/\`spec:\` blocker-question legs; apply: \`task:\`/\`spec:\`
315
+ # AND \`observation:\` legs — an answered observation sidecar is consumed by
316
+ # the apply rung too, so it MUST carry through here). CI runs IN-PLACE, so we use
317
+ # \`scan --here\`: it reports ONLY the cwd checkout (\`cwd.repo.*\`) and SKIPS
318
+ # the cross-repo registry loop (no N-mirror fetches; a fresh runner has no
319
+ # registered mirror anyway). The \`cwd\` arbiter is the checkout's own clone,
320
+ # so the fetch-first is a near-noop. \`jq\` still reads the (now-empty)
321
+ # \`repos[]\` branches harmlessly; we union + dedup so the matrix has one
322
+ # leg per item.
323
+ run: |
324
+ items="$(dorfl scan --json --here \\
325
+ | jq -c '[(.repos[].items[]?, .cwd.repo.items[]?) | select(.eligibility.eligible == true) | "task:" + .slug] + [(.repos[].specs[]?, .cwd.repo.specs[]?) | select(.eligibility.eligible == true) | "spec:" + .slug] + [(.repos[].lifecycle.triage[]?, .cwd.repo.lifecycle.triage[]?) | "obs:" + .slug] + [(.repos[].lifecycle.surface[]?, .cwd.repo.lifecycle.surface[]?, .repos[].lifecycle.apply[]?, .cwd.repo.lifecycle.apply[]?) | .namespace + ":" + .slug] | unique')"
326
+ echo "items=\${items}" >> "$GITHUB_OUTPUT"
327
+ if [ "$(echo "\${items}" | jq 'length')" -gt 0 ]; then
328
+ echo "any=true" >> "$GITHUB_OUTPUT"
329
+ else
330
+ echo "any=false" >> "$GITHUB_OUTPUT"
331
+ fi
332
+
333
+ # ── PROPOSE: a MATRIX of independent jobs (one PR per item) ──────────────────
334
+ # True parallelism — each item is an independent PR, so a matrix is the right
335
+ # parallel shape and \`-n\` is NOT needed. Each leg passes \`--propose\`, tying the
336
+ # integration mode to THIS shape: it sits at the top of the precedence chain, so
337
+ # the workflow mode always wins over the repo config default and a leg can NEVER
338
+ # merge to main. Explicit \`task:\`/\`spec:\` prefixes only, never bare.
339
+ advance-propose:
340
+ needs: enumerate
341
+ if: \${{ (github.event.inputs.integrationMode || 'propose') == 'propose' && needs.enumerate.outputs.any == 'true' }}
342
+ runs-on: ubuntu-latest
343
+ strategy:
344
+ # Independent PRs: one failing item must NOT cancel the others.
345
+ fail-fast: false
346
+ # Cap concurrent legs (config \`maxParallel\`, install-ci --max-parallel):
347
+ # each leg spawns a FULL agent session (build + Gate-2 review), so an
348
+ # unbounded fan-out over a large item set exhausts the model-provider API
349
+ # rate limit (429s that strand legs as transient-infra stuck) AND thrashes
350
+ # the arbiter-main CAS. A bounded fan-out drains steadily instead.
351
+ max-parallel: ${config.maxParallel}
352
+ matrix:
353
+ item: \${{ fromJson(needs.enumerate.outputs.items) }}
354
+ steps:
355
+ - uses: actions/checkout@v4
356
+ with:
357
+ fetch-depth: 0
358
+ - uses: ./.github/actions/dorfl-setup${setupWith}
359
+ - name: apply dispatch gate overrides (one-shot, this run only)
360
+ # Mirror of the enumerate-job override (see there): export each gate's
361
+ # DORFL_* ONLY on a workflow_dispatch with a non-blank input, so the
362
+ # one-shot override also reaches the \`advance\` leg that builds the item.
363
+ if: \${{ github.event_name == 'workflow_dispatch' }}
364
+ run: |
365
+ [ -n "\${{ github.event.inputs.autoBuild }}" ] && echo "DORFL_AUTO_BUILD=\${{ github.event.inputs.autoBuild }}" >> "$GITHUB_ENV"
366
+ [ -n "\${{ github.event.inputs.autoTask }}" ] && echo "DORFL_AUTO_TASK=\${{ github.event.inputs.autoTask }}" >> "$GITHUB_ENV"
367
+ [ -n "\${{ github.event.inputs.observationTriage }}" ] && echo "DORFL_OBSERVATION_TRIAGE=\${{ github.event.inputs.observationTriage }}" >> "$GITHUB_ENV"
368
+ [ -n "\${{ github.event.inputs.surfaceBlockers }}" ] && echo "DORFL_SURFACE_BLOCKERS=\${{ github.event.inputs.surfaceBlockers }}" >> "$GITHUB_ENV"
369
+ true
370
+ - name: advance one item in-place (propose ⇒ opens a PR)
371
+ # In-place in this checkout (no --isolated/--remote): the CI container IS
372
+ # the isolation. \`--propose\` can ONLY ride a matrix leg, never the merge
373
+ # job, so a parallel merge-to-main is structurally impossible.
374
+ # \`--propose\` shells \`gh\` to open the PR, which reads \`GH_TOKEN\` from the
375
+ # env (a workflow PERMISSION is not a credential). Prefer a dedicated
376
+ # \`DORFL_GH_TOKEN\` secret (a PAT / App token) so PRs carry YOUR
377
+ # identity AND trigger downstream workflows (PRs opened with the built-in
378
+ # \`GITHUB_TOKEN\` are \`github-actions[bot]\` and do NOT trigger further
379
+ # \`on: pull_request\` runs). Falls back to the auto \`GITHUB_TOKEN\` so it
380
+ # works zero-config; the job's \`pull-requests: write\` scopes that token.
381
+ env:
382
+ GH_TOKEN: \${{ secrets.DORFL_GH_TOKEN || secrets.GITHUB_TOKEN }}
383
+ # \`--watch\` streams the build agent's high-signal turns (assistant text,
384
+ # tool calls, finish) into THIS job log live, so the run shows the agent
385
+ # working instead of freezing after "Start work". A read-only observer (no
386
+ # outcome/gate/git effect). It fits because each matrix leg names ONE item
387
+ # (one pi session to tail) — the merge job is now a per-item matrix too
388
+ # (see below) and streams the same way.
389
+ run: dorfl advance "\${{ matrix.item }}" --propose --watch --arbiter origin
390
+
391
+ # ── MERGE: a MATRIX of independent jobs (parallel build/gate/review, serialised land) ──
392
+ # PRD \`land-time-reverify-and-parallel-merge-ceiling\` (stories 4 + 6): each item
393
+ # gets its own leg; build/gate/review run concurrently across siblings; the LAND
394
+ # TAIL is serialised by the engine's \`mergeRetries\` CAS-retry loop — the
395
+ # git-alone floor — NOT by the workflow shape. A non-fast-forward push triggers
396
+ # re-rebase + re-gate + retry up to the resolved \`mergeRetries\` cap; never a
397
+ # \`--force\`. NO host-specific \`concurrency:\` group on this job (it would be
398
+ # load-bearing for cross-job safety, breaking the floor framing).
399
+ # The fully-autonomous-to-main path (this job + all gates on) is still a LOUD,
400
+ # NON-DEFAULT opt-in: the default integrationMode is \`propose\`, so reaching
401
+ # merge-to-main requires deliberately dispatching/pinning \`merge\`.
402
+ advance-merge:
403
+ needs: enumerate
404
+ if: \${{ (github.event.inputs.integrationMode || 'propose') == 'merge' && needs.enumerate.outputs.any == 'true' }}
405
+ runs-on: ubuntu-latest
406
+ strategy:
407
+ # Independent landings: one failing item must NOT cancel the others; a
408
+ # loser of the CAS race re-rebases + re-gates + retries.
409
+ fail-fast: false
410
+ # Cap concurrent legs (config \`maxParallel\`, see advance-propose): a FULL
411
+ # agent session per leg, so bound the fan-out to avoid API-429s + CAS thrash.
412
+ max-parallel: ${config.maxParallel}
413
+ matrix:
414
+ item: \${{ fromJson(needs.enumerate.outputs.items) }}
415
+ steps:
416
+ - uses: actions/checkout@v4
417
+ with:
418
+ fetch-depth: 0
419
+ - uses: ./.github/actions/dorfl-setup${setupWith}
420
+ - name: apply dispatch gate overrides (one-shot, this run only)
421
+ # Mirror of the enumerate-job override (see there): export each gate's
422
+ # DORFL_* ONLY on a workflow_dispatch with a non-blank input. The
423
+ # merge job re-scans the pool inside \`advance -n\`, so it needs the override
424
+ # too for the lifecycle/task pools to reflect it.
425
+ if: \${{ github.event_name == 'workflow_dispatch' }}
426
+ run: |
427
+ [ -n "\${{ github.event.inputs.autoBuild }}" ] && echo "DORFL_AUTO_BUILD=\${{ github.event.inputs.autoBuild }}" >> "$GITHUB_ENV"
428
+ [ -n "\${{ github.event.inputs.autoTask }}" ] && echo "DORFL_AUTO_TASK=\${{ github.event.inputs.autoTask }}" >> "$GITHUB_ENV"
429
+ [ -n "\${{ github.event.inputs.observationTriage }}" ] && echo "DORFL_OBSERVATION_TRIAGE=\${{ github.event.inputs.observationTriage }}" >> "$GITHUB_ENV"
430
+ [ -n "\${{ github.event.inputs.surfaceBlockers }}" ] && echo "DORFL_SURFACE_BLOCKERS=\${{ github.event.inputs.surfaceBlockers }}" >> "$GITHUB_ENV"
431
+ true
432
+ - name: advance one item in-place (merge ⇒ rebase + CAS land on main)
433
+ # In-place (no --isolated/--remote). \`--merge\` ties the integration mode
434
+ # to THIS (matrix) shape: it sits at the top of the precedence chain, so
435
+ # the workflow mode always wins over the repo's \`.dorfl.json\` default.
436
+ # Cross-job land safety comes from the engine's CAS-retry loop, not from
437
+ # this workflow's job shape. \`gh\` (merge / PR housekeeping) reads
438
+ # \`GH_TOKEN\` from the env.
439
+ env:
440
+ GH_TOKEN: \${{ secrets.DORFL_GH_TOKEN || secrets.GITHUB_TOKEN }}
441
+ # \`--watch\` streams the build agent's high-signal turns into THIS job
442
+ # log live; each leg names ONE item, so it fits the same way it does on
443
+ # the propose legs.
444
+ run: dorfl advance "\${{ matrix.item }}" --merge --watch --arbiter origin
445
+
446
+ # ── REAP merged remote work/* branches (capability F, the hygiene sweep) ─────
447
+ # PRESERVED from the seed (NOT a separate gc-sweep workflow): the provider-
448
+ # agnostic counterpart of the worktree reaper. Deletes remote \`work/<slug>\`
449
+ # branches that are PROVABLY MERGED into \`origin/main\`, so an out-of-band
450
+ # human/UI PR merge stops leaving its branch lingering on the arbiter.
451
+ # Independent of the integration mode (both propose- and merge-mode repos
452
+ # accumulate out-of-band-merged branches), so it runs on EVERY tick regardless
453
+ # of \`integrationMode\` — gated ONLY by the \`sweepMergedBranches\` opt-out (ON by
454
+ # default). It NEVER touches an un-merged/in-flight branch and NEVER \`--force\`s.
455
+ # Plain git, so it works against any provider (incl. a \`--bare\` arbiter).
456
+ #
457
+ # OPTIONAL belt-and-suspenders for a GitHub arbiter: enable the repo-level
458
+ # "Automatically delete head branches" setting (\`delete_branch_on_merge\`), owned
459
+ # by the install-ci wizard — an ADDITIVE GitHub-only convenience, NOT a
460
+ # replacement for this sweep (the only thing that reaps on a \`--bare\`/non-GitHub
461
+ # arbiter).
462
+ reap-merged-branches:
463
+ if: \${{ (github.event.inputs.sweepMergedBranches || 'true') == 'true' }}
464
+ runs-on: ubuntu-latest
465
+ steps:
466
+ - uses: actions/checkout@v4
467
+ with:
468
+ fetch-depth: 0
469
+ - uses: ./.github/actions/dorfl-setup
470
+ - name: reap merged remote work/* branches + orphan sidecars (gc --remote-branches)
471
+ # Deletes ONLY branches provably merged into origin/main; reports
472
+ # deleted-vs-retained-with-reason. Safe to run every tick (idempotent).
473
+ # This invocation ALSO reaps ORPHAN question sidecars: a
474
+ # sidecar under the questions queue (<type>-<slug>.md) whose source item
475
+ # was deleted out-of-band (git rm; the sidecar's working-tree source no
476
+ # longer exists). The orphan sweep rides THIS scheduled invocation
477
+ # precisely so it is never "in the code but never invoked in CI".
478
+ run: dorfl gc --remote-branches --arbiter origin
479
+ `;
480
+ }
481
+
482
+ /** A single structural problem found in the generated workflow. */
483
+ export interface AdvanceLifecycleProblem {
484
+ /** A short, stable id for the violated invariant (for tests/assertions). */
485
+ id: string;
486
+ /** Human-readable description of what is missing or wrong. */
487
+ message: string;
488
+ }
489
+
490
+ /** The result of {@link validateAdvanceLifecycleWorkflow}. */
491
+ export interface AdvanceLifecycleValidation {
492
+ /** True iff the workflow satisfies EVERY structural invariant. */
493
+ ok: boolean;
494
+ /** Each violated invariant (empty when `ok`). */
495
+ problems: AdvanceLifecycleProblem[];
496
+ }
497
+
498
+ /**
499
+ * Structurally validate the advance-lifecycle workflow against the task's
500
+ * acceptance criteria. Dependency-free (no YAML lib): presence/shape assertions
501
+ * over the raw text, mirroring {@link validateAdvanceCiTemplate}.
502
+ */
503
+ export function validateAdvanceLifecycleWorkflow(
504
+ text: string,
505
+ ): AdvanceLifecycleValidation {
506
+ const problems: AdvanceLifecycleProblem[] = [];
507
+ const require = (id: string, present: boolean, message: string): void => {
508
+ if (!present) {
509
+ problems.push({id, message});
510
+ }
511
+ };
512
+
513
+ // The OPERATIVE (non-comment) lines: the prohibitions below (no `--isolated`/
514
+ // `--remote`/`do`/`autoAdvance`/`.github/workflows` self-edit) are about what
515
+ // the job DOES, not what the explanatory comments MENTION. A YAML `#` comment
516
+ // line is documentation, so strip full-line comments before the negative checks.
517
+ // The positive presence checks run over the full text (comments are harmless).
518
+ const operative = text
519
+ .split('\n')
520
+ .filter((line) => !/^\s*#/.test(line))
521
+ .join('\n');
522
+
523
+ // --- Always invokes `advance`, NEVER `do` ----------------------------------
524
+ require('invokes-advance', /dorfl advance\b/.test(
525
+ text,
526
+ ), 'the workflow must invoke the `advance` driver (CI always runs `advance`).');
527
+ require('never-invokes-do', !/dorfl do\b/.test(
528
+ operative,
529
+ ), 'the workflow must NEVER invoke `do` directly (CI always invokes `advance`, ' +
530
+ 'ADR ci-config-policy-and-gate-family §1).');
531
+
532
+ // --- Triggers: cron + workflow_dispatch + the on-answer-committed push -------
533
+ require('trigger-cron', /\bschedule:\s*[\s\S]*?-\s*cron:/.test(
534
+ text,
535
+ ), 'must trigger on a cron schedule (`on.schedule[].cron`).');
536
+ require('trigger-workflow-dispatch', /\bworkflow_dispatch:/.test(
537
+ text,
538
+ ), 'must trigger on `workflow_dispatch` (manual catch-up/debug).');
539
+ require('dispatch-integration-mode-input', /workflow_dispatch:[\s\S]*?inputs:[\s\S]*?integrationMode:/.test(
540
+ text,
541
+ ), 'the `workflow_dispatch` must carry an `integrationMode` input.');
542
+ // The DEFINING lifecycle trigger: an on-answer-committed push (a push touching
543
+ // `work/questions/**`) re-runs the loop so a freshly-answered sidecar applies
544
+ // promptly. This is what `advance` adds over the build/task tick.
545
+ require('trigger-on-answer-committed', /\bpush:\s*[\s\S]*?paths:[\s\S]*?work\/questions\//.test(
546
+ text,
547
+ ), 'must trigger on-answer-committed (a push touching `work/questions/**`) — ' +
548
+ 'the lifecycle answer loop.');
549
+
550
+ // --- integrationMode drives BOTH shape and flag (one word, one meaning) -----
551
+ require('integration-mode-one-word', /integrationMode:/.test(text) &&
552
+ /github\.event\.inputs\.integrationMode/.test(
553
+ text,
554
+ ), 'the dispatch input must be `integrationMode` (one word driving BOTH the ' +
555
+ 'flag and the derived job shape).');
556
+
557
+ // --- propose ⇒ a DYNAMIC matrix enumerated via `scan --json` ----------------
558
+ require('propose-matrix', /strategy:\s*[\s\S]*?matrix:/.test(
559
+ text,
560
+ ), '`propose` mode must emit a MATRIX of jobs (`strategy.matrix`).');
561
+ require('propose-enumerates-via-scan', /dorfl scan --json/.test(
562
+ text,
563
+ ), 'the matrix items must be ENUMERATED via the eligible-pool scan ' +
564
+ '(`dorfl scan --json`).');
565
+ require('propose-one-advance-per-item', /dorfl advance "?\$\{\{\s*matrix\./.test(
566
+ text,
567
+ ), 'each matrix leg must run one `dorfl advance <matrix item>` ' +
568
+ '(one PR per item).');
569
+ require('propose-leg-carries-propose-flag', /advance-propose:[\s\S]*?dorfl advance "?\$\{\{\s*matrix\.[\s\S]*?--propose\b/.test(
570
+ text,
571
+ ), 'each `propose` matrix leg must pass `--propose` so the integration mode is ' +
572
+ 'TIED to the matrix shape (a leg can never merge to main / desync from the ' +
573
+ 'dispatch mode).');
574
+
575
+ // --- merge ⇒ a MATRIX per item (parallel build/gate/review, serialised land) -
576
+ // PRD `land-time-reverify-and-parallel-merge-ceiling` stories 4 + 6: build/
577
+ // gate/review fan out; the LAND tail is serialised by the engine's
578
+ // `mergeRetries` CAS-retry loop (the git-alone floor), NOT the workflow.
579
+ require('merge-matrix', /advance-merge:[\s\S]*?strategy:\s*[\s\S]*?matrix:/.test(
580
+ text,
581
+ ), 'the `merge` job must use a MATRIX (parallel build/gate/review per item; ' +
582
+ "the land tail is serialised by the engine's `mergeRetries` CAS-retry " +
583
+ "loop, not by the workflow's job shape).");
584
+ require('merge-leg-carries-merge-flag', /advance-merge:[\s\S]*?dorfl advance "?\$\{\{\s*matrix\.[\s\S]*?--merge\b/.test(
585
+ text,
586
+ ), 'each `merge` matrix leg must pass `--merge` so the integration mode is ' +
587
+ 'TIED to the matrix shape (a leg can never propose-only / desync from the ' +
588
+ 'dispatch mode).');
589
+ // No host-specific cross-job serialiser on the merge job: a GitHub Actions
590
+ // `concurrency:` block there would make cross-job land safety depend on a host
591
+ // feature, breaking the git-alone-floor framing (Applied Answer q1).
592
+ require('merge-no-host-concurrency-serialiser', !/advance-merge:[\s\S]*?\n\s{4}concurrency:/.test(
593
+ text,
594
+ ), 'the `merge` job must NOT carry a `concurrency:` group: a host-specific ' +
595
+ 'serialiser would make the cross-job land safety depend on a GitHub Actions ' +
596
+ "feature; the engine's `mergeRetries` CAS-retry loop is the git-alone floor.");
597
+
598
+ // --- The DORFL_* gate family must NOT be carried as workflow env -----
599
+ // The workflow emits NO active gate env line for any of AUTO_BUILD / AUTO_TASK
600
+ // / OBSERVATION_TRIAGE / SURFACE_BLOCKERS: the env layer is the OPTIONAL CI-only
601
+ // override layer, NOT the carrier of defaults. Emitting any of them would FORCE
602
+ // env to win over the repo's own .dorfl.json (the precedence is
603
+ // flag > env > per-repo > global > default), silently shadowing per-repo gate
604
+ // config in CI — exactly the bug this task closes. A user who genuinely wants a
605
+ // CI-SPECIFIC override adds the env var themselves (the opt-in CI override the
606
+ // env layer is FOR). Check the OPERATIVE (non-comment) lines so the explanatory
607
+ // header comment that NAMES these keys is not a false positive.
608
+ require('no-gate-env-auto-build', !/DORFL_AUTO_BUILD\s*:/.test(
609
+ operative,
610
+ ), 'the workflow must NOT emit an `DORFL_AUTO_BUILD:` env assignment ' +
611
+ '(env carries no defaults; the gate is resolved from per-repo config / built-in default).');
612
+ require('no-gate-env-auto-task', !/DORFL_AUTO_TASK\s*:/.test(
613
+ operative,
614
+ ), 'the workflow must NOT emit an `DORFL_AUTO_TASK:` env assignment ' +
615
+ '(env carries no defaults; the gate is resolved from per-repo config / built-in default).');
616
+ require('no-gate-env-observation-triage', !/DORFL_OBSERVATION_TRIAGE\s*:/.test(
617
+ operative,
618
+ ), 'the workflow must NOT emit an `DORFL_OBSERVATION_TRIAGE:` env ' +
619
+ 'assignment (env carries no defaults; resolved from per-repo config / built-in default).');
620
+ require('no-gate-env-surface-blockers', !/DORFL_SURFACE_BLOCKERS\s*:/.test(
621
+ operative,
622
+ ), 'the workflow must NOT emit an `DORFL_SURFACE_BLOCKERS:` env ' +
623
+ 'assignment (env carries no defaults; resolved from per-repo config / built-in default).');
624
+ // --- Gate-family DISPATCH OVERRIDES (one-shot, dispatch only) ---------------
625
+ // Each gate is exposed as a `workflow_dispatch` input AND its override is wired
626
+ // (as a guarded `$GITHUB_ENV` write, NOT a YAML `env:` key — so the
627
+ // `no-gate-env-*` invariants above still hold) into EVERY job that resolves the
628
+ // gate family: `enumerate` (it gates the matrix pools via `scan`), plus the two
629
+ // agent-running jobs. The enumerate wiring is the load-bearing one: without it a
630
+ // dispatch override of `observationTriage`/`surfaceBlockers`/`autoTask` produces
631
+ // an empty matrix and is silently inert (the bug this task's review caught).
632
+ for (const input of [
633
+ 'autoBuild',
634
+ 'autoTask',
635
+ 'observationTriage',
636
+ 'surfaceBlockers',
637
+ ]) {
638
+ require(`dispatch-${input}-input`, new RegExp(
639
+ `workflow_dispatch:[\\s\\S]*?inputs:[\\s\\S]*?\\b${input}:`,
640
+ ).test(
641
+ text,
642
+ ), `the \`workflow_dispatch\` must carry a \`${input}\` gate-override input.`);
643
+ }
644
+ for (const [input, envVar] of [
645
+ ['autoBuild', 'DORFL_AUTO_BUILD'],
646
+ ['autoTask', 'DORFL_AUTO_TASK'],
647
+ ['observationTriage', 'DORFL_OBSERVATION_TRIAGE'],
648
+ ['surfaceBlockers', 'DORFL_SURFACE_BLOCKERS'],
649
+ ] as const) {
650
+ // The override is a guarded shell write: `[ -n <input> ] && echo <ENV>=<input> >> $GITHUB_ENV`.
651
+ const guardedWrite = new RegExp(
652
+ `\\[ -n "\\$\\{\\{ github\\.event\\.inputs\\.${input} \\}\\}" \\][\\s\\S]*?${envVar}=`,
653
+ );
654
+ require(`dispatch-${input}-guarded-write`, guardedWrite.test(
655
+ text,
656
+ ), `the \`${input}\` override must be a blank-guarded write of \`${envVar}\` ` +
657
+ 'to `$GITHUB_ENV` (blank dispatch input / schedule / push emit nothing).');
658
+ }
659
+ // The ENUMERATE job MUST carry the override before its `scan` step — else the
660
+ // matrix pools are built from the un-overridden gates and the override is inert.
661
+ require('enumerate-carries-gate-override', /enumerate:[\s\S]*?DORFL_OBSERVATION_TRIAGE=[\s\S]*?id: scan/.test(
662
+ text,
663
+ ), 'the `enumerate` job must apply the dispatch gate override BEFORE its `scan` ' +
664
+ 'step (scan gates the matrix pools by the gate family; otherwise the ' +
665
+ 'override is silently inert for the lifecycle/task pools).');
666
+ // The override must be GUARDED by the workflow_dispatch event so schedule/push
667
+ // runs never even enter the write step.
668
+ require('gate-override-dispatch-guarded', /if:\s*\$\{\{\s*github\.event_name == 'workflow_dispatch'\s*\}\}/.test(
669
+ text,
670
+ ), 'the gate-override step must be guarded by `if: github.event_name == ' +
671
+ "'workflow_dispatch'` so schedule/push ticks export nothing.");
672
+
673
+ // There is NO autoAdvance gate (the lifecycle decomposes into the gate family).
674
+ require('no-auto-advance-gate', !/DORFL_AUTO_ADVANCE\b/.test(operative) &&
675
+ !/autoAdvance/.test(
676
+ operative,
677
+ ), 'there must be NO `autoAdvance` gate (the lifecycle decomposes into the ' +
678
+ 'existing gate family; ADR ci-config-policy-and-gate-family §2).');
679
+
680
+ // --- Capability F: the reap job + sweep input PRESERVED (not stripped) ------
681
+ require('reap-merged-branches-job', /reap-merged-branches:/.test(
682
+ text,
683
+ ), "the absorbed seed's `reap-merged-branches` job (capability F) must be " +
684
+ 'PRESERVED, not stripped.');
685
+ require('reap-uses-gc-remote-branches', /dorfl gc --remote-branches\b/.test(
686
+ text,
687
+ ), 'the reap job must run `dorfl gc --remote-branches` (the provider-' +
688
+ 'agnostic merged-branch sweep).');
689
+ require('reap-sweep-dispatch-input', /sweepMergedBranches:/.test(
690
+ text,
691
+ ), 'the `sweepMergedBranches` dispatch input (capability F, opt-out) must be ' +
692
+ 'preserved.');
693
+ // The ORPHAN-SIDECAR reap (prd
694
+ // `agentic-question-resolution-retire-disposition-vocabulary`, US #10) rides
695
+ // the SAME scheduled `dorfl gc --remote-branches` invocation, so it provably
696
+ // FIRES on the cron tick (not behind an un-passed flag). The reap step that
697
+ // runs `gc --remote-branches` MUST be checked out WITH a working tree (the
698
+ // orphan sweep is working-tree based: it reads `work/questions/` + the
699
+ // lifecycle folders from the checkout). `actions/checkout` provides that, and
700
+ // the step's name/comment names the orphan-sidecar duty so the linkage is not
701
+ // silently lost on a future template edit.
702
+ require('reap-checks-out-working-tree', /reap-merged-branches:[\s\S]*?uses:\s*actions\/checkout/.test(
703
+ text,
704
+ ), 'the reap job must `actions/checkout` a working tree before ' +
705
+ '`gc --remote-branches`: the orphan-sidecar sweep that rides that invocation ' +
706
+ 'reads `work/questions/` + the lifecycle folders from the checkout.');
707
+ require('reap-names-orphan-sidecars', /reap-merged-branches:[\s\S]*?orphan sidecar/i.test(
708
+ text,
709
+ ), 'the reap step (running `gc --remote-branches`) must name the ORPHAN ' +
710
+ 'SIDECAR reap it ALSO performs (US #10), so the scheduled invocation that ' +
711
+ 'fires it is visible and not silently dropped on a future edit.');
712
+
713
+ // --- CI runs IN-PLACE: no isolation machinery ------------------------------
714
+ require('no-isolated-flag', !/--isolated\b/.test(
715
+ operative,
716
+ ), 'CI runs IN-PLACE (the container IS the isolation): no `--isolated` flag.');
717
+ // Guard `--remote` the LAPTOP affordance, but NOT `--remote-branches` (the
718
+ // preserved capability-F `gc --remote-branches` sweep): a negative lookahead
719
+ // for a following `-`/word char so the gc flag is not a false positive.
720
+ require('no-remote-flag', !/--remote(?![-\w])/.test(
721
+ operative,
722
+ ), 'CI runs IN-PLACE: no `--remote` flag (laptop-only affordance).');
723
+
724
+ // --- A CI concurrency group ------------------------------------------------
725
+ require('concurrency-group', /\bconcurrency:\s*[\s\S]*?group:/.test(
726
+ text,
727
+ ), 'must carry a CI `concurrency.group` so overlapping ticks never collide.');
728
+
729
+ // --- US #9: NO `workflows` permission; cannot self-edit triggers ------------
730
+ require('no-workflows-permission', !/\bworkflows:\s*write\b/.test(
731
+ text,
732
+ ), 'the running job must request NO `workflows` permission (US #9: it can ' +
733
+ 'never edit `.github/workflows/**` / rewrite its own triggers).');
734
+ require('never-edits-dot-github-workflows', !/\.github\/workflows\//.test(
735
+ operative,
736
+ ), 'no emitted job step may touch `.github/workflows/**` (US #9).');
737
+
738
+ // --- Explicit slug prefixes, never bare ------------------------------------
739
+ require('explicit-task-prefix', /"task:" \+ \.slug/.test(text) ||
740
+ /task:/.test(
741
+ text,
742
+ ), 'CI must use explicit `task:`/`spec:` slug prefixes, never bare (ADR ' +
743
+ 'command-surface-and-journeys §3a).');
744
+
745
+ // --- The propose `enumerate` matrix must UNION taskable prds --------------
746
+ // (`ci-propose-matrix-must-enumerate-sliceable-prds-not-only-slices`): a
747
+ // task-only `jq` would render `DORFL_AUTO_TASK: 'true'` dead on the
748
+ // hourly cron — a ready ungated PRD would never become a matrix leg. The `jq`
749
+ // must enumerate `spec:<slug>` ids from `scan --json`'s taskable-SPEC pool
750
+ // (`repos[].specs[]` + `cwd.repo.specs[]`) alongside the eligible-task legs.
751
+ require('propose-enumerates-taskable-specs', /"spec:" \+ \.slug/.test(text) &&
752
+ /\.specs\[\]/.test(
753
+ text,
754
+ ), 'the propose-mode `enumerate` `jq` must union taskable specs into the ' +
755
+ "matrix as `spec:<slug>` legs (read from `scan --json`'s `repos[].specs[]` " +
756
+ '+ `cwd.repo.specs[]` pools), so a ready ungated SPEC becomes one auto-task ' +
757
+ 'matrix leg per item alongside the eligible-task legs ' +
758
+ '(`ci-propose-matrix-must-enumerate-sliceable-prds-not-only-slices`).');
759
+
760
+ // --- The propose `enumerate` matrix must UNION the LIFECYCLE pools ----------
761
+ // (`ci-propose-matrix-enumerates-lifecycle-items`): a build/task-only `jq`
762
+ // runs the answer-loop ONLY in merge mode — a `needsAnswers` item is
763
+ // `eligible:false` and untriaged observations are not in the task/prd pools at
764
+ // all, so NO lifecycle rung (triage/surface/apply) ever gets a propose leg. The
765
+ // `jq` must enumerate the three lifecycle sub-pools from `scan --json`
766
+ // (`repos[].lifecycle.*` + `cwd.repo.lifecycle.*`): `triage[]` → `obs:<slug>`,
767
+ // and `surface[]`/`apply[]` → `.namespace + ":" + .slug`. Match all four shape
768
+ // signals so a regression that drops any one leg is caught.
769
+ require('propose-enumerates-lifecycle-items', /"obs:" \+ \.slug/.test(text) &&
770
+ /\.lifecycle\.triage\[\]/.test(text) &&
771
+ /\.lifecycle\.surface\[\]/.test(text) &&
772
+ /\.lifecycle\.apply\[\]/.test(text) &&
773
+ /\.namespace \+ ":" \+ \.slug/.test(
774
+ text,
775
+ ), 'the propose-mode `enumerate` `jq` must union the LIFECYCLE pools into the ' +
776
+ "matrix (read from `scan --json`'s `repos[].lifecycle.*` + " +
777
+ '`cwd.repo.lifecycle.*`): `triage[]` as `obs:<slug>` legs, and ' +
778
+ '`surface[]`/`apply[]` as `.namespace + ":" + .slug` (`task:`/`spec:`, plus ' +
779
+ '`observation:` for an answered-observation apply leg) legs, ' +
780
+ 'so the WHOLE answer-loop (triage + surface + apply) runs in propose mode, ' +
781
+ 'not only in merge mode ' +
782
+ '(`ci-propose-matrix-enumerates-lifecycle-items`).');
783
+
784
+ // --- Wires the SHARED composite setup action -------------------------------
785
+ require('uses-shared-setup-action', /uses:\s*\.\/\.github\/actions\/dorfl-setup\b/.test(
786
+ text,
787
+ ), 'every job must wire the shared composite setup action ' +
788
+ '(`./.github/actions/dorfl-setup`, emitted by the core task).');
789
+
790
+ return {ok: problems.length === 0, problems};
791
+ }