dorfl 0.14.2 → 0.15.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 (418) hide show
  1. package/dist/advance-ci-template.d.ts +17 -16
  2. package/dist/advance-ci-template.d.ts.map +1 -1
  3. package/dist/advance-ci-template.js +42 -53
  4. package/dist/advance-ci-template.js.map +1 -1
  5. package/dist/advance-drivers.d.ts +8 -0
  6. package/dist/advance-drivers.d.ts.map +1 -1
  7. package/dist/advance-drivers.js +28 -4
  8. package/dist/advance-drivers.js.map +1 -1
  9. package/dist/advance-isolated.d.ts.map +1 -1
  10. package/dist/advance-isolated.js +3 -2
  11. package/dist/advance-isolated.js.map +1 -1
  12. package/dist/advance-lifecycle-template.d.ts +41 -40
  13. package/dist/advance-lifecycle-template.d.ts.map +1 -1
  14. package/dist/advance-lifecycle-template.js +309 -489
  15. package/dist/advance-lifecycle-template.js.map +1 -1
  16. package/dist/advance-loop-driver.d.ts.map +1 -1
  17. package/dist/advance-loop-driver.js +3 -2
  18. package/dist/advance-loop-driver.js.map +1 -1
  19. package/dist/advance-treeless-publish.d.ts +31 -0
  20. package/dist/advance-treeless-publish.d.ts.map +1 -1
  21. package/dist/advance-treeless-publish.js +40 -0
  22. package/dist/advance-treeless-publish.js.map +1 -1
  23. package/dist/advance.d.ts +63 -3
  24. package/dist/advance.d.ts.map +1 -1
  25. package/dist/advance.js +80 -12
  26. package/dist/advance.js.map +1 -1
  27. package/dist/advancing-lock.d.ts +9 -0
  28. package/dist/advancing-lock.d.ts.map +1 -1
  29. package/dist/advancing-lock.js +21 -1
  30. package/dist/advancing-lock.js.map +1 -1
  31. package/dist/agent-env.d.ts +61 -0
  32. package/dist/agent-env.d.ts.map +1 -0
  33. package/dist/agent-env.js +144 -0
  34. package/dist/agent-env.js.map +1 -0
  35. package/dist/agent-stop.d.ts +35 -0
  36. package/dist/agent-stop.d.ts.map +1 -1
  37. package/dist/agent-stop.js +62 -0
  38. package/dist/agent-stop.js.map +1 -1
  39. package/dist/apply-merge-action.d.ts +76 -34
  40. package/dist/apply-merge-action.d.ts.map +1 -1
  41. package/dist/apply-merge-action.js +339 -129
  42. package/dist/apply-merge-action.js.map +1 -1
  43. package/dist/apply-stuck-action.js +2 -2
  44. package/dist/apply-stuck-action.js.map +1 -1
  45. package/dist/ci-agent-result.d.ts +151 -0
  46. package/dist/ci-agent-result.d.ts.map +1 -0
  47. package/dist/ci-agent-result.js +314 -0
  48. package/dist/ci-agent-result.js.map +1 -0
  49. package/dist/ci-handoff-apply.d.ts +162 -0
  50. package/dist/ci-handoff-apply.d.ts.map +1 -0
  51. package/dist/ci-handoff-apply.js +497 -0
  52. package/dist/ci-handoff-apply.js.map +1 -0
  53. package/dist/ci-handoff-format.d.ts +369 -0
  54. package/dist/ci-handoff-format.d.ts.map +1 -0
  55. package/dist/ci-handoff-format.js +646 -0
  56. package/dist/ci-handoff-format.js.map +1 -0
  57. package/dist/ci-handoff-lfs.d.ts +146 -0
  58. package/dist/ci-handoff-lfs.d.ts.map +1 -0
  59. package/dist/ci-handoff-lfs.js +397 -0
  60. package/dist/ci-handoff-lfs.js.map +1 -0
  61. package/dist/ci-handoff.d.ts +99 -0
  62. package/dist/ci-handoff.d.ts.map +1 -0
  63. package/dist/ci-handoff.js +277 -0
  64. package/dist/ci-handoff.js.map +1 -0
  65. package/dist/ci-lock-outputs.d.ts +93 -0
  66. package/dist/ci-lock-outputs.d.ts.map +1 -0
  67. package/dist/ci-lock-outputs.js +223 -0
  68. package/dist/ci-lock-outputs.js.map +1 -0
  69. package/dist/ci-phase-build.d.ts +178 -0
  70. package/dist/ci-phase-build.d.ts.map +1 -0
  71. package/dist/ci-phase-build.js +989 -0
  72. package/dist/ci-phase-build.js.map +1 -0
  73. package/dist/ci-phase-driver.d.ts +247 -0
  74. package/dist/ci-phase-driver.d.ts.map +1 -0
  75. package/dist/ci-phase-driver.js +370 -0
  76. package/dist/ci-phase-driver.js.map +1 -0
  77. package/dist/ci-phase-intake.d.ts +172 -0
  78. package/dist/ci-phase-intake.d.ts.map +1 -0
  79. package/dist/ci-phase-intake.js +555 -0
  80. package/dist/ci-phase-intake.js.map +1 -0
  81. package/dist/ci-phase-tasking.d.ts +205 -0
  82. package/dist/ci-phase-tasking.d.ts.map +1 -0
  83. package/dist/ci-phase-tasking.js +906 -0
  84. package/dist/ci-phase-tasking.js.map +1 -0
  85. package/dist/ci-phase-treeless.d.ts +224 -0
  86. package/dist/ci-phase-treeless.d.ts.map +1 -0
  87. package/dist/ci-phase-treeless.js +1482 -0
  88. package/dist/ci-phase-treeless.js.map +1 -0
  89. package/dist/ci-read-token.d.ts +47 -0
  90. package/dist/ci-read-token.d.ts.map +1 -0
  91. package/dist/ci-read-token.js +80 -0
  92. package/dist/ci-read-token.js.map +1 -0
  93. package/dist/cli.d.ts.map +1 -1
  94. package/dist/cli.js +447 -22
  95. package/dist/cli.js.map +1 -1
  96. package/dist/close-job-template.d.ts +10 -1
  97. package/dist/close-job-template.d.ts.map +1 -1
  98. package/dist/close-job-template.js +46 -14
  99. package/dist/close-job-template.js.map +1 -1
  100. package/dist/close-job.d.ts +20 -5
  101. package/dist/close-job.d.ts.map +1 -1
  102. package/dist/close-job.js +65 -12
  103. package/dist/close-job.js.map +1 -1
  104. package/dist/complete.d.ts.map +1 -1
  105. package/dist/complete.js +20 -1
  106. package/dist/complete.js.map +1 -1
  107. package/dist/config.d.ts +41 -44
  108. package/dist/config.d.ts.map +1 -1
  109. package/dist/config.js +2 -4
  110. package/dist/config.js.map +1 -1
  111. package/dist/continue-branch.d.ts +63 -15
  112. package/dist/continue-branch.d.ts.map +1 -1
  113. package/dist/continue-branch.js +75 -8
  114. package/dist/continue-branch.js.map +1 -1
  115. package/dist/crashed-run-save.d.ts +73 -0
  116. package/dist/crashed-run-save.d.ts.map +1 -0
  117. package/dist/crashed-run-save.js +86 -0
  118. package/dist/crashed-run-save.js.map +1 -0
  119. package/dist/cwd-section.d.ts.map +1 -1
  120. package/dist/cwd-section.js +10 -2
  121. package/dist/cwd-section.js.map +1 -1
  122. package/dist/decision-engine.d.ts +10 -0
  123. package/dist/decision-engine.d.ts.map +1 -1
  124. package/dist/decision-engine.js.map +1 -1
  125. package/dist/do-config.d.ts +2 -24
  126. package/dist/do-config.d.ts.map +1 -1
  127. package/dist/do-config.js +1 -33
  128. package/dist/do-config.js.map +1 -1
  129. package/dist/do.d.ts +149 -1
  130. package/dist/do.d.ts.map +1 -1
  131. package/dist/do.js +115 -25
  132. package/dist/do.js.map +1 -1
  133. package/dist/dorfl-item-template.d.ts +98 -0
  134. package/dist/dorfl-item-template.d.ts.map +1 -0
  135. package/dist/dorfl-item-template.js +504 -0
  136. package/dist/dorfl-item-template.js.map +1 -0
  137. package/dist/env-config.d.ts.map +1 -1
  138. package/dist/env-config.js +7 -5
  139. package/dist/env-config.js.map +1 -1
  140. package/dist/frontmatter.d.ts +52 -0
  141. package/dist/frontmatter.d.ts.map +1 -1
  142. package/dist/frontmatter.js +136 -2
  143. package/dist/frontmatter.js.map +1 -1
  144. package/dist/gc.d.ts +13 -0
  145. package/dist/gc.d.ts.map +1 -1
  146. package/dist/gc.js +16 -2
  147. package/dist/gc.js.map +1 -1
  148. package/dist/git.d.ts +18 -1
  149. package/dist/git.d.ts.map +1 -1
  150. package/dist/git.js +70 -5
  151. package/dist/git.js.map +1 -1
  152. package/dist/harness.d.ts +44 -5
  153. package/dist/harness.d.ts.map +1 -1
  154. package/dist/harness.js +24 -1
  155. package/dist/harness.js.map +1 -1
  156. package/dist/index.d.ts +11 -4
  157. package/dist/index.d.ts.map +1 -1
  158. package/dist/index.js +7 -3
  159. package/dist/index.js.map +1 -1
  160. package/dist/install-ci-action-pins.d.ts +123 -0
  161. package/dist/install-ci-action-pins.d.ts.map +1 -0
  162. package/dist/install-ci-action-pins.js +190 -0
  163. package/dist/install-ci-action-pins.js.map +1 -0
  164. package/dist/install-ci-actions-pr-creation.d.ts +70 -0
  165. package/dist/install-ci-actions-pr-creation.d.ts.map +1 -0
  166. package/dist/install-ci-actions-pr-creation.js +106 -0
  167. package/dist/install-ci-actions-pr-creation.js.map +1 -0
  168. package/dist/install-ci-capabilities/dorfl-item.d.ts +12 -0
  169. package/dist/install-ci-capabilities/dorfl-item.d.ts.map +1 -0
  170. package/dist/install-ci-capabilities/dorfl-item.js +26 -0
  171. package/dist/install-ci-capabilities/dorfl-item.js.map +1 -0
  172. package/dist/install-ci-core.d.ts +155 -37
  173. package/dist/install-ci-core.d.ts.map +1 -1
  174. package/dist/install-ci-core.js +304 -200
  175. package/dist/install-ci-core.js.map +1 -1
  176. package/dist/install-ci-github.d.ts +47 -2
  177. package/dist/install-ci-github.d.ts.map +1 -1
  178. package/dist/install-ci-github.js +113 -1
  179. package/dist/install-ci-github.js.map +1 -1
  180. package/dist/install-ci.d.ts +25 -6
  181. package/dist/install-ci.d.ts.map +1 -1
  182. package/dist/install-ci.js +72 -36
  183. package/dist/install-ci.js.map +1 -1
  184. package/dist/intake-marker.d.ts +6 -1
  185. package/dist/intake-marker.d.ts.map +1 -1
  186. package/dist/intake-marker.js.map +1 -1
  187. package/dist/intake-triage.d.ts.map +1 -1
  188. package/dist/intake-triage.js +6 -2
  189. package/dist/intake-triage.js.map +1 -1
  190. package/dist/intake-trigger-template.d.ts +31 -25
  191. package/dist/intake-trigger-template.d.ts.map +1 -1
  192. package/dist/intake-trigger-template.js +107 -292
  193. package/dist/intake-trigger-template.js.map +1 -1
  194. package/dist/intake.d.ts +186 -4
  195. package/dist/intake.d.ts.map +1 -1
  196. package/dist/intake.js +533 -416
  197. package/dist/intake.js.map +1 -1
  198. package/dist/integration-core.d.ts +154 -1
  199. package/dist/integration-core.d.ts.map +1 -1
  200. package/dist/integration-core.js +759 -486
  201. package/dist/integration-core.js.map +1 -1
  202. package/dist/integrator.d.ts +12 -0
  203. package/dist/integrator.d.ts.map +1 -1
  204. package/dist/integrator.js +21 -0
  205. package/dist/integrator.js.map +1 -1
  206. package/dist/isolation.d.ts +12 -2
  207. package/dist/isolation.d.ts.map +1 -1
  208. package/dist/isolation.js +19 -8
  209. package/dist/isolation.js.map +1 -1
  210. package/dist/item-lock.d.ts +93 -11
  211. package/dist/item-lock.d.ts.map +1 -1
  212. package/dist/item-lock.js +233 -65
  213. package/dist/item-lock.js.map +1 -1
  214. package/dist/land-question-residue.d.ts +58 -0
  215. package/dist/land-question-residue.d.ts.map +1 -0
  216. package/dist/land-question-residue.js +95 -0
  217. package/dist/land-question-residue.js.map +1 -0
  218. package/dist/lifecycle-gather.d.ts +16 -0
  219. package/dist/lifecycle-gather.d.ts.map +1 -1
  220. package/dist/lifecycle-gather.js +54 -6
  221. package/dist/lifecycle-gather.js.map +1 -1
  222. package/dist/merge-answer.d.ts +41 -0
  223. package/dist/merge-answer.d.ts.map +1 -0
  224. package/dist/merge-answer.js +60 -0
  225. package/dist/merge-answer.js.map +1 -0
  226. package/dist/merge-question-surfacer.d.ts +105 -30
  227. package/dist/merge-question-surfacer.d.ts.map +1 -1
  228. package/dist/merge-question-surfacer.js +202 -91
  229. package/dist/merge-question-surfacer.js.map +1 -1
  230. package/dist/merge-question-tick.d.ts +64 -0
  231. package/dist/merge-question-tick.d.ts.map +1 -0
  232. package/dist/merge-question-tick.js +96 -0
  233. package/dist/merge-question-tick.js.map +1 -0
  234. package/dist/mint-adr.d.ts.map +1 -1
  235. package/dist/mint-adr.js +20 -2
  236. package/dist/mint-adr.js.map +1 -1
  237. package/dist/needs-attention.d.ts +72 -2
  238. package/dist/needs-attention.d.ts.map +1 -1
  239. package/dist/needs-attention.js +275 -38
  240. package/dist/needs-attention.js.map +1 -1
  241. package/dist/phase-recorder.d.ts +168 -0
  242. package/dist/phase-recorder.d.ts.map +1 -0
  243. package/dist/phase-recorder.js +218 -0
  244. package/dist/phase-recorder.js.map +1 -0
  245. package/dist/phase.d.ts +94 -0
  246. package/dist/phase.d.ts.map +1 -0
  247. package/dist/phase.js +148 -0
  248. package/dist/phase.js.map +1 -0
  249. package/dist/pi-harness.d.ts.map +1 -1
  250. package/dist/pi-harness.js +19 -6
  251. package/dist/pi-harness.js.map +1 -1
  252. package/dist/prepare.d.ts.map +1 -1
  253. package/dist/prepare.js +4 -0
  254. package/dist/prepare.js.map +1 -1
  255. package/dist/prompt.d.ts +4 -0
  256. package/dist/prompt.d.ts.map +1 -1
  257. package/dist/prompt.js +48 -1
  258. package/dist/prompt.js.map +1 -1
  259. package/dist/protocol/CLAIM-PROTOCOL.md +3 -1
  260. package/dist/protocol/WORK-CONTRACT.md +1 -1
  261. package/dist/reap-branches.d.ts +48 -0
  262. package/dist/reap-branches.d.ts.map +1 -1
  263. package/dist/reap-branches.js +64 -0
  264. package/dist/reap-branches.js.map +1 -1
  265. package/dist/ref-write.d.ts +198 -0
  266. package/dist/ref-write.d.ts.map +1 -0
  267. package/dist/ref-write.js +79 -0
  268. package/dist/ref-write.js.map +1 -0
  269. package/dist/repo-config.js +8 -8
  270. package/dist/repo-config.js.map +1 -1
  271. package/dist/repo-mirror.d.ts +36 -0
  272. package/dist/repo-mirror.d.ts.map +1 -1
  273. package/dist/repo-mirror.js +91 -1
  274. package/dist/repo-mirror.js.map +1 -1
  275. package/dist/review-verdict.d.ts +1 -1
  276. package/dist/review-verdict.js +1 -1
  277. package/dist/run.d.ts +7 -1
  278. package/dist/run.d.ts.map +1 -1
  279. package/dist/run.js +28 -4
  280. package/dist/run.js.map +1 -1
  281. package/dist/scan.d.ts +19 -1
  282. package/dist/scan.d.ts.map +1 -1
  283. package/dist/scan.js +21 -8
  284. package/dist/scan.js.map +1 -1
  285. package/dist/sidecar.d.ts +14 -0
  286. package/dist/sidecar.d.ts.map +1 -1
  287. package/dist/sidecar.js +21 -0
  288. package/dist/sidecar.js.map +1 -1
  289. package/dist/single-job-warning.d.ts +63 -0
  290. package/dist/single-job-warning.d.ts.map +1 -0
  291. package/dist/single-job-warning.js +110 -0
  292. package/dist/single-job-warning.js.map +1 -0
  293. package/dist/skills/setup/protocol/CLAIM-PROTOCOL.md +3 -1
  294. package/dist/skills/setup/protocol/WORK-CONTRACT.md +1 -1
  295. package/dist/spec-complete.d.ts +13 -6
  296. package/dist/spec-complete.d.ts.map +1 -1
  297. package/dist/spec-complete.js +23 -11
  298. package/dist/spec-complete.js.map +1 -1
  299. package/dist/start.d.ts.map +1 -1
  300. package/dist/start.js +47 -14
  301. package/dist/start.js.map +1 -1
  302. package/dist/status.d.ts +12 -0
  303. package/dist/status.d.ts.map +1 -1
  304. package/dist/status.js +11 -3
  305. package/dist/status.js.map +1 -1
  306. package/dist/tasking.d.ts +246 -1
  307. package/dist/tasking.d.ts.map +1 -1
  308. package/dist/tasking.js +452 -358
  309. package/dist/tasking.js.map +1 -1
  310. package/dist/triage-persist.d.ts.map +1 -1
  311. package/dist/triage-persist.js +21 -2
  312. package/dist/triage-persist.js.map +1 -1
  313. package/dist/verify-workflow-template.d.ts.map +1 -1
  314. package/dist/verify-workflow-template.js +8 -4
  315. package/dist/verify-workflow-template.js.map +1 -1
  316. package/dist/verify.d.ts.map +1 -1
  317. package/dist/verify.js +4 -0
  318. package/dist/verify.js.map +1 -1
  319. package/dist/watch-session.d.ts +42 -13
  320. package/dist/watch-session.d.ts.map +1 -1
  321. package/dist/watch-session.js +52 -23
  322. package/dist/watch-session.js.map +1 -1
  323. package/dist/work-layout.d.ts +10 -4
  324. package/dist/work-layout.d.ts.map +1 -1
  325. package/dist/work-layout.js +11 -3
  326. package/dist/work-layout.js.map +1 -1
  327. package/dist/workspace.d.ts +65 -4
  328. package/dist/workspace.d.ts.map +1 -1
  329. package/dist/workspace.js +159 -11
  330. package/dist/workspace.js.map +1 -1
  331. package/package.json +1 -1
  332. package/src/advance-ci-template.ts +80 -81
  333. package/src/advance-drivers.ts +45 -6
  334. package/src/advance-isolated.ts +3 -5
  335. package/src/advance-lifecycle-template.ts +375 -538
  336. package/src/advance-loop-driver.ts +3 -5
  337. package/src/advance-treeless-publish.ts +61 -0
  338. package/src/advance.ts +145 -15
  339. package/src/advancing-lock.ts +36 -1
  340. package/src/agent-env.ts +174 -0
  341. package/src/agent-stop.ts +81 -0
  342. package/src/apply-merge-action.ts +401 -154
  343. package/src/apply-stuck-action.ts +2 -2
  344. package/src/ci-agent-result.ts +421 -0
  345. package/src/ci-handoff-apply.ts +737 -0
  346. package/src/ci-handoff-format.ts +926 -0
  347. package/src/ci-handoff-lfs.ts +519 -0
  348. package/src/ci-handoff.ts +392 -0
  349. package/src/ci-lock-outputs.ts +273 -0
  350. package/src/ci-phase-build.ts +1328 -0
  351. package/src/ci-phase-driver.ts +548 -0
  352. package/src/ci-phase-intake.ts +861 -0
  353. package/src/ci-phase-tasking.ts +1255 -0
  354. package/src/ci-phase-treeless.ts +2028 -0
  355. package/src/ci-read-token.ts +90 -0
  356. package/src/cli.ts +591 -29
  357. package/src/close-job-template.ts +52 -15
  358. package/src/close-job.ts +77 -12
  359. package/src/complete.ts +19 -1
  360. package/src/config.ts +43 -48
  361. package/src/continue-branch.ts +121 -16
  362. package/src/crashed-run-save.ts +162 -0
  363. package/src/cwd-section.ts +10 -0
  364. package/src/decision-engine.ts +10 -0
  365. package/src/do-config.ts +2 -57
  366. package/src/do.ts +170 -28
  367. package/src/dorfl-item-template.ts +556 -0
  368. package/src/env-config.ts +7 -5
  369. package/src/frontmatter.ts +155 -2
  370. package/src/gc.ts +27 -2
  371. package/src/git.ts +83 -5
  372. package/src/harness.ts +58 -6
  373. package/src/index.ts +50 -1
  374. package/src/install-ci-action-pins.ts +209 -0
  375. package/src/install-ci-actions-pr-creation.ts +186 -0
  376. package/src/install-ci-capabilities/dorfl-item.ts +33 -0
  377. package/src/install-ci-core.ts +388 -233
  378. package/src/install-ci-github.ts +149 -1
  379. package/src/install-ci.ts +83 -37
  380. package/src/intake-marker.ts +6 -1
  381. package/src/intake-triage.ts +7 -3
  382. package/src/intake-trigger-template.ts +126 -327
  383. package/src/intake.ts +725 -544
  384. package/src/integration-core.ts +975 -523
  385. package/src/integrator.ts +28 -0
  386. package/src/isolation.ts +29 -10
  387. package/src/item-lock.ts +308 -92
  388. package/src/land-question-residue.ts +122 -0
  389. package/src/lifecycle-gather.ts +82 -10
  390. package/src/merge-answer.ts +82 -0
  391. package/src/merge-question-surfacer.ts +320 -112
  392. package/src/merge-question-tick.ts +182 -0
  393. package/src/mint-adr.ts +28 -2
  394. package/src/needs-attention.ts +350 -42
  395. package/src/phase-recorder.ts +350 -0
  396. package/src/phase.ts +177 -0
  397. package/src/pi-harness.ts +25 -5
  398. package/src/prepare.ts +4 -0
  399. package/src/prompt.ts +68 -1
  400. package/src/reap-branches.ts +107 -0
  401. package/src/ref-write.ts +324 -0
  402. package/src/repo-config.ts +8 -8
  403. package/src/repo-mirror.ts +107 -1
  404. package/src/review-verdict.ts +1 -1
  405. package/src/run.ts +47 -6
  406. package/src/scan.ts +37 -7
  407. package/src/sidecar.ts +36 -0
  408. package/src/single-job-warning.ts +135 -0
  409. package/src/spec-complete.ts +36 -14
  410. package/src/start.ts +55 -16
  411. package/src/status.ts +29 -3
  412. package/src/tasking.ts +593 -378
  413. package/src/triage-persist.ts +24 -2
  414. package/src/verify-workflow-template.ts +8 -4
  415. package/src/verify.ts +4 -0
  416. package/src/watch-session.ts +86 -28
  417. package/src/work-layout.ts +11 -3
  418. package/src/workspace.ts +210 -14
