dorfl 0.0.0 → 0.1.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 (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 +3094 -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 +215 -0
  162. package/dist/frontmatter.d.ts.map +1 -0
  163. package/dist/frontmatter.js +345 -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 +315 -0
  330. package/dist/prd-to-spec.d.ts.map +1 -0
  331. package/dist/prd-to-spec.js +684 -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 +360 -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 +952 -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 +4369 -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 +485 -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 +1023 -0
  581. package/src/prepare.ts +230 -0
  582. package/src/prompt.ts +760 -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 +1438 -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
package/src/config.ts ADDED
@@ -0,0 +1,883 @@
1
+ import {readFileSync, writeFileSync, existsSync, mkdirSync} from 'node:fs';
2
+ import {homedir} from 'node:os';
3
+ import {dirname, join} from 'node:path';
4
+ import {brand} from './brand.js';
5
+ import {type Identity, validateIdentity} from './identity.js';
6
+ import {
7
+ DEFAULT_SELECTION_ORDER,
8
+ type SelectionOrderConfig,
9
+ } from './select-order.js';
10
+
11
+ /**
12
+ * How a completed item is integrated back to the arbiter's `main`. `merge` lands
13
+ * it directly on `main` (ff/rebase + push); `propose` pushes a branch + requests
14
+ * review. (`propose` is provider-neutral; the old `pr` name was GitHub jargon.
15
+ * See ADR §6.)
16
+ */
17
+ export type IntegrationMode = 'propose' | 'merge';
18
+
19
+ /**
20
+ * **Per-repo TASK-PLACEMENT default** (prd
21
+ * `staging-pool-position-gate-and-trust-model`, task
22
+ * `runner-deterministic-slice-placement-policy-and-precedence`, governing ADR
23
+ * `placement-is-runner-deterministic-humanonly-is-agent-judgement`). Which
24
+ * folder the runner lands the tasker's emitted task files in BY DEFAULT —
25
+ * `'pre-backlog'` (staging — durable + readable but NOT in the agent-eligible
26
+ * POOL; a runner/human promotion is needed to make an item claimable; the on-disk
27
+ * folder for this value is `work/tasks/backlog/`) or `'ready'` (the agent-eligible
28
+ * POOL — the trusted fast-path landing, on-disk `work/tasks/ready/`). The pool
29
+ * value was renamed `'backlog'` → `'todo'` → `'ready'` (ADR
30
+ * `rename-task-pool-folder-todo-to-ready`, a CLEAN BREAK matching the on-disk
31
+ * folder `tasks/ready/` and the spec-side `'ready'` pool spelling). The runner-deterministic
32
+ * placement RESOLVER (`src/placement.ts`) layers on top: `explicit operator flag
33
+ * > untrusted-origin ⇒ pre-backlog > tasksLandIn default > built-in
34
+ * (pre-backlog)`. An untrusted-origin tasker output is FORCED to staging even in
35
+ * a `'ready'` repo (the positional analogue of the existing
36
+ * `untrusted-origin-forces-build-propose` rule).
37
+ */
38
+ export type TasksLandIn = 'pre-backlog' | 'ready';
39
+
40
+ /**
41
+ * **Per-repo PRD-PLACEMENT default** (prd
42
+ * `staging-pool-position-gate-and-trust-model`, task
43
+ * `pre-prd-staging-pool-split-and-untrusted-prd-placement`, governing ADR
44
+ * `placement-is-runner-deterministic-humanonly-is-agent-judgement`). Which
45
+ * folder the runner lands `intake`-authored prd files in BY DEFAULT —
46
+ * `'pre-proposed'` (staging — durable + readable but NOT in the auto-tasking
47
+ * POOL; a runner/human promotion is needed to make the prd auto-taskable; the
48
+ * on-disk folder for this value is `work/prds/proposed/`) or `'ready'` (the
49
+ * auto-tasking POOL — the trusted fast-path landing, on-disk
50
+ * `work/prds/ready/`). The same runner-deterministic placement RESOLVER
51
+ * (`src/placement.ts`) layers on top:
52
+ * `explicit operator flag > untrusted-origin ⇒ pre-proposed > specsLandIn
53
+ * default > built-in (pre-proposed)`. An untrusted-origin intake spec is FORCED
54
+ * to staging even in a `'ready'` repo (the positional analogue of the existing
55
+ * `untrusted-origin-forces-build-propose` rule). The PRD twin of
56
+ * {@link TasksLandIn}; the SAME shape, the SAME precedence chain. The value
57
+ * spellings mirror the live prd folders (`prds/proposed/` staging,
58
+ * `prds/ready/` pool), exactly as {@link TasksLandIn} mirrors the task folders.
59
+ */
60
+ export type SpecsLandIn = 'pre-proposed' | 'ready';
61
+
62
+ /**
63
+ * The observation-triage gate (ADR `ci-config-policy-and-gate-family` §2): a
64
+ * 3-state ENUM governing the observation INBOX (raw captured signal). It REPLACES
65
+ * the old `autoTriage` boolean, whose name read like "is triage on?" but only
66
+ * gated the auto-DISPOSITION exception (the resolved naming trap). The three
67
+ * states say what they gate:
68
+ * - `off` (default): the triage rung is dropped from the auto-pick SELECTION —
69
+ * observations are left untouched (the NEW state the boolean could not
70
+ * express, "leave my observations alone entirely");
71
+ * - `ask`: the observation pool IS selected; surface a promote/keep/delete
72
+ * question for every untriaged observation (the old `autoTriage:false`);
73
+ * - `auto`: the observation pool is selected; auto-dispose ONLY the no-question
74
+ * cases (exact-duplicate ⇒ recommend delete; unambiguous map) and surface a
75
+ * question for the rest (the old `autoTriage:true`). It still NEVER
76
+ * auto-deletes a non-duplicate or auto-promotes a judgement call.
77
+ */
78
+ export type ObservationTriage = 'off' | 'ask' | 'auto';
79
+
80
+ /**
81
+ * **The `mergeQuestions` gate axis** — the 3-state member of the question-
82
+ * surfacing gate family that governs the MERGE-QUESTION surfacer (prd
83
+ * `land-time-reverify-and-parallel-merge-ceiling` Story 17 / task
84
+ * `merge-questions-gate-axis`). MIRRORS `observationTriage`'s shape
85
+ * (`off | ask | auto`) but is a SEPARATE axis — "should this built work merge?"
86
+ * is materially more consequential than "is this observation worth promoting?",
87
+ * so a merge-question must NEVER ride `observationTriage` and must NOT default
88
+ * `off` (a silently-dropped merge-question means finished, pushed work never
89
+ * lands). The states:
90
+ * - `off` ⇒ the merge-question surfacer is not invoked (only correct for a
91
+ * repo that lands by some other means);
92
+ * - `ask` (DEFAULT) ⇒ the surfacer enumerates unmerged `work/*` branches +
93
+ * emits a merge-question sidecar; a human's plain `merge | hold | drop`
94
+ * answer is required before the land. The conservative default that honours
95
+ * propose semantics and never silently drops pushed work;
96
+ * - `auto` ⇒ the runner self-supplies the `merge` answer without surfacing
97
+ * and lands through the SAME deterministic answer-driven runner-action
98
+ * dispatch + apply-time re-verify (the merge-mode-like fast path). Does NOT
99
+ * invoke the agentic decider — a merge-land is never an agent decision.
100
+ * Resolved through the SAME precedence chain as the other gates (flag > env >
101
+ * per-repo > global > default `ask`). The exact name + default + shape were
102
+ * answered in this task's Applied answers 2026-06-26 (q1/q2/q3) + PRD sidecar
103
+ * Q3.
104
+ */
105
+ export type MergeQuestions = 'off' | 'ask' | 'auto';
106
+
107
+ /**
108
+ * Which harness adapter (ADR §5) launches a job's agent and reports its
109
+ * liveness: `null` (shell out to `agentCmd`) or `pi` (the pi CLI). Selected via
110
+ * the `harness` config field; defaults to `null`.
111
+ */
112
+ export type HarnessAdapter = 'null' | 'pi';
113
+
114
+ /**
115
+ * The `propose`-mode review-request provider (ADR §6): `github` (`gh pr
116
+ * create`) or `none` (push-only). This names which provider the ARBITER URL
117
+ * RESOLVES to (`selectProvider`) — it is NOT a config OVERRIDE axis (there is
118
+ * none; the provider is purely arbiter-derived: a GitHub remote ⇒ `github`, else
119
+ * `none`). Whether `gh` can actually open the PR is the identity's
120
+ * `providers.github` / ambient `gh` auth; whether to open a PR at all is the
121
+ * separate `noPR` intent. `merge` mode is provider-agnostic and ignores all of
122
+ * this.
123
+ */
124
+ export type ReviewProviderName = 'none' | 'github';
125
+
126
+ /**
127
+ * The per-repo acceptance gate: a single shell command, or an ordered list of
128
+ * commands run in sequence (all must pass). See `verify.ts` / ADR §8.
129
+ */
130
+ export type VerifyConfig = string | string[];
131
+
132
+ /**
133
+ * **The `promptGuidance` NAMESPACE** — per-repo prompt-text NUDGES the runner
134
+ * folds into the worker's in-band prompt (`prompt.ts` + `CLAIM-PROTOCOL.md`).
135
+ * Categorically SEPARATE from the gate family (`verify`/`autoBuild`/`humanOnly`):
136
+ * a nudge changes the agent's DISPOSITION, never the acceptance bar (the `verify`
137
+ * gate is still the sole pass/fail). The namespace name is deliberate — it
138
+ * signals "guidance, not guarantee" — and is shaped to grow (`testFirst` is just
139
+ * the first member; later siblings, e.g. `preferSmallDiffs`, land here too).
140
+ */
141
+ export interface PromptGuidance {
142
+ /**
143
+ * Strengthen the wrapper's existing soft "TDD where the task asks for it"
144
+ * line into an explicit TEST-FIRST nudge ("at the agreed seam, write the
145
+ * failing test BEFORE the production code; this is guidance, not a gate —
146
+ * the `verify` step still decides pass/fail"). The strengthened text lives
147
+ * in `CLAIM-PROTOCOL.md` (the single source of truth), gated by the
148
+ * `<!-- if promptGuidance.testFirst --> … <!-- else --> … <!-- /if -->`
149
+ * conditional-fragment convention the extractor in `prompt.ts` honours.
150
+ * Default `false` (omitted ⇒ false); the worker prompt is byte-identical
151
+ * to today when this is off. Resolved like the gate family: flag > env
152
+ * (`DORFL_PROMPT_GUIDANCE_TEST_FIRST`) > per-repo > global >
153
+ * default (`false`). NEVER an enforced acceptance criterion.
154
+ */
155
+ testFirst: boolean;
156
+ }
157
+
158
+ /**
159
+ * Resolve the `promptGuidance` namespace down to its concrete boolean fields
160
+ * with the documented defaults applied — so callers can read
161
+ * `resolvePromptGuidance(cfg).testFirst` without re-checking the namespace's
162
+ * presence (a per-repo file may legitimately omit `promptGuidance` entirely,
163
+ * or supply only a subset). Mirrors the gate family's defaults-resolved
164
+ * convention.
165
+ */
166
+ export function resolvePromptGuidance(cfg: Config): PromptGuidance {
167
+ return {testFirst: cfg.promptGuidance?.testFirst === true};
168
+ }
169
+
170
+ /**
171
+ * Resolved runner configuration. There is NO `roots`/`remotes` field: discovery
172
+ * is the registered hub-mirror set under `<workspacesDir>/repos/` (the registry,
173
+ * ADR `command-surface-and-journeys` §1), NOT a config roots walk. `scan` reads
174
+ * the eligibility fields per repo; `run --once` additionally consumes the
175
+ * execution fields (maxParallel, perRepoMax, defaultArbiter, integration,
176
+ * agentCmd).
177
+ */
178
+ export interface Config {
179
+ /**
180
+ * Per-repo policy: may agents auto-BUILD *undeclared* (not `humanOnly`) tasks
181
+ * in this repo? `false` (default, strict) ⇒ agents claim nothing automatically;
182
+ * `true` ⇒ agents may claim any task that is not `humanOnly: true`. Resolved
183
+ * like `integration`: flag (`--auto-build`/`--no-auto-build`) > `DORFL_AUTO_BUILD`
184
+ * env > per-repo > global > default. The build member of the per-action gate family
185
+ * (`autoBuild`/`autoTask` + the question-surfacing gates `observationTriage`/
186
+ * `surfaceBlockers`).
187
+ */
188
+ autoBuild: boolean;
189
+ /**
190
+ * **The `promptGuidance` NUDGE namespace** (see {@link PromptGuidance}). A
191
+ * NUDGE modifies the worker's IN-BAND PROMPT text (`prompt.ts` + the
192
+ * `CLAIM-PROTOCOL.md` wrapper); it is CATEGORICALLY SEPARATE from the gate
193
+ * family (`verify`/`autoBuild`/`humanOnly`) — guidance, never guarantee. The
194
+ * `verify` gate's semantics are unaffected regardless of any value here.
195
+ * Resolution mirrors the gate family per-member: flag > env > per-repo >
196
+ * global > default. Defaults to `{testFirst: false}` (worker prompt is
197
+ * byte-identical to today when every member is off). Designed to grow:
198
+ * later sibling nudges (e.g. `preferSmallDiffs`) land as new members.
199
+ */
200
+ promptGuidance: PromptGuidance;
201
+ /**
202
+ * Per-repo policy: may an agent auto-task *undeclared* (not `humanOnly`,
203
+ * no open questions) prds in this repo? `false` (default, strict, human-first)
204
+ * ⇒ a human must drive every prd's tasking; `true` ⇒ an agent may auto-task
205
+ * any prd that is not `humanOnly: true` and has no `needsAnswers`. Resolved like
206
+ * `autoBuild`: flag > `DORFL_AUTO_TASK` env > per-repo > global >
207
+ * default. The two-axis tasking gate (`work/prds/auto-task.md`), one level up
208
+ * from the build gate's `autoBuild`.
209
+ */
210
+ autoTask: boolean;
211
+ /**
212
+ * Per-repo policy governing the OBSERVATION INBOX (raw captured signal) — the
213
+ * 3-state member of the question-surfacing gate family (its sibling is
214
+ * `surfaceBlockers`, which governs DECLARED blocked work; the two are orthogonal
215
+ * peers, ADR `ci-config-policy-and-gate-family` §2). It REPLACES the old
216
+ * `autoTriage` boolean (cleanly, no alias — this repo has no external users yet,
217
+ * decided 2026-06-12). `off` (default) ⇒ the triage pool is dropped from the
218
+ * auto-pick SELECTION (observations untouched); `ask` ⇒ surface a
219
+ * promote/keep/delete question for every untriaged observation; `auto` ⇒
220
+ * auto-dispose ONLY the no-question cases (duplicate ⇒ recommend delete /
221
+ * unambiguous map) and surface a question for the rest (still NEVER auto-deletes
222
+ * a non-duplicate or auto-promotes). Resolved like `integration`/`autoBuild`:
223
+ * flag (`--observation-triage`) > `DORFL_OBSERVATION_TRIAGE` env >
224
+ * per-repo > global > default `off`. Gates the CREATE phase only; APPLY (consume
225
+ * a committed answer) stays ALWAYS allowed.
226
+ */
227
+ observationTriage: ObservationTriage;
228
+ /**
229
+ * Per-repo policy governing the MERGE-QUESTION SURFACER — the 3-state member
230
+ * of the question-surfacing gate family (prd
231
+ * `land-time-reverify-and-parallel-merge-ceiling` Story 17 / task
232
+ * `merge-questions-gate-axis`). MIRRORS `observationTriage`'s SHAPE
233
+ * (`off | ask | auto`) but is a SEPARATE axis with a DIFFERENT default —
234
+ * `observationTriage` defaults `off` (a dropped observation is safely
235
+ * ignorable), `mergeQuestions` defaults `ask` (a dropped merge-question means
236
+ * pushed work never lands). `off` ⇒ the surfacer is NOT invoked (only for a
237
+ * repo that lands by some other means); `ask` (default) ⇒ the surfacer
238
+ * enumerates unmerged `work/*` branches and emits a merge-question sidecar a
239
+ * human answers; `auto` ⇒ the runner self-supplies the `merge` answer without
240
+ * surfacing and lands via the SAME deterministic answer-driven runner-action
241
+ * dispatch + apply-time re-verify (the merge-mode-like fast path; NOT the
242
+ * agentic decider). Resolved like `observationTriage`/`integration`: flag
243
+ * (`--merge-questions`) > `DORFL_MERGE_QUESTIONS` env > per-repo > global >
244
+ * default `ask`. Gates the SURFACE phase of the merge-question loop only;
245
+ * APPLY (consume a committed merge-answer) stays ALWAYS allowed (the
246
+ * create-vs-consume invariant the gate family obeys, ADR
247
+ * `ci-config-policy-and-gate-family` §4).
248
+ */
249
+ mergeQuestions: MergeQuestions;
250
+ /**
251
+ * Per-repo policy governing DECLARED blocked work — the BOOLEAN member of the
252
+ * question-surfacing gate family (its orthogonal PEER is `observationTriage`,
253
+ * which governs the raw observation INBOX; ADR `ci-config-policy-and-gate-family`
254
+ * §2). It gates whether a task/prd carrying `needsAnswers: true` is rendered
255
+ * into an answerable question sidecar (`on`) or left silently blocked in the
256
+ * backlog (`off`). `false` (default, calm) ⇒ the `needsAnswers`-blocked pool is
257
+ * dropped from the auto-pick SELECTION, so a bare `advance` does NOT proactively
258
+ * surface a declared blocker; `true` ⇒ the blocked pool IS enumerated and
259
+ * `advance`'s surface rung renders the declared blocker into a sidecar the human
260
+ * can answer + unblock in-repo. This is a DIFFERENT job from `observationTriage`:
261
+ * it is about committed work items, not the raw inbox (so
262
+ * `observationTriage: ask|auto` + `surfaceBlockers: off` — "groom my inbox, leave
263
+ * my blocked work alone" — is expressible). Resolved like `autoBuild`: flag
264
+ * (`--surface-blockers`/`--no-surface-blockers`) > `DORFL_SURFACE_BLOCKERS`
265
+ * env > per-repo > global > default `false`. Gates the CREATE (surface) phase
266
+ * only; APPLY (consume a committed answer) stays ALWAYS allowed, and
267
+ * `needs-attention` (a stuck build) is a SEPARATE always-on mechanism this gate
268
+ * does NOT touch.
269
+ */
270
+ surfaceBlockers: boolean;
271
+ /**
272
+ * Per-repo policy governing whether SURFACING (the question-minting polarity)
273
+ * inspects STAGING in addition to the agent pool — the BOOLEAN gate-family
274
+ * member added by prd `staging-surface-and-apply-promote-safety` (F2). The
275
+ * BUILD polarity is UNCHANGED in either mode: staging items stay non-claimable,
276
+ * the trust model is untouched. `true` (default) ⇒ the SURFACE candidate set
277
+ * draws from STAGING (`tasks/backlog/`, `prds/proposed/`) PLUS the pool, so
278
+ * a `needsAnswers` task/prd in staging surfaces its questions BEFORE a human
279
+ * promotes it (you promote an already-clarified item, not blind and then get
280
+ * asked after); `false` ⇒ the legacy POOL-ONLY behaviour (staging is not
281
+ * inspected for questions). Resolved like `surfaceBlockers`/`autoBuild`:
282
+ * flag > `DORFL_SURFACE_STAGING` env > per-repo > global > default
283
+ * `true`. Surfacing is read-only-ish (writes a question sidecar; touches only
284
+ * the item's per-item lock), so widening it into staging does NOT loosen the
285
+ * BUILD trust gate — it only stops the surface polarity from being
286
+ * gratuitously trust-gated identically to it.
287
+ */
288
+ surfaceStaging: boolean;
289
+ /**
290
+ * Per-repo SELECTION ORDER across the four ORDERABLE auto-pick pools (`build` =
291
+ * eligible tasks, `task` = taskable prds, `surface` = `needsAnswers`
292
+ * blockers, `triage` = untriaged observations). `apply` (consume a committed
293
+ * answer) is PINNED FIRST and is NOT orderable (consume-always-wins). The value
294
+ * is EITHER a PRESET keyword (`drain` (default) ⇒ `[build, task, surface,
295
+ * triage]`, drain ready work then create then ask; `groom` ⇒ `[surface, triage,
296
+ * build, task]`) OR an explicit ordered pool-name list (the env comma form
297
+ * `build,task,surface,triage`); the preset is sugar over the list. It only
298
+ * REORDERS pools; the gates decide what is PRESENT (a gated-off pool named in
299
+ * the order is a no-op). SUBSUMES the old `prdsFirst` boolean: `drain`
300
+ * reproduces its default, `[task, build, ...]` reproduces `prdsFirst: true`.
301
+ * Resolved per-repo like `autoBuild`/`autoTask`: flag
302
+ * (`--selection-order`) > `DORFL_SELECTION_ORDER` env (the `'list'`
303
+ * coercion) > per-repo > global > default (`drain`). An unknown name/keyword
304
+ * FAILS LOUDLY (`select-order.ts` `resolveSelectionOrder`).
305
+ */
306
+ selectionOrder: SelectionOrderConfig;
307
+ /** Global cap on how many items the runner claims+runs in one tick. */
308
+ maxParallel: number;
309
+ /** Per-repo cap on concurrent claims (≤ maxParallel in effect). */
310
+ perRepoMax: number;
311
+ /** Name of the git remote that serializes claims (the arbiter). */
312
+ defaultArbiter: string;
313
+ /**
314
+ * The execution working area: bare hub mirrors (`<dir>/repos/<key>.git`) and
315
+ * job worktrees (`<dir>/work/<work-id>/`). STATE, not cache (ADR §3) — lives
316
+ * under a single visible `~/.dorfl/`, NEVER `~/.cache`. Overridable so
317
+ * tests (and unusual setups) can relocate it.
318
+ */
319
+ workspacesDir: string;
320
+ /**
321
+ * Where local `--bare` arbiters (offline source of truth) are provisioned:
322
+ * `<dir>/<host>/<org>/<name>.git` (hierarchical, reusing the repo→key
323
+ * encoding). Arbiters are precious DATA, not state/cache (ADR §7): they live
324
+ * under a visible `~/git/` and MUST NEVER be placed under `~/.dorfl/`
325
+ * (a `gc`/cleanup mishap could nuke the only copy). Overridable so tests can
326
+ * relocate it.
327
+ */
328
+ arbitersDir: string;
329
+ /**
330
+ * Where the HUMAN `work-on` command checks out its parallel worktrees:
331
+ * `<dir>/<key>/<slug>/` on branch `work/<slug>`. This is a **human-only**,
332
+ * editor-facing area — deliberately NOT under `~/.dorfl/` (the agents'
333
+ * execution state, ADR §3), so a `work-on` worktree never carries the human's
334
+ * secrets into an agent context. It is intentionally OPTIONAL with **no silent
335
+ * default**: `work-on` prompts for it on first use and saves it here (offering a
336
+ * sensible suggestion that does NOT share a prefix with the user's code dirs, so
337
+ * shell tab-completion never collides). `undefined` ⇒ not yet configured.
338
+ */
339
+ humanWorktreesDir?: string;
340
+ /** Integration mode for completed items: `propose` (default) or `merge`. */
341
+ integration: IntegrationMode;
342
+ /**
343
+ * **Per-TRANSITION override for the prd→tasks (TASKING) transition only.** When
344
+ * set, the tasking transition (a `do prd:<slug>` run: emit `work/tasks/backlog/*.md` +
345
+ * the `work/prds/ready/ → work/prds/tasked/` lifecycle move) integrates with THIS
346
+ * mode instead of the flat {@link integration}; the task-BUILD transition is
347
+ * unaffected (it always reads {@link integration}). UNSET (the default) ⇒ tasking
348
+ * falls back to {@link integration} — byte-for-byte today's behaviour for any repo
349
+ * that does not set it. The maintainer's target is `integration: 'propose'` +
350
+ * `taskingIntegration: 'merge'`: task a prd straight onto `main` (the task FILES
351
+ * land, no PR) but build each task as a reviewable PR. Resolved per-repo like
352
+ * {@link integration}: flag (`--merge`/`--propose`) > env
353
+ * (`DORFL_TASKING_INTEGRATION`) > per-repo > global > (fall back to)
354
+ * `integration` > default `propose`. DISTINCT from intake's per-EMITTED-TYPE
355
+ * `{task, prd}` resolver (front door, author-trust-resolved): this is a
356
+ * per-LIFECYCLE-TRANSITION knob, inside the trust boundary, operator/config-only.
357
+ */
358
+ taskingIntegration?: IntegrationMode;
359
+ /**
360
+ * **Per-repo DEFAULT landing for the TASKER's emitted tasks** (prd
361
+ * `staging-pool-position-gate-and-trust-model` US #5, task
362
+ * `runner-deterministic-slice-placement-policy-and-precedence`). Resolved
363
+ * per-repo EXACTLY like {@link taskingIntegration} (flag `--tasks-land-in`
364
+ * > env `DORFL_TASKS_LAND_IN` > per-repo > global > built-in
365
+ * `'pre-backlog'`). The tasking path reads it and passes it as the
366
+ * CONFIGURED-DEFAULT rung into the shared placement resolver
367
+ * (`src/placement.ts`); the resolver overlays an EXPLICIT operator flag
368
+ * (top) and the UNTRUSTED-ORIGIN force (staging) on top, in that order. The
369
+ * tasker NEVER sets placement itself. Prd US #6 / the governing ADR: the
370
+ * runner OWNS placement from unforgeable inputs; the agent cannot
371
+ * influence it.
372
+ */
373
+ tasksLandIn: TasksLandIn;
374
+ /**
375
+ * **Per-repo DEFAULT landing for `intake`-authored spec files** (spec
376
+ * `staging-pool-position-gate-and-trust-model` US #2/#5/#6/#12). The SPEC twin
377
+ * of {@link tasksLandIn}: resolved per-repo EXACTLY like it (flag
378
+ * `--specs-land-in` > env `DORFL_SPECS_LAND_IN` > per-repo > global >
379
+ * built-in `'pre-proposed'`). `intake`'s spec dispatch reads it and passes it as
380
+ * the CONFIGURED-DEFAULT rung into the shared placement resolver
381
+ * (`src/placement.ts`); the resolver overlays an EXPLICIT operator flag
382
+ * (top) and the UNTRUSTED-ORIGIN force (staging) on top, in that order.
383
+ * `intake` NEVER sets placement itself. Spec US #6 / the governing ADR: the
384
+ * runner OWNS placement from unforgeable inputs; the agent cannot
385
+ * influence it. KEY-LEVEL SYMMETRY with `tasksLandIn` — one resolver, two
386
+ * lifecycles, one precedence change touches ONE place.
387
+ *
388
+ * The sole spec-placement key after the prd → spec HARD CUTOVER (spec
389
+ * `prd-to-spec-vocabulary-cutover-and-migration-command`): the legacy
390
+ * `prdsLandIn` config key + `--prds-land-in` flag are GONE (clean break).
391
+ */
392
+ specsLandIn: SpecsLandIn;
393
+ /**
394
+ * **The PR-INTENT axis** (ADR §6): on the `propose` path, do NOT open a review
395
+ * request even on a GitHub arbiter with auth — push the branch (the
396
+ * safety-bearing recovery point) but SKIP `openRequest`. `true` ⇒ deliberately
397
+ * no PR (the explicit, no-warning "suppress the PR" intent that re-homes the old
398
+ * `provider: none` use); `false`/unset (default) ⇒ "I want a PR", so propose
399
+ * opens it via the arbiter-derived provider as normal. This is NOT a provider
400
+ * choice — `selectProvider` stays purely arbiter-derived; `noPR` is an intent
401
+ * LAYERED on top. Its honest-failure twin: when `noPR` is unset + propose + a
402
+ * GitHub arbiter but a `gh` auth PROBE says `gh` cannot open a PR, the run FAILS
403
+ * UP FRONT (a pre-flight guard) instead of silently degrading. `merge` mode
404
+ * ignores it (it never opens a PR). Resolved per-repo like `review`: flag
405
+ * (`--no-pr`) > env > per-repo > global > default `false`.
406
+ */
407
+ noPR: boolean;
408
+ /**
409
+ * The command the runner shells out to for one task. The runner appends the
410
+ * built prompt on stdin; the command does NO git ops on the repo (the runner
411
+ * owns those). Empty string ⇒ no agent configured (run will refuse). Consumed
412
+ * by the **null** harness adapter (it shells out to this verbatim); the **pi**
413
+ * adapter ignores it (it invokes the pi CLI directly — see `harness`).
414
+ */
415
+ agentCmd: string;
416
+ /**
417
+ * The model a job's agent runs on (harness-agnostic ROUTING intent, ADR §13).
418
+ * dorfl decides WHICH model; it never touches auth/keys (those stay the
419
+ * harness's job). Optional with NO default so "unset" is meaningful: unset ⇒
420
+ * dorfl forces no model (the harness's own default / a model baked into
421
+ * `agentCmd` is used untouched). Carried through the harness seam
422
+ * (`LaunchInput.model`); the ADAPTER decides HOW it reaches its tool — the pi
423
+ * adapter passes `--model <model>` natively, the null/shell adapter substitutes
424
+ * a `{model}` placeholder in `agentCmd`. Resolved per-repo like `integration`:
425
+ * flag (`--model`) > env > per-repo > global > default (unset).
426
+ */
427
+ model?: string;
428
+ /**
429
+ * Which harness adapter launches + reports liveness for a job's agent (the
430
+ * harness seam, ADR §5): `null` (default — shells out to `agentCmd`,
431
+ * PID-only liveness) or `pi` (invokes the pi CLI with the work-agent prompt;
432
+ * liveness from PID + the pi session dir/log, never mtime). pi specifics stay
433
+ * behind the adapter; the core only sees the `Harness` interface.
434
+ */
435
+ harness?: HarnessAdapter;
436
+ /**
437
+ * The pi CLI binary the `pi` harness invokes (default `pi` on `PATH`).
438
+ * Overridable so an operator can pin a path; tests stub it. Ignored unless
439
+ * `harness` is `pi`.
440
+ */
441
+ piBin?: string;
442
+ /**
443
+ * The ROOT folder under which the runner generates a job's pi session FILE —
444
+ * the adapter passes `--session <sessionsDir>/<unique-id>.jsonl` (a literal
445
+ * file path pi creates + writes; never `--session-dir`). A **HOST-ONLY machine
446
+ * path** (same class as `piBin`/`workspacesDir`): resolved flag (`--sessions-
447
+ * dir`) > env (`DORFL_SESSIONS_DIR`) > global > default — there is NO
448
+ * per-repo layer (a committed repo file must not redirect where the host writes
449
+ * session logs), so it is in `REPO_REJECTED_KEYS`. Optional with a DYNAMIC
450
+ * default (NOT a `DEFAULT_CONFIG` entry): unset ⇒ the path generator derives
451
+ * pi's default per-cwd sessions folder at launch from the job cwd (a direct
452
+ * child of `~/.pi/agent/sessions/`, so the dashboard's non-recursive `listAll`
453
+ * scans it). Set ⇒ any folder (e.g. a dedicated `run` fleet folder).
454
+ */
455
+ sessionsDir?: string;
456
+ /**
457
+ * The per-repo ENV-PREP step (install deps, fetch submodules, run codegen) —
458
+ * the SIBLING of `verify`, NOT part of it. `prepare` makes a freshly-
459
+ * materialised worktree's environment READY; `verify` checks the tree is
460
+ * GREEN. The runner sequences `prepare` THEN `verify`: `prepare` runs ONCE,
461
+ * before the FIRST `verify`, on a worktree that needs deps but does not have
462
+ * them (a fresh job worktree off the hub mirror). Install MUST NOT be baked
463
+ * into `verify` — that would make `verify` stop being a pure, cheaply-re-
464
+ * runnable acceptance check and make every gate run pay the install cost.
465
+ * `prepare` is where install belongs. A deterministic shell command (or an
466
+ * ordered list, all must pass); no model in the loop. Same shape and the SAME
467
+ * resolution/precedence as `verify` (flag > env > per-repo > global > default).
468
+ * The ONE difference from `verify`: unset (omitted) ⇒ NO prepare step (a
469
+ * no-op) — there is NO default install (a repo with no deps needs none; we
470
+ * never invent a default that would run `pnpm install` in a repo that has no
471
+ * lockfile). See `prepare.ts`.
472
+ */
473
+ prepare?: VerifyConfig;
474
+ /**
475
+ * The per-repo acceptance gate run by `dorfl verify` (a deterministic
476
+ * shell command, or an ordered list of commands). NOT per-task and NOT model-
477
+ * interpreted — it is declared, auditable config (ADR §8). Unset (omitted) ⇒
478
+ * a sensible `pnpm -r build && test && format:check` default; the field is
479
+ * intentionally optional so "unset" is distinguishable from "empty". Install
480
+ * must NOT be baked into `verify` — env-prep belongs in the sibling `prepare`
481
+ * field, which the runner runs ONCE before the first `verify` on a fresh
482
+ * worktree (the prepare=env-ready / verify=tree-green split).
483
+ */
484
+ verify?: VerifyConfig;
485
+ /**
486
+ * **Gate 2 — the PR/code review gate** (GATES prd `work/prds/tasked/review.md`): run the
487
+ * `review` SKILL as a fresh-context judgement gate ON TOP of the deterministic
488
+ * `verify` floor, AFTER `verify` passes and BEFORE the done-move, on the
489
+ * `do`/`complete` path. Default **OFF** (it puts a model on the merge path —
490
+ * opt-in, ADR §8). Resolved per-repo like `integration`: flag
491
+ * (`--review`/`--no-review`) > env > per-repo > global > default false.
492
+ * `verify` is never replaced — review is layered, never a substitute.
493
+ */
494
+ review: boolean;
495
+ /**
496
+ * The model the REVIEW agent runs on (de-correlation from the builder's
497
+ * `model`). Optional with NO default so "unset" means "no forced review model"
498
+ * (the harness's own default). Carried to the review-agent launch through the
499
+ * EXISTING harness seam (`LaunchInput.model` / `substituteModel`) — NOT a new
500
+ * mechanism. Resolved like `model`: flag (`--review-model`) > env > per-repo >
501
+ * global > default (unset). Distinct from the builder's `model`.
502
+ */
503
+ reviewModel?: string;
504
+ /**
505
+ * How many CORROBORATING review rounds Gate 2 runs on the SAME tip. Semantics are
506
+ * UNANIMOUS-APPROVAL, not retry-until-pass: the gate approves ONLY if EVERY round
507
+ * approves, and a `block` is TERMINAL (it short-circuits the loop and is never
508
+ * re-rolled — re-reviewing an unchanged tip after a block would just be a
509
+ * stochastic dice re-roll that could launder a real reject into a pass). So a
510
+ * value > 1 makes a FALSE APPROVE harder to slip through (each extra round is a
511
+ * veto), it does NOT give blocked work a second chance. A non-approve forces
512
+ * `needs-attention/` (never silently merges or loops), per the maintainer
513
+ * decision. Default a small N (2): two independent approvals required. (A future
514
+ * builder-REVISE step that MUTATES the tree between rounds is the only thing that
515
+ * should make a block retryable, because it changes the artifact under review; it
516
+ * is not implemented yet.) Resolved like `integration`: flag
517
+ * (`--review-max-rounds`) > env > per-repo > global > default.
518
+ */
519
+ reviewMaxRounds: number;
520
+ /**
521
+ * **The tasker IMPROVER loop on/off toggle** (`--tasker-loop` /
522
+ * `--no-tasker-loop`). On the `do prd:<slug>` tasking path the improver loop is
523
+ * the task path's quality engine (auto-tasking has no `verify` floor), so it is
524
+ * ON by default; setting this false gates wiring the loop seam (the candidate
525
+ * tasks land as-is). Resolved per-repo like `integration`: flag
526
+ * (`--tasker-loop`/`--no-tasker-loop`) > env > per-repo > global > default (on).
527
+ * DISTINCT from the acceptance gate's `review` toggle.
528
+ */
529
+ taskerLoop: boolean;
530
+ /**
531
+ * **The tasker IMPROVER loop's convergence cap** (`slicer-review-edit-loop`,
532
+ * GATES prd `work/prds/tasked/review.md` RESOLVED DESIGN — Shape 2 / insertion point
533
+ * A). On the `do prd:<slug>` tasking path, AFTER the agent produces candidate
534
+ * tasks the loop runs the `review` SKILL, APPLIES its edits, and re-reviews
535
+ * until a pass finds no NEW blocking issue (the natural terminator).
536
+ * `taskerLoopMax` is the HARD CAP on the in-context review passes (N) so the
537
+ * loop can never run forever; on hitting it WITH unresolved blockers the loop
538
+ * REJECTS via the needsAnswers / needs-attention sink. It lives on the LOOP,
539
+ * never on a gate (the orphaned `reviewMaxRounds` belongs to the Gate-2 path —
540
+ * separate cleanup). A cheap default (3). Resolved per-repo like `integration`:
541
+ * flag (`--tasker-loop-max`) > env > per-repo > global > default. Distinct from
542
+ * Gate-2's `reviewMaxRounds`.
543
+ */
544
+ taskerLoopMax: number;
545
+ /**
546
+ * The model the tasker IMPROVER loop's review agent runs on (de-correlation
547
+ * from the tasker). Optional with NO default so "unset" means "no forced model"
548
+ * (the harness's own default). Carried to the review-agent launch through the
549
+ * EXISTING harness seam (`LaunchInput.model` / `substituteModel`). Resolved like
550
+ * `model`: flag (`--tasker-loop-model`) > env > per-repo > global > default
551
+ * (unset). DISTINCT from the acceptance gate's `reviewModel` (build
552
+ * `--review-model`).
553
+ */
554
+ taskerLoopModel?: string;
555
+ /**
556
+ * **The fresh-worktree acceptance-gate toggle** (`--fresh-worktree-gate` /
557
+ * `--no-fresh-worktree-gate`). When ON (the default), the acceptance gate
558
+ * (`prepare` then `verify`) runs in a CLEAN throwaway worktree cut from the
559
+ * work branch REBASED onto the latest `<arbiter>/main` — i.e. the exact tree
560
+ * the arbiter will integrate — rather than the agent's pre-rebase working
561
+ * checkout. So a green gate provably describes the merged artifact: a
562
+ * gitignored/uncommitted file the checkout has but the committed/pushed tree
563
+ * does NOT cannot leak into a falsely-green gate, and a change introduced only
564
+ * by the integration rebase IS gated. When OFF (`freshWorktreeGate: false` /
565
+ * `--no-fresh-worktree-gate`), `verify` runs in the agent's build worktree
566
+ * exactly as before (the PRE-rebase gate) — the opt-out for when the per-gate
567
+ * install cost is too high. The throwaway gate worktree is fresh (no deps), so
568
+ * `prepare` runs in it before `verify` (the per-gate install cost the opt-out
569
+ * exists for). Modelled EXACTLY on `taskerLoop`: a POSITIVE boolean, default
570
+ * ON, `--no-` negation. Resolved per-repo like `integration`: flag
571
+ * (`--fresh-worktree-gate`/`--no-fresh-worktree-gate`) > env > per-repo >
572
+ * global > default (on). DISTINCT from `review`/`taskerLoop` (a separate
573
+ * concern: WHICH tree the gate runs against, not whether a review runs).
574
+ *
575
+ * The shared gate→integrate band (`performIntegration`) simply HONOURS the
576
+ * boolean it is handed (caller-agnostic). The `run` FLEET caller passes
577
+ * `(resolvedFlag && perRepoMax === 1)` so the fresh gate is used only when
578
+ * same-repo concurrency is OFF (two pre-existing run-fleet races would
579
+ * otherwise fire at `perRepoMax > 1`; they are their own task). Single-job
580
+ * callers (`do` in-place / `--isolated` / `--remote` / `complete`) pass the
581
+ * resolved flag UNCONDITIONALLY.
582
+ */
583
+ freshWorktreeGate: boolean;
584
+ /**
585
+ * **The cross-job merge serialiser's CAS-retry cap** — the git-alone FLOOR of the
586
+ * land-time cross-job queue (prd `land-time-reverify-and-parallel-merge-ceiling`,
587
+ * Story 5 + Applied Answer q1 (a)). The merge-mode `${branch}:main` push retries
588
+ * a non-fast-forward rejection by re-rebasing onto the moved `<arbiter>/main` and
589
+ * pushing again, up to this cap; only after exhaustion does a loser bounce to
590
+ * needs-attention. The in-process `integrateLock` only serialises sibling
591
+ * INTEGRATES in ONE process; across separate CI jobs the CAS loop IS the queue,
592
+ * and this cap is what determines how wide a matrix burst converges before any
593
+ * spurious bounce. A wide-matrix CI raises it; the default stays modest. Race-1
594
+ * safety is unchanged (a lost CAS costs only a re-rebase + re-gate retry, never a
595
+ * `--force`, never a both-land-broken) — scaling the cap only changes WHEN a
596
+ * genuinely-stuck loser gives up. Resolved per-repo like `freshWorktreeGate`:
597
+ * flag (`--merge-retries`) > env (`DORFL_MERGE_RETRIES`) > per-repo > global >
598
+ * default. The default matches `integration-core.ts`'s built-in fallback (1000 —
599
+ * the C2 rebase-until-real-conflict liveness ceiling, not a small Race-1 budget),
600
+ * so resolving it through this layer is byte-for-byte today's behaviour when no
601
+ * source sets it. Forwarded into `performIntegration`'s `mergeRetries` (resolved
602
+ * ONCE per `performIntegration` call, fixed across that call's CAS-retry loop —
603
+ * the same per-item resolution `freshWorktreeGate` / `review` use).
604
+ */
605
+ mergeRetries: number;
606
+ /**
607
+ * **Per-repo OPT-IN strictness layered on the OQ6 stale-approval default**
608
+ * (prd `land-time-reverify-and-parallel-merge-ceiling`, sidecar OQ6 / task
609
+ * `strict-merge-approval-gate`). Controls how the apply rung treats a prior
610
+ * merge-answer when the merge-base CHANGED between the human's answer and
611
+ * the apply step. The default (`false`) honours the prior answer and lands
612
+ * when the rebased tip re-verifies GREEN — a green re-verify is trusted as
613
+ * sufficient (the cheap fast-path). `true` re-surfaces the merge-question
614
+ * (clears the answer back to no-answer and re-authors the question on
615
+ * `main`/runner under the `advancing` lock — no branch-side mutation)
616
+ * instead of auto-landing on a merge-base change, even on a green re-verify
617
+ * — the host-agnostic analogue of GitHub's "dismiss stale approvals when
618
+ * the base changes". Story #16's RED-re-verify refusal is UNCHANGED and
619
+ * independent of this flag.
620
+ *
621
+ * This module ONLY resolves the boolean; the re-surface vs. land branch
622
+ * lives in `apply-rung-merge-disposition`'s consumer. Resolved per-repo
623
+ * through the SAME gate-family precedence chain as the sibling gates
624
+ * (flag `--strict-merge-approval` > env `DORFL_STRICT_MERGE_APPROVAL` >
625
+ * per-repo > global > default `false`). DOES NOT alter `mergeQuestions` /
626
+ * `observationTriage` default or shape — a SEPARATE, independent axis.
627
+ */
628
+ strictMergeApproval: boolean;
629
+ /**
630
+ * The optional runner **identity** (a bot): run the runner's git + provider
631
+ * operations as a configured entity via process-scoped env overrides, without
632
+ * mutating the user's global git/`gh` config (see `identity.ts`). HOST-ONLY
633
+ * (it carries secrets and is per-machine) ⇒ rejected in a per-repo file
634
+ * (`REPO_REJECTED_KEYS`); it lives only in the global config. Optional with NO
635
+ * default: unset ⇒ fully ambient (today's behaviour, byte-for-byte) — the CI
636
+ * path relies on `actions/checkout`'s ambient HTTPS+`GITHUB_TOKEN`. When set,
637
+ * `auth` is mandatory and validated at load time ({@link validateIdentity}).
638
+ */
639
+ identity?: Identity;
640
+ }
641
+
642
+ /** A partial config, e.g. loaded from a JSON file or built from CLI flags. */
643
+ export type PartialConfig = Partial<Config>;
644
+
645
+ /**
646
+ * The DEPRECATED config/env keys: present in an OLD config keeps working but is
647
+ * IGNORED with a one-line warning (never a hard error), so an existing setup is
648
+ * not broken by a removal. Each maps to the human-facing replacement hint. Mirrors
649
+ * the `allowAgents`→`autoBuild` removal-with-warning precedent.
650
+ *
651
+ * `provider` (the review-request provider OVERRIDE + `--provider` flag) was
652
+ * removed: the provider is purely ARBITER-derived now (a GitHub remote ⇒ the
653
+ * GitHub provider, else `none`), so an override could only contradict the arbiter.
654
+ * The legitimate `provider: none` use ("suppress the PR") is re-homed to the
655
+ * `noPR` intent axis.
656
+ */
657
+ export const DEPRECATED_CONFIG_KEYS: Readonly<Record<string, string>> = {
658
+ provider:
659
+ 'the `provider` axis was removed — the review-request provider is now purely ' +
660
+ 'arbiter-derived (a GitHub remote ⇒ the GitHub provider, else none). To ' +
661
+ 'deliberately suppress the PR (the old `provider: none` use), set `noPR: true` ' +
662
+ '(or pass `--no-pr`).',
663
+ };
664
+
665
+ /**
666
+ * Warn (once per offending key) for any DEPRECATED key present in a parsed config
667
+ * object, then DELETE it from the object so it never lingers in the resolved
668
+ * config. A stale key is IGNORED, not an error — an existing config keeps working.
669
+ * For `provider`, the warning points specifically at the `noPR` replacement when
670
+ * the stale value was the old `none` ("suppress the PR") use.
671
+ */
672
+ export function warnDeprecatedConfigKeys(
673
+ parsed: Record<string, unknown>,
674
+ source: string,
675
+ warn: (message: string) => void = (m) => console.error(`>> ${m}`),
676
+ ): void {
677
+ for (const key of Object.keys(DEPRECATED_CONFIG_KEYS)) {
678
+ if (!(key in parsed) || parsed[key] === undefined) {
679
+ continue;
680
+ }
681
+ const staleNone = key === 'provider' && parsed[key] === 'none';
682
+ const hint = DEPRECATED_CONFIG_KEYS[key];
683
+ warn(
684
+ `Ignoring deprecated key '${key}' in ${source}: ${hint}` +
685
+ (staleNone
686
+ ? ' (your `provider: none` maps directly to `noPR: true`.)'
687
+ : ''),
688
+ );
689
+ delete parsed[key];
690
+ }
691
+ }
692
+
693
+ /**
694
+ * Built-in defaults. Chosen so that zero-config is useful: stay strict about the
695
+ * autonomy gate (agents claim nothing unless a repo opts in via `autoBuild`).
696
+ * Discovery has no default `roots` — it is the registered hub-mirror set (empty
697
+ * until `remote add`/`remote find` registers a target).
698
+ */
699
+ export const DEFAULT_CONFIG: Config = {
700
+ autoBuild: false,
701
+ // The `promptGuidance` nudge namespace defaults to ALL members off — so the
702
+ // worker prompt is byte-identical to today when no repo opts in. NOT a gate;
703
+ // `verify` remains the sole acceptance bar regardless.
704
+ promptGuidance: {testFirst: false},
705
+ // Auto-tasking is human-first by default: an agent tasks nothing unless a
706
+ // repo opts in via `autoTask` (mirrors `autoBuild`, one level up).
707
+ autoTask: false,
708
+ // The observation INBOX is calm by default (`off`): the triage pool is dropped
709
+ // from the auto-pick selection, so observations are left untouched unless a repo
710
+ // opts in via `observationTriage` (`ask` ⇒ surface a question for each; `auto` ⇒
711
+ // auto-dispose the no-question cases). ADR `ci-config-policy-and-gate-family` §3.
712
+ observationTriage: 'off',
713
+ // The merge-question SURFACER defaults to `ask` — the conservative default
714
+ // (prd `land-time-reverify-and-parallel-merge-ceiling` Applied answer q2 /
715
+ // task `merge-questions-gate-axis` Applied answer q2). NEVER `off` by default:
716
+ // a silently-dropped merge-question means finished, pushed work never lands —
717
+ // strictly more consequential than a dropped observation-promote prompt, so
718
+ // this gate axis is DELIBERATELY HIGHER than `observationTriage`'s `off`. A
719
+ // trusted-repo fast path opts into `auto` (runner self-supplies the `merge`
720
+ // answer + lands via the SAME deterministic apply-time re-verify); a repo that
721
+ // lands by some other means opts into `off`. Resolved per-repo through the
722
+ // SAME precedence chain (flag > env > per-repo > global > default).
723
+ mergeQuestions: 'ask',
724
+ // DECLARED blocked work is calm by default (`false`): the `needsAnswers`-blocked
725
+ // pool is dropped from the auto-pick selection, so `advance` does NOT proactively
726
+ // render a declared blocker into a question sidecar unless a repo opts in via
727
+ // `surfaceBlockers`. Orthogonal PEER to `observationTriage`; `needs-attention`
728
+ // (a stuck build) is separate + always-on. ADR `ci-config-policy-and-gate-family` §3.
729
+ surfaceBlockers: false,
730
+ // SURFACING widens to STAGING by default (`true`) — a `needsAnswers` task in
731
+ // `tasks/backlog/` or a `needsAnswers` prd in `prds/proposed/` surfaces
732
+ // its questions BEFORE promotion, so a human promotes an already-clarified
733
+ // item. Prd `staging-surface-and-apply-promote-safety` (F2). BUILD/claim
734
+ // stays pool-only + trust-gated regardless: this widens ONLY the surface
735
+ // polarity, not the build polarity. Set `false` to restore the legacy
736
+ // pool-only surface behaviour.
737
+ surfaceStaging: true,
738
+ // The `drain` selection-order preset by default (ADR `ci-config-policy-and-gate-
739
+ // family`, selection-order section): drain ready work (build eligible tasks →
740
+ // task taskable prds) before creating/asking (surface → triage); `apply` is
741
+ // always first. Reproduces today's tasks-first two-pool default. Subsumes the
742
+ // removed `prdsFirst` boolean (`[task, build, ...]` reproduces `prdsFirst: true`).
743
+ selectionOrder: DEFAULT_SELECTION_ORDER,
744
+ maxParallel: 4,
745
+ perRepoMax: 2,
746
+ defaultArbiter: 'origin',
747
+ workspacesDir: join(homedir(), brand.workdirName),
748
+ arbitersDir: join(homedir(), 'git'),
749
+ integration: 'propose',
750
+ // The PR-INTENT axis defaults to `false` ("I want a PR"): on a GitHub arbiter,
751
+ // propose opens the PR via the arbiter-derived provider. Set `true` to push the
752
+ // branch but deliberately skip the PR (the explicit suppress-PR intent that
753
+ // re-homes the old `provider: none` use). NOT a provider choice.
754
+ noPR: false,
755
+ // The tasker's emitted tasks land STAGED (`pre-backlog/`) by default — the
756
+ // conservative landing that preserves the tracer task's behaviour: an item is
757
+ // durable + readable but NOT in the agent-eligible pool until a human/runner
758
+ // promotes it. A repo opts into the trusted fast-path with `tasksLandIn:
759
+ // 'ready'` (or `--tasks-land-in ready` / `DORFL_TASKS_LAND_IN=ready`).
760
+ // The runner-deterministic resolver overlays explicit-flag + untrusted-origin
761
+ // force on top of this default (`src/placement.ts`).
762
+ tasksLandIn: 'pre-backlog',
763
+ // `intake`-authored specs land STAGED (`pre-proposed/`) by default — the
764
+ // conservative landing that mirrors `tasksLandIn`'s built-in floor: a spec is
765
+ // durable + readable but NOT in the auto-tasking POOL until a human/runner
766
+ // promotes it. A repo opts into the trusted fast-path with `specsLandIn: 'ready'`
767
+ // (or `--specs-land-in ready` / `DORFL_SPECS_LAND_IN=ready`). The same
768
+ // runner-deterministic resolver overlays explicit-flag + untrusted-origin
769
+ // force on top of this default (`src/placement.ts`).
770
+ specsLandIn: 'pre-proposed',
771
+ agentCmd: '',
772
+ // Gate 2 (PR/code review) defaults OFF — it puts a model on the merge path, so
773
+ // it is opt-in (ADR §8). On an `approve` a resolved `merge` lands automatically
774
+ // (`merge` IS the auto-land mode); `propose` always leaves the merge to a human.
775
+ // The loop bound is a small N so an unattended revise↔review can never run forever.
776
+ review: false,
777
+ reviewMaxRounds: 2,
778
+ // The tasker improver loop is ON by default — auto-tasking has no `verify`
779
+ // floor, so the loop is the task path's quality engine (distinct from the
780
+ // acceptance gate's `review`, which defaults OFF).
781
+ taskerLoop: true,
782
+ // The tasker improver loop's hard cap on in-context review passes — a cheap
783
+ // default so an unattended review→edit→re-review can never run forever (the
784
+ // natural terminator is "no new blocking issue"; this is the ceiling on top).
785
+ taskerLoopMax: 3,
786
+ // The fresh-worktree acceptance gate is ON by default: most CI/tooling caches
787
+ // deps so `pnpm install` is fast, so correctness-first (the gate tests what
788
+ // MERGES, not the agent's pre-rebase checkout) is the right default. The
789
+ // opt-out (`--no-fresh-worktree-gate`) runs `verify` in the build worktree as
790
+ // before, for when the per-gate install cost is too high. Mirrors `taskerLoop`
791
+ // (positive name, default-on).
792
+ freshWorktreeGate: true,
793
+ // The cross-job merge serialiser's CAS-retry cap — the git-alone FLOOR of the
794
+ // land-time cross-job queue (prd `land-time-reverify-and-parallel-merge-ceiling`,
795
+ // Story 5 + Applied Answer q1 (a)). Matches `integration-core.ts`'s built-in
796
+ // `DEFAULT_MERGE_RETRIES` fallback (1000 — the C2 large liveness ceiling, NOT a
797
+ // small Race-1 budget) so resolving it through this layer is byte-for-byte
798
+ // today's behaviour when no source sets it. A wide-matrix CI raises it via
799
+ // `--merge-retries`/`DORFL_MERGE_RETRIES`/per-repo `mergeRetries`.
800
+ mergeRetries: 1000,
801
+ // The strict-merge-approval gate defaults OFF (sidecar OQ6 / task
802
+ // `strict-merge-approval-gate`): the cheap "green re-verify is enough" path
803
+ // is the default; the OQ6 PRD answer pins this. A repo opts in to the
804
+ // host-agnostic "dismiss stale approvals on base change" discipline with
805
+ // `strictMergeApproval: true` (or `--strict-merge-approval` /
806
+ // `DORFL_STRICT_MERGE_APPROVAL=true`). The re-surface vs. land branch is
807
+ // `apply-rung-merge-disposition`'s consumer, NOT here.
808
+ strictMergeApproval: false,
809
+ };
810
+
811
+ /** The conventional config location (`~/.config/dorfl/config.json`). */
812
+ export function defaultConfigPath(): string {
813
+ return join(homedir(), '.config', brand.configDirName, 'config.json');
814
+ }
815
+
816
+ /** Merge a partial config over the built-in defaults; arrays are replaced. */
817
+ export function mergeConfig(overrides: PartialConfig): Config {
818
+ const merged: Config = {...DEFAULT_CONFIG};
819
+ // Iterate the override's own keys (not the defaults') so optional keys like
820
+ // `verify` (absent from DEFAULT_CONFIG, left unset by design) are carried over.
821
+ for (const key of Object.keys(overrides) as (keyof Config)[]) {
822
+ const value = overrides[key];
823
+ if (value !== undefined) {
824
+ // Assign through `unknown`: each key's value type matches by construction.
825
+ (merged as Record<keyof Config, unknown>)[key] = value;
826
+ }
827
+ }
828
+ return merged;
829
+ }
830
+
831
+ /**
832
+ * Persist `config` to `path` as pretty JSON (creating the parent dir). Used by
833
+ * `work-on` to SAVE the prompted `humanWorktreesDir` on first use so the human is
834
+ * never asked again. Only the keys present in `config` are written — we round-trip
835
+ * whatever the loader produced (defaults + file + the new key), which keeps the
836
+ * on-disk file explicit and stable.
837
+ */
838
+ export function saveConfig(config: PartialConfig, path: string): void {
839
+ mkdirSync(dirname(path), {recursive: true});
840
+ writeFileSync(path, JSON.stringify(config, null, 2) + '\n');
841
+ }
842
+
843
+ /**
844
+ * Load config from `path`, merged over defaults. A missing file is not an error
845
+ * (defaults make the tool work out of the box); invalid JSON is.
846
+ */
847
+ export function loadConfig(path: string = defaultConfigPath()): Config {
848
+ if (!existsSync(path)) {
849
+ return mergeConfig({});
850
+ }
851
+ let raw: string;
852
+ try {
853
+ raw = readFileSync(path, 'utf8');
854
+ } catch (err) {
855
+ throw new Error(
856
+ `Failed to read config at ${path}: ${(err as Error).message}`,
857
+ );
858
+ }
859
+ let parsed: PartialConfig;
860
+ try {
861
+ parsed = JSON.parse(raw) as PartialConfig;
862
+ } catch (err) {
863
+ throw new Error(
864
+ `Invalid JSON in config at ${path}: ${(err as Error).message}`,
865
+ );
866
+ }
867
+ // Drop (with a one-line warning) any DEPRECATED key (e.g. the removed `provider`
868
+ // override) so an existing config keeps working — ignored, never a hard error.
869
+ warnDeprecatedConfigKeys(parsed as Record<string, unknown>, path);
870
+ // Validate a present identity at LOAD time (dumb — no arbiter URL resolution;
871
+ // the transport-coherence check is push-time). A bad identity is a hard config
872
+ // error, never a silent ambient fallback.
873
+ if (parsed.identity !== undefined) {
874
+ try {
875
+ validateIdentity(parsed.identity);
876
+ } catch (err) {
877
+ throw new Error(
878
+ `Invalid identity in config at ${path}: ${(err as Error).message}`,
879
+ );
880
+ }
881
+ }
882
+ return mergeConfig(parsed);
883
+ }