dorfl 0.1.1 → 0.2.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 (492) hide show
  1. package/dist/advance-ci-template.d.ts +3 -3
  2. package/dist/advance-ci-template.js +1 -1
  3. package/dist/advance-ci-template.js.map +1 -1
  4. package/dist/advance-classify.d.ts +5 -5
  5. package/dist/advance-classify.d.ts.map +1 -1
  6. package/dist/advance-classify.js +4 -4
  7. package/dist/advance-drivers.d.ts +8 -8
  8. package/dist/advance-drivers.d.ts.map +1 -1
  9. package/dist/advance-drivers.js +20 -8
  10. package/dist/advance-drivers.js.map +1 -1
  11. package/dist/advance-isolated.d.ts +3 -3
  12. package/dist/advance-isolated.d.ts.map +1 -1
  13. package/dist/advance-isolated.js +1 -1
  14. package/dist/advance-lifecycle-template.d.ts +2 -2
  15. package/dist/advance-lifecycle-template.d.ts.map +1 -1
  16. package/dist/advance-lifecycle-template.js +85 -13
  17. package/dist/advance-lifecycle-template.js.map +1 -1
  18. package/dist/advance-loop-driver.d.ts +3 -3
  19. package/dist/advance-loop-driver.d.ts.map +1 -1
  20. package/dist/advance-loop-driver.js +1 -1
  21. package/dist/advance-treeless-publish.d.ts +24 -1
  22. package/dist/advance-treeless-publish.d.ts.map +1 -1
  23. package/dist/advance-treeless-publish.js +41 -0
  24. package/dist/advance-treeless-publish.js.map +1 -1
  25. package/dist/advance.d.ts +69 -17
  26. package/dist/advance.d.ts.map +1 -1
  27. package/dist/advance.js +409 -102
  28. package/dist/advance.js.map +1 -1
  29. package/dist/advancing-lock.d.ts +31 -3
  30. package/dist/advancing-lock.d.ts.map +1 -1
  31. package/dist/advancing-lock.js +55 -5
  32. package/dist/advancing-lock.js.map +1 -1
  33. package/dist/agent-launch.d.ts +12 -0
  34. package/dist/agent-launch.d.ts.map +1 -1
  35. package/dist/agent-launch.js +22 -12
  36. package/dist/agent-launch.js.map +1 -1
  37. package/dist/agent-stop.d.ts +40 -2
  38. package/dist/agent-stop.d.ts.map +1 -1
  39. package/dist/agent-stop.js +30 -2
  40. package/dist/agent-stop.js.map +1 -1
  41. package/dist/apply-decide.d.ts +19 -5
  42. package/dist/apply-decide.d.ts.map +1 -1
  43. package/dist/apply-decide.js +38 -9
  44. package/dist/apply-decide.js.map +1 -1
  45. package/dist/apply-merge-action.d.ts +20 -8
  46. package/dist/apply-merge-action.d.ts.map +1 -1
  47. package/dist/apply-merge-action.js +44 -9
  48. package/dist/apply-merge-action.js.map +1 -1
  49. package/dist/apply-persist.d.ts +62 -31
  50. package/dist/apply-persist.d.ts.map +1 -1
  51. package/dist/apply-persist.js +173 -44
  52. package/dist/apply-persist.js.map +1 -1
  53. package/dist/apply-stuck-action.d.ts +151 -0
  54. package/dist/apply-stuck-action.d.ts.map +1 -0
  55. package/dist/apply-stuck-action.js +125 -0
  56. package/dist/apply-stuck-action.js.map +1 -0
  57. package/dist/brand.d.ts +12 -1
  58. package/dist/brand.d.ts.map +1 -1
  59. package/dist/brand.js +2 -1
  60. package/dist/brand.js.map +1 -1
  61. package/dist/buildable-body.d.ts +14 -14
  62. package/dist/buildable-body.js +9 -9
  63. package/dist/claim-cas.d.ts +3 -3
  64. package/dist/claim-cas.js +1 -1
  65. package/dist/claim-cas.js.map +1 -1
  66. package/dist/cli-spinner.d.ts +1 -1
  67. package/dist/cli-spinner.js +1 -1
  68. package/dist/cli.d.ts +10 -0
  69. package/dist/cli.d.ts.map +1 -1
  70. package/dist/cli.js +385 -128
  71. package/dist/cli.js.map +1 -1
  72. package/dist/close-job-template.d.ts +3 -3
  73. package/dist/close-job-template.js +9 -9
  74. package/dist/close-job.d.ts +8 -8
  75. package/dist/close-job.js +25 -25
  76. package/dist/close-job.js.map +1 -1
  77. package/dist/complete.d.ts +9 -6
  78. package/dist/complete.d.ts.map +1 -1
  79. package/dist/complete.js +99 -45
  80. package/dist/complete.js.map +1 -1
  81. package/dist/concurrency.d.ts +1 -1
  82. package/dist/concurrency.js +1 -1
  83. package/dist/config.d.ts +86 -40
  84. package/dist/config.d.ts.map +1 -1
  85. package/dist/config.js +61 -9
  86. package/dist/config.js.map +1 -1
  87. package/dist/continue-branch.d.ts +1 -1
  88. package/dist/continue-branch.d.ts.map +1 -1
  89. package/dist/continue-branch.js +23 -1
  90. package/dist/continue-branch.js.map +1 -1
  91. package/dist/cwd-section.js +1 -1
  92. package/dist/cwd-section.js.map +1 -1
  93. package/dist/decision-engine.d.ts +39 -11
  94. package/dist/decision-engine.d.ts.map +1 -1
  95. package/dist/decision-engine.js +10 -6
  96. package/dist/decision-engine.js.map +1 -1
  97. package/dist/do-autopick.d.ts +6 -6
  98. package/dist/do-autopick.d.ts.map +1 -1
  99. package/dist/do-autopick.js +16 -6
  100. package/dist/do-autopick.js.map +1 -1
  101. package/dist/do-config.d.ts +4 -4
  102. package/dist/do-config.js +3 -3
  103. package/dist/do-config.js.map +1 -1
  104. package/dist/do-remote-auto.d.ts +2 -2
  105. package/dist/do-remote-auto.js +1 -1
  106. package/dist/do.d.ts +74 -81
  107. package/dist/do.d.ts.map +1 -1
  108. package/dist/do.js +439 -50
  109. package/dist/do.js.map +1 -1
  110. package/dist/drop-source.d.ts +2 -2
  111. package/dist/env-config.d.ts.map +1 -1
  112. package/dist/env-config.js +19 -11
  113. package/dist/env-config.js.map +1 -1
  114. package/dist/failure-cause.d.ts +3 -2
  115. package/dist/failure-cause.d.ts.map +1 -1
  116. package/dist/failure-cause.js +28 -1
  117. package/dist/failure-cause.js.map +1 -1
  118. package/dist/format.d.ts +6 -6
  119. package/dist/format.d.ts.map +1 -1
  120. package/dist/format.js +13 -30
  121. package/dist/format.js.map +1 -1
  122. package/dist/frontmatter.d.ts +28 -15
  123. package/dist/frontmatter.d.ts.map +1 -1
  124. package/dist/frontmatter.js +38 -24
  125. package/dist/frontmatter.js.map +1 -1
  126. package/dist/gc.d.ts +65 -6
  127. package/dist/gc.d.ts.map +1 -1
  128. package/dist/gc.js +126 -9
  129. package/dist/gc.js.map +1 -1
  130. package/dist/github.d.ts +14 -0
  131. package/dist/github.d.ts.map +1 -1
  132. package/dist/github.js +73 -0
  133. package/dist/github.js.map +1 -1
  134. package/dist/harness.d.ts +25 -0
  135. package/dist/harness.d.ts.map +1 -1
  136. package/dist/harness.js.map +1 -1
  137. package/dist/index.d.ts +4 -1
  138. package/dist/index.d.ts.map +1 -1
  139. package/dist/index.js +2 -1
  140. package/dist/index.js.map +1 -1
  141. package/dist/install-ci-branch-protection.d.ts +133 -39
  142. package/dist/install-ci-branch-protection.d.ts.map +1 -1
  143. package/dist/install-ci-branch-protection.js +191 -49
  144. package/dist/install-ci-branch-protection.js.map +1 -1
  145. package/dist/install-ci-capabilities/advance-lifecycle.d.ts +1 -1
  146. package/dist/install-ci-capabilities/advance-lifecycle.js +1 -1
  147. package/dist/install-ci-capabilities/close-job.d.ts +1 -1
  148. package/dist/install-ci-capabilities/close-job.js +1 -1
  149. package/dist/install-ci-capabilities/example-noop.d.ts +1 -1
  150. package/dist/install-ci-capabilities/example-noop.js +1 -1
  151. package/dist/install-ci-capabilities/intake.d.ts +2 -2
  152. package/dist/install-ci-capabilities/intake.js +2 -2
  153. package/dist/install-ci-capabilities/verify.d.ts +1 -1
  154. package/dist/install-ci-capabilities/verify.js +1 -1
  155. package/dist/install-ci-core.d.ts +24 -4
  156. package/dist/install-ci-core.d.ts.map +1 -1
  157. package/dist/install-ci-core.js +12 -5
  158. package/dist/install-ci-core.js.map +1 -1
  159. package/dist/install-ci-github.d.ts +33 -1
  160. package/dist/install-ci-github.d.ts.map +1 -1
  161. package/dist/install-ci-github.js +74 -1
  162. package/dist/install-ci-github.js.map +1 -1
  163. package/dist/install-ci.d.ts +1 -1
  164. package/dist/install-ci.js +4 -4
  165. package/dist/install-ci.js.map +1 -1
  166. package/dist/install-skills.d.ts +123 -0
  167. package/dist/install-skills.d.ts.map +1 -0
  168. package/dist/install-skills.js +100 -0
  169. package/dist/install-skills.js.map +1 -0
  170. package/dist/intake-event.d.ts +6 -6
  171. package/dist/intake-event.js +6 -6
  172. package/dist/intake-marker.d.ts +3 -3
  173. package/dist/intake-marker.d.ts.map +1 -1
  174. package/dist/intake-triage.d.ts +1 -1
  175. package/dist/intake-triage.js +2 -2
  176. package/dist/intake-trigger-template.d.ts +8 -8
  177. package/dist/intake-trigger-template.d.ts.map +1 -1
  178. package/dist/intake-trigger-template.js +17 -17
  179. package/dist/intake-trigger-template.js.map +1 -1
  180. package/dist/intake.d.ts +65 -52
  181. package/dist/intake.d.ts.map +1 -1
  182. package/dist/intake.js +92 -76
  183. package/dist/intake.js.map +1 -1
  184. package/dist/integration-core.d.ts +27 -24
  185. package/dist/integration-core.d.ts.map +1 -1
  186. package/dist/integration-core.js +191 -77
  187. package/dist/integration-core.js.map +1 -1
  188. package/dist/integrator.d.ts +1 -1
  189. package/dist/integrator.d.ts.map +1 -1
  190. package/dist/integrator.js +19 -3
  191. package/dist/integrator.js.map +1 -1
  192. package/dist/isolation.d.ts +4 -4
  193. package/dist/isolation.d.ts.map +1 -1
  194. package/dist/isolation.js +9 -0
  195. package/dist/isolation.js.map +1 -1
  196. package/dist/issue-provider.d.ts +4 -4
  197. package/dist/issue-provider.js +1 -1
  198. package/dist/item-lock.d.ts +216 -149
  199. package/dist/item-lock.d.ts.map +1 -1
  200. package/dist/item-lock.js +345 -270
  201. package/dist/item-lock.js.map +1 -1
  202. package/dist/item-path.d.ts +2 -2
  203. package/dist/item-path.js +2 -2
  204. package/dist/ledger-lint.d.ts +9 -9
  205. package/dist/ledger-lint.js +9 -9
  206. package/dist/ledger-read.d.ts +57 -57
  207. package/dist/ledger-read.d.ts.map +1 -1
  208. package/dist/ledger-read.js +24 -24
  209. package/dist/ledger-read.js.map +1 -1
  210. package/dist/ledger-write.d.ts +33 -28
  211. package/dist/ledger-write.d.ts.map +1 -1
  212. package/dist/ledger-write.js +100 -122
  213. package/dist/ledger-write.js.map +1 -1
  214. package/dist/lifecycle-gather.d.ts +18 -1
  215. package/dist/lifecycle-gather.d.ts.map +1 -1
  216. package/dist/lifecycle-gather.js +23 -17
  217. package/dist/lifecycle-gather.js.map +1 -1
  218. package/dist/lifecycle-pools.d.ts +44 -7
  219. package/dist/lifecycle-pools.d.ts.map +1 -1
  220. package/dist/lifecycle-pools.js +27 -7
  221. package/dist/lifecycle-pools.js.map +1 -1
  222. package/dist/merge-question-surfacer.d.ts +18 -4
  223. package/dist/merge-question-surfacer.d.ts.map +1 -1
  224. package/dist/merge-question-surfacer.js +20 -5
  225. package/dist/merge-question-surfacer.js.map +1 -1
  226. package/dist/migrate-stuck-locks.d.ts +129 -0
  227. package/dist/migrate-stuck-locks.d.ts.map +1 -0
  228. package/dist/migrate-stuck-locks.js +355 -0
  229. package/dist/migrate-stuck-locks.js.map +1 -0
  230. package/dist/mint-adr.js +4 -4
  231. package/dist/mirror-pool-scan.d.ts +2 -2
  232. package/dist/mirror-pool-scan.js +3 -3
  233. package/dist/mirror-pool-scan.js.map +1 -1
  234. package/dist/needs-attention.d.ts +304 -27
  235. package/dist/needs-attention.d.ts.map +1 -1
  236. package/dist/needs-attention.js +542 -67
  237. package/dist/needs-attention.js.map +1 -1
  238. package/dist/orphan-sidecar.d.ts +10 -6
  239. package/dist/orphan-sidecar.d.ts.map +1 -1
  240. package/dist/orphan-sidecar.js +35 -2
  241. package/dist/orphan-sidecar.js.map +1 -1
  242. package/dist/pi-harness.d.ts +16 -0
  243. package/dist/pi-harness.d.ts.map +1 -1
  244. package/dist/pi-harness.js +82 -2
  245. package/dist/pi-harness.js.map +1 -1
  246. package/dist/placement.d.ts +8 -8
  247. package/dist/placement.js +3 -3
  248. package/dist/prd-to-spec.d.ts.map +1 -1
  249. package/dist/prd-to-spec.js +9 -5
  250. package/dist/prd-to-spec.js.map +1 -1
  251. package/dist/prompt.d.ts +16 -19
  252. package/dist/prompt.d.ts.map +1 -1
  253. package/dist/prompt.js +17 -19
  254. package/dist/prompt.js.map +1 -1
  255. package/dist/protocol/CLAIM-PROTOCOL.md +17 -10
  256. package/dist/protocol/REVIEW-PROTOCOL.md +4 -1
  257. package/dist/protocol/SURFACE-PROTOCOL.md +16 -2
  258. package/dist/protocol/TASKING-PROTOCOL.md +3 -1
  259. package/dist/protocol/WORK-CONTRACT.md +22 -18
  260. package/dist/protocol/task-template.md +1 -1
  261. package/dist/readiness.d.ts +1 -1
  262. package/dist/reap-branches.d.ts +12 -9
  263. package/dist/reap-branches.d.ts.map +1 -1
  264. package/dist/reap-branches.js +25 -7
  265. package/dist/reap-branches.js.map +1 -1
  266. package/dist/recover-isolated.d.ts +12 -0
  267. package/dist/recover-isolated.d.ts.map +1 -1
  268. package/dist/recover-isolated.js +6 -1
  269. package/dist/recover-isolated.js.map +1 -1
  270. package/dist/repo-config.d.ts +23 -2
  271. package/dist/repo-config.d.ts.map +1 -1
  272. package/dist/repo-config.js +64 -18
  273. package/dist/repo-config.js.map +1 -1
  274. package/dist/repo-mirror.d.ts.map +1 -1
  275. package/dist/repo-mirror.js +18 -2
  276. package/dist/repo-mirror.js.map +1 -1
  277. package/dist/review-gate.d.ts +3 -3
  278. package/dist/review-gate.d.ts.map +1 -1
  279. package/dist/review-gate.js +11 -10
  280. package/dist/review-gate.js.map +1 -1
  281. package/dist/review-verdict.d.ts +2 -2
  282. package/dist/review-verdict.d.ts.map +1 -1
  283. package/dist/review-verdict.js +2 -2
  284. package/dist/review-verdict.js.map +1 -1
  285. package/dist/run.d.ts +2 -2
  286. package/dist/run.d.ts.map +1 -1
  287. package/dist/run.js +58 -23
  288. package/dist/run.js.map +1 -1
  289. package/dist/scan.d.ts +26 -17
  290. package/dist/scan.d.ts.map +1 -1
  291. package/dist/scan.js +29 -15
  292. package/dist/scan.js.map +1 -1
  293. package/dist/select-order.d.ts +1 -1
  294. package/dist/select-priority.d.ts +14 -14
  295. package/dist/select-priority.d.ts.map +1 -1
  296. package/dist/select-priority.js +5 -5
  297. package/dist/select-priority.js.map +1 -1
  298. package/dist/sidecar-apply.js +1 -1
  299. package/dist/sidecar-apply.js.map +1 -1
  300. package/dist/sidecar.d.ts +47 -12
  301. package/dist/sidecar.d.ts.map +1 -1
  302. package/dist/sidecar.js +84 -4
  303. package/dist/sidecar.js.map +1 -1
  304. package/dist/skills/answer-questions/SKILL.md +89 -0
  305. package/dist/skills/capture-signal/SKILL.md +52 -0
  306. package/dist/skills/convert-from-prd-to-spec/SKILL.md +90 -0
  307. package/dist/skills/drive-tasks/SKILL.md +218 -0
  308. package/dist/skills/from-idea/SKILL.md +83 -0
  309. package/dist/skills/merge-prs/SKILL.md +70 -0
  310. package/dist/skills/orchestrate/SKILL.md +101 -0
  311. package/dist/skills/promote/SKILL.md +35 -0
  312. package/dist/skills/review/SKILL.md +16 -0
  313. package/dist/skills/setup/SKILL.md +258 -0
  314. package/dist/skills/setup/protocol/ADR-FORMAT.md +47 -0
  315. package/dist/skills/setup/protocol/CLAIM-PROTOCOL.md +224 -0
  316. package/dist/skills/setup/protocol/REVIEW-PROTOCOL.md +122 -0
  317. package/dist/skills/setup/protocol/SURFACE-PROTOCOL.md +135 -0
  318. package/dist/skills/setup/protocol/TASKING-PROTOCOL.md +124 -0
  319. package/dist/skills/setup/protocol/WORK-CONTRACT.md +280 -0
  320. package/dist/skills/setup/protocol/spec-template.md +71 -0
  321. package/dist/skills/setup/protocol/task-template.md +65 -0
  322. package/dist/skills/surface-questions/SKILL.md +16 -0
  323. package/dist/skills/to-spec/SKILL.md +34 -0
  324. package/dist/skills/to-task/SKILL.md +19 -0
  325. package/dist/skills/triage-observations/SKILL.md +78 -0
  326. package/dist/skills/work/SKILL.md +51 -0
  327. package/dist/slug-namespace.d.ts +6 -6
  328. package/dist/slug-namespace.js +8 -8
  329. package/dist/slug-namespace.js.map +1 -1
  330. package/dist/spec-complete.d.ts.map +1 -1
  331. package/dist/spec-complete.js +4 -5
  332. package/dist/spec-complete.js.map +1 -1
  333. package/dist/start.d.ts +1 -1
  334. package/dist/start.d.ts.map +1 -1
  335. package/dist/start.js +54 -60
  336. package/dist/start.js.map +1 -1
  337. package/dist/status.d.ts +3 -3
  338. package/dist/status.js +4 -4
  339. package/dist/status.js.map +1 -1
  340. package/dist/surface-gate.d.ts +2 -2
  341. package/dist/surface-gate.d.ts.map +1 -1
  342. package/dist/surface-gate.js +10 -3
  343. package/dist/surface-gate.js.map +1 -1
  344. package/dist/surface-persist.d.ts +2 -2
  345. package/dist/surface-persist.d.ts.map +1 -1
  346. package/dist/surface-persist.js +1 -1
  347. package/dist/surface-persist.js.map +1 -1
  348. package/dist/tasker-review-loop.d.ts +11 -10
  349. package/dist/tasker-review-loop.d.ts.map +1 -1
  350. package/dist/tasker-review-loop.js +8 -8
  351. package/dist/tasker-review-loop.js.map +1 -1
  352. package/dist/tasking-eligibility.d.ts +21 -21
  353. package/dist/tasking-eligibility.d.ts.map +1 -1
  354. package/dist/tasking-eligibility.js +10 -10
  355. package/dist/tasking-lock.d.ts +10 -10
  356. package/dist/tasking-lock.d.ts.map +1 -1
  357. package/dist/tasking-lock.js +69 -49
  358. package/dist/tasking-lock.js.map +1 -1
  359. package/dist/tasking.d.ts +73 -39
  360. package/dist/tasking.d.ts.map +1 -1
  361. package/dist/tasking.js +309 -95
  362. package/dist/tasking.js.map +1 -1
  363. package/dist/triage-gate.d.ts +1 -1
  364. package/dist/triage-persist.d.ts +15 -11
  365. package/dist/triage-persist.d.ts.map +1 -1
  366. package/dist/triage-persist.js +48 -18
  367. package/dist/triage-persist.js.map +1 -1
  368. package/dist/vendor/incur/agents.d.ts +58 -0
  369. package/dist/vendor/incur/agents.d.ts.map +1 -0
  370. package/dist/vendor/incur/agents.js +343 -0
  371. package/dist/vendor/incur/agents.js.map +1 -0
  372. package/dist/verify-workflow-template.d.ts +1 -1
  373. package/dist/verify-workflow-template.js +3 -3
  374. package/dist/watch-session.d.ts +11 -3
  375. package/dist/watch-session.d.ts.map +1 -1
  376. package/dist/watch-session.js +94 -7
  377. package/dist/watch-session.js.map +1 -1
  378. package/dist/work-layout.d.ts +15 -9
  379. package/dist/work-layout.d.ts.map +1 -1
  380. package/dist/work-layout.js +14 -9
  381. package/dist/work-layout.js.map +1 -1
  382. package/dist/workspace.d.ts +2 -2
  383. package/package.json +2 -2
  384. package/src/advance-ci-template.ts +4 -4
  385. package/src/advance-classify.ts +5 -5
  386. package/src/advance-drivers.ts +26 -13
  387. package/src/advance-isolated.ts +3 -3
  388. package/src/advance-lifecycle-template.ts +98 -13
  389. package/src/advance-loop-driver.ts +3 -3
  390. package/src/advance-treeless-publish.ts +46 -1
  391. package/src/advance.ts +495 -115
  392. package/src/advancing-lock.ts +102 -7
  393. package/src/agent-launch.ts +37 -12
  394. package/src/agent-stop.ts +60 -2
  395. package/src/apply-decide.ts +38 -9
  396. package/src/apply-merge-action.ts +49 -11
  397. package/src/apply-persist.ts +236 -62
  398. package/src/apply-stuck-action.ts +260 -0
  399. package/src/brand.ts +14 -2
  400. package/src/buildable-body.ts +14 -14
  401. package/src/claim-cas.ts +4 -4
  402. package/src/cli-spinner.ts +1 -1
  403. package/src/cli.ts +472 -141
  404. package/src/close-job-template.ts +9 -9
  405. package/src/close-job.ts +26 -26
  406. package/src/complete.ts +121 -63
  407. package/src/concurrency.ts +1 -1
  408. package/src/config.ts +143 -49
  409. package/src/continue-branch.ts +23 -1
  410. package/src/cwd-section.ts +1 -1
  411. package/src/decision-engine.ts +57 -19
  412. package/src/do-autopick.ts +21 -10
  413. package/src/do-config.ts +7 -7
  414. package/src/do-remote-auto.ts +2 -2
  415. package/src/do.ts +558 -85
  416. package/src/drop-source.ts +2 -2
  417. package/src/env-config.ts +19 -11
  418. package/src/failure-cause.ts +30 -1
  419. package/src/format.ts +13 -33
  420. package/src/frontmatter.ts +55 -35
  421. package/src/gc.ts +172 -9
  422. package/src/github.ts +78 -0
  423. package/src/harness.ts +25 -0
  424. package/src/index.ts +10 -0
  425. package/src/install-ci-branch-protection.ts +283 -58
  426. package/src/install-ci-capabilities/advance-lifecycle.ts +1 -1
  427. package/src/install-ci-capabilities/close-job.ts +1 -1
  428. package/src/install-ci-capabilities/example-noop.ts +1 -1
  429. package/src/install-ci-capabilities/intake.ts +2 -2
  430. package/src/install-ci-capabilities/verify.ts +1 -1
  431. package/src/install-ci-core.ts +34 -7
  432. package/src/install-ci-github.ts +87 -1
  433. package/src/install-ci.ts +4 -4
  434. package/src/install-skills.ts +166 -0
  435. package/src/intake-event.ts +6 -6
  436. package/src/intake-marker.ts +3 -3
  437. package/src/intake-triage.ts +2 -2
  438. package/src/intake-trigger-template.ts +18 -18
  439. package/src/intake.ts +138 -103
  440. package/src/integration-core.ts +234 -100
  441. package/src/integrator.ts +22 -9
  442. package/src/isolation.ts +13 -4
  443. package/src/issue-provider.ts +4 -4
  444. package/src/item-lock.ts +505 -361
  445. package/src/item-path.ts +2 -2
  446. package/src/ledger-lint.ts +9 -9
  447. package/src/ledger-read.ts +81 -81
  448. package/src/ledger-write.ts +137 -152
  449. package/src/lifecycle-gather.ts +45 -22
  450. package/src/lifecycle-pools.ts +71 -13
  451. package/src/merge-question-surfacer.ts +32 -8
  452. package/src/migrate-stuck-locks.ts +451 -0
  453. package/src/mint-adr.ts +4 -4
  454. package/src/mirror-pool-scan.ts +5 -5
  455. package/src/needs-attention.ts +877 -104
  456. package/src/orphan-sidecar.ts +49 -8
  457. package/src/pi-harness.ts +82 -2
  458. package/src/placement.ts +8 -8
  459. package/src/prd-to-spec.ts +13 -5
  460. package/src/prompt.ts +20 -25
  461. package/src/readiness.ts +1 -1
  462. package/src/reap-branches.ts +38 -14
  463. package/src/recover-isolated.ts +18 -1
  464. package/src/repo-config.ts +66 -17
  465. package/src/repo-mirror.ts +23 -1
  466. package/src/review-gate.ts +12 -11
  467. package/src/review-verdict.ts +3 -3
  468. package/src/run.ts +69 -23
  469. package/src/scan.ts +36 -22
  470. package/src/select-order.ts +1 -1
  471. package/src/select-priority.ts +15 -15
  472. package/src/sidecar-apply.ts +1 -1
  473. package/src/sidecar.ts +141 -14
  474. package/src/slug-namespace.ts +10 -10
  475. package/src/spec-complete.ts +4 -5
  476. package/src/start.ts +57 -63
  477. package/src/status.ts +7 -7
  478. package/src/surface-gate.ts +12 -5
  479. package/src/surface-persist.ts +3 -3
  480. package/src/tasker-review-loop.ts +18 -17
  481. package/src/tasking-eligibility.ts +21 -21
  482. package/src/tasking-lock.ts +75 -60
  483. package/src/tasking.ts +381 -135
  484. package/src/triage-gate.ts +1 -1
  485. package/src/triage-persist.ts +71 -27
  486. package/src/vendor/incur/LICENSE +21 -0
  487. package/src/vendor/incur/README.md +19 -0
  488. package/src/vendor/incur/agents.ts +392 -0
  489. package/src/verify-workflow-template.ts +3 -3
  490. package/src/watch-session.ts +102 -7
  491. package/src/work-layout.ts +14 -9
  492. package/src/workspace.ts +2 -2