@@ -157,19 +157,172 @@ function extractBlock(content: string): string | undefined {
157
157
  return lines.slice(1, closing).join('\n');
158
158
  }
159
159
 
160
- /** Strip surrounding single or double quotes from a scalar token. */
160
+ /**
161
+ * Strip surrounding single or double quotes from a scalar token. A
162
+ * SINGLE-quoted scalar also has its one YAML escape decoded (`''` is a literal
163
+ * `'`), so a value written by {@link quoteYamlScalar} reads back verbatim.
164
+ * Double-quoted scalars keep their inner text as-is (no backslash decoding).
165
+ */
161
166
  function unquote(value: string): string {
162
167
  const trimmed = value.trim();
163
168
  if (trimmed.length >= 2) {
164
169
  const first = trimmed[0];
165
170
  const last = trimmed[trimmed.length - 1];
166
171
  if ((first === '"' || first === "'") && last === first) {
167
- return trimmed.slice(1, -1);
172
+ const inner = trimmed.slice(1, -1);
173
+ return first === "'" ? inner.replace(/''/g, "'") : inner;
168
174
  }
169
175
  }
170
176
  return trimmed;
171
177
  }
172
178
 
179
+ /**
180
+ * The read half of {@link quoteYamlScalar}, for the frontmatter readers that
181
+ * live outside this module (the `title:` readers in `tasking.ts` and
182
+ * `integration-core.ts`), so a quoted title reads back the same everywhere.
183
+ */
184
+ export function unquoteYamlScalar(value: string): string {
185
+ return unquote(value);
186
+ }
187
+
188
+ /**
189
+ * Raised when a runner-side renderer is handed a value it cannot write safely
190
+ * into frontmatter, or when the rendered document does not read back the keys
191
+ * the runner meant to write (task
192
+ * `intake-frontmatter-title-injection-strips-origin-stamp`).
193
+ */
194
+ export class FrontmatterRenderError extends Error {
195
+ constructor(message: string) {
196
+ super(message);
197
+ this.name = 'FrontmatterRenderError';
198
+ }
199
+ }
200
+
201
+ /**
202
+ * Any character that can end or fold a YAML line, or any other control
203
+ * character: C0 controls (incl. tab, LF, CR), DEL, the C1 range (incl. NEL
204
+ * U+0085, a YAML 1.1 line break), and the Unicode line/paragraph separators.
205
+ */
206
+ // eslint-disable-next-line no-control-regex
207
+ const SCALAR_CONTROL_RE = /[\u0000-\u001f\u007f-\u009f\u2028\u2029]/;
208
+
209
+ /**
210
+ * Why `value` cannot be a one-line frontmatter scalar, or `undefined` when it
211
+ * can. The verdict boundaries (intake, ADR mint) use it to refuse an
212
+ * agent-drafted title before anything is rendered.
213
+ */
214
+ export function singleLineScalarProblem(value: string): string | undefined {
215
+ return SCALAR_CONTROL_RE.test(value)
216
+ ? 'must be a single line with no control characters'
217
+ : undefined;
218
+ }
219
+
220
+ /**
221
+ * THE shared quoter for agent-supplied text a runner writes into frontmatter
222
+ * (task `intake-frontmatter-title-injection-strips-origin-stamp`). Returns a
223
+ * YAML single-quoted scalar (`'...'`, an embedded `'` doubled), which is valid
224
+ * YAML for every one-line string and reads back verbatim through
225
+ * {@link unquote} (and so {@link readFrontmatterField}). A single-quoted scalar
226
+ * has no escape for a line break, so a value that is not one line, or holds any
227
+ * control character, THROWS {@link FrontmatterRenderError}: callers must reject
228
+ * such a value at their verdict boundary, and this throw is the backstop.
229
+ */
230
+ export function quoteYamlScalar(value: string): string {
231
+ const problem = singleLineScalarProblem(value);
232
+ if (problem !== undefined) {
233
+ throw new FrontmatterRenderError(
234
+ `frontmatter value ${JSON.stringify(value)} ${problem}`,
235
+ );
236
+ }
237
+ return `'${value.replace(/'/g, "''")}'`;
238
+ }
239
+
240
+ /** A top-level `key: value` frontmatter line (the key grammar {@link parseFrontmatter} uses). */
241
+ const TOP_LEVEL_KEY_RE = /^([A-Za-z0-9_.]+)\s*:\s*(.*)$/;
242
+
243
+ /**
244
+ * The post-render RE-PARSE assertion (task
245
+ * `intake-frontmatter-title-injection-strips-origin-stamp`). A runner renders a
246
+ * document, then calls this with the frontmatter values it MEANT to write;
247
+ * any disagreement THROWS {@link FrontmatterRenderError}, so a document whose
248
+ * runner-owned keys were displaced (a closed-early fence demoting the
249
+ * `originTrust` stamp into the body, a smuggled duplicate `slug:`) is never
250
+ * emitted.
251
+ *
252
+ * For each `expected` entry: a string value means the key must appear EXACTLY
253
+ * ONCE as a top-level key and read back (via {@link unquote}) equal to it;
254
+ * `undefined` means the key must be ABSENT. The typed keys that
255
+ * {@link parseFrontmatter} models (`slug`, `issue`, `origin`, `originTrust`,
256
+ * `humanOnly`, `needsAnswers`) are ALSO cross-checked through that parser, the
257
+ * same reader the rest of dorfl uses. With `exact`, the frontmatter may hold no
258
+ * top-level key outside `expected` (for a document the runner renders whole).
259
+ */
260
+ export function assertFrontmatterFields(
261
+ content: string,
262
+ expected: Readonly<Record<string, string | undefined>>,
263
+ options: {exact?: boolean} = {},
264
+ ): void {
265
+ const block = extractBlock(content);
266
+ if (block === undefined) {
267
+ throw new FrontmatterRenderError(
268
+ 'rendered document has no frontmatter block',
269
+ );
270
+ }
271
+ const seen = new Map<string, string[]>();
272
+ for (const line of block.split('\n')) {
273
+ const match = TOP_LEVEL_KEY_RE.exec(line);
274
+ if (!match) continue;
275
+ const values = seen.get(match[1]) ?? [];
276
+ values.push(unquote(match[2]));
277
+ seen.set(match[1], values);
278
+ }
279
+ const fail = (detail: string): never => {
280
+ throw new FrontmatterRenderError(
281
+ `rendered frontmatter does not read back as written: ${detail}`,
282
+ );
283
+ };
284
+ for (const [key, want] of Object.entries(expected)) {
285
+ const got = seen.get(key) ?? [];
286
+ if (want === undefined) {
287
+ if (got.length > 0) fail(`'${key}' must be absent`);
288
+ continue;
289
+ }
290
+ if (got.length !== 1) {
291
+ fail(`'${key}' appears ${got.length} time(s), expected once`);
292
+ }
293
+ if (got[0] !== want) {
294
+ fail(
295
+ `'${key}' reads ${JSON.stringify(got[0])}, expected ${JSON.stringify(want)}`,
296
+ );
297
+ }
298
+ }
299
+ if (options.exact === true) {
300
+ for (const key of seen.keys()) {
301
+ if (!(key in expected)) fail(`unexpected key '${key}'`);
302
+ }
303
+ }
304
+ // Cross-check through the typed parser (last-wins, value-normalising), so a
305
+ // document that passes the line check but that dorfl would READ differently
306
+ // still fails.
307
+ const fm = parseFrontmatter(content);
308
+ const typed: Record<string, string | undefined> = {
309
+ slug: fm.slug,
310
+ issue: fm.issue === undefined ? undefined : String(fm.issue),
311
+ origin: fm.origin,
312
+ originTrust: fm.originTrust,
313
+ humanOnly: fm.humanOnly === undefined ? undefined : String(fm.humanOnly),
314
+ needsAnswers:
315
+ fm.needsAnswers === undefined ? undefined : String(fm.needsAnswers),
316
+ };
317
+ for (const [key, parsed] of Object.entries(typed)) {
318
+ if (key in expected && parsed !== expected[key]) {
319
+ fail(
320
+ `parsed '${key}' is ${JSON.stringify(parsed)}, expected ${JSON.stringify(expected[key])}`,
321
+ );
322
+ }
323
+ }
324
+ }
325
+
173
326
  /**
174
327
  * Extract the `[...]` body of a YAML flow-style inline list, IGNORING anything
175
328
  * after the matching closing `]` (notably a trailing `# comment`, the documented
package/src/gc.ts CHANGED
@@ -247,6 +247,30 @@ export interface RetainedJob extends GcJob {
247
247
  reason: RetainReason;
248
248
  /** Human-readable reason text (`RETAIN_REASON_TEXT[reason]`). */
