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
@@ -0,0 +1,550 @@
1
+ import {readFileSync, existsSync} from 'node:fs';
2
+ import {join} from 'node:path';
3
+ import {
4
+ mergeConfig,
5
+ warnDeprecatedConfigKeys,
6
+ type Config,
7
+ type PartialConfig,
8
+ } from './config.js';
9
+ import {envOverrides, type EnvMap} from './env-config.js';
10
+ import {brand} from './brand.js';
11
+ import {encodeRepoKey} from './repo-key.js';
12
+ import type {ConfigOverrideMap} from './config-override.js';
13
+ import {run} from './git.js';
14
+
15
+ /**
16
+ * The per-repo config layer.
17
+ *
18
+ * A repo may commit a `.dorfl.json` at its root. It travels WITH the repo
19
+ * (it is committed) and overrides the global `~/.config/dorfl/config.json`
20
+ * FOR THAT REPO ONLY — so repo-local properties (how this repo integrates, its
21
+ * acceptance `verify` gate, which remote arbitrates its claims) are agreed by all
22
+ * collaborators and agents rather than living in one person's global config.
23
+ *
24
+ * Resolution is per-key, highest wins:
25
+ *
26
+ * flag (where a command offers one) > ENV (DORFL_*) > per-repo file >
27
+ * global > built-in default
28
+ *
29
+ * The mechanism is multi-repo aware: each repo resolves against its OWN
30
+ * `.dorfl.json`, so repo A can be `merge` while repo B is `propose` in the
31
+ * SAME run (see {@link resolveRepoConfig}).
32
+ *
33
+ * Only keys that are genuinely repo properties are honoured in the COMMITTED
34
+ * per-repo file. Runner/host-only keys (`piBin`, `agentCmd`, `maxParallel`, …)
35
+ * describe the runner or the host machine, NOT a single repo;
36
+ * if present in a per-repo file they are ignored and reported with a clear
37
+ * message ({@link loadRepoConfig}).
38
+ *
39
+ * The sharpened host-only principle (ADR §13): **host-only keys must come from a
40
+ * per-machine source — a CLI flag, an `DORFL_*` env var, or the global
41
+ * config file — NEVER the committed repo file.** The allow/reject split below
42
+ * therefore governs ONLY the committed repo file; env (a per-machine source like
43
+ * the global file / a flag) may set ANY key, host-only included (see
44
+ * {@link envOverrides}).
45
+ *
46
+ * A repo with no `.dorfl.json` resolves to exactly the global config —
47
+ * behaviour is unchanged from before this layer existed.
48
+ */
49
+
50
+ /**
51
+ * The conventional per-repo config filename, committed at the repo root. Derived
52
+ * from the single brand identity (`.{base}.json`) so a rename flips it in lockstep
53
+ * (see `brand.ts`).
54
+ */
55
+ export const REPO_CONFIG_FILENAME = brand.repoConfigFilename;
56
+
57
+ /**
58
+ * Config keys that are genuinely repo properties and so are honoured in a
59
+ * per-repo `.dorfl.json`. Deliberately a subset of {@link Config};
60
+ * extend this list as more keys become legitimately repo-scoped.
61
+ */
62
+ export const REPO_ALLOWED_KEYS = [
63
+ 'integration',
64
+ // `taskingIntegration` (the per-TRANSITION override for the prd→tasks TASKING
65
+ // transition ONLY) is a genuine repo property exactly like `integration`: whether
66
+ // THIS repo tasks a prd straight onto `main` (task FILES land, no PR) while it
67
+ // still BUILDS each task as a reviewable PR is agreed by all collaborators +
68
+ // travels with the repo. Resolved per-repo through the SAME chain as
69
+ // `integration`, then falls back to `integration` when unset. DISTINCT from
70
+ // intake's per-EMITTED-TYPE `{task, prd}` resolver (front door, author-trust):
71
+ // this is a per-lifecycle-transition knob, inside the boundary, config-resolved.
72
+ 'taskingIntegration',
73
+ // `tasksLandIn` (the per-repo TASK-PLACEMENT default — staging vs pool, prd
74
+ // `staging-pool-position-gate-and-trust-model` US #5) is a genuine repo property
75
+ // exactly like `taskingIntegration`/`integration`: whether THIS repo's tasker
76
+ // output lands STAGED (`pre-backlog/`, review-without-PR human-promote path) or
77
+ // straight in the agent-eligible POOL (`ready/`, trusted fast-path) is agreed
78
+ // by all collaborators + travels with the repo. Resolved per-repo through the
79
+ // SAME chain as `taskingIntegration` (flag > env > per-repo > global > built-in
80
+ // `pre-backlog`). DISTINCT from intake's per-emitted-type stamps (front door):
81
+ // this is a per-lifecycle PLACEMENT knob, inside the trust boundary,
82
+ // config-resolved. Fed into the shared placement resolver as the
83
+ // configured-default rung (`src/placement.ts`).
84
+ 'tasksLandIn',
85
+ // `specsLandIn` (the per-repo SPEC-PLACEMENT default — staging vs pool, spec
86
+ // `staging-pool-position-gate-and-trust-model` US #2/#5/#6/#12) is a genuine
87
+ // repo property exactly like `tasksLandIn`: whether THIS repo's intake-
88
+ // authored specs land STAGED (`specs/proposed/`, review-without-PR human-promote
89
+ // path) or straight in the auto-tasking POOL (`specs/ready/`, trusted fast-path)
90
+ // is agreed by all collaborators + travels with the repo. Resolved per-repo
91
+ // through the SAME chain as `tasksLandIn` (flag `--specs-land-in` > env
92
+ // `DORFL_SPECS_LAND_IN` > per-repo > global > built-in). Fed into the shared
93
+ // placement resolver as the configured-default rung for the spec lifecycle
94
+ // (`src/placement.ts`). The sole spec-placement key after the prd → spec HARD
95
+ // CUTOVER (the legacy `prdsLandIn` key is GONE — clean break, no accepted alias).
96
+ 'specsLandIn',
97
+ // `noPR` (the PR-INTENT axis — push the branch but deliberately skip the PR) is
98
+ // a genuine repo property exactly like `integration`/`review`: whether this
99
+ // repo's propose runs open a PR is agreed by all collaborators + travels with
100
+ // the repo. Resolved per-repo through the SAME chain. (The removed `provider`
101
+ // OVERRIDE is gone — a stale `provider` key is ignored with a deprecation
102
+ // warning, see `loadRepoConfigFromContent`.)
103
+ 'noPR',
104
+ 'verify',
105
+ // `prepare` (the env-prep / install step run ONCE before the first `verify` on
106
+ // a fresh worktree) is a genuine repo property exactly like `verify` — how this
107
+ // repo's environment is made ready (install deps / submodules / codegen) is
108
+ // agreed by all collaborators + travels with the repo. Resolved per-repo
109
+ // through the SAME chain as `verify`. Install belongs HERE, never baked into
110
+ // `verify`.
111
+ 'prepare',
112
+ 'defaultArbiter',
113
+ // `autoBuild` (may an agent auto-BUILD undeclared, not-`humanOnly` tasks in
114
+ // this repo?) is a genuine repo property — the build member of the symmetric
115
+ // per-action gate family.
116
+ 'autoBuild',
117
+ // `autoTask` (may an agent auto-task undeclared prds in this repo?) is a
118
+ // genuine repo property — the tasking-autonomy mirror of `autoBuild`
119
+ // (`work/prds/auto-task.md`), resolved per-repo through the same chain.
120
+ 'autoTask',
121
+ // `observationTriage` (the 3-state `off|ask|auto` gate over the observation
122
+ // INBOX) is a genuine repo property — the observation-side question-surfacing
123
+ // gate (ADR `ci-config-policy-and-gate-family`), resolved per-repo through the
124
+ // same chain as `integration`/`autoBuild`. It REPLACES the old `autoTriage`
125
+ // boolean (no alias; no external users owed a migration window, 2026-06-12).
126
+ 'observationTriage',
127
+ // `mergeQuestions` (the 3-state `off|ask|auto` gate over the MERGE-QUESTION
128
+ // SURFACER — prd `land-time-reverify-and-parallel-merge-ceiling` Story 17 /
129
+ // task `merge-questions-gate-axis`) is a genuine repo property exactly like
130
+ // `observationTriage`: whether THIS repo's unmerged `work/*` branches surface
131
+ // as merge-questions (and whether they auto-land) is agreed by all
132
+ // collaborators + travels with the repo. SEPARATE axis from
133
+ // `observationTriage` (never rides it) with a HIGHER default (`ask`, never
134
+ // `off` — a dropped merge-question means pushed work never lands). Resolved
135
+ // per-repo through the SAME precedence chain as the rest of the gate family
136
+ // (flag > env > per-repo > global > default `ask`).
137
+ 'mergeQuestions',
138
+ // `surfaceBlockers` (the BOOLEAN gate over DECLARED blocked work — whether a
139
+ // task/prd carrying `needsAnswers:true` is rendered into a question sidecar) is a
140
+ // genuine repo property — the blocked-work side of the question-surfacing gate
141
+ // family (ADR `ci-config-policy-and-gate-family`), the orthogonal peer of
142
+ // `observationTriage`, resolved per-repo through the same chain as `autoBuild`.
143
+ 'surfaceBlockers',
144
+ // `surfaceStaging` (the BOOLEAN gate-family member that widens SURFACE into
145
+ // STAGING — prd `staging-surface-and-apply-promote-safety` F2) is a genuine
146
+ // repo property exactly like its siblings (`surfaceBlockers`/`autoBuild`):
147
+ // whether THIS repo inspects staging for questions is agreed by all
148
+ // collaborators + travels with the repo. Default `true`; resolved per-repo
149
+ // through the SAME chain (flag > env > per-repo > global > built-in `true`).
150
+ // Does NOT touch the BUILD/claim candidate set — staging stays non-claimable.
151
+ 'surfaceStaging',
152
+ // `selectionOrder` (the configurable order across the four orderable auto-pick
153
+ // pools — build/task/surface/triage; `apply` is pinned first) is a genuine repo
154
+ // property — the per-repo selection-order field ADR `ci-config-policy-and-gate-
155
+ // family` specifies, resolved per-repo like `autoTask`. SUBSUMES the removed
156
+ // `prdsFirst` boolean (a preset keyword or an explicit pool-name list).
157
+ 'selectionOrder',
158
+ // `model` (which model this repo's work runs on) and `harness` (which adapter)
159
+ // are legitimate repo properties (ADR §13) — model is routing intent, not auth,
160
+ // and a repo may prefer a given harness. `piBin`/`agentCmd` stay host-only
161
+ // (machine paths/commands), so they are rejected below.
162
+ 'model',
163
+ 'harness',
164
+ // Gate 2 (PR/code review) policy is a genuine repo property (GATES prd
165
+ // `work/prds/tasked/review.md`), resolved per-repo like `integration`/`autoBuild`:
166
+ // whether this repo runs Gate 2 (`review`), which model the review agent runs
167
+ // on (`reviewModel`), and the revise↔review loop bound (`reviewMaxRounds`).
168
+ // `reviewModel` is routing intent (not auth), so — like `model` — it is
169
+ // repo-appropriate, not host-only.
170
+ 'review',
171
+ 'reviewModel',
172
+ 'reviewMaxRounds',
173
+ // The tasker IMPROVER-loop family (`taskerLoop` on/off, `taskerLoopMax` hard
174
+ // cap on in-context review passes, `taskerLoopModel` the loop reviewer's
175
+ // de-correlated model) are genuine repo properties — like `review`/`reviewModel`
176
+ // they tune the per-repo review discipline, resolved per-repo through the same
177
+ // chain. They live on the LOOP (task-generation review), not on a gate, and are
178
+ // DISTINCT from the acceptance gate's `--review*` family.
179
+ 'taskerLoop',
180
+ 'taskerLoopMax',
181
+ 'taskerLoopModel',
182
+ // `freshWorktreeGate` (run the acceptance gate against the REBASED tip in a
183
+ // clean throwaway worktree, ON by default) is a genuine repo property exactly
184
+ // like `verify`/`prepare`/`review`: whether this repo's gate tests the merged
185
+ // artifact (and pays the per-gate install cost) is agreed by all collaborators
186
+ // + travels with the repo. Resolved per-repo through the SAME chain.
187
+ 'freshWorktreeGate',
188
+ // `mergeRetries` (the cross-job merge serialiser's CAS-retry cap — prd
189
+ // `land-time-reverify-and-parallel-merge-ceiling` Story 5 / Applied Answer q1 (a))
190
+ // is a genuine repo property exactly like `freshWorktreeGate`: "how many
191
+ // re-rebase-and-retry attempts before a contender bounces to needs-attention"
192
+ // is agreed by all collaborators in a wide-matrix CI repo + travels with the
193
+ // repo. Resolved per-repo through the SAME chain as `freshWorktreeGate`
194
+ // (flag > env > per-repo > global > default). Safety is unchanged — a lost
195
+ // CAS still costs only a re-rebase + re-gate retry, never a `--force`.
196
+ 'mergeRetries',
197
+ // `strictMergeApproval` (the OPT-IN strictness layered on the OQ6
198
+ // stale-approval default — prd `land-time-reverify-and-parallel-merge-ceiling`
199
+ // sidecar OQ6 / task `strict-merge-approval-gate`) is a genuine repo property
200
+ // exactly like `mergeQuestions`/`mergeRetries`: whether THIS repo re-surfaces
201
+ // the merge-question on a merge-base change (the host-agnostic analogue of
202
+ // GitHub's "dismiss stale approvals when the base changes") instead of
203
+ // auto-landing on a green re-verify is agreed by all collaborators + travels
204
+ // with the repo. Resolved per-repo through the SAME gate-family precedence
205
+ // chain (flag > env > per-repo > global > default `false`). SEPARATE,
206
+ // independent axis — does NOT alter `mergeQuestions`/`observationTriage`
207
+ // default or shape. The re-surface vs. land branch is
208
+ // `apply-rung-merge-disposition`'s consumer, never here.
209
+ 'strictMergeApproval',
210
+ // `promptGuidance` (the NUDGE namespace — prompt-text knobs that strengthen
211
+ // the worker's in-band wrapper line, e.g. `testFirst`) is a genuine repo
212
+ // property: "is this repo nudged toward test-first?" travels with the repo
213
+ // and is agreed by all collaborators. CATEGORICALLY SEPARATE from the gate
214
+ // family (`verify`/`autoBuild`/`humanOnly`) — a nudge changes the agent's
215
+ // disposition, NEVER the acceptance bar. Resolved per-repo through the SAME
216
+ // chain as `autoBuild` (flag > env > per-repo > global > default).
217
+ 'promptGuidance',
218
+ ] as const satisfies readonly (keyof Config)[];
219
+
220
+ /** A key honoured in a per-repo file. */
221
+ export type RepoAllowedKey = (typeof REPO_ALLOWED_KEYS)[number];
222
+
223
+ /**
224
+ * Config keys that describe the RUNNER or the HOST machine, not a single repo,
225
+ * and so are rejected (ignored + reported) in a per-repo file. These remain the
226
+ * domain of the global config / CLI flags.
227
+ */
228
+ export const REPO_REJECTED_KEYS = [
229
+ 'maxParallel',
230
+ 'perRepoMax',
231
+ 'agentCmd',
232
+ // `piBin` is a machine PATH/command, not repo policy, so it is host-only and
233
+ // rejected per-repo (ADR §13). It must come from a per-machine source — a
234
+ // flag, an `DORFL_PI_BIN` env var, or the global file — never a
235
+ // committed repo file. (`harness`, by contrast, is repo-appropriate and so is
236
+ // deliberately NOT rejected.)
237
+ 'piBin',
238
+ // `sessionsDir` is a machine PATH (where the host writes pi session logs), not
239
+ // repo policy, so it is host-only and rejected per-repo: a committed repo file
240
+ // must NOT redirect where the host writes sessions. It must come from a per-
241
+ // machine source — a flag (`--sessions-dir`), `DORFL_SESSIONS_DIR`, or
242
+ // the global file (exactly like `piBin`).
243
+ 'sessionsDir',
244
+ // `identity` carries SECRETS (a `gh` token, an SSH key path) and is a per-
245
+ // MACHINE concept (a bot's credentials), never repo policy — so a committed
246
+ // repo file must NOT supply it. Host-only: it comes from the global config
247
+ // only. Rejected per-repo (ADR identity §; same class as `piBin`).
248
+ 'identity',
249
+ // Reserved/future host-only keys callers may name; rejected proactively so a
250
+ // typo or a copy-pasted global config never silently leaks host policy into a
251
+ // repo. (`humanWorktreesDir` is a planned host-only path.)
252
+ 'humanWorktreesDir',
253
+ ] as const;
254
+
255
+ /** A key rejected from a per-repo file. */
256
+ export type RepoRejectedKey = (typeof REPO_REJECTED_KEYS)[number];
257
+
258
+ const ALLOWED_SET = new Set<string>(REPO_ALLOWED_KEYS);
259
+
260
+ /** The path to a repo's `.dorfl.json` (repo root + filename). */
261
+ export function repoConfigPath(repoPath: string): string {
262
+ return join(repoPath, REPO_CONFIG_FILENAME);
263
+ }
264
+
265
+ /** The result of reading (and filtering) a repo's `.dorfl.json`. */
266
+ export interface LoadedRepoConfig {
267
+ /** Where we looked (whether or not the file exists). */
268
+ path: string;
269
+ /**
270
+ * Only the repo-appropriate keys found in the file, ready to layer over the
271
+ * global config. Unknown and rejected keys are NOT present here.
272
+ */
273
+ config: PartialConfig;
274
+ /**
275
+ * Runner/host-only keys that WERE present in the file and were ignored. Empty
276
+ * when nothing was rejected.
277
+ */
278
+ rejected: string[];
279
+ /**
280
+ * A clear, human-facing message naming the rejected keys and the file they
281
+ * came from. `undefined` when nothing was rejected.
282
+ */
283
+ message?: string;
284
+ }
285
+
286
+ /**
287
+ * Read a repo's `.dorfl.json` and split it into the honoured subset and
288
+ * the rejected runner/host-only keys. A missing file is not an error (the repo
289
+ * simply resolves to the global config); invalid JSON is. Unknown keys are
290
+ * silently dropped (neither honoured nor reported as rejected). Only keys in
291
+ * {@link REPO_ALLOWED_KEYS} are carried into `config`.
292
+ */
293
+ export function loadRepoConfig(repoPath: string): LoadedRepoConfig {
294
+ const path = repoConfigPath(repoPath);
295
+ if (!existsSync(path)) {
296
+ return {path, config: {}, rejected: []};
297
+ }
298
+
299
+ let raw: string;
300
+ try {
301
+ raw = readFileSync(path, 'utf8');
302
+ } catch (err) {
303
+ throw new Error(`Failed to read ${path}: ${(err as Error).message}`);
304
+ }
305
+
306
+ return loadRepoConfigFromContent(raw, path);
307
+ }
308
+
309
+ /**
310
+ * The content-based half of {@link loadRepoConfig}: parse + apply the SAME
311
+ * allow/reject split to ALREADY-READ `.dorfl.json` bytes, labelling the
312
+ * source as `sourceLabel` (a path, or e.g. `<arbiter>/main:.dorfl.json`)
313
+ * in the rejected-key message. Used wherever the committed repo file is sourced
314
+ * from somewhere OTHER than a working-tree path — notably `do --remote`, which
315
+ * reads it from the arbiter's `main` (`git show`) since there is no checkout.
316
+ * Reuses the allow/reject SET verbatim (no parallel split), so a host-only key
317
+ * is rejected identically however the bytes were sourced. Invalid JSON throws.
318
+ */
319
+ export function loadRepoConfigFromContent(
320
+ content: string,
321
+ sourceLabel: string,
322
+ ): LoadedRepoConfig {
323
+ let parsed: Record<string, unknown>;
324
+ try {
325
+ parsed = JSON.parse(content) as Record<string, unknown>;
326
+ } catch (err) {
327
+ throw new Error(
328
+ `Invalid JSON in ${sourceLabel}: ${(err as Error).message}`,
329
+ );
330
+ }
331
+
332
+ // Drop (with a one-line warning) any DEPRECATED key (e.g. the removed `provider`
333
+ // override) before the allow/reject split, so an existing committed config keeps
334
+ // working — ignored, never an error, and never mistaken for an unknown key.
335
+ warnDeprecatedConfigKeys(parsed, sourceLabel);
336
+
337
+ const config: PartialConfig = {};
338
+ const rejected: string[] = [];
339
+ for (const key of Object.keys(parsed)) {
340
+ const value = parsed[key];
341
+ if (value === undefined) {
342
+ continue;
343
+ }
344
+ if (ALLOWED_SET.has(key)) {
345
+ // Type matches by construction: key ∈ REPO_ALLOWED_KEYS ⊂ keyof Config.
346
+ (config as Record<string, unknown>)[key] = value;
347
+ } else if (isRejectedKey(key)) {
348
+ rejected.push(key);
349
+ }
350
+ // else: unknown key ⇒ silently ignored.
351
+ }
352
+
353
+ const rejectedMessage =
354
+ rejected.length > 0
355
+ ? `Ignoring runner/host-only key(s) in ${REPO_CONFIG_FILENAME} ` +
356
+ `(${sourceLabel}): ${rejected.join(', ')}. ` +
357
+ `These describe the runner/host, not a single repo, and belong in ` +
358
+ `the global config or a CLI flag.`
359
+ : undefined;
360
+
361
+ const message = rejectedMessage;
362
+
363
+ return {path: sourceLabel, config, rejected, ...(message ? {message} : {})};
364
+ }
365
+
366
+ function isRejectedKey(key: string): boolean {
367
+ return (REPO_REJECTED_KEYS as readonly string[]).includes(key);
368
+ }
369
+
370
+ /** Inputs to {@link resolveRepoConfig}. */
371
+ export interface ResolveRepoConfigOptions {
372
+ /** Absolute path to the repo root (where `.dorfl.json` would live). */
373
+ repoPath: string;
374
+ /**
375
+ * The fully-resolved GLOBAL config (already merged over built-in defaults,
376
+ * e.g. via {@link mergeConfig} / `loadConfig`). The per-repo file and any
377
+ * flags layer OVER this; it provides the global + default layers of the
378
+ * precedence chain.
379
+ */
380
+ global: Config;
381
+ /**
382
+ * Command-level flag overrides (where a command offers one). These sit at the
383
+ * TOP of the precedence chain: flag > env > per-repo > global > default. Only
384
+ * keys a command actually exposes need appear here.
385
+ */
386
+ flags?: PartialConfig;
387
+ /**
388
+ * The raw environment map the `DORFL_*` layer is read from (defaults to
389
+ * `process.env`). Env sits ABOVE the per-repo file and BELOW a flag, and — as
390
+ * a per-machine source — may set ANY key, host-only included (it is NOT subject
391
+ * to the per-repo allow/reject split). Injectable so tests need not mutate the
392
+ * real `process.env`.
393
+ */
394
+ env?: EnvMap;
395
+ /**
396
+ * The per-machine {@link ConfigOverrideMap} (from `loadConfigOverride`),
397
+ * inserted between the committed per-repo file and env in the precedence chain
398
+ * (ADR `per-machine-config-override-layer`). The hub-key bucket beats the
399
+ * `"*"` bucket. Default: empty (no override applied) — byte-identical to the
400
+ * pre-override behaviour. Injectable so tests need not touch the real
401
+ * `~/.config/dorfl/`.
402
+ */
403
+ override?: ConfigOverrideMap;
404
+ /**
405
+ * The resolved arbiter URL used to compute the hub key (via
406
+ * {@link encodeRepoKey}) for the override lookup. If omitted, the URL is
407
+ * resolved from `repoPath` + `global.defaultArbiter` (`git remote get-url`).
408
+ * Unresolvable ⇒ the hub-key bucket is SKIPPED and only the `"*"` bucket
409
+ * applies (graceful degrade, never an error).
410
+ */
411
+ arbiterUrl?: string;
412
+ }
413
+
414
+ /**
415
+ * The thin `git remote get-url <name>` reader used by {@link resolveRepoConfig}
416
+ * to derive a CHECKOUT's arbiter URL for the override hub-key lookup. Mirrors
417
+ * `resolveArbiterUrlFromCheckout` in `do.ts` (which is the same primitive on the
418
+ * `do --isolated` path); duplicated here — a single-line `run('git', …)` call —
419
+ * to avoid a `repo-config.ts` → `do.ts` dependency that would close a cycle
420
+ * (`do.ts` → `repo-mirror.ts` → `repo-config.ts`). Returns `undefined` when the
421
+ * remote is unset or the cwd is not a git repo — the override layer DEGRADES
422
+ * GRACEFULLY on an unresolvable URL.
423
+ */
424
+ function gitRemoteGetUrl(
425
+ cwd: string,
426
+ remote: string,
427
+ env: NodeJS.ProcessEnv | undefined,
428
+ ): string | undefined {
429
+ const res = run('git', ['remote', 'get-url', remote], cwd, {env});
430
+ if (res.status !== 0) {
431
+ return undefined;
432
+ }
433
+ const url = res.stdout.trim();
434
+ return url === '' ? undefined : url;
435
+ }
436
+
437
+ /** The effective config for one repo, plus any rejected-key diagnostics. */
438
+ export interface ResolvedRepoConfig {
439
+ /** The layered, effective {@link Config} for this repo. */
440
+ config: Config;
441
+ /** Runner/host-only keys ignored in this repo's file (see {@link loadRepoConfig}). */
442
+ rejected: string[];
443
+ /** Clear message for the rejected keys, if any. */
444
+ message?: string;
445
+ }
446
+
447
+ /**
448
+ * Resolve the effective config for ONE repo by layering, per key:
449
+ *
450
+ * flag > ENV (DORFL_*) > per-repo `.dorfl.json` > global >
451
+ * built-in default
452
+ *
453
+ * The `global` argument already carries the global + default layers (it is the
454
+ * output of `loadConfig`/`mergeConfig`). We layer the repo's honoured keys over
455
+ * it, then the `DORFL_*` env layer over that (env may set host-only keys
456
+ * the per-repo file rejected — it is a per-machine source), then any flags on
457
+ * top. The shared `global` object is never mutated, so calling this once per repo
458
+ * in a multi-repo run yields INDEPENDENT results — repo A can be `merge` while
459
+ * repo B is `propose` in the same run.
460
+ *
461
+ * A repo with no `.dorfl.json` (and no env) resolves to exactly `global`
462
+ * (unchanged behaviour).
463
+ */
464
+ export function resolveRepoConfig(
465
+ options: ResolveRepoConfigOptions,
466
+ ): ResolvedRepoConfig {
467
+ const {repoPath, global, flags, env, override} = options;
468
+ const repo = loadRepoConfig(repoPath);
469
+ // Resolve the arbiter URL for the override hub-key lookup from the CHECKOUT's
470
+ // configured `<defaultArbiter>` remote (the working-tree analogue of the
471
+ // mirror's `origin`). Unresolvable (no remote, not a git repo) ⇒ hub-key
472
+ // lookup skipped; the `"*"` bucket still applies (graceful degrade).
473
+ const arbiterRemote = flags?.defaultArbiter ?? global.defaultArbiter;
474
+ const arbiterUrl =
475
+ options.arbiterUrl ?? gitRemoteGetUrl(repoPath, arbiterRemote, env);
476
+ return resolveRepoConfigFromLoaded(repo, {
477
+ global,
478
+ flags,
479
+ env,
480
+ override,
481
+ ...(arbiterUrl !== undefined ? {arbiterUrl} : {}),
482
+ });
483
+ }
484
+
485
+ /**
486
+ * Layer an ALREADY-LOADED {@link LoadedRepoConfig} (the honoured subset + its
487
+ * rejected-key diagnostics) into the SAME precedence chain {@link resolveRepoConfig}
488
+ * applies:
489
+ *
490
+ * flag > ENV (DORFL_*) > per-repo > global > built-in default
491
+ *
492
+ * This is the source-agnostic core: {@link resolveRepoConfig} feeds it a
493
+ * working-tree read ({@link loadRepoConfig}); `do --remote` feeds it the arbiter's
494
+ * committed file read from `main` via {@link loadRepoConfigFromContent}. EITHER
495
+ * way the layering + the rejected-key passthrough are IDENTICAL — only the bytes'
496
+ * origin differs (the task's one genuinely-new seam).
497
+ */
498
+ export function resolveRepoConfigFromLoaded(
499
+ repo: LoadedRepoConfig,
500
+ options: {
501
+ global: Config;
502
+ flags?: PartialConfig;
503
+ env?: EnvMap;
504
+ /**
505
+ * The per-machine {@link ConfigOverrideMap}; default empty (no override).
506
+ * Inserted between the committed per-repo file and env in the precedence
507
+ * chain (ADR `per-machine-config-override-layer`).
508
+ */
509
+ override?: ConfigOverrideMap;
510
+ /**
511
+ * The resolved arbiter URL used to look up the hub-key override bucket
512
+ * (via {@link encodeRepoKey}). Unresolvable ⇒ skip the hub-key bucket;
513
+ * the `"*"` bucket still applies (graceful degrade).
514
+ */
515
+ arbiterUrl?: string;
516
+ },
517
+ ): ResolvedRepoConfig {
518
+ const {global, flags, env, override, arbiterUrl} = options;
519
+ // The per-machine override layer (ADR `per-machine-config-override-layer`):
520
+ // the `"*"` (all-repos) bucket then the hub-key (this-repo) bucket, spread
521
+ // BETWEEN the committed per-repo file and env. Hub-key beats `"*"`. An
522
+ // unresolvable arbiter URL skips the hub-key lookup but keeps `"*"` — never
523
+ // an error. The override may set ANY key (host-only included): it is a
524
+ // per-machine source like env / flag / the global file, NOT subject to the
525
+ // per-repo allow/reject split.
526
+ const overrideStar = override?.['*'] ?? {};
527
+ const hubKey =
528
+ arbiterUrl !== undefined ? encodeRepoKey(arbiterUrl) : undefined;
529
+ const overrideHub =
530
+ hubKey !== undefined && override !== undefined
531
+ ? (override[hubKey] ?? {})
532
+ : {};
533
+ // mergeConfig copies `global` (spreads DEFAULT_CONFIG then assigns) so the
534
+ // shared global object is never mutated. Layer per-repo, then the override
535
+ // (`"*"` then hub-key — hub-key wins), then env (a per-machine source — may
536
+ // set host-only keys), then flags on top.
537
+ const config = mergeConfig({
538
+ ...global,
539
+ ...repo.config,
540
+ ...overrideStar,
541
+ ...overrideHub,
542
+ ...envOverrides(env),
543
+ ...(flags ?? {}),
544
+ });
545
+ return {
546
+ config,
547
+ rejected: repo.rejected,
548
+ ...(repo.message ? {message: repo.message} : {}),
549
+ };
550
+ }
@@ -0,0 +1,74 @@
1
+ /**
2
+ * The arbiter-URL → **hub key** encoder, extracted from `repo-mirror.ts` so it
3
+ * is importable WITHOUT pulling in the rest of the hub-mirror plumbing (which
4
+ * itself depends on `repo-config.ts`). The split exists for ONE reason: the
5
+ * per-machine `config.override.json` layer (resolved in `repo-config.ts`)
6
+ * needs the hub key to look up the per-repo override bucket — but
7
+ * `repo-config.ts` cannot import from `repo-mirror.ts` without a cycle. The
8
+ * key encoder is pure (URL → string) and has no business depending on the
9
+ * mirror or the per-repo config, so it lives here. `repo-mirror.ts` re-exports
10
+ * {@link encodeRepoKey} so existing callers see no change.
11
+ */
12
+
13
+ /**
14
+ * Deterministically encode an arbiter remote URL into a hierarchical hub key:
15
+ * drop the scheme / user / `.git` suffix, then replace `.` → `-` **per path
16
+ * segment** (lossless and reversible; avoids the dotted-segment hazard that
17
+ * trips editors / tools and our own dotdir-pruning). E.g.
18
+ * `git@github.com:wighawag/dorfl.git` → `github-com/wighawag/dorfl`.
19
+ */
20
+ export function encodeRepoKey(url: string): string {
21
+ const segments = urlSegments(url);
22
+ return segments.map(dashDots).join('/');
23
+ }
24
+
25
+ /**
26
+ * Split a remote URL into its host + path segments (lossy only of scheme/user/
27
+ * port/`.git`, which carry no identity for keying). Handles the four shapes the
28
+ * arbiter can take: scp-like ssh (`git@host:org/repo.git`), `ssh://`, `https://`
29
+ * / `http://`, `file://`, and a plain local filesystem path to a bare repo.
30
+ */
31
+ function urlSegments(url: string): string[] {
32
+ const trimmed = url.trim();
33
+
34
+ // scp-like ssh: [user@]host:path (no `://`, has a `:` before the path).
35
+ const scp = /^(?:[^@/]+@)?([^/:]+):(.+)$/;
36
+ if (!trimmed.includes('://')) {
37
+ const m = scp.exec(trimmed);
38
+ if (m && !trimmed.startsWith('/')) {
39
+ return [m[1], ...pathSegments(m[2])];
40
+ }
41
+ // Otherwise a plain local path (e.g. `/srv/git/org/repo.git`).
42
+ return pathSegments(trimmed);
43
+ }
44
+
45
+ // scheme://[user@]host[:port]/path — or file:///abs/path (empty host).
46
+ const schemeEnd = trimmed.indexOf('://');
47
+ const rest = trimmed.slice(schemeEnd + 3);
48
+ const slash = rest.indexOf('/');
49
+ const authority = slash === -1 ? rest : rest.slice(0, slash);
50
+ const path = slash === -1 ? '' : rest.slice(slash + 1);
51
+ const host = stripUserAndPort(authority);
52
+ const hostSegments = host === '' ? [] : [host];
53
+ return [...hostSegments, ...pathSegments(path)];
54
+ }
55
+
56
+ /** Drop `user@` and `:port` from an authority, leaving the bare host. */
57
+ function stripUserAndPort(authority: string): string {
58
+ const afterUser = authority.includes('@')
59
+ ? authority.slice(authority.lastIndexOf('@') + 1)
60
+ : authority;
61
+ const colon = afterUser.indexOf(':');
62
+ return colon === -1 ? afterUser : afterUser.slice(0, colon);
63
+ }
64
+
65
+ /** Split a `/`-path into non-empty segments, dropping a trailing `.git`. */
66
+ function pathSegments(path: string): string[] {
67
+ const noGit = path.replace(/\.git\/?$/, '');
68
+ return noGit.split('/').filter((s) => s.length > 0);
69
+ }
70
+
71
+ /** Replace every `.` with `-` within a single segment (per-segment, lossless). */
72
+ function dashDots(segment: string): string {
73
+ return segment.replace(/\./g, '-');
74
+ }