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/gc.ts ADDED
@@ -0,0 +1,510 @@
1
+ import {existsSync, readdirSync, statSync} from 'node:fs';
2
+ import {join} from 'node:path';
3
+ import {git, run} from './git.js';
4
+ import {
5
+ JOB_RECORD_FILENAME,
6
+ jobRecordPath,
7
+ readJobRecord,
8
+ removeJobRecord,
9
+ type JobRecord,
10
+ } from './workspace.js';
11
+ import {workBranchRef} from './slug-namespace.js';
12
+
13
+ /**
14
+ * The **reaper** for job worktrees, governed by the **provably-safe deletion
15
+ * predicate** (ADR §4 in `docs/adr/execution-substrate-decisions.md`, the
16
+ * authoritative source). Split out of `agent-workspaces` so the substrate stays
17
+ * thin; this module owns deletion.
18
+ *
19
+ * A job's worktree is removed (auto, at end-of-job; or by `gc`) **iff**:
20
+ *
21
+ * 1. its working tree is **clean** (no uncommitted changes), AND
22
+ * 2. its branch tip is **reachable on the arbiter** — either merged into
23
+ * `<arbiter>/main` (`git merge-base --is-ancestor <tip> <arbiter>/main`),
24
+ * OR pushed as an up-to-date branch (`<arbiter>/<branch>` tip == local tip).
25
+ *
26
+ * Both hold ⇒ the worktree is genuinely redundant (reconstructible from the
27
+ * arbiter) ⇒ remove. Otherwise ⇒ **retain for the human** (a retained worktree
28
+ * is a reliable "needs attention" signal that dovetails with `watch`'s
29
+ * surface-failures rail).
30
+ *
31
+ * The trigger is **provable safety, not "success"**: a successful-but-unpushed
32
+ * job is retained; a job whose commits are on the arbiter is reaped. One rule,
33
+ * no done-vs-failed special-casing. Removal is always `git worktree remove`
34
+ * (+ prune), NEVER a bare `rm -rf` (which would leave a dangling worktree
35
+ * registration on the hub).
36
+ *
37
+ * `--force` overrides the predicate (discard un-saved work) — it must be loud
38
+ * and explicit, NEVER the default.
39
+ */
40
+
41
+ /** The arbiter remote name valid INSIDE a job worktree (ADR §2: cut from the
42
+ * bare hub mirror whose clone remote is `origin`). */
43
+ const ARBITER_REMOTE = 'origin';
44
+
45
+ /**
46
+ * Why a job's worktree was retained (not provably safe to remove). The reaper
47
+ * surfaces exactly one of these per retained job (the FIRST failing clause, in
48
+ * predicate order: dirty tree dominates, then arbiter-reachability).
49
+ */
50
+ export type RetainReason =
51
+ | 'dirty-tree' // uncommitted changes in the working tree
52
+ | 'unmerged-commits' // clean, but the branch tip is NOT on the arbiter at all
53
+ | 'branch-not-pushed'; // clean + a remote branch exists, but its tip != local tip
54
+
55
+ /** Human-readable text for each retain reason (used in `gc` reports). */
56
+ export const RETAIN_REASON_TEXT: Record<RetainReason, string> = {
57
+ 'dirty-tree': 'dirty tree (uncommitted changes)',
58
+ 'unmerged-commits': 'unmerged commits (branch tip not on the arbiter)',
59
+ 'branch-not-pushed': 'branch not pushed (remote tip differs from local tip)',
60
+ };
61
+
62
+ /** How a job's branch tip is reachable on the arbiter (when it is). */
63
+ export type ReachableVia = 'merged' | 'pushed';
64
+
65
+ /** The result of applying the deletion-safety predicate to one job worktree. */
66
+ export interface SafetyVerdict {
67
+ /** True iff the worktree is provably safe to remove (clean AND reachable). */
68
+ safe: boolean;
69
+ /** When `safe`, HOW the tip is reachable on the arbiter. */
70
+ reachableVia?: ReachableVia;
71
+ /** When NOT `safe`, why it was retained. */
72
+ reason?: RetainReason;
73
+ }
74
+
75
+ export interface EvaluateSafetyInput {
76
+ /** The job worktree directory to evaluate. */
77
+ dir: string;
78
+ /** The work branch checked out there (`work/<slug>`). */
79
+ branch: string;
80
+ /**
81
+ * The arbiter remote name valid inside the worktree. Defaults to `origin`
82
+ * (the bare hub mirror's clone remote — ADR §2). Tests with a different
83
+ * layout can override it.
84
+ */
85
+ arbiter?: string;
86
+ /**
87
+ * Drop the CLEAN-TREE half of the predicate, keeping ONLY the
88
+ * reachable-on-arbiter half. A worktree whose durable branch is provably on
89
+ * the arbiter is then safe to reap EVEN WHEN its tree has incidental churn
90
+ * (uncommitted doc-churn / artefacts) — because the durable artefact is the
91
+ * PUSHED branch, not the worktree files.
92
+ *
93
+ * Scoped, deliberate opt-in for the FAILURE-return path of `performDoRemote`,
94
+ * where the needs-attention seam has ALREADY surfaced the item + pushed the
95
+ * branch, so we KNOW the work is safe. The reachability half is NEVER dropped
96
+ * (we never reap work not yet on the arbiter — never lose work). The default
97
+ * (`false`) keeps the full clean-AND-reachable predicate the clean-completion
98
+ * path and `gc`'s default sweep use unchanged.
99
+ */
100
+ reachableOnly?: boolean;
101
+ env?: NodeJS.ProcessEnv;
102
+ }
103
+
104
+ /**
105
+ * Apply the provably-safe deletion predicate (ADR §4) to ONE job worktree:
106
+ *
107
+ * 1. the working tree must be **clean** (no uncommitted changes), AND
108
+ * 2. the branch tip must be **reachable on the arbiter** — merged
109
+ * (`merge-base --is-ancestor <tip> <arbiter>/main`) OR pushed
110
+ * (`<arbiter>/<branch>` tip == local tip).
111
+ *
112
+ * Reaches out to the arbiter (a `git fetch`) so the remote-tracking refs reflect
113
+ * the live arbiter before checking reachability. Never mutates the worktree.
114
+ * Pure verdict — the caller decides whether to reap.
115
+ */
116
+ export function evaluateDeletionSafety(
117
+ input: EvaluateSafetyInput,
118
+ ): SafetyVerdict {
119
+ const env = input.env;
120
+ const arbiter = input.arbiter ?? ARBITER_REMOTE;
121
+
122
+ // 1. Clean tree? Dirty dominates (we never reap over uncommitted work) —
123
+ // UNLESS `reachableOnly` was opted into (the failure path, where the branch
124
+ // is already pushed so the durable artefact is the branch, not the tree).
125
+ if (input.reachableOnly !== true && !isWorkingTreeClean(input.dir, env)) {
126
+ return {safe: false, reason: 'dirty-tree'};
127
+ }
128
+
129
+ // Refresh the arbiter's refs so reachability is checked against the LIVE
130
+ // arbiter (not a stale local mirror). A job worktree is cut from a bare hub
131
+ // mirror whose `origin` remote has NO fetch refspec (so `origin/main` /
132
+ // `origin/<branch>` would not otherwise resolve) — so we fetch the two refs
133
+ // we need EXPLICITLY into remote-tracking refs (the same technique
134
+ // `integrator.rebaseOntoArbiterMain` uses). A plain `git fetch origin` would
135
+ // instead try to clobber the checked-out branch on a mirror. Best-effort: an
136
+ // unreachable arbiter leaves the local refs in place and the predicate reads
137
+ // as not-reachable → retain (the safe direction).
138
+ fetchTracking(input.dir, arbiter, 'main', env);
139
+ fetchTracking(input.dir, arbiter, input.branch, env);
140
+
141
+ const localTip = revParse(input.dir, 'HEAD', env);
142
+
143
+ // 2a. Merged: the tip is an ancestor of <arbiter>/main.
144
+ if (isAncestor(input.dir, localTip, `refs/remotes/${arbiter}/main`, env)) {
145
+ return {safe: true, reachableVia: 'merged'};
146
+ }
147
+
148
+ // 2b. Pushed: <arbiter>/<branch> exists AND its tip == the local tip.
149
+ const remoteTip = revParseOrUndefined(
150
+ input.dir,
151
+ `refs/remotes/${arbiter}/${input.branch}`,
152
+ env,
153
+ );
154
+ if (remoteTip !== undefined && remoteTip === localTip) {
155
+ return {safe: true, reachableVia: 'pushed'};
156
+ }
157
+
158
+ // Clean, but NOT on the arbiter: distinguish "a remote branch exists but its
159
+ // tip differs (un-pushed amend)" from "no remote presence at all".
160
+ if (remoteTip !== undefined) {
161
+ return {safe: false, reason: 'branch-not-pushed'};
162
+ }
163
+ return {safe: false, reason: 'unmerged-commits'};
164
+ }
165
+
166
+ export interface ReapInput extends EvaluateSafetyInput {
167
+ /**
168
+ * The bare hub mirror the worktree was cut from. `git worktree remove` +
169
+ * `prune` are run there (the worktree's registration lives on the mirror).
170
+ */
171
+ mirrorPath: string;
172
+ /**
173
+ * Override the predicate: remove the worktree even when NOT provably safe
174
+ * (discard un-saved work). Loud + explicit — NEVER the default (ADR §4).
175
+ */
176
+ force?: boolean;
177
+ }
178
+
179
+ export interface ReapResult {
180
+ /** True iff the worktree was actually removed. */
181
+ removed: boolean;
182
+ /** The verdict the decision was based on. */
183
+ verdict: SafetyVerdict;
184
+ /** True iff removal happened only because `force` overrode the predicate. */
185
+ forced: boolean;
186
+ }
187
+
188
+ /**
189
+ * Auto-reap ONE job worktree iff the predicate holds (or `force` overrides):
190
+ * `git worktree remove` then `git worktree prune` on the hub mirror — NEVER a
191
+ * bare `rm -rf` (ADR §4). Returns whether it removed the worktree + the verdict
192
+ * it acted on (so the caller can report a retained job's reason).
193
+ *
194
+ * Used at end-of-job (the runner calls it after integrating) and by `gc` (the
195
+ * catch-up when auto-reap didn't run). A job whose work is NOT on the arbiter is
196
+ * never removed here (force is the only override, and it is explicit).
197
+ */
198
+ export function reapJob(input: ReapInput): ReapResult {
199
+ const verdict = evaluateDeletionSafety(input);
200
+ const force = input.force === true;
201
+ if (!verdict.safe && !force) {
202
+ return {removed: false, verdict, forced: false};
203
+ }
204
+ removeWorktree(input.mirrorPath, input.dir, input.branch, input.env);
205
+ return {removed: true, verdict, forced: !verdict.safe};
206
+ }
207
+
208
+ /** One job the `gc` sweep evaluated. */
209
+ export interface GcJob {
210
+ /** Absolute path to the job worktree. */
211
+ dir: string;
212
+ /** The work slug (from the record, else derived from the dir name). */
213
+ slug: string;
214
+ /** The work branch (`work/<slug>`). */
215
+ branch: string;
216
+ /** The per-job record, when present. */
217
+ record?: JobRecord;
218
+ }
219
+
220
+ /** A worktree `gc` reaped (provably safe, or forced). */
221
+ export interface ReapedJob extends GcJob {
222
+ verdict: SafetyVerdict;
223
+ /** True iff removed only because `--force` overrode the predicate. */
224
+ forced: boolean;
225
+ }
226
+
227
+ /** A worktree `gc` retained, with the human-readable reason it kept it. */
228
+ export interface RetainedJob extends GcJob {
229
+ reason: RetainReason;
230
+ /** Human-readable reason text (`RETAIN_REASON_TEXT[reason]`). */
231
+ reasonText: string;
232
+ }
233
+
234
+ export interface GcOptions {
235
+ /** The execution working area (config `workspacesDir`, default `~/.dorfl`). */
236
+ workspacesDir: string;
237
+ /**
238
+ * Override the predicate for EVERY job: discard un-saved work. Loud +
239
+ * explicit (the CLI guards it behind a confirmation) — NEVER the default.
240
+ */
241
+ force?: boolean;
242
+ /** Sink for human-readable progress notes (per reaped / retained job). */
243
+ note?: (message: string) => void;
244
+ env?: NodeJS.ProcessEnv;
245
+ }
246
+
247
+ export interface GcResult {
248
+ /** The worktrees reaped this sweep (provably safe, or forced). */
249
+ reaped: ReapedJob[];
250
+ /** The worktrees retained, each with a clear reason. */
251
+ retained: RetainedJob[];
252
+ }
253
+
254
+ /**
255
+ * Re-apply the deletion-safety predicate across every `<workspacesDir>/work/*`
256
+ * job (ADR §4): reap the provably-safe ones, RETAIN the rest and report each
257
+ * with a clear reason. This is the safety-net catch-up for when auto-reap didn't
258
+ * run (a runner crash/kill left the worktree behind).
259
+ *
260
+ * `force: true` overrides the predicate for every job (discard un-saved work) —
261
+ * loud + explicit (the CLI confirms first), NEVER the default. A job whose work
262
+ * is NOT on the arbiter is never auto-removed without `force`.
263
+ */
264
+ export function gc(options: GcOptions): GcResult {
265
+ const note = options.note ?? (() => {});
266
+ const env = options.env;
267
+ const reaped: ReapedJob[] = [];
268
+ const retained: RetainedJob[] = [];
269
+
270
+ for (const job of discoverJobs(options.workspacesDir)) {
271
+ const mirrorPath = resolveMirrorPath(options.workspacesDir, job);
272
+ const result = reapJob({
273
+ dir: job.dir,
274
+ branch: job.branch,
275
+ mirrorPath,
276
+ force: options.force,
277
+ env,
278
+ });
279
+
280
+ if (result.removed) {
281
+ reaped.push({...job, verdict: result.verdict, forced: result.forced});
282
+ note(
283
+ result.forced
284
+ ? `Reaped ${job.slug} (FORCED — discarded un-saved work).`
285
+ : `Reaped ${job.slug} (${result.verdict.reachableVia}).`,
286
+ );
287
+ continue;
288
+ }
289
+
290
+ const reason = result.verdict.reason ?? 'unmerged-commits';
291
+ const reasonText = RETAIN_REASON_TEXT[reason];
292
+ retained.push({...job, reason, reasonText});
293
+ note(`Retained ${job.slug}: ${reasonText}.`);
294
+ }
295
+
296
+ return {reaped, retained};
297
+ }
298
+
299
+ /**
300
+ * Discover every job worktree under `<workspacesDir>/work/*` (the flat layout —
301
+ * ADR §2). The per-job record is a SIBLING of the worktree dir
302
+ * (`<work-id>.json` next to `<work-id>/`, {@link jobRecordPath}) — OUTSIDE the
303
+ * checked-out tree so it can never be swept into a commit — so a work-id dir is
304
+ * a job iff its sibling record file exists (with a LEGACY fallback to an in-tree
305
+ * record left by an old binary, via {@link readJobRecord}). The branch comes
306
+ * from the record (falling back to `work/<derived-slug>`).
307
+ */
308
+ export function discoverJobs(workspacesDir: string): GcJob[] {
309
+ const workDir = join(workspacesDir, 'work');
310
+ if (!existsSync(workDir)) {
311
+ return [];
312
+ }
313
+ const jobs: GcJob[] = [];
314
+ for (const entry of readdirSync(workDir)) {
315
+ const dir = join(workDir, entry);
316
+ let isDir: boolean;
317
+ try {
318
+ isDir = statSync(dir).isDirectory();
319
+ } catch {
320
+ continue;
321
+ }
322
+ if (!isDir) {
323
+ continue; // skip the sibling `<work-id>.json` record files themselves
324
+ }
325
+ // A job iff a record exists — the sibling path first, then the legacy
326
+ // in-tree path (an old-binary worktree). Mirrors `readJobRecord`'s order.
327
+ if (
328
+ !existsSync(jobRecordPath(dir)) &&
329
+ !existsSync(join(dir, JOB_RECORD_FILENAME))
330
+ ) {
331
+ continue; // not a job worktree (no record at either location)
332
+ }
333
+ const record = readJobRecord(dir);
334
+ const slug = record?.slug ?? deriveSlug(entry);
335
+ // The job record carries the (already-namespaced) branch — the SOURCE OF
336
+ // TRUTH. Only when a record is missing/legacy do we synthesise a fallback;
337
+ // the flat work-id dir name cannot recover the type, so default to the
338
+ // overwhelmingly-common `task` namespace (a recordless worktree is a rare
339
+ // legacy/corrupt case).
340
+ const branch = record?.branch ?? workBranchRef('task', slug);
341
+ jobs.push({dir, slug, branch, record});
342
+ }
343
+ return jobs;
344
+ }
345
+
346
+ /** Derive a slug from a flat work-id dir name (`host__org__repo__slug`). */
347
+ function deriveSlug(workId: string): string {
348
+ const parts = workId.split('__');
349
+ return parts[parts.length - 1] || workId;
350
+ }
351
+
352
+ /**
353
+ * The hub mirror a job worktree was cut from. We do NOT reconstruct it from the
354
+ * encoded repo key (the key may not round-trip the arbiter URL): a worktree's
355
+ * `.git` file points at its mirror's `worktrees/<id>` admin dir, so we read the
356
+ * mirror's common dir directly from the worktree (robust + layout-agnostic).
357
+ */
358
+ function resolveMirrorPath(workspacesDir: string, job: GcJob): string {
359
+ const common = run(
360
+ 'git',
361
+ ['rev-parse', '--path-format=absolute', '--git-common-dir'],
362
+ job.dir,
363
+ );
364
+ const dir = common.stdout.trim();
365
+ if (common.status === 0 && dir !== '') {
366
+ return dir;
367
+ }
368
+ // Fallback: the repos hub under the workspaces dir (best-effort).
369
+ return join(workspacesDir, 'repos');
370
+ }
371
+
372
+ /**
373
+ * True iff the working tree has NO uncommitted WORK (tracked, staged, or
374
+ * untracked). The agent's edits and any untracked artefacts count: untracked
375
+ * work is still un-saved work.
376
+ *
377
+ * The `.dorfl-job.json` exclusion below is now INERT: the per-job record
378
+ * lives at a SIBLING path OUTSIDE the worktree, so it can no longer appear in
379
+ * the worktree's `git status` at all. It used to be load-bearing (the record
380
+ * was written INSIDE the worktree, so a perfectly-saved job would otherwise read
381
+ * as "dirty" purely because the runner wrote its own state file there). It is
382
+ * kept as a harmless no-op that still names the record for a hypothetical
383
+ * old-binary worktree whose record is still in-tree (the read-fallback case);
384
+ * removing it would only risk regressing that edge with no upside. The
385
+ * `work/`-ledger exclusion is a SEPARATE concern and stays.
386
+ */
387
+ function isWorkingTreeClean(
388
+ dir: string,
389
+ env: NodeJS.ProcessEnv | undefined,
390
+ ): boolean {
391
+ // `status --porcelain` prints one line per change; empty ⇒ clean. Includes
392
+ // staged, unstaged, and untracked files.
393
+ const res = run('git', ['status', '--porcelain'], dir, {env});
394
+ if (res.status !== 0) {
395
+ // Can't determine cleanliness ⇒ treat as dirty (the safe direction).
396
+ return false;
397
+ }
398
+ const lines = res.stdout
399
+ .split('\n')
400
+ .map((l) => l.trimEnd())
401
+ .filter((l) => l !== '');
402
+ // Each porcelain line is `XY <path>` (path starts at column 3). Drop the
403
+ // runner's own job-record line; any remaining change ⇒ genuinely dirty.
404
+ const work = lines.filter((l) => l.slice(3).trim() !== JOB_RECORD_FILENAME);
405
+ return work.length === 0;
406
+ }
407
+
408
+ /**
409
+ * Fetch a single arbiter head into its remote-tracking ref EXPLICITLY
410
+ * (`+refs/heads/<head>:refs/remotes/<arbiter>/<head>`). A bare hub mirror has no
411
+ * fetch refspec, so this is the only way the remote-tracking ref exists; it is
412
+ * also harmless on a normal clone. Best-effort: the arbiter may be unreachable
413
+ * (offline) or the head may not exist there — either way the local ref simply
414
+ * stays absent/stale and the predicate reads as not-reachable → retain.
415
+ */
416
+ function fetchTracking(
417
+ dir: string,
418
+ arbiter: string,
419
+ head: string,
420
+ env: NodeJS.ProcessEnv | undefined,
421
+ ): void {
422
+ run(
423
+ 'git',
424
+ [
425
+ 'fetch',
426
+ '--quiet',
427
+ arbiter,
428
+ `+refs/heads/${head}:refs/remotes/${arbiter}/${head}`,
429
+ ],
430
+ dir,
431
+ {env},
432
+ );
433
+ }
434
+
435
+ /**
436
+ * True iff `ancestor` is an ancestor of (or equal to) `descendant`, both
437
+ * resolved IN the local repo `dir` (`git merge-base --is-ancestor`). This is the
438
+ * ONE provably-merged reachability predicate in the system: the worktree reaper
439
+ * above uses it for `<tip> --is-ancestor <arbiter>/main`, and the remote
440
+ * merged-branch sweep (`reap-branches.ts`) REUSES it (not a second predicate) to
441
+ * decide a remote `work/<slug>` branch is provably merged before deleting it.
442
+ * EXPORTED so that single source of truth is shared, never forked.
443
+ */
444
+ export function isAncestor(
445
+ dir: string,
446
+ ancestor: string,
447
+ descendant: string,
448
+ env: NodeJS.ProcessEnv | undefined,
449
+ ): boolean {
450
+ const res = run(
451
+ 'git',
452
+ ['merge-base', '--is-ancestor', ancestor, descendant],
453
+ dir,
454
+ {env},
455
+ );
456
+ return res.status === 0;
457
+ }
458
+
459
+ /** Resolve a ref to its 40-hex sha (throws if it doesn't resolve). */
460
+ function revParse(
461
+ dir: string,
462
+ ref: string,
463
+ env: NodeJS.ProcessEnv | undefined,
464
+ ): string {
465
+ return git(['rev-parse', '--verify', '--quiet', ref], dir, {env}).trim();
466
+ }
467
+
468
+ /** Resolve a ref to its sha, or `undefined` if it doesn't resolve. */
469
+ function revParseOrUndefined(
470
+ dir: string,
471
+ ref: string,
472
+ env: NodeJS.ProcessEnv | undefined,
473
+ ): string | undefined {
474
+ const res = run('git', ['rev-parse', '--verify', '--quiet', ref], dir, {env});
475
+ if (res.status !== 0) {
476
+ return undefined;
477
+ }
478
+ const sha = res.stdout.trim();
479
+ return sha === '' ? undefined : sha;
480
+ }
481
+
482
+ /**
483
+ * Remove a job worktree the contract-safe way: `git worktree remove` then
484
+ * `git worktree prune` on the hub mirror, plus dropping the now-orphaned work
485
+ * branch AND the now-orphaned per-job record (a SIBLING of the worktree since
486
+ * the relocation — it no longer goes away WITH the worktree dir, so we delete it
487
+ * explicitly so a reaped job leaves no `<work-id>.json` litter). NEVER a bare
488
+ * `rm -rf` of the WORKTREE (ADR §4): a raw delete leaves a dangling worktree
489
+ * registration on the hub. Best-effort on prune/branch-drop/record (idempotent
490
+ * re-runs of `gc` must not error on an already-clean hub).
491
+ */
492
+ function removeWorktree(
493
+ mirrorPath: string,
494
+ dir: string,
495
+ branch: string,
496
+ env: NodeJS.ProcessEnv | undefined,
497
+ ): void {
498
+ git(['worktree', 'remove', '--force', dir], mirrorPath, {env});
499
+ removeJobRecord(dir);
500
+ try {
501
+ git(['worktree', 'prune'], mirrorPath, {env});
502
+ } catch {
503
+ // best-effort
504
+ }
505
+ try {
506
+ git(['branch', '-D', branch], mirrorPath, {env});
507
+ } catch {
508
+ // branch may already be gone
509
+ }
510
+ }
@@ -0,0 +1,53 @@
1
+ import {type RunResult} from './git.js';
2
+
3
+ /**
4
+ * **Shared `gh`-failure diagnostics** for the two `gh`-backed provider seams (the
5
+ * review-request `GitHubProvider` in `github.ts` and the `GitHubIssueProvider` in
6
+ * `issue-provider.ts`).
7
+ *
8
+ * Both providers shell out to `gh` and must, on a failure, surface the REAL cause
9
+ * — the actual `gh` stderr (a rate-limit, a permissions error, a transient 5xx),
10
+ * NOT a hard-coded "`gh` is unavailable or unauthenticated" guess that sends an
11
+ * operator chasing a phantom auth problem. This module is the single source of
12
+ * truth for that distillation so the two providers can NEVER drift apart on the
13
+ * next fix (the drift the original hard-coded strings created).
14
+ *
15
+ * Both `gh`-shelling helpers (`runGh`) return `RunResult | undefined`, where
16
+ * `undefined` = the `gh` BINARY could not be spawned (missing / not on `PATH`).
17
+ * That case has no `RunResult` to read, so the PAIR below resolves it to a fixed
18
+ * "binary missing" string and reserves {@link ghFailureReason} for a genuine
19
+ * `RunResult`.
20
+ */
21
+
22
+ /** The fixed reason for a missing/unspawnable `gh` binary (no `RunResult` to read). */
23
+ export const GH_BINARY_MISSING = '`gh` is not available (binary missing).';
24
+
25
+ /**
26
+ * Distil the REAL reason a `gh` invocation failed from its result — the trimmed
27
+ * stderr (the actual cause, e.g. `'dorfl:processing' not found`), falling
28
+ * back to the exit status when stderr is empty. This is what replaces the old
29
+ * hard-coded "unavailable or unauthenticated" guess: the cause must be diagnosable.
30
+ *
31
+ * Requires a NON-undefined `RunResult` (it reads `stderr`/`status`); a missing
32
+ * binary (`undefined`) has no result to read — use {@link ghFailureDetail} when
33
+ * the value may be `undefined`.
34
+ */
35
+ export function ghFailureReason(result: RunResult): string {
36
+ const stderr = result.stderr.trim();
37
+ if (stderr) {
38
+ return stderr;
39
+ }
40
+ return `\`gh\` exited ${result.status}.`;
41
+ }
42
+
43
+ /**
44
+ * Resolve the real failure detail for a `gh` shell-out whose result MAY be
45
+ * `undefined` (binary missing) — the two-arm guard both providers' degrade paths
46
+ * need: a missing binary yields the fixed {@link GH_BINARY_MISSING} string, and
47
+ * only a genuine `RunResult` is passed to {@link ghFailureReason}. This keeps the
48
+ * undefined-vs-`RunResult` split in ONE place so no degrade branch ever calls
49
+ * `ghFailureReason(undefined)`.
50
+ */
51
+ export function ghFailureDetail(result: RunResult | undefined): string {
52
+ return result === undefined ? GH_BINARY_MISSING : ghFailureReason(result);
53
+ }