249
249
  reasonText: string;
250
+ /**
251
+ * How to SAVE the retained work, for a task job (every retain reason means the
252
+ * worktree holds work the arbiter lacks): `requeue <slug>` pushes it to the
253
+ * work branch before releasing a crashed run's lock (task
254
+ * `a-crashed-runs-local-work-is-saved-before-its-lock-is-released`). Absent
255
+ * for a non-task branch.
256
+ */
257
+ hint?: string;
258
+ }
259
+
260
+ /**
261
+ * The save hint {@link gc} attaches to a retained TASK job (see
262
+ * {@link RetainedJob.hint}), or `undefined` for any other branch.
263
+ */
264
+ export function retainedWorkHint(job: GcJob): string | undefined {
265
+ const parsed = parseWorkBranchRef(job.branch);
266
+ if (parsed === undefined || parsed.namespace !== 'task') {
267
+ return undefined;
268
+ }
269
+ return (
270
+ `it holds work the arbiter lacks; if its run is dead and its lock still ` +
271
+ `held, \`dorfl requeue ${parsed.slug}\` saves it to ${job.branch} before ` +
272
+ `releasing the lock (else push ${job.branch} from ${job.dir})`
273
+ );
250
274
  }
251
275
 
252
276
  export interface GcOptions {
@@ -363,8 +387,9 @@ export function gc(options: GcOptions): GcResult {
363
387
 
364
388
  const reason = result.verdict.reason ?? 'unmerged-commits';
365
389
  const reasonText = RETAIN_REASON_TEXT[reason];
366
- retained.push({...job, reason, reasonText});
367
- note(`Retained ${job.slug}: ${reasonText}.`);
390
+ const hint = retainedWorkHint(job);
391
+ retained.push({...job, reason, reasonText, ...(hint ? {hint} : {})});
392
+ note(`Retained ${job.slug}: ${reasonText}${hint ? ` (${hint})` : ''}.`);
368
393
  }
369
394
 
370
395
  return {reaped, retained, sweptOrphans};
package/src/git.ts CHANGED
@@ -1,6 +1,7 @@
1
1
  import {spawnSync, spawn} from 'node:child_process';
2
2
  import {existsSync, mkdirSync, statSync} from 'node:fs';
3
3
  import {delimiter, dirname, isAbsolute, join} from 'node:path';
4
+ import {gitChildEnv} from './ci-read-token.js';
4
5
 
5
6
  /** Result of running a git (or any) command. */
6
7
  export interface RunResult {
@@ -28,7 +29,49 @@ const SYSTEM_PATH_DIRS = [
28
29
  ];
29
30
 
30
31
  /**
31
- * `PATH` with {@link SYSTEM_PATH_DIRS} APPENDED (caller entries kept FIRST, so a
32
+ * The NixOS system profiles. NixOS has no FHS `/usr/bin/git`: a system-wide git
33
+ * lives under `/run/current-system/sw/bin` (the NixOS system profile) or
34
+ * `/nix/var/nix/profiles/default/bin` (the multi-user Nix default profile), both
35
+ * symlinks into the Nix store. Without these, a spawn whose env has no usable
36
+ * `PATH` (a caller or test passing `env: {}`) cannot find git on NixOS at all.
37
+ * APPENDED after {@link SYSTEM_PATH_DIRS}, so the caller's own `PATH` and the FHS
38
+ * dirs still win; on a non-NixOS host these dirs simply do not exist and are
39
+ * skipped by the probe (and harmless on the spawn `PATH`).
40
+ */
41
+ const NIXOS_PROFILE_DIRS = [
42
+ '/run/current-system/sw/bin',
43
+ '/nix/var/nix/profiles/default/bin',
44
+ ];
45
+
46
+ /** The default fallback probe list: FHS dirs first, then the NixOS profiles. */
47
+ const DEFAULT_FALLBACK_PATH_DIRS: readonly string[] = [
48
+ ...SYSTEM_PATH_DIRS,
49
+ ...NIXOS_PROFILE_DIRS,
50
+ ];
51
+
52
+ /**
53
+ * The fallback dirs actually in use. Defaults to
54
+ * {@link DEFAULT_FALLBACK_PATH_DIRS}; replaceable ONLY via
55
+ * {@link setFallbackPathDirsForTest}, the probe-list seam a test uses to point
56
+ * the fallback at a fake bin dir.
57
+ */
58
+ let fallbackPathDirs: readonly string[] = DEFAULT_FALLBACK_PATH_DIRS;
59
+
60
+ /**
61
+ * Replace the fallback probe list (tests only); pass `undefined` to restore the
62
+ * default. Clears the {@link resolveGitBinary} cache so no stale resolution from
63
+ * the previous list survives.
64
+ */
65
+ export function setFallbackPathDirsForTest(
66
+ dirs: readonly string[] | undefined,
67
+ ): void {
68
+ fallbackPathDirs = dirs ?? DEFAULT_FALLBACK_PATH_DIRS;
69
+ gitBinaryCache.clear();
70
+ }
71
+
72
+ /**
73
+ * `PATH` with the fallback dirs ({@link SYSTEM_PATH_DIRS}, then
74
+ * {@link NIXOS_PROFILE_DIRS}) APPENDED (caller entries kept FIRST, so a
32
75
  * pinned tool earlier on `PATH` still wins; missing system dirs are added, not
33
76
  * substituted). Deduplicated, preserving first-seen order.
34
77
  */
@@ -37,7 +80,7 @@ function pathWithSystemDirs(path: string | undefined): string {
37
80
  const out: string[] = [];
38
81
  for (const dir of [
39
82
  ...(path ? path.split(delimiter) : []),
40
- ...SYSTEM_PATH_DIRS,
83
+ ...fallbackPathDirs,
41
84
  ]) {
42
85
  if (dir !== '' && !seen.has(dir)) {
43
86
  seen.add(dir);
@@ -85,7 +128,9 @@ export function resetResolvedGitBinaryForTest(): void {
85
128
  * 2. a probe of the env's OWN `PATH` FIRST (so a shim / pinned git earlier on
86
129
  * `PATH` wins), then the standard system dirs APPENDED — so `/usr/bin/git`
87
130
  * is still found when the caller dropped `/usr/bin`, but never AHEAD of the
88
- * caller's own entries.
131
+ * caller's own entries. LAST come the NixOS system profiles
132
+ * ({@link NIXOS_PROFILE_DIRS}), so git resolves on NixOS even when the env
133
+ * carries no `PATH` at all.
89
134
  *
90
135
  * Falls back to the bare name `'git'` when nothing resolves (git genuinely
91
136
  * absent) so the spawn still runs and produces the diagnostic path. Cached PER
@@ -145,8 +190,13 @@ function resolveSpawn(
145
190
  env: NodeJS.ProcessEnv,
146
191
  ): {command: string; env: NodeJS.ProcessEnv} {
147
192
  const hardenedEnv = envWithSystemPath(env);
148
- const resolved = command === 'git' ? resolveGitBinary(hardenedEnv) : command;
149
- return {command: resolved, env: hardenedEnv};
193
+ if (command !== 'git') {
194
+ return {command, env: hardenedEnv};
195
+ }
196
+ // In the CI `agent` phase, the job's read token rides on this ONE git child
197
+ // process (never `.git/config`); a no-op otherwise. See `ci-read-token.ts`.
198
+ const gitEnv = gitChildEnv(hardenedEnv);
199
+ return {command: resolveGitBinary(gitEnv), env: gitEnv};
150
200
  }
151
201
 
152
202
  /**
@@ -261,6 +311,34 @@ export function git(
261
311
  return result.stdout;
262
312
  }
263
313
 
314
+ /**
315
+ * Run `git <args>` in `cwd` and return its stdout as raw BYTES (no text
316
+ * decoding), for output that mixes headers with object contents (`cat-file
317
+ * --batch`). Throws on a non-zero exit, like {@link git}.
318
+ */
319
+ export function gitBytes(
320
+ args: string[],
321
+ cwd: string,
322
+ options: {input?: string; env?: NodeJS.ProcessEnv} = {},
323
+ ): Buffer {
324
+ const {command: exe, env} = resolveSpawn('git', options.env ?? process.env);
325
+ const result = spawnSync(exe, args, {
326
+ cwd,
327
+ input: options.input,
328
+ env,
329
+ maxBuffer: 64 * 1024 * 1024,
330
+ });
331
+ if (result.error) {
332
+ throw new Error(spawnErrorMessage('git', exe, env, result.error));
333
+ }
334
+ if (result.status !== 0) {
335
+ throw new Error(
336
+ `git ${args.join(' ')} failed (exit ${result.status}): ${String(result.stderr).trim()}`,
337
+ );
338
+ }
339
+ return result.stdout;
340
+ }
341
+
264
342
  /**
265
343
  * Move a tracked file with `git mv`, creating the destination directory first
266
344
  * (`mkdir -p`). The `work/` contract requires this: git does not track empty
package/src/harness.ts CHANGED
@@ -1,4 +1,6 @@
1
1
  import {spawnSync} from 'node:child_process';
2
+ import {agentEnvFor} from './agent-env.js';
3
+ import {assertAgentOrRepoCodeAllowed} from './phase.js';
2
4
 
3
5
  /**
4
6
  * The **harness seam** (ADR §5): how a job's command is launched and how its
@@ -214,17 +216,32 @@ export interface LaunchResult {
214
216
  * **The model OUTPUT-CAP signal** (observation
215
217
  * `tasker-review-edits-payload-caps-the-verdict-response`): present iff the
216
218
  * adapter detected the agent's final assistant turn was TRUNCATED at the
217
- * model's output-token cap before it finished — i.e. its `stop_reason` is not a
218
- * natural turn-end (`null`/`None`/`max_tokens`) AND it produced a positive
219
- * `usage.output` token count. The value is that token count (the observed cap).
219
+ * model's output-token cap before it finished — i.e. its stop reason is the
220
+ * cap signal (pi's `stopReason: 'length'`, or a raw `max_tokens`) AND it
221
+ * produced a positive `usage.output` token count. A normal end, an error, or no
222
+ * recorded stop reason is NOT a cap. The value is that token count (the observed cap).
220
223
  * A gate that fails to parse a verdict AND sees this signal names the failure
221
224
  * a cap-truncation (NOT a generic parse error) so an operator does not mis-read
222
225
  * it as a model flake and retry blindly. `undefined` when the adapter has no
223
- * usage/stop_reason telemetry (the null/shell adapter) or the turn ended
224
- * naturally — in which case a parse failure stays the generic `ReviewParseError`
226
+ * usage/stop-reason telemetry (the null/shell adapter) or the turn did not
227
+ * hit the cap — in which case a parse failure stays the generic `ReviewParseError`
225
228
  * (still needs-attention, NEVER a silent approve).
226
229
  */
227
230
  outputCapped?: number;
231
+ /**
232
+ * **The agent's FINAL model turn was CUT OFF** (task
233
+ * `a-truncated-agent-turn-routes-as-agent-failed`, observation
234
+ * `a-truncated-model-turn-is-read-as-nothing-to-do-and-defaults-to-cancel`):
235
+ * present iff the LAST assistant message of the run (whatever it carried: text,
236
+ * a tool call, or only a thinking block) ended with a `length` (the per-turn
237
+ * output-token cap) or `error` (a provider error) stop rather than a normal end
238
+ * of turn. The run ending there is a HARNESS failure, not the agent's judgement
239
+ * that there was nothing to build, so the build pipelines route an empty diff
240
+ * with this signal as `agent-failed` instead of the empty-diff STOP backstop.
241
+ * `undefined` when the final turn ended normally or the adapter has no
242
+ * stop-reason telemetry (the null/shell adapter).
243
+ */
244
+ cutOffTurn?: CutOffTurn;
228
245
  /**
229
246
  * **The verified outcome of reaping the agent's process TREE** after a deadline
230
247
  * stop (observation
@@ -242,6 +259,17 @@ export interface LaunchResult {
242
259
  reap?: AgentTreeReap;
243
260
  }
244
261
 
262
+ /**
263
+ * Why the agent's final model turn ended abnormally (see
264
+ * {@link LaunchResult.cutOffTurn}): `length` = the turn hit the model's per-turn
265
+ * output-token cap; `error` = the provider ended the turn with an error.
266
+ * `errorMessage` is the provider's error text when the session recorded one.
267
+ */
268
+ export interface CutOffTurn {
269
+ cause: 'length' | 'error';
270
+ errorMessage?: string;
271
+ }
272
+
245
273
  /**
246
274
  * The harness-reported result of reaping a stopped agent's process tree — the
247
275
  * adapter-agnostic projection of `reap-agent-tree.ts`'s `ReapResult`.
@@ -296,6 +324,26 @@ export function isBenignPromptWriteError(error: Error): boolean {
296
324
  return (error as NodeJS.ErrnoException).code === 'EPIPE';
297
325
  }
298
326
 
327
+ /**
328
+ * The environment an autonomous AGENT is launched with. In GitHub Actions every
329
+ * GitHub credential is removed (`GH_TOKEN`, `GITHUB_TOKEN`, `DORFL_GH_TOKEN`,
330
+ * any value containing a GitHub token, the Actions OIDC/runtime tokens, the
331
+ * runner command files, and git env config carrying a credential; see
332
+ * `agent-env.ts`). Applied INSIDE every adapter's autonomous launch, so no
333
+ * caller and no workflow can hand a CI agent the token by accident. On a laptop
334
+ * the caller's env passes through unchanged.
335
+ *
336
+ * PHASE GUARD: throws a `PhaseGuardError` in the CI `lock` and `apply` phases
337
+ * (their jobs hold the write token, so no agent may launch there; see
338
+ * `phase.ts`).
339
+ */
340
+ export function agentLaunchEnv(
341
+ env: NodeJS.ProcessEnv | undefined,
342
+ ): NodeJS.ProcessEnv {
343
+ assertAgentOrRepoCodeAllowed('agent-launch-env');
344
+ return agentEnvFor(env ?? process.env);
345
+ }
346
+
299
347
  /**
300
348
  * The **null adapter**: runs the configured command synchronously to completion
301
349
  * in the job dir, recording the PID. Liveness is `process.kill(pid, 0)` against
@@ -307,6 +355,8 @@ export class NullHarness implements Harness {
307
355
  readonly adapter = 'null';
308
356
 
309
357
  launch(input: LaunchInput): LaunchResult {
358
+ // PHASE GUARD first: no launch at all in the CI lock/apply phases.
359
+ assertAgentOrRepoCodeAllowed('harness-launch');
310
360
  // BACKSTOP (config error, NOT a spawn failure): an empty/whitespace command
311
361
  // resolves the null adapter to `bash -c ''`, which exits 0 with no output — a
312
362
  // "successful" build that ran NOTHING. The `do`/`run`/`--remote` CLI sites
@@ -328,7 +378,8 @@ export class NullHarness implements Harness {
328
378
  cwd: input.dir,
329
379
  encoding: 'utf8',
330
380
  input: input.prompt,
331
- env: input.env ?? process.env,
381
+ // No GitHub token reaches a CI agent (see agentLaunchEnv).
382
+ env: agentLaunchEnv(input.env),
332
383
  maxBuffer: 64 * 1024 * 1024,
333
384
  });
334
385
  if (result.error && !isBenignPromptWriteError(result.error)) {
@@ -366,6 +417,7 @@ export class NullHarness implements Harness {
366
417
  * shelling out the wrong way.
367
418
  */
368
419
  launchInteractive(_input: InteractiveLaunchInput): InteractiveLaunchResult {
420
+ assertAgentOrRepoCodeAllowed('harness-launch');
369
421
  throw new Error(
370
422
  'interactive launch requires the pi harness; configure `harness: pi` ' +
371
423
  '(the null/shell adapter only supports the captured autonomous launch).',
package/src/index.ts CHANGED
@@ -200,6 +200,50 @@ export type {
200
200
  LedgerWriteStrategy,
201
201
  } from './ledger-write.js';
202
202
  export {currentLedgerWrite, ledgerWrite} from './ledger-write.js';
203
+ export type {
204
+ RefWriteStrategy,
205
+ LockRefCreateInput,
206
+ LockRefDeleteInput,
207
+ ContinuedBranchPushInput,
208
+ TaskingCandidatesPushInput,
209
+ } from './ref-write.js';
210
+ export {currentRefWrite, refWrite} from './ref-write.js';
211
+
212
+ export type {Phase, GuardedOperation} from './phase.js';
213
+ export {
214
+ PHASES,
215
+ AGENT_SPAWNING_VERBS,
216
+ NON_AGENT_VERBS,
217
+ PhaseGuardError,
218
+ PhaseUsageError,
219
+ parsePhase,
220
+ activePhase,
221
+ enterPhase,
222
+ assertAgentOrRepoCodeAllowed,
223
+ } from './phase.js';
224
+ export type {
225
+ WriteSeamName,
226
+ WriteSeamCall,
227
+ RecordedWriteIntent,
228
+ PhaseRecorder,
229
+ AgentPhaseOutcome,
230
+ } from './phase-recorder.js';
231
+ export {
232
+ PhaseHaltSentinel,
233
+ UnrecordedWriteError,
234
+ createPhaseRecorder,
235
+ installRecordingSeams,
236
+ recordingReviewProvider,
237
+ recordingIssueProvider,
238
+ runAgentPhase,
239
+ activateProcessPhase,
240
+ } from './phase-recorder.js';
241
+ export {
242
+ resolveReadToken,
243
+ readTokenHeaderKey,
244
+ withReadTokenGitConfig,
245
+ gitChildEnv,
246
+ } from './ci-read-token.js';
203
247
 
204
248
  export type {ReadyItem, ScannedItem, RepoReport, ScanReport} from './scan.js';
205
249
  export {scan, scanRepoPaths, readReadyItems, readDoneSlugs} from './scan.js';
@@ -331,6 +375,7 @@ export type {
331
375
  ReleaseHeldResult,
332
376
  LockReportEntry,
333
377
  ItemLockReport,
378
+ LockKeptFor,
334
379
  } from './item-lock.js';
335
380
  export {
336
381
  LOCK_REF_PREFIX,
@@ -352,6 +397,9 @@ export {
352
397
  listItemLocks,
353
398
  listItemLockEntries,
354
399
  heldTaskSlugs,
400
+ proposeKeptTaskSlugs,
401
+ markLockKeptForProposePr,
402
+ takeOverProposeKeptLock,
355
403
  resolveLockHolder,
356
404
  serialiseLockEntry,
357
405
  parseLockEntry,
@@ -501,6 +549,7 @@ export {
501
549
  encodeWorkId,
502
550
  jobWorktreePath,
503
551
  createJob,
552
+ RetainedWorktreeUnsavedWorkError,
504
553
  writeJobRecord,
505
554
  readJobRecord,
506
555
  updateJobRecord,
@@ -797,7 +846,7 @@ export {
797
846
  resolveCIConfig,
798
847
  exportCIConfig,
799
848
  generateSetupAction,
800
- REFRESH_OAUTH_SCRIPT,
849
+ AUTH_JSON_REMOVED_MESSAGE,
801
850
  buildSetupArtifacts,
802
851
  outputBaseName,
803
852
  writeArtifacts,