package/src/github.ts CHANGED
@@ -209,6 +209,26 @@ export class GitHubProvider implements ReviewProvider {
209
209
  return this.parseOpened(input, first);
210
210
  }
211
211
 
212
+ // PR ALREADY EXISTS (task `committed-recovery-completes-existing-pr`): a
213
+ // re-pushed branch whose PR is still open makes `gh pr create` fail with
214
+ // "a pull request for branch ... already exists". This is NOT an outage and
215
+ // NOT a missing/unauth `gh` — retrying is pointless (it fails identically)
216
+ // and degrading to push-only would DROP the refreshed body + the Gate-2
217
+ // review comment on a PR that genuinely exists (the committed-recovery re-run
218
+ // case). Instead RESOLVE the existing PR, UPDATE its title/body to match what
219
+ // this run would have created, and return it as `opened` so the caller's
220
+ // review-comment path fires normally. NEVER throws; a failed edit still
221
+ // returns the resolved PR (the comment is the more important audit trail).
222
+ if (prAlreadyExists(first)) {
223
+ const existing = this.updateExistingRequest(input);
224
+ if (existing !== undefined) {
225
+ return existing;
226
+ }
227
+ // Could not resolve the existing PR's url (e.g. a transient `gh pr view`
228
+ // failure) — fall through to the degrade path rather than crashing; the
229
+ // branch is already pushed, so the work is safe.
230
+ }
231
+
212
232
  // Failed once — distinguish DETERMINISTIC (missing/unauth) from a TRANSIENT
