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
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ci-handoff.d.ts","sourceRoot":"","sources":["../src/ci-handoff.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAmBH,OAAO,EAMN,KAAK,aAAa,EAClB,KAAK,WAAW,EAChB,KAAK,YAAY,EACjB,KAAK,SAAS,EACd,MAAM,wBAAwB,CAAC;AAEhC,uCAAuC;AACvC,eAAO,MAAM,YAAY,iBAAiB,CAAC;AAC3C,sEAAsE;AACtE,eAAO,MAAM,cAAc,gBAAgB,CAAC;AAC5C,sDAAsD;AACtD,eAAO,MAAM,eAAe,QAAQ,CAAC;AAYrC,mFAAmF;AACnF,MAAM,WAAW,YAAY;IAC5B,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,MAAM,CAAC;IACZ,aAAa,EAAE,MAAM,EAAE,CAAC;CACxB;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,YAAY,CA8B5D;AAgFD,mEAAmE;AACnE,MAAM,WAAW,mBAAmB;IACnC,iDAAiD;IACjD,IAAI,EAAE,MAAM,CAAC;IACb,+EAA+E;IAC/E,UAAU,EAAE,MAAM,CAAC;IACnB,oEAAoE;IACpE,OAAO,EAAE,MAAM,CAAC;CAChB;AAED;;;;;;;;GAQG;AACH,wBAAgB,YAAY,CAAC,MAAM,EAAE;IACpC,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,WAAW,CAAC;IAClB,MAAM,EAAE,aAAa,CAAC;IACtB,MAAM,CAAC,EAAE,mBAAmB,CAAC;CAC7B,GAAG;IAAC,UAAU,EAAE,MAAM,EAAE,CAAA;CAAC,CA0BzB;AAkCD,+EAA+E;AAC/E,MAAM,WAAW,gBAAgB;IAChC,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;CACb;AAED,iCAAiC;AACjC,MAAM,WAAW,WAAW;IAC3B,MAAM,EAAE,aAAa,CAAC;IACtB,6DAA6D;IAC7D,GAAG,EAAE,SAAS,CAAC;IACf,2EAA2E;IAC3E,MAAM,CAAC,EAAE;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAC,GAAG,YAAY,CAAC;IACrD,UAAU,EAAE,gBAAgB,EAAE,CAAC;CAC/B;AAED;;;;;;;;GAQG;AACH,wBAAgB,WAAW,CAAC,MAAM,EAAE;IACnC,GAAG,EAAE,MAAM,CAAC;IACZ,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,YAAY,CAAC;CACpB,GAAG,WAAW,CAuFd"}
@@ -0,0 +1,277 @@
1
+ /**
2
+ * **The CI handoff artifact on disk**: the writer (agent job) and the safe
3
+ * reader (apply job). The record format and its intent table are
4
+ * `ci-handoff-format.ts`.
5
+ *
6
+ * The artifact directory holds exactly:
7
+ *
8
+ * - `handoff.json`: the record;
9
+ * - `work.bundle`: for code-carrying intents only, `git bundle create
10
+ * work.bundle <work-branch> ^<baseSha>`, exactly one ref;
11
+ * - `lfs/<oid>`: the object of every LFS pointer the bundle's new commits
12
+ * add or change (`ci-handoff-lfs.ts`; the reader here checks only their
13
+ * names and sizes, the apply validation checks them against the pointers).
14
+ *
15
+ * The reader treats the directory as HOSTILE (the agent controls everything in
16
+ * its job): it must sit under `$RUNNER_TEMP`, only those names are read, a
17
+ * symlink or any other entry rejects the whole handoff, files are opened with
18
+ * `O_NOFOLLOW`, and every size limit is checked before anything is parsed. The
19
+ * bundle header is parsed here without running git on hostile bytes; the
20
+ * bundle's CONTENT (history, protected paths) is task
21
+ * `ci-split-apply-rejects-hostile-bundle`.
22
+ */
23
+ import { closeSync, constants as fsConstants, fstatSync, lstatSync, mkdirSync, openSync, readdirSync, readSync, realpathSync, statSync, writeFileSync, } from 'node:fs';
24
+ import { isAbsolute, join, relative, sep } from 'node:path';
25
+ import { git } from './git.js';
26
+ import { writeLfsObjects } from './ci-handoff-lfs.js';
27
+ import { canonicalHandoffItem, handoffByteLimits, rejectHandoff as reject, validateHandoffRecord, } from './ci-handoff-format.js';
28
+ /** The record file of the artifact. */
29
+ export const HANDOFF_JSON = 'handoff.json';
30
+ /** The git bundle of the work branch (code-carrying intents only). */
31
+ export const HANDOFF_BUNDLE = 'work.bundle';
32
+ /** The directory of LFS objects, one file per oid. */
33
+ export const HANDOFF_LFS_DIR = 'lfs';
34
+ /** The most a bundle header (signature, capabilities, prerequisites, one ref) may take. */
35
+ const MAX_BUNDLE_HEADER_BYTES = 64 * 1024;
36
+ const HEX_OID = /^(?:[0-9a-f]{40}|[0-9a-f]{64})$/;
37
+ const LFS_OID = /^[0-9a-f]{64}$/;
38
+ /**
39
+ * Parse the header of a git bundle (v2, or v3 with only `@object-format`)
40
+ * without running git, and require exactly one ref.
41
+ */
42
+ export function parseBundleHeader(head) {
43
+ const end = head.indexOf('\n\n');
44
+ if (end === -1)
45
+ reject('bundle-format', 'no bundle header terminator');
46
+ const lines = head.subarray(0, end).toString('latin1').split('\n');
47
+ const signature = lines.shift();
48
+ const v3 = signature === '# v3 git bundle';
49
+ if (signature !== '# v2 git bundle' && !v3) {
50
+ reject('bundle-format', 'not a v2 or v3 git bundle');
51
+ }
52
+ const prerequisites = [];
53
+ const refs = [];
54
+ for (const l of lines) {
55
+ if (l.startsWith('@')) {
56
+ if (!v3 || !/^@object-format=(?:sha1|sha256)$/.test(l)) {
57
+ reject('bundle-format', 'unsupported bundle capability');
58
+ }
59
+ }
60
+ else if (l.startsWith('-')) {
61
+ const oid = l.slice(1).split(' ', 1)[0];
62
+ if (!HEX_OID.test(oid))
63
+ reject('bundle-format', 'bad prerequisite line');
64
+ prerequisites.push(oid);
65
+ }
66
+ else {
67
+ const m = /^([0-9a-f]{40}|[0-9a-f]{64}) (refs\/[\x21-\x7e]+)$/.exec(l);
68
+ if (m === null)
69
+ reject('bundle-format', 'bad bundle ref line');
70
+ refs.push({ tip: m[1], ref: m[2] });
71
+ }
72
+ }
73
+ if (refs.length !== 1) {
74
+ reject('bundle-refs', `the bundle carries ${refs.length} refs, not 1`);
75
+ }
76
+ return { ...refs[0], prerequisites };
77
+ }
78
+ // ---------------------------------------------------------------------------
79
+ // Low-level safe reads
80
+ // ---------------------------------------------------------------------------
81
+ /** Open a path for reading, refusing a symlink at open time (`O_NOFOLLOW`). */
82
+ function openNoFollow(path, name) {
83
+ try {
84
+ return openSync(path, fsConstants.O_RDONLY | fsConstants.O_NOFOLLOW);
85
+ }
86
+ catch {
87
+ reject('symlink', `${name} could not be opened as a regular file`);
88
+ }
89
+ }
90
+ /**
91
+ * Read a regular file of at most `max` bytes (whole, or only its first
92
+ * `headOnly` bytes), refusing a symlink and re-checking the size on the open
93
+ * descriptor so a file swapped after the directory scan is still bounded.
94
+ */
95
+ function readBounded(path, name, max, headOnly) {
96
+ const fd = openNoFollow(path, name);
97
+ try {
98
+ const st = fstatSync(fd);
99
+ if (!st.isFile())
100
+ reject('layout', `${name} is not a regular file`);
101
+ if (st.size > max)
102
+ reject('size', `${name} is over ${max} bytes`);
103
+ const want = headOnly ?? max + 1;
104
+ const buf = Buffer.alloc(Math.min(want, st.size + 1));
105
+ const n = readSync(fd, buf, 0, buf.length, 0);
106
+ if (headOnly === undefined && n > max) {
107
+ reject('size', `${name} is over ${max} bytes`);
108
+ }
109
+ return buf.subarray(0, n);
110
+ }
111
+ finally {
112
+ closeSync(fd);
113
+ }
114
+ }
115
+ /** `lstat` an entry; refuse a symlink or an entry of the wrong type. */
116
+ function entryStat(path, name, want) {
117
+ const st = lstatSync(path);
118
+ if (st.isSymbolicLink())
119
+ reject('symlink', `${name} is a symlink`);
120
+ const ok = want === 'file' ? st.isFile() : st.isDirectory();
121
+ if (!ok) {
122
+ reject('layout', `${name} is not a ${want === 'file' ? 'file' : 'directory'}`);
123
+ }
124
+ return st;
125
+ }
126
+ function isStrictlyInside(root, path) {
127
+ const rel = relative(root, path);
128
+ return (rel !== '' &&
129
+ rel !== '..' &&
130
+ !rel.startsWith(`..${sep}`) &&
131
+ !isAbsolute(rel));
132
+ }
133
+ function checkBundlePresence(row, present) {
134
+ if (row.bundle.rule === 'required' && !present) {
135
+ reject('bundle-presence', `${row.kind} needs ${HANDOFF_BUNDLE}`);
136
+ }
137
+ if (row.bundle.rule === 'none' && present) {
138
+ reject('bundle-presence', `${row.kind} carries no ${HANDOFF_BUNDLE}`);
139
+ }
140
+ }
141
+ /**
142
+ * Write the handoff into `dir` (created, and required to be empty): validate
143
+ * the record exactly as the reader will, then write `handoff.json` and, for a
144
+ * code-carrying intent, `work.bundle` with exactly one ref, and `lfs/<oid>` for
145
+ * the object of every LFS pointer its new commits add or change (from the
146
+ * local store; one the store lacks is left out and returned in `lfsMissing`,
147
+ * and the apply job then rejects the handoff naming it). The record's item is
148
+ * written in its canonical form.
149
+ */
150
+ export function writeHandoff(params) {
151
+ const { dir, rung, bundle } = params;
152
+ const item = canonicalHandoffItem(params.record.item);
153
+ const json = JSON.stringify({ ...params.record, item });
154
+ const { row } = validateHandoffRecord(JSON.parse(json), { item, rung });
155
+ checkBundlePresence(row, bundle !== undefined);
156
+ if (Buffer.byteLength(json) > handoffByteLimits().handoffJsonBytes) {
157
+ reject('size', `${HANDOFF_JSON} is over ${handoffByteLimits().handoffJsonBytes} bytes`);
158
+ }
159
+ mkdirSync(dir, { recursive: true });
160
+ if (readdirSync(dir).length > 0) {
161
+ reject('layout', `the handoff directory ${dir} is not empty`);
162
+ }
163
+ writeFileSync(join(dir, HANDOFF_JSON), json);
164
+ if (bundle === undefined)
165
+ return { lfsMissing: [] };
166
+ writeBundle(dir, bundle);
167
+ const { missing } = writeLfsObjects({
168
+ dir,
169
+ repo: bundle.repo,
170
+ ref: `refs/heads/${bundle.workBranch}`,
171
+ baseSha: bundle.baseSha,
172
+ });
173
+ return { lfsMissing: missing };
174
+ }
175
+ /** `git bundle create work.bundle refs/heads/<branch> ^<baseSha>`, then check it. */
176
+ function writeBundle(dir, source) {
177
+ if (!HEX_OID.test(source.baseSha)) {
178
+ reject('bundle-format', 'baseSha is not a full commit id');
179
+ }
180
+ const ref = `refs/heads/${source.workBranch}`;
181
+ git(['check-ref-format', ref], source.repo);
182
+ const out = join(dir, HANDOFF_BUNDLE);
183
+ git(['bundle', 'create', out, ref, `^${source.baseSha}`], source.repo);
184
+ const header = parseBundleHeader(readBounded(out, HANDOFF_BUNDLE, Number.MAX_SAFE_INTEGER, MAX_BUNDLE_HEADER_BYTES));
185
+ if (header.ref !== ref) {
186
+ reject('bundle-refs', `the bundle carries ${header.ref}, not ${ref}`);
187
+ }
188
+ if (statSync(out).size > handoffByteLimits().bundleBytes) {
189
+ reject('size', `${HANDOFF_BUNDLE} is over ${handoffByteLimits().bundleBytes} bytes`);
190
+ }
191
+ }
192
+ /**
193
+ * Read and validate the handoff the agent job uploaded. `dir` is where the
194
+ * artifact was downloaded: a real directory strictly inside `runnerTemp`
195
+ * (`$RUNNER_TEMP`). Rejects ({@link HandoffRejected}) a symlink anywhere, any
196
+ * entry but `handoff.json`, `work.bundle` and `lfs/<64-hex oid>`, any size over
197
+ * the byte limits (`handoffByteLimits`), a record that fails `validateHandoffRecord`, a bundle
198
+ * the intent forbids or lacks, `lfs/` without a bundle, and a bundle whose
199
+ * header is malformed or carries other than one ref.
200
+ */
201
+ export function readHandoff(params) {
202
+ const { dir, runnerTemp, trust } = params;
203
+ const rootStat = lstatSync(dir, { throwIfNoEntry: false });
204
+ if (rootStat === undefined) {
205
+ reject('layout', 'the handoff directory is missing');
206
+ }
207
+ if (rootStat.isSymbolicLink()) {
208
+ reject('symlink', 'the handoff directory is a symlink');
209
+ }
210
+ if (!rootStat.isDirectory()) {
211
+ reject('layout', 'the handoff path is not a directory');
212
+ }
213
+ if (!isStrictlyInside(realpathSync(runnerTemp), realpathSync(dir))) {
214
+ reject('location', 'the handoff directory is not under $RUNNER_TEMP');
215
+ }
216
+ let total = 0;
217
+ let hasJson = false;
218
+ let hasBundle = false;
219
+ let lfsTotal = 0;
220
+ const lfsObjects = [];
221
+ for (const name of readdirSync(dir)) {
222
+ const path = join(dir, name);
223
+ if (name === HANDOFF_JSON) {
224
+ total += entryStat(path, name, 'file').size;
225
+ hasJson = true;
226
+ }
227
+ else if (name === HANDOFF_BUNDLE) {
228
+ total += entryStat(path, name, 'file').size;
229
+ hasBundle = true;
230
+ }
231
+ else if (name === HANDOFF_LFS_DIR) {
232
+ entryStat(path, name, 'dir');
233
+ for (const oid of readdirSync(path)) {
234
+ const objName = `${HANDOFF_LFS_DIR}/${JSON.stringify(oid).slice(0, 80)}`;
235
+ if (!LFS_OID.test(oid))
236
+ reject('layout', `unexpected entry ${objName}`);
237
+ const objPath = join(path, oid);
238
+ const size = entryStat(objPath, objName, 'file').size;
239
+ lfsTotal += size;
240
+ lfsObjects.push({ oid, path: objPath, size });
241
+ }
242
+ }
243
+ else {
244
+ reject('layout', `unexpected entry ${JSON.stringify(name).slice(0, 80)}`);
245
+ }
246
+ }
247
+ if (!hasJson)
248
+ reject('layout', `${HANDOFF_JSON} is missing`);
249
+ if (lfsTotal > handoffByteLimits().lfsBytes) {
250
+ reject('size', `the LFS objects are over ${handoffByteLimits().lfsBytes} bytes`);
251
+ }
252
+ total += lfsTotal;
253
+ if (total > handoffByteLimits().artifactBytes) {
254
+ reject('size', `the artifact is over ${handoffByteLimits().artifactBytes} bytes`);
255
+ }
256
+ if (lfsObjects.length > 0 && !hasBundle) {
257
+ reject('layout', `${HANDOFF_LFS_DIR}/ without ${HANDOFF_BUNDLE}`);
258
+ }
259
+ const raw = readBounded(join(dir, HANDOFF_JSON), HANDOFF_JSON, handoffByteLimits().handoffJsonBytes);
260
+ let parsed;
261
+ try {
262
+ parsed = JSON.parse(raw.toString('utf8'));
263
+ }
264
+ catch {
265
+ reject('json', `${HANDOFF_JSON} is not valid JSON`);
266
+ }
267
+ const { record, row } = validateHandoffRecord(parsed, trust);
268
+ checkBundlePresence(row, hasBundle);
269
+ let bundle;
270
+ if (hasBundle) {
271
+ const path = join(dir, HANDOFF_BUNDLE);
272
+ const head = readBounded(path, HANDOFF_BUNDLE, handoffByteLimits().bundleBytes, MAX_BUNDLE_HEADER_BYTES);
273
+ bundle = { path, size: lstatSync(path).size, ...parseBundleHeader(head) };
274
+ }
275
+ return { record, row, bundle, lfsObjects };
276
+ }
277
+ //# sourceMappingURL=ci-handoff.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ci-handoff.js","sourceRoot":"","sources":["../src/ci-handoff.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,93 @@
1
+ /**
2
+ * **The lock job's `$GITHUB_OUTPUT` facts** (spec
3
+ * `ci-agent-job-without-write-token`).
4
+ *
5
+ * The lock job's outputs are the apply job's TRUSTED channel
6
+ * (`needs.lock.outputs.*`): they choose refs, rungs and artifact names. So the
7
+ * serializer emits only values that cannot carry attacker text: commit ids,
8
+ * enums, booleans, bounded integers (the agent timeout), provider-assigned
9
+ * comment ids and the dorfl-derived artifact name. Every key is known here with its type, and every
10
+ * value is re-checked at runtime (a TypeScript type does not stop a string read
11
+ * from an issue), so free text such as an issue title is REFUSED, never
12
+ * escaped.
13
+ */
14
+ import type { IntegrationMode } from './config.js';
15
+ import { type HandoffRung } from './ci-handoff-format.js';
16
+ /** The facts a lock job publishes (task `ci-split-generate-workflows` lists them). */
17
+ export interface LockOutputs {
18
+ /** Whether the lock job took the item's locks. */
19
+ acquired?: boolean;
20
+ /** `false` when the rung runs no agent (decision 11). */
21
+ needsAgent?: boolean;
22
+ /** The classified rung. */
23
+ rung?: HandoffRung;
24
+ /** The arbiter's `main` tip the item was classified against. */
25
+ baseSha?: string;
26
+ /** The lock ref's sha after the acquire. */
27
+ lockSha?: string;
28
+ /** The kept work branch's tip, when one exists (decision 7). */
29
+ continueTip?: string;
30
+ /** The artifact name (`handoffName`). */
31
+ handoffName?: string;
32
+ /** The agent job's timeout, from `dorfl.json` at `baseSha`. */
33
+ agentTimeoutMinutes?: number;
34
+ /** The intake origin trust. */
35
+ originTrust?: 'trusted' | 'untrusted';
36
+ /** The intake document mode. */
37
+ documentMode?: IntegrationMode;
38
+ /**
39
+ * The issue comment ids the lock job read (intake), as the issue provider
40
+ * reports them: a REST database id (a positive integer) or a GraphQL node id
41
+ * (`IC_kwDO...`, what `gh issue view --json comments` reports). A parsed
42
+ * integer id stays a number; a node id is a string.
43
+ */
44
+ seenCommentIds?: Array<number | string>;
45
+ }
46
+ /** A lock output the serializer will not emit. */
47
+ export declare class LockOutputRefused extends Error {
48
+ constructor(message: string);
49
+ }
50
+ /** The largest agent timeout accepted (GitHub's self-hosted job maximum: 5 days). */
51
+ export declare const MAX_AGENT_TIMEOUT_MINUTES = 7200;
52
+ /** The most comment ids one output may list. */
53
+ export declare const MAX_SEEN_COMMENT_IDS = 5000;
54
+ /**
55
+ * Every lock output key, in output order. The generated lock job declares
56
+ * exactly these as its job `outputs` (task `ci-split-generate-workflows`), so
57
+ * `toJSON(needs.lock.outputs)` carries no key {@link parseLockOutputs} refuses.
58
+ */
59
+ export declare const LOCK_OUTPUT_KEYS: ReadonlyArray<keyof LockOutputs>;
60
+ /**
61
+ * Serialize lock facts as `$GITHUB_OUTPUT` lines (`key=value\n`, in a fixed
62
+ * order; an `undefined` fact is omitted). Throws {@link LockOutputRefused} for
63
+ * an unknown key or any value outside its type, so free text never reaches the
64
+ * trusted channel.
65
+ */
66
+ export declare function serializeLockOutputs(facts: LockOutputs): string;
67
+ /**
68
+ * The environment variable the agent and apply jobs receive the lock job's
69
+ * outputs in: the JSON object `toJSON(needs.lock.outputs)` (every value a
70
+ * string, an unset output an empty string), passed through `env:` like every
71
+ * other value that reaches a `run:` script.
72
+ */
73
+ export declare const LOCK_OUTPUTS_ENV = "DORFL_LOCK_OUTPUTS";
74
+ /**
75
+ * Parse the lock job's outputs as the agent and apply jobs receive them (a
76
+ * `key -> string` object), re-checking every value with the same rules
77
+ * {@link serializeLockOutputs} applied. An empty string is an unset output
78
+ * (GitHub renders an output the job never wrote as `''`). Throws
79
+ * {@link LockOutputRefused} for an unknown key or a malformed value.
80
+ */
81
+ export declare function parseLockOutputs(raw: unknown): LockOutputs;
82
+ /**
83
+ * Parse `$GITHUB_OUTPUT` lines as {@link serializeLockOutputs} writes them
84
+ * (`key=value`, one per line), for tests and local replays of the lock job.
85
+ */
86
+ export declare function parseLockOutputLines(text: string): LockOutputs;
87
+ /**
88
+ * Read the lock job's outputs from {@link LOCK_OUTPUTS_ENV}. Throws
89
+ * {@link LockOutputRefused} when it is missing or malformed: the agent and
90
+ * apply phases act on nothing but these trusted facts.
91
+ */
92
+ export declare function readLockOutputsFromEnv(env: NodeJS.ProcessEnv): LockOutputs;
93
+ //# sourceMappingURL=ci-lock-outputs.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ci-lock-outputs.d.ts","sourceRoot":"","sources":["../src/ci-lock-outputs.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAK,EAAC,eAAe,EAAC,MAAM,aAAa,CAAC;AACjD,OAAO,EAGN,KAAK,WAAW,EAChB,MAAM,wBAAwB,CAAC;AAEhC,sFAAsF;AACtF,MAAM,WAAW,WAAW;IAC3B,kDAAkD;IAClD,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,yDAAyD;IACzD,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,2BAA2B;IAC3B,IAAI,CAAC,EAAE,WAAW,CAAC;IACnB,gEAAgE;IAChE,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,4CAA4C;IAC5C,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,gEAAgE;IAChE,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,yCAAyC;IACzC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,+DAA+D;IAC/D,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,+BAA+B;IAC/B,WAAW,CAAC,EAAE,SAAS,GAAG,WAAW,CAAC;IACtC,gCAAgC;IAChC,YAAY,CAAC,EAAE,eAAe,CAAC;IAC/B;;;;;OAKG;IACH,cAAc,CAAC,EAAE,KAAK,CAAC,MAAM,GAAG,MAAM,CAAC,CAAC;CACxC;AAED,kDAAkD;AAClD,qBAAa,iBAAkB,SAAQ,KAAK;gBAC/B,OAAO,EAAE,MAAM;CAI3B;AAED,qFAAqF;AACrF,eAAO,MAAM,yBAAyB,OAAO,CAAC;AAC9C,gDAAgD;AAChD,eAAO,MAAM,oBAAoB,OAAO,CAAC;AAyEzC;;;;GAIG;AACH,eAAO,MAAM,gBAAgB,EAA0B,aAAa,CACnE,MAAM,WAAW,CACjB,CAAC;AAEF;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,WAAW,GAAG,MAAM,CAa/D;AAMD;;;;;GAKG;AACH,eAAO,MAAM,gBAAgB,uBAAuB,CAAC;AAuCrD;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,OAAO,GAAG,WAAW,CAc1D;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,GAAG,WAAW,CAS9D;AAED;;;;GAIG;AACH,wBAAgB,sBAAsB,CAAC,GAAG,EAAE,MAAM,CAAC,UAAU,GAAG,WAAW,CAc1E"}
@@ -0,0 +1,223 @@
1
+ /**
2
+ * **The lock job's `$GITHUB_OUTPUT` facts** (spec
3
+ * `ci-agent-job-without-write-token`).
4
+ *
5
+ * The lock job's outputs are the apply job's TRUSTED channel
6
+ * (`needs.lock.outputs.*`): they choose refs, rungs and artifact names. So the
7
+ * serializer emits only values that cannot carry attacker text: commit ids,
8
+ * enums, booleans, bounded integers (the agent timeout), provider-assigned
9
+ * comment ids and the dorfl-derived artifact name. Every key is known here with its type, and every
10
+ * value is re-checked at runtime (a TypeScript type does not stop a string read
11
+ * from an issue), so free text such as an issue title is REFUSED, never
12
+ * escaped.
13
+ */
14
+ import { HANDOFF_NAME_RE, HANDOFF_RUNGS, } from './ci-handoff-format.js';
15
+ /** A lock output the serializer will not emit. */
16
+ export class LockOutputRefused extends Error {
17
+ constructor(message) {
18
+ super(`lock output refused: ${message}`);
19
+ this.name = 'LockOutputRefused';
20
+ }
21
+ }
22
+ /** The largest agent timeout accepted (GitHub's self-hosted job maximum: 5 days). */
23
+ export const MAX_AGENT_TIMEOUT_MINUTES = 7200;
24
+ /** The most comment ids one output may list. */
25
+ export const MAX_SEEN_COMMENT_IDS = 5000;
26
+ const SHA_RE = /^(?:[0-9a-f]{40}|[0-9a-f]{64})$/;
27
+ /**
28
+ * A GitHub GraphQL node id (`IC_kwDODKw3uc7tpgEC`): an upper-case type prefix,
29
+ * `_`, then URL-safe base64. Assigned by GitHub, never chosen by an issue
30
+ * author; the charset holds no `,` (the list separator), `=`, space or line
31
+ * break, so it cannot forge another output line.
32
+ */
33
+ const NODE_ID_RE = /^[A-Z]{1,8}_[A-Za-z0-9_-]{1,80}$/;
34
+ function refuse(key, why) {
35
+ throw new LockOutputRefused(`${key} ${why}`);
36
+ }
37
+ function boolean(key, v) {
38
+ if (typeof v !== 'boolean')
39
+ refuse(key, 'is not a boolean');
40
+ return String(v);
41
+ }
42
+ function sha(key, v) {
43
+ if (typeof v !== 'string' || !SHA_RE.test(v)) {
44
+ refuse(key, 'is not a full lower-case commit id');
45
+ }
46
+ return v;
47
+ }
48
+ function oneOf(values) {
49
+ return (key, v) => {
50
+ if (typeof v !== 'string' || !values.includes(v)) {
51
+ refuse(key, `is not one of ${values.join(', ')}`);
52
+ }
53
+ return v;
54
+ };
55
+ }
56
+ function integer(min, max) {
57
+ return (key, v) => {
58
+ if (typeof v !== 'number' || !Number.isInteger(v) || v < min || v > max) {
59
+ refuse(key, `is not an integer in ${min}..${max}`);
60
+ }
61
+ return String(v);
62
+ };
63
+ }
64
+ /** Every key, in output order, with its value check. */
65
+ const SCHEMA = {
66
+ acquired: boolean,
67
+ needsAgent: boolean,
68
+ rung: oneOf(HANDOFF_RUNGS),
69
+ baseSha: sha,
70
+ lockSha: sha,
71
+ continueTip: sha,
72
+ handoffName: (key, v) => {
73
+ if (typeof v !== 'string' || !HANDOFF_NAME_RE.test(v)) {
74
+ refuse(key, 'is not a dorfl handoff artifact name');
75
+ }
76
+ return v;
77
+ },
78
+ agentTimeoutMinutes: integer(1, MAX_AGENT_TIMEOUT_MINUTES),
79
+ originTrust: oneOf(['trusted', 'untrusted']),
80
+ documentMode: oneOf(['propose', 'merge']),
81
+ seenCommentIds: (key, v) => {
82
+ if (!Array.isArray(v) || v.length > MAX_SEEN_COMMENT_IDS) {
83
+ refuse(key, `is not a list of at most ${MAX_SEEN_COMMENT_IDS} ids`);
84
+ }
85
+ const check = integer(1, Number.MAX_SAFE_INTEGER);
86
+ return v
87
+ .map((id) => typeof id === 'string' && NODE_ID_RE.test(id) ? id : check(key, id))
88
+ .join(',');
89
+ },
90
+ };
91
+ /**
92
+ * Every lock output key, in output order. The generated lock job declares
93
+ * exactly these as its job `outputs` (task `ci-split-generate-workflows`), so
94
+ * `toJSON(needs.lock.outputs)` carries no key {@link parseLockOutputs} refuses.
95
+ */
96
+ export const LOCK_OUTPUT_KEYS = Object.keys(SCHEMA);
97
+ /**
98
+ * Serialize lock facts as `$GITHUB_OUTPUT` lines (`key=value\n`, in a fixed
99
+ * order; an `undefined` fact is omitted). Throws {@link LockOutputRefused} for
100
+ * an unknown key or any value outside its type, so free text never reaches the
101
+ * trusted channel.
102
+ */
103
+ export function serializeLockOutputs(facts) {
104
+ for (const key of Object.keys(facts)) {
105
+ if (!Object.hasOwn(SCHEMA, key)) {
106
+ refuse(JSON.stringify(key).slice(0, 80), 'is not a lock output');
107
+ }
108
+ }
109
+ let out = '';
110
+ for (const [key, check] of Object.entries(SCHEMA)) {
111
+ const v = facts[key];
112
+ if (v === undefined)
113
+ continue;
114
+ out += `${key}=${check(key, v)}\n`;
115
+ }
116
+ return out;
117
+ }
118
+ // ---------------------------------------------------------------------------
119
+ // Reading the facts back (the agent and apply jobs)
120
+ // ---------------------------------------------------------------------------
121
+ /**
122
+ * The environment variable the agent and apply jobs receive the lock job's
123
+ * outputs in: the JSON object `toJSON(needs.lock.outputs)` (every value a
124
+ * string, an unset output an empty string), passed through `env:` like every
125
+ * other value that reaches a `run:` script.
126
+ */
127
+ export const LOCK_OUTPUTS_ENV = 'DORFL_LOCK_OUTPUTS';
128
+ const PARSE = {
129
+ acquired: parseBoolean,
130
+ needsAgent: parseBoolean,
131
+ rung: (key, raw) => {
132
+ SCHEMA.rung(key, raw);
133
+ return raw;
134
+ },
135
+ baseSha: (key, raw) => sha(key, raw),
136
+ lockSha: (key, raw) => sha(key, raw),
137
+ continueTip: (key, raw) => sha(key, raw),
138
+ handoffName: (key, raw) => SCHEMA.handoffName(key, raw),
139
+ agentTimeoutMinutes: (key, raw) => {
140
+ const n = /^[0-9]{1,9}$/.test(raw) ? Number(raw) : Number.NaN;
141
+ SCHEMA.agentTimeoutMinutes(key, n);
142
+ return n;
143
+ },
144
+ originTrust: (key, raw) => SCHEMA.originTrust(key, raw),
145
+ documentMode: (key, raw) => SCHEMA.documentMode(key, raw),
146
+ seenCommentIds: (key, raw) => {
147
+ const ids = raw.split(',').map((part) => {
148
+ if (NODE_ID_RE.test(part))
149
+ return part;
150
+ if (!/^[0-9]{1,16}$/.test(part)) {
151
+ refuse(key, 'is not a comma-separated list of ids');
152
+ }
153
+ return Number(part);
154
+ });
155
+ SCHEMA.seenCommentIds(key, ids);
156
+ return ids;
157
+ },
158
+ };
159
+ function parseBoolean(key, raw) {
160
+ if (raw !== 'true' && raw !== 'false')
161
+ refuse(key, 'is not a boolean');
162
+ return raw === 'true';
163
+ }
164
+ /**
165
+ * Parse the lock job's outputs as the agent and apply jobs receive them (a
166
+ * `key -> string` object), re-checking every value with the same rules
167
+ * {@link serializeLockOutputs} applied. An empty string is an unset output
168
+ * (GitHub renders an output the job never wrote as `''`). Throws
169
+ * {@link LockOutputRefused} for an unknown key or a malformed value.
170
+ */
171
+ export function parseLockOutputs(raw) {
172
+ if (typeof raw !== 'object' || raw === null || Array.isArray(raw)) {
173
+ throw new LockOutputRefused('the lock outputs are not an object');
174
+ }
175
+ const facts = {};
176
+ for (const [key, value] of Object.entries(raw)) {
177
+ if (!Object.hasOwn(PARSE, key)) {
178
+ refuse(JSON.stringify(key).slice(0, 80), 'is not a lock output');
179
+ }
180
+ if (value === '' || value === undefined || value === null)
181
+ continue;
182
+ if (typeof value !== 'string')
183
+ refuse(key, 'is not a string');
184
+ facts[key] = PARSE[key](key, value);
185
+ }
186
+ return facts;
187
+ }
188
+ /**
189
+ * Parse `$GITHUB_OUTPUT` lines as {@link serializeLockOutputs} writes them
190
+ * (`key=value`, one per line), for tests and local replays of the lock job.
191
+ */
192
+ export function parseLockOutputLines(text) {
193
+ const raw = {};
194
+ for (const line of text.split('\n')) {
195
+ if (line === '')
196
+ continue;
197
+ const eq = line.indexOf('=');
198
+ if (eq <= 0)
199
+ throw new LockOutputRefused('a line is not key=value');
200
+ raw[line.slice(0, eq)] = line.slice(eq + 1);
201
+ }
202
+ return parseLockOutputs(raw);
203
+ }
204
+ /**
205
+ * Read the lock job's outputs from {@link LOCK_OUTPUTS_ENV}. Throws
206
+ * {@link LockOutputRefused} when it is missing or malformed: the agent and
207
+ * apply phases act on nothing but these trusted facts.
208
+ */
209
+ export function readLockOutputsFromEnv(env) {
210
+ const raw = env[LOCK_OUTPUTS_ENV];
211
+ if (raw === undefined || raw.trim() === '') {
212
+ throw new LockOutputRefused(`${LOCK_OUTPUTS_ENV} is not set (the lock job's outputs, as JSON)`);
213
+ }
214
+ let parsed;
215
+ try {
216
+ parsed = JSON.parse(raw);
217
+ }
218
+ catch {
219
+ throw new LockOutputRefused(`${LOCK_OUTPUTS_ENV} is not valid JSON`);
220
+ }
221
+ return parseLockOutputs(parsed);
222
+ }
223
+ //# sourceMappingURL=ci-lock-outputs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ci-lock-outputs.js","sourceRoot":"","sources":["../src/ci-lock-outputs.ts"],"names":[],"mappings":"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"}