213
233
  // outage by an availability probe. Missing/unauth ⇒ degrade now (no retry).
214
234
  // Thread the FAILED first attempt so the degrade surfaces the REAL `gh` cause
@@ -246,6 +266,47 @@ export class GitHubProvider implements ReviewProvider {
246
266
  return this.parseOpened(input, attempt.value);
247
267
  }
248
268
 
269
+ /**
270
+ * The PR for this branch ALREADY EXISTS (task
271
+ * `committed-recovery-completes-existing-pr`): resolve its url, REFRESH its
272
+ * title/body via `gh pr edit` (so a committed-recovery re-run's synthesised
273
+ * title + task-pointer body replace the earlier run's blank `--fill` ones),
274
+ * and return it as `{opened: true, url}` so the caller's review-comment path
275
+ * fires on the existing PR. Returns `undefined` when the url cannot be
276
+ * resolved (the caller then falls through to the degrade path). The `gh pr
277
+ * edit` is best-effort: a failed edit still returns the resolved PR (posting
278
+ * the review comment matters more than refreshing the body), and it is only
279
+ * attempted when this run actually has explicit title/body to set (else the
280
+ * existing PR's content is left untouched).
281
+ */
282
+ private updateExistingRequest(
283
+ input: OpenRequestInput,
284
+ ): OpenRequestResult | undefined {
285
+ const url = this.resolvePrUrlForBranch(input.branch, input.cwd, input.env);
286
+ if (url === undefined) {
287
+ return undefined;
288
+ }
289
+ // Refresh the PR body/title only when this run supplies them (a committed-
290
+ // recovery re-run does; an unset run leaves the existing content alone).
291
+ if (input.title !== undefined || input.body !== undefined) {
292
+ const editArgs = ['pr', 'edit', url];
293
+ if (input.title !== undefined) {
294
+ editArgs.push('--title', input.title);
295
+ }
296
+ if (input.body !== undefined) {
297
+ editArgs.push('--body', input.body);
298
+ }
299
+ // Best-effort: ignore the result. A failed edit must not lose the PR (or
300
+ // the upcoming review comment) — NEVER throws (runGh swallows spawn errors).
301
+ this.runGh(editArgs, input.cwd, input.env);
302
+ }
303
+ return {
304
+ opened: true,
305
+ url,
306
+ instruction: `Updated the existing GitHub PR for ${input.branch}: ${url}`,
307
+ };
308
+ }
309
+
249
310
  /** Map a successful `gh pr create` RunResult to an OpenRequestResult. */
250
311
  private parseOpened(
251
312
  input: OpenRequestInput,
@@ -457,6 +518,23 @@ export function prCreateContentArgs(input: {
457
518
  return ['--title', input.title ?? '', '--body', input.body ?? ''];
458
519
  }
459
520
 
521
+ /**
522
+ * Does a FAILED `gh pr create` result mean "a PR for this branch already
523
+ * exists" (task `committed-recovery-completes-existing-pr`)? `gh` exits non-zero
524
+ * with a message like `a pull request for branch "work/task-x" into branch
525
+ * "main" already exists: https://github.com/.../pull/357`. We match on the
526
+ * stable "already exists" phrase in `gh`'s stderr/stdout so a re-pushed branch
527
+ * whose PR is still open is treated as an UPDATE, not a transient outage. A
528
+ * missing `gh` (`undefined`) or a success is not this case.
529
+ */
530
+ function prAlreadyExists(result: RunResult | undefined): boolean {
531
+ if (result === undefined || result.status === 0) {
532
+ return false;
533
+ }
534
+ const text = `${result.stderr ?? ''}\n${result.stdout ?? ''}`.toLowerCase();
535
+ return text.includes('already exists');
536
+ }
537
+
460
538
  /**
461
539
  * Parse the PR URL `gh pr create` prints to stdout. `gh` prints the PR URL as a
462
540
  * line (often the only/last line); we pick the first GitHub PR URL we find. Any
package/src/harness.ts CHANGED
@@ -61,6 +61,21 @@ export interface LaunchInput {
61
61
  * `undefined` ⇒ the pi adapter falls back to a generated default for its cwd.
62
62
  */
63
63
  session?: string;
64
+ /**
65
+ * **Optional agent-session DEADLINE** (absolute epoch-ms wall-clock timestamp)
66
+ * for the ASYNC {@link Harness} launch (spec
67
+ * `graceful-pre-timeout-wip-checkpoint`). When set AND the future arrives
68
+ * before the child exits, the harness sends SIGTERM (a ~10s grace, then
69
+ * SIGKILL) and resolves the {@link LaunchResult} with `timedOut: true` — so
70
+ * the caller can route the run as a CHECKPOINT (save WIP + auto-continue /
71
+ * surface) rather than a generic agent-failure. Ignored on the synchronous
72
+ * {@link Harness.launch} path (`spawnSync` cannot be interrupted from the
73
+ * same event loop; the async path is where CI's `--watch` legs run and where
74
+ * the checkpoint discipline lives). Absent ⇒ no deadline (byte-for-byte the
75
+ * pre-task behaviour: a run finishing before its deadline is unchanged; on
76
+ * `exit` the timer is cleared).
77
+ */
78
+ deadlineMs?: number;
64
79
  env?: NodeJS.ProcessEnv;
65
80
  }
66
81
 
@@ -170,6 +185,16 @@ export interface LaunchResult {
170
185
  record: HarnessRecord;
171
186
  /** Failure detail when `ok` is false (the stderr/failure channel). */
172
187
  detail?: string;
188
+ /**
189
+ * **True iff the launch was stopped by the dorfl-internal DEADLINE**
190
+ * ({@link LaunchInput.deadlineMs}) rather than exiting on its own (spec
191
+ * `graceful-pre-timeout-wip-checkpoint`). Distinct from `ok` (a deadline
192
+ * stop is neither a success nor a generic failure — it is a CHECKPOINT the
193
+ * caller routes through the save+auto-continue/surface path). Absent/false
194
+ * when the child exited before the deadline, so a run that finishes
195
+ * normally is byte-for-byte unchanged.
196
+ */
197
+ timedOut?: boolean;
173
198
  /**
174
199
  * The agent's final ANSWER (task `harness-agent-output`): the concatenated
175
200
  * `text` of the LAST assistant turn the invocation produced. This is the
package/src/index.ts CHANGED
@@ -26,6 +26,8 @@ export type {
26
26
  } from './repo-config.js';
27
27
  export {
28
28
  REPO_CONFIG_FILENAME,
29
+ REPO_CONFIG_FILENAME_LEGACY,
30
+ resolveRepoConfigPath,
29
31
  REPO_ALLOWED_KEYS,
30
32
  REPO_REJECTED_KEYS,
31
33
  repoConfigPath,
@@ -783,3 +785,11 @@ export type {
783
785
  InstallCIResult,
784
786
  } from './install-ci.js';
785
787
  export {installCI, runWizard} from './install-ci.js';
788
+
789
+ export type {
790
+ InstallSkillsOptions,
791
+ InstallSkillsResult,
792
+ InstalledAgent,
793
+ } from './install-skills.js';
794
+ export {installSkills, resolveSkillsSourceDir} from './install-skills.js';
795
+ export type {Agent} from './vendor/incur/agents.js';
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Tier-1 GitHub branch-protection STEP for `install-ci` (prd
2
+ * Tier-1 GitHub branch-protection STEP for `install-ci` (spec
3
3
  * `land-time-reverify-and-parallel-merge-ceiling`, task
4
4
  * `install-ci-tier1-branch-protection`; Story 11). Closes the propose-mode
5
5
  * PR-merge-time drift window on a GitHub arbiter: a required `verify` check + a
@@ -34,28 +34,44 @@
34
34
  * change can flip it knowingly; the spec calls this "pick the cheaper of the
35
35
  * two and record the choice."
36
36
  *
37
- * DEADLOCK GUARDa NEVER-RUN required check would block every merge (GitHub
38
- * treats an unreported required check as pending). install-ci ORDERS the steps
39
- * to avoid that:
37
+ * DEFAULT BRANCHNOT hardcoded to `main`. The GitHub adapter resolves the
38
+ * repo's real default branch ({@link CIProviderContext.getDefaultBranch}, via
39
+ * `gh repo view --json defaultBranchRef`); the orchestrator threads it into
40
+ * BOTH the classic PUT and the printed `gh api` fallback so a `master`-defaulted
41
+ * (or otherwise-renamed) repo is protected on the correct branch instead of
42
+ * 404-ing a hardcoded `main`. The lookup falls back to {@link
43
+ * DEFAULT_PROTECTED_BRANCH} (`main`) only when it fails/empties, and that
44
+ * fallback is LOGGED so it is visible. An explicit `branch` option still wins
45
+ * over auto-detection (a repo whose protected branch is not its default).
40
46
  *
41
- * 1. write the verify workflow artifact (the `verify.yml` whose job is named
42
- * exactly {@link VERIFY_CHECK_CONTEXT}); the human commits + pushes it to
43
- * `main` so the workflow file lands BEFORE the next PR;
44
- * 2. THEN (this step) set the branch-protection rule.
47
+ * DEADLOCK GUARD a required check that has NEVER reported blocks every merge
48
+ * (GitHub treats an unreported required check as pending), so a PR opened before
49
+ * `verify.yml` first ran would deadlock. The guard is a RUNTIME MECHANISM, not a
50
+ * log line: the required-`verify` check is enforced through a branch RULESET
51
+ * ({@link buildBranchProtectionRuleset}, `POST /repos/{owner}/{repo}/rulesets`)
52
+ * whose `required_status_checks` rule carries `do_not_enforce_on_create: true` —
53
+ * GitHub's native "require this check, but do not fail refs created before the
54
+ * rule / before the check first ran" toggle. The ruleset targets the resolved
55
+ * default branch via `conditions.ref_name`.
45
56
  *
46
- * Because the verify workflow uses `on: pull_request`, every PR opened AFTER
47
- * `verify.yml` is on `main` triggers the workflow and produces the required
48
- * `verify` check the protection never deadlocks new PRs. The only edge case
49
- * is an IN-FLIGHT PR opened BEFORE `verify.yml` landed on `main`: it has no
50
- * `verify` check waiting; installCI prints exactly that re-trigger remediation
51
- * in the success log. We chose this "run-the-check-once-by-construction-of-the-
52
- * trigger" ordering over the ruleset `do_not_enforce_on_create` toggle because
53
- * (a) one PUT against the existing branch-protection endpoint is simpler than
54
- * minting a ruleset shape this spec otherwise does not need, AND (b) the
55
- * `merge_queue` Tier-2 forward seam already lives in the verify workflow's
56
- * `on:` trigger (so the ruleset seam is not needed here either it is the
57
- * follow-on spec's lever). Trade-off RECORDED so a future merge-queue task can
58
- * flip to rulesets knowingly without re-deciding why we did not now.
57
+ * WHY RULESET FOR THE GUARD BUT CLASSIC PUT FOR THE BASE (nit-a preserved).
58
+ * The base protection stays a single classic PUT
59
+ * ({@link buildBranchProtectionSpec}: `strict: true` = "require branches up to
60
+ * date before merging") because that endpoint is the simplest way to express
61
+ * up-to-date-ness and nit-a ratified the classic-PUT choice. ONLY the deadlock-
62
+ * prone piece — the required-status-check gate moves to a ruleset, because the
63
+ * `do_not_enforce_on_create` create-exemption exists ONLY on rulesets, not on
64
+ * the classic `required_status_checks` object. Keeping the required check in the
65
+ * classic PUT AND adding the ruleset would double-enforce it and NULLIFY the
66
+ * exemption (the classic copy has no exemption), so the required check lives in
67
+ * the ruleset ALONE; the classic PUT keeps `strict` with an EMPTY `checks`
68
+ * array (valid: "require up to date", no named required check at the classic
69
+ * layer). This is exactly "only the deadlock-guard aspect needs the ruleset"
70
+ * not a full base-protection migration. Chosen over the pre-run mechanism
71
+ * (`gh workflow run` + wait) because `writeArtifacts` writes `verify.yml`
72
+ * LOCALLY and does NOT push, so at install time the workflow is not yet on the
73
+ * default branch and a pre-run has nothing to dispatch. The ruleset toggle needs
74
+ * no pushed workflow and no wait, so it is the only viable runtime guard here.
59
75
  */
60
76
 
61
77
  import {VERIFY_CHECK_CONTEXT} from './verify-workflow-template.js';
@@ -64,15 +80,17 @@ import type {CIProviderContext} from './install-ci-core.js';
64
80
  export {VERIFY_CHECK_CONTEXT};
65
81
 
66
82
  /**
67
- * The branch-protection request body the GitHub adapter PUTs at
83
+ * The BASE branch-protection request body the GitHub adapter PUTs at
68
84
  * `/repos/{owner}/{repo}/branches/{branch}/protection`. Shape mirrors the REST
69
85
  * docs (the GitHub PUT REQUIRES `enforce_admins`, `required_pull_request_reviews`,
70
86
  * and `restrictions` to be present; `null` for "not configured"). We set only
71
- * the two fields the spec names the required `${VERIFY_CHECK_CONTEXT}` check
72
- * AND `strict: true` (= "require branches up to date before merging") and
73
- * leave the others `null` so install-ci does not silently impose unrelated
74
- * gates (reviews, admin enforcement, push restrictions) the user did not opt
75
- * into.
87
+ * `strict: true` (= "require branches up to date before merging") with an EMPTY
88
+ * `checks` array the required `${VERIFY_CHECK_CONTEXT}` check is NOT here; it
89
+ * lives in the deadlock-guard RULESET ({@link buildBranchProtectionRuleset}) so
90
+ * its `do_not_enforce_on_create` create-exemption is meaningful (see module
91
+ * header). The other required fields stay `null` so install-ci does not silently
92
+ * impose unrelated gates (reviews, admin enforcement, push restrictions) the
93
+ * user did not opt into.
76
94
  */
77
95
  export interface BranchProtectionSpec {
78
96
  required_status_checks: {
@@ -85,16 +103,15 @@ export interface BranchProtectionSpec {
85
103
  }
86
104
 
87
105
  /**
88
- * Build the Tier-1 branch-protection spec the GitHub adapter PUTs. The required
89
- * `context` is the SAME constant the emitted verify workflow names its job
90
- * after ({@link VERIFY_CHECK_CONTEXT}) by construction, not by hand-typed
91
- * agreement, so the two cannot drift.
106
+ * Build the Tier-1 BASE branch-protection spec the GitHub adapter PUTs
107
+ * (`strict: true`, no named required check — the required check is the ruleset's
108
+ * job, see {@link buildBranchProtectionRuleset} and the module header).
92
109
  */
93
110
  export function buildBranchProtectionSpec(): BranchProtectionSpec {
94
111
  return {
95
112
  required_status_checks: {
96
113
  strict: true,
97
- checks: [{context: VERIFY_CHECK_CONTEXT}],
114
+ checks: [],
98
115
  },
99
116
  enforce_admins: null,
100
117
  required_pull_request_reviews: null,
@@ -102,6 +119,70 @@ export function buildBranchProtectionSpec(): BranchProtectionSpec {
102
119
  };
103
120
  }
104
121
 
122
+ /** The name the deadlock-guard ruleset is created under (stable/idempotent-ish). */
123
+ export const BRANCH_PROTECTION_RULESET_NAME = 'dorfl-verify-required';
124
+
125
+ /**
126
+ * The deadlock-guard RULESET body the GitHub adapter POSTs at
127
+ * `/repos/{owner}/{repo}/rulesets`. It carries the required-`${VERIFY_CHECK_CONTEXT}`
128
+ * status-check rule with `do_not_enforce_on_create: true` — GitHub's native
129
+ * "require this check, but do not fail refs that predate the rule / the check's
130
+ * first run" toggle (the runtime deadlock guard). `enforcement: 'active'` +
131
+ * `conditions.ref_name` scope it to the resolved default branch. The required
132
+ * `context` is the SAME {@link VERIFY_CHECK_CONTEXT} constant the emitted verify
133
+ * workflow names its job after — by construction, so the two cannot drift.
134
+ */
135
+ export interface BranchProtectionRuleset {
136
+ name: string;
137
+ target: 'branch';
138
+ enforcement: 'active';
139
+ conditions: {
140
+ ref_name: {
141
+ include: string[];
142
+ exclude: string[];
143
+ };
144
+ };
145
+ rules: {
146
+ type: 'required_status_checks';
147
+ parameters: {
148
+ strict_required_status_checks_policy: boolean;
149
+ do_not_enforce_on_create: true;
150
+ required_status_checks: {context: string}[];
151
+ };
152
+ }[];
153
+ }
154
+
155
+ /**
156
+ * Build the deadlock-guard ruleset for `branch` (the resolved default branch).
157
+ * The `ref_name` include uses the exact-ref form (`refs/heads/<branch>`) so the
158
+ * rule targets only that branch. `do_not_enforce_on_create: true` is the guard.
159
+ */
160
+ export function buildBranchProtectionRuleset(
161
+ branch: string = DEFAULT_PROTECTED_BRANCH,
162
+ ): BranchProtectionRuleset {
163
+ return {
164
+ name: BRANCH_PROTECTION_RULESET_NAME,
165
+ target: 'branch',
166
+ enforcement: 'active',
167
+ conditions: {
168
+ ref_name: {
169
+ include: [`refs/heads/${branch}`],
170
+ exclude: [],
171
+ },
172
+ },
173
+ rules: [
174
+ {
175
+ type: 'required_status_checks',
176
+ parameters: {
177
+ strict_required_status_checks_policy: true,
178
+ do_not_enforce_on_create: true,
179
+ required_status_checks: [{context: VERIFY_CHECK_CONTEXT}],
180
+ },
181
+ },
182
+ ],
183
+ };
184
+ }
185
+
105
186
  /**
106
187
  * The repo's default branch the protection rule targets (the rule the spec
107
188
  * names: protect `main` so a propose-mode PR cannot be merged stale). Exposed
@@ -132,6 +213,26 @@ export function formatManualBranchProtectionCommand(
132
213
  );
133
214
  }
134
215
 
216
+ /**
217
+ * The exact `gh api` command the user runs themselves to create the deadlock-
218
+ * guard RULESET when install-ci cannot auto-configure (no admin scope). Quoted
219
+ * body is the same {@link BranchProtectionRuleset} the auto path POSTs, so
220
+ * reproducing the call by copy-paste is byte-equivalent to a successful auto
221
+ * run. Pure string, no I/O.
222
+ */
223
+ export function formatManualBranchRulesetCommand(
224
+ repo: string,
225
+ branch: string = DEFAULT_PROTECTED_BRANCH,
226
+ ): string {
227
+ const body = JSON.stringify(buildBranchProtectionRuleset(branch));
228
+ return (
229
+ `echo '${body}' | gh api -X POST ` +
230
+ `-H "Accept: application/vnd.github+json" ` +
231
+ `repos/${repo}/rulesets ` +
232
+ `--input -`
233
+ );
234
+ }
235
+
135
236
  /** Options for {@link installCIBranchProtectionStep}. */
136
237
  export interface BranchProtectionStepOptions {
137
238
  /** The CI-provider seam (GitHub adapter in production; stub in tests). */
@@ -140,7 +241,13 @@ export interface BranchProtectionStepOptions {
140
241
  fake?: boolean;
141
242
  /** Sink for human-facing progress lines. */
142
243
  log: (line: string) => void;
143
- /** The branch the rule targets (default `main`). */
244
+ /**
245
+ * Explicitly override the branch the rule targets. When OMITTED, the step
246
+ * auto-detects the repo's default branch via
247
+ * {@link CIProviderContext.getDefaultBranch}, falling back to
248
+ * {@link DEFAULT_PROTECTED_BRANCH} (`main`) and logging the fallback. An
249
+ * explicit value always wins over auto-detection.
250
+ */
144
251
  branch?: string;
145
252
  }
146
253
 
@@ -168,41 +275,105 @@ export interface BranchProtectionStepResult {
168
275
  error?: string;
169
276
  /** The branch the step targeted (echoed for tests / logs). */
170
277
  branch: string;
278
+ /**
279
+ * Whether the branch was AUTO-DETECTED (`true`) or came from an explicit
280
+ * `branch` option / the `main` fallback (`false`). Echoed for tests / logs.
281
+ */
282
+ branchAutoDetected?: boolean;
283
+ /**
284
+ * The deadlock-guard RULESET outcome (only on the admin auto path):
285
+ * - `set` — the ruleset POST succeeded;
286
+ * - `failed` — the ruleset POST was rejected (detail in `rulesetError`);
287
+ * - `skipped-no-seam` — the provider does not implement the ruleset seam.
288
+ * Absent on the non-admin / skipped paths.
289
+ */
290
+ rulesetStatus?: 'set' | 'failed' | 'skipped-no-seam';
291
+ /** The ruleset failure detail when `rulesetStatus === 'failed'`. */
292
+ rulesetError?: string;
293
+ }
294
+
295
+ /**
296
+ * Resolve the branch the protection targets. An EXPLICIT `branch` option always
297
+ * wins; otherwise auto-detect the repo's default branch via
298
+ * {@link CIProviderContext.getDefaultBranch}, falling back to `main` (LOGGED)
299
+ * when the lookup fails/empties. Returns the branch + whether it was
300
+ * auto-detected (for the result / log lines).
301
+ */
302
+ async function resolveTargetBranch(
303
+ ctx: CIProviderContext,
304
+ explicit: string | undefined,
305
+ log: (line: string) => void,
306
+ ): Promise<{branch: string; autoDetected: boolean}> {
307
+ if (explicit !== undefined) {
308
+ return {branch: explicit, autoDetected: false};
309
+ }
310
+ const detected = ctx.getDefaultBranch
311
+ ? await ctx.getDefaultBranch().catch(() => undefined)
312
+ : undefined;
313
+ if (detected) {
314
+ return {branch: detected, autoDetected: true};
315
+ }
316
+ log(
317
+ `branch protection: could not detect the default branch; ` +
318
+ `falling back to \`${DEFAULT_PROTECTED_BRANCH}\`.`,
319
+ );
320
+ return {branch: DEFAULT_PROTECTED_BRANCH, autoDetected: false};
171
321
  }
172
322
 
173
323
  /**
174
324
  * The orchestrator install-ci calls AFTER artifacts are written + secrets are
175
- * orchestrated: detect admin scope (cheapest path: {@link
176
- * CIProviderContext.getRepoAdminScope}), then EITHER call
177
- * {@link CIProviderContext.setBranchProtection} (admin) OR print the exact
178
- * ready-to-run `gh api` command + the one-liner manual fallback (non-admin).
325
+ * orchestrated:
326
+ *
327
+ * 1. RESOLVE the target branch (explicit option > auto-detected default
328
+ * branch > `main` fallback), so the PUT + printed fallback target the real
329
+ * default branch (see module header, "DEFAULT BRANCH");
330
+ * 2. detect admin scope (cheapest path: {@link
331
+ * CIProviderContext.getRepoAdminScope});
332
+ * 3. ADMIN: PUT the base protection ({@link
333
+ * CIProviderContext.setBranchProtection}) AND create the deadlock-guard
334
+ * ruleset ({@link CIProviderContext.setBranchRuleset}); NON-ADMIN: print
335
+ * the exact ready-to-run `gh api` commands (PUT + ruleset POST) + the
336
+ * manual UI fallback.
179
337
  *
180
- * Never throws — a `setBranchProtection` rejection is reported as `failed` so
181
- * install-ci's later steps still run, and the user sees both the failure detail
182
- * AND the manual command to retry by hand.
338
+ * Never throws — a `setBranchProtection` rejection is reported as `failed`, a
339
+ * `setBranchRuleset` rejection as `rulesetStatus: 'failed'`, so install-ci's
340
+ * later steps still run and the user sees the failure detail AND the manual
341
+ * command to retry by hand.
183
342
  */
184
343
  export async function installCIBranchProtectionStep(
185
344
  options: BranchProtectionStepOptions,
186
345
  ): Promise<BranchProtectionStepResult> {
187
- const branch = options.branch ?? DEFAULT_PROTECTED_BRANCH;
188
346
  const {ctx, log, fake} = options;
189
347
 
190
348
  if (fake) {
191
- log(`branch protection: skipped (--fake; would have targeted ${branch})`);
192
- return {status: 'skipped-fake', branch};
349
+ const target = options.branch ?? DEFAULT_PROTECTED_BRANCH;
350
+ log(`branch protection: skipped (--fake; would have targeted ${target})`);
351
+ return {status: 'skipped-fake', branch: target};
193
352
  }
194
353
  if (!ctx.setBranchProtection) {
195
354
  log(
196
355
  'branch protection: skipped (provider does not implement the seam — non-GitHub host).',
197
356
  );
198
- return {status: 'skipped-no-seam', branch};
357
+ return {
358
+ status: 'skipped-no-seam',
359
+ branch: options.branch ?? DEFAULT_PROTECTED_BRANCH,
360
+ };
199
361
  }
200
362
  if (!ctx.repo) {
201
363
  log('branch protection: skipped (repo unknown — pass --repo to enable).');
202
- return {status: 'skipped-no-repo', branch};
364
+ return {
365
+ status: 'skipped-no-repo',
366
+ branch: options.branch ?? DEFAULT_PROTECTED_BRANCH,
367
+ };
203
368
  }
204
369
 
205
370
  const repo = ctx.repo;
371
+ const {branch, autoDetected} = await resolveTargetBranch(
372
+ ctx,
373
+ options.branch,
374
+ log,
375
+ );
376
+
206
377
  // Cheapest scope-detection: one repo-permissions read (see module header).
207
378
  // `undefined` ⇒ unknown ⇒ treat as non-admin (instruct, never silently
208
379
  // attempt a call that would fail with 403 anyway).
@@ -213,20 +384,30 @@ export async function installCIBranchProtectionStep(
213
384
  if (adminScope !== true) {
214
385
  log('branch protection: no admin-scoped credential detected.');
215
386
  log(
216
- ` install-ci will NOT call the GitHub API. Run this yourself (admin token required):`,
387
+ ` install-ci will NOT call the GitHub API. Run these yourself (admin token required):`,
217
388
  );
218
389
  log(` ${formatManualBranchProtectionCommand(repo, branch)}`);
390
+ log(
391
+ ` Then create the deadlock-guard ruleset (required check \`${VERIFY_CHECK_CONTEXT}\`, ` +
392
+ `do_not_enforce_on_create):`,
393
+ );
394
+ log(` ${formatManualBranchRulesetCommand(repo, branch)}`);
219
395
  log(
220
396
  ` Manual UI fallback: https://github.com/${repo}/settings/branches ` +
221
397
  `→ "Add branch protection rule" → branch name pattern \`${branch}\` ` +
222
- `→ enable "Require status checks to pass" + "Require branches to be up to date" ` +
223
- `→ add required check \`${VERIFY_CHECK_CONTEXT}\`.`,
398
+ `→ enable "Require branches to be up to date", then add a RULESET ` +
399
+ `requiring \`${VERIFY_CHECK_CONTEXT}\` with "Do not require ... on creation".`,
224
400
  );
225
401
  log(
226
402
  ` (The ambient CI \`GITHUB_TOKEN\` is NEVER admin; a human admin's \`gh\` ` +
227
403
  `or a configured PAT/App token with "Administration: write" is required.)`,
228
404
  );
229
- return {status: 'instructed', adminScope, branch};
405
+ return {
406
+ status: 'instructed',
407
+ adminScope,
408
+ branch,
409
+ branchAutoDetected: autoDetected,
410
+ };
230
411
  }
231
412
 
232
413
  const spec = buildBranchProtectionSpec();
@@ -234,15 +415,8 @@ export async function installCIBranchProtectionStep(
234
415
  await ctx.setBranchProtection(branch, spec);
235
416
  log(
236
417
  `branch protection: set on ${repo}@${branch} ` +
237
- `(required check \`${VERIFY_CHECK_CONTEXT}\`, strict: true).`,
418
+ `(strict: true = require branches up to date).`,
238
419
  );
239
- log(
240
- ` NOTE: PRs opened BEFORE \`verify.yml\` lands on \`${branch}\` have ` +
241
- `no \`${VERIFY_CHECK_CONTEXT}\` check waiting. Push/merge \`verify.yml\` ` +
242
- `to \`${branch}\` first; existing in-flight PRs may need a no-op push ` +
243
- `(or close/reopen) to re-trigger the check.`,
244
- );
245
- return {status: 'set', adminScope, branch};
246
420
  } catch (err) {
247
421
  const error = err instanceof Error ? err.message : String(err);
248
422
  log(`branch protection: FAILED (${error})`);
@@ -250,6 +424,57 @@ export async function installCIBranchProtectionStep(
250
424
  ` Retry by hand (admin token required):\n` +
251
425
  ` ${formatManualBranchProtectionCommand(repo, branch)}`,
252
426
  );
253
- return {status: 'failed', adminScope, error, branch};
427
+ return {
428
+ status: 'failed',
429
+ adminScope,
430
+ error,
431
+ branch,
432
+ branchAutoDetected: autoDetected,
433
+ };
254
434
  }
435
+
436
+ // The deadlock guard: the required `verify` check lives in a RULESET with
437
+ // `do_not_enforce_on_create: true` (see module header), NOT in the classic
438
+ // PUT above — so a ref that predates the rule / the check's first run is not
439
+ // deadlocked by a never-reported required check.
440
+ let rulesetStatus: 'set' | 'failed' | 'skipped-no-seam';
441
+ let rulesetError: string | undefined;
442
+ if (!ctx.setBranchRuleset) {
443
+ rulesetStatus = 'skipped-no-seam';
444
+ log(
445
+ ` deadlock guard: provider does not implement the ruleset seam; ` +
446
+ `required check \`${VERIFY_CHECK_CONTEXT}\` NOT enforced.`,
447
+ );
448
+ } else {
449
+ try {
450
+ await ctx.setBranchRuleset(buildBranchProtectionRuleset(branch));
451
+ rulesetStatus = 'set';
452
+ log(
453
+ `deadlock-guard ruleset: created on ${repo}@${branch} ` +
454
+ `(required check \`${VERIFY_CHECK_CONTEXT}\`, do_not_enforce_on_create: true).`,
455
+ );
456
+ log(
457
+ ` NOTE: still push/merge \`verify.yml\` to \`${branch}\` so the check ` +
458
+ `can report on new PRs; the ruleset's create-exemption keeps existing ` +
459
+ `in-flight refs from deadlocking on the not-yet-run check.`,
460
+ );
461
+ } catch (err) {
462
+ rulesetError = err instanceof Error ? err.message : String(err);
463
+ rulesetStatus = 'failed';
464
+ log(`deadlock-guard ruleset: FAILED (${rulesetError})`);
465
+ log(
466
+ ` Retry by hand (admin token required):\n` +
467
+ ` ${formatManualBranchRulesetCommand(repo, branch)}`,
468
+ );
469
+ }
470
+ }
471
+
472
+ return {
473
+ status: 'set',
474
+ adminScope,
475
+ branch,
476
+ branchAutoDetected: autoDetected,
477
+ rulesetStatus,
478
+ rulesetError,
479
+ };
255
480
  }
@@ -1,5 +1,5 @@
1
1
  /**
2
- * The ADVANCE-LIFECYCLE capability emitter (PRD `runner-in-ci`, task
2
+ * The ADVANCE-LIFECYCLE capability emitter (SPEC `runner-in-ci`, task
3
3
  * `install-ci-advance-lifecycle-workflow`; capability C: auto-triage observations
4
4
  * + surface declared blockers + apply committed answers). A SELF-REGISTERING
5
5
  * module: it calls {@link registerCapability} at import time, so
@@ -1,5 +1,5 @@
1
1
  /**
2
- * The CLOSE-JOB capability emitter (PRD `runner-in-ci`, task
2
+ * The CLOSE-JOB capability emitter (SPEC `runner-in-ci`, task
3
3
  * `install-ci-close-job-workflow`; capability E: close issues when their work
4
4
  * lands). A SELF-REGISTERING module: it calls {@link registerCapability} at import
5
5
  * time, so {@link loadCapabilityRegistry} picks it up WITHOUT any edit to a shared
@@ -1,5 +1,5 @@
1
1
  /**
2
- * REFERENCE capability registration (PRD `runner-in-ci`, task
2
+ * REFERENCE capability registration (SPEC `runner-in-ci`, task
3
3
  * `install-ci-core-and-github-adapter`). This file proves the capability-emitter
4
4
  * REGISTRY seam works as a DIRECTORY of self-registering modules: a new capability
5
5
  * is a NEW file in `install-ci-capabilities/` that calls {@link registerCapability}
@@ -1,7 +1,7 @@
1
1
  /**
2
- * The ISSUE-INTAKE capability emitter (PRD `runner-in-ci`, task
2
+ * The ISSUE-INTAKE capability emitter (SPEC `runner-in-ci`, task
3
3
  * `install-ci-intake-trigger-and-review-surface`; capability D: consider incoming
4
- * issues → task/PRD, PLUS insertion point E: surface the review verdict into the
4
+ * issues → task/SPEC, PLUS insertion point E: surface the review verdict into the
5
5
  * issue thread). A SELF-REGISTERING module: it calls {@link registerCapability} at
6
6
  * import time, so {@link loadCapabilityRegistry} picks it up WITHOUT any edit to a
7
7
  * shared central list/switch (the file-orthogonality contract — this task and the
@@ -1,5 +1,5 @@
1
1
  /**
2
- * The VERIFY capability emitter (prd
2
+ * The VERIFY capability emitter (spec
3
3
  * `land-time-reverify-and-parallel-merge-ceiling`, task
4
4
  * `install-ci-tier1-branch-protection`; Story 11 — Tier-1 GitHub ceiling).
5
5
  * A SELF-REGISTERING module: it calls {@link registerCapability} at import