@hominis/fireforge 0.45.0 → 0.46.1

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 (662) hide show
  1. package/CHANGELOG.md +409 -446
  2. package/dist/bin/fireforge.d.ts +1 -1
  3. package/dist/bin/fireforge.js +21 -15
  4. package/dist/build-info.json +4 -4
  5. package/dist/src/cli-usage-error.d.ts +46 -0
  6. package/dist/src/cli-usage-error.js +81 -0
  7. package/dist/src/cli.d.ts +7 -2
  8. package/dist/src/cli.js +47 -47
  9. package/dist/src/commands/bootstrap-checks.js +2 -1
  10. package/dist/src/commands/bootstrap.js +3 -4
  11. package/dist/src/commands/build.js +27 -17
  12. package/dist/src/commands/config.js +9 -9
  13. package/dist/src/commands/destructive-decision.d.ts +19 -0
  14. package/dist/src/commands/destructive-decision.js +31 -0
  15. package/dist/src/commands/discard.js +5 -5
  16. package/dist/src/commands/doctor-check-core.d.ts +4 -10
  17. package/dist/src/commands/doctor-check-core.js +0 -8
  18. package/dist/src/commands/doctor-external-toolchains.js +2 -2
  19. package/dist/src/commands/doctor-furnace-config-sync.d.ts +2 -2
  20. package/dist/src/commands/doctor-furnace-config-sync.js +20 -20
  21. package/dist/src/commands/doctor-furnace-jar.d.ts +1 -1
  22. package/dist/src/commands/doctor-furnace-jar.js +1 -1
  23. package/dist/src/commands/doctor-furnace.js +22 -22
  24. package/dist/src/commands/doctor-orphaned-harness.d.ts +10 -17
  25. package/dist/src/commands/doctor-orphaned-harness.js +14 -23
  26. package/dist/src/commands/doctor-patch-manifest.d.ts +2 -1
  27. package/dist/src/commands/doctor-patch-manifest.js +7 -6
  28. package/dist/src/commands/doctor-post-rebase-audit.js +3 -3
  29. package/dist/src/commands/doctor-source-pin.d.ts +12 -12
  30. package/dist/src/commands/doctor-source-pin.js +14 -14
  31. package/dist/src/commands/doctor-working-tree.d.ts +3 -3
  32. package/dist/src/commands/doctor-working-tree.js +3 -3
  33. package/dist/src/commands/doctor.d.ts +3 -1
  34. package/dist/src/commands/doctor.js +15 -16
  35. package/dist/src/commands/download.js +50 -37
  36. package/dist/src/commands/export-all.js +29 -12
  37. package/dist/src/commands/export-flow.d.ts +5 -5
  38. package/dist/src/commands/export-flow.js +29 -59
  39. package/dist/src/commands/export-placement-conflicts.d.ts +3 -3
  40. package/dist/src/commands/export-placement-conflicts.js +12 -12
  41. package/dist/src/commands/export-placement-gate.d.ts +2 -2
  42. package/dist/src/commands/export-placement-gate.js +7 -13
  43. package/dist/src/commands/export-placement-policy.d.ts +1 -1
  44. package/dist/src/commands/export-placement-policy.js +4 -6
  45. package/dist/src/commands/export-shared.d.ts +51 -32
  46. package/dist/src/commands/export-shared.js +17 -32
  47. package/dist/src/commands/export.js +14 -5
  48. package/dist/src/commands/furnace/apply.js +16 -16
  49. package/dist/src/commands/furnace/authoring-config.d.ts +13 -0
  50. package/dist/src/commands/furnace/authoring-config.js +19 -0
  51. package/dist/src/commands/furnace/chrome-doc-remove.d.ts +1 -1
  52. package/dist/src/commands/furnace/chrome-doc-remove.js +2 -2
  53. package/dist/src/commands/furnace/chrome-doc-templates.d.ts +14 -14
  54. package/dist/src/commands/furnace/chrome-doc-templates.js +17 -17
  55. package/dist/src/commands/furnace/chrome-doc-tests.d.ts +2 -2
  56. package/dist/src/commands/furnace/chrome-doc-tests.js +4 -4
  57. package/dist/src/commands/furnace/chrome-doc.d.ts +8 -8
  58. package/dist/src/commands/furnace/chrome-doc.js +18 -18
  59. package/dist/src/commands/furnace/create-browser-test.d.ts +1 -1
  60. package/dist/src/commands/furnace/create-browser-test.js +7 -12
  61. package/dist/src/commands/furnace/create-dry-run.d.ts +4 -4
  62. package/dist/src/commands/furnace/create-dry-run.js +6 -9
  63. package/dist/src/commands/furnace/create-features.d.ts +2 -2
  64. package/dist/src/commands/furnace/create-features.js +2 -2
  65. package/dist/src/commands/furnace/create-mochikit.d.ts +4 -4
  66. package/dist/src/commands/furnace/create-mochikit.js +7 -7
  67. package/dist/src/commands/furnace/create-templates.d.ts +31 -15
  68. package/dist/src/commands/furnace/create-templates.js +20 -19
  69. package/dist/src/commands/furnace/create-xpcshell.d.ts +5 -5
  70. package/dist/src/commands/furnace/create-xpcshell.js +8 -8
  71. package/dist/src/commands/furnace/create.d.ts +1 -1
  72. package/dist/src/commands/furnace/create.js +35 -29
  73. package/dist/src/commands/furnace/deploy.js +15 -6
  74. package/dist/src/commands/furnace/diff.js +7 -7
  75. package/dist/src/commands/furnace/index.js +1 -1
  76. package/dist/src/commands/furnace/init.js +17 -16
  77. package/dist/src/commands/furnace/list.js +2 -2
  78. package/dist/src/commands/furnace/override.d.ts +1 -1
  79. package/dist/src/commands/furnace/override.js +43 -34
  80. package/dist/src/commands/furnace/preview.js +17 -17
  81. package/dist/src/commands/furnace/refresh.js +15 -7
  82. package/dist/src/commands/furnace/remove-mutations.d.ts +9 -10
  83. package/dist/src/commands/furnace/remove-mutations.js +19 -19
  84. package/dist/src/commands/furnace/remove-state.d.ts +1 -1
  85. package/dist/src/commands/furnace/remove-state.js +1 -1
  86. package/dist/src/commands/furnace/remove.js +4 -8
  87. package/dist/src/commands/furnace/rename-browser-test.js +10 -15
  88. package/dist/src/commands/furnace/rename-xpcshell.d.ts +2 -2
  89. package/dist/src/commands/furnace/rename-xpcshell.js +3 -3
  90. package/dist/src/commands/furnace/rename.js +36 -36
  91. package/dist/src/commands/furnace/scan.js +3 -3
  92. package/dist/src/commands/furnace/status.js +19 -16
  93. package/dist/src/commands/furnace/sync.js +6 -6
  94. package/dist/src/commands/furnace/test-file-name.d.ts +28 -0
  95. package/dist/src/commands/furnace/test-file-name.js +39 -0
  96. package/dist/src/commands/furnace/validate.js +11 -12
  97. package/dist/src/commands/furnace/validation-output.d.ts +21 -9
  98. package/dist/src/commands/furnace/validation-output.js +3 -8
  99. package/dist/src/commands/import.js +22 -29
  100. package/dist/src/commands/lint-per-patch.d.ts +2 -2
  101. package/dist/src/commands/lint-per-patch.js +27 -12
  102. package/dist/src/commands/lint-per-run-checkjs.d.ts +14 -15
  103. package/dist/src/commands/lint-per-run-checkjs.js +14 -15
  104. package/dist/src/commands/lint-report.d.ts +3 -3
  105. package/dist/src/commands/lint-report.js +4 -4
  106. package/dist/src/commands/lint.d.ts +5 -4
  107. package/dist/src/commands/lint.js +36 -36
  108. package/dist/src/commands/manifest.d.ts +4 -4
  109. package/dist/src/commands/manifest.js +1 -1
  110. package/dist/src/commands/package.js +4 -6
  111. package/dist/src/commands/patch/compact.d.ts +2 -2
  112. package/dist/src/commands/patch/compact.js +19 -20
  113. package/dist/src/commands/patch/delete.d.ts +1 -1
  114. package/dist/src/commands/patch/delete.js +23 -33
  115. package/dist/src/commands/patch/entry-projection.d.ts +13 -0
  116. package/dist/src/commands/patch/entry-projection.js +24 -0
  117. package/dist/src/commands/patch/lint-ignore.d.ts +3 -12
  118. package/dist/src/commands/patch/lint-ignore.js +33 -44
  119. package/dist/src/commands/patch/move-files-create.d.ts +2 -2
  120. package/dist/src/commands/patch/move-files-create.js +29 -15
  121. package/dist/src/commands/patch/move-files-into.d.ts +2 -2
  122. package/dist/src/commands/patch/move-files-into.js +41 -37
  123. package/dist/src/commands/patch/move-files.js +5 -14
  124. package/dist/src/commands/patch/patch-context.d.ts +1 -1
  125. package/dist/src/commands/patch/rename.d.ts +4 -4
  126. package/dist/src/commands/patch/rename.js +35 -49
  127. package/dist/src/commands/patch/reorder.js +35 -48
  128. package/dist/src/commands/patch/split-plan.d.ts +7 -8
  129. package/dist/src/commands/patch/split-plan.js +10 -13
  130. package/dist/src/commands/patch/split.d.ts +2 -2
  131. package/dist/src/commands/patch/split.js +50 -48
  132. package/dist/src/commands/patch/staged-dependency-validate.d.ts +1 -1
  133. package/dist/src/commands/patch/staged-dependency-validate.js +3 -3
  134. package/dist/src/commands/patch/staged-dependency.d.ts +1 -1
  135. package/dist/src/commands/patch/staged-dependency.js +22 -28
  136. package/dist/src/commands/patch/tier.d.ts +2 -2
  137. package/dist/src/commands/patch/tier.js +20 -30
  138. package/dist/src/commands/patch-rename-map.d.ts +19 -0
  139. package/dist/src/commands/patch-rename-map.js +36 -0
  140. package/dist/src/commands/pending-resolution.d.ts +15 -0
  141. package/dist/src/commands/pending-resolution.js +25 -0
  142. package/dist/src/commands/re-export-adjacent.d.ts +25 -3
  143. package/dist/src/commands/re-export-adjacent.js +40 -24
  144. package/dist/src/commands/re-export-bulk-scan.d.ts +3 -3
  145. package/dist/src/commands/re-export-bulk-scan.js +23 -27
  146. package/dist/src/commands/re-export-drift.d.ts +10 -10
  147. package/dist/src/commands/re-export-drift.js +33 -33
  148. package/dist/src/commands/re-export-files.d.ts +2 -3
  149. package/dist/src/commands/re-export-files.js +52 -44
  150. package/dist/src/commands/re-export-lint.d.ts +29 -30
  151. package/dist/src/commands/re-export-lint.js +36 -29
  152. package/dist/src/commands/re-export-options.d.ts +1 -1
  153. package/dist/src/commands/re-export-options.js +1 -1
  154. package/dist/src/commands/re-export-register.d.ts +1 -1
  155. package/dist/src/commands/re-export-register.js +1 -1
  156. package/dist/src/commands/re-export-scan.d.ts +1 -1
  157. package/dist/src/commands/re-export-scan.js +12 -9
  158. package/dist/src/commands/re-export-single.d.ts +23 -4
  159. package/dist/src/commands/re-export-single.js +39 -31
  160. package/dist/src/commands/re-export.js +35 -17
  161. package/dist/src/commands/rebase/abort.js +9 -14
  162. package/dist/src/commands/rebase/continue.js +20 -19
  163. package/dist/src/commands/rebase/index.d.ts +1 -1
  164. package/dist/src/commands/rebase/index.js +5 -5
  165. package/dist/src/commands/rebase/patch-loop.d.ts +2 -2
  166. package/dist/src/commands/rebase/patch-loop.js +20 -24
  167. package/dist/src/commands/register.js +5 -5
  168. package/dist/src/commands/reset.js +1 -1
  169. package/dist/src/commands/resolve.d.ts +2 -2
  170. package/dist/src/commands/resolve.js +21 -13
  171. package/dist/src/commands/run.d.ts +0 -13
  172. package/dist/src/commands/run.js +38 -51
  173. package/dist/src/commands/setup-support.d.ts +16 -4
  174. package/dist/src/commands/setup-support.js +20 -20
  175. package/dist/src/commands/setup.js +4 -10
  176. package/dist/src/commands/source.js +9 -2
  177. package/dist/src/commands/status-check.d.ts +3 -3
  178. package/dist/src/commands/status-check.js +6 -6
  179. package/dist/src/commands/status-json.d.ts +14 -13
  180. package/dist/src/commands/status-json.js +9 -8
  181. package/dist/src/commands/status-output.d.ts +3 -3
  182. package/dist/src/commands/status-output.js +5 -5
  183. package/dist/src/commands/status-ownership.d.ts +3 -3
  184. package/dist/src/commands/status-ownership.js +3 -3
  185. package/dist/src/commands/status.js +25 -26
  186. package/dist/src/commands/test-build-phase.d.ts +3 -3
  187. package/dist/src/commands/test-build-phase.js +48 -24
  188. package/dist/src/commands/test-diagnose.d.ts +1 -1
  189. package/dist/src/commands/test-diagnose.js +20 -20
  190. package/dist/src/commands/test-modes.d.ts +4 -4
  191. package/dist/src/commands/test-modes.js +4 -5
  192. package/dist/src/commands/test-register.js +5 -3
  193. package/dist/src/commands/test-run.d.ts +11 -11
  194. package/dist/src/commands/test-run.js +40 -33
  195. package/dist/src/commands/test-stale-gate.d.ts +12 -12
  196. package/dist/src/commands/test-stale-gate.js +17 -17
  197. package/dist/src/commands/test-verdict.d.ts +19 -5
  198. package/dist/src/commands/test-verdict.js +26 -11
  199. package/dist/src/commands/test.d.ts +3 -3
  200. package/dist/src/commands/test.js +73 -36
  201. package/dist/src/commands/token-coverage.js +3 -3
  202. package/dist/src/commands/token-list.d.ts +26 -0
  203. package/dist/src/commands/token-list.js +153 -0
  204. package/dist/src/commands/token.js +26 -10
  205. package/dist/src/commands/tree.js +26 -21
  206. package/dist/src/commands/typecheck.d.ts +6 -6
  207. package/dist/src/commands/typecheck.js +16 -16
  208. package/dist/src/commands/verify.d.ts +3 -3
  209. package/dist/src/commands/verify.js +10 -10
  210. package/dist/src/commands/watch.js +11 -11
  211. package/dist/src/commands/wire.js +17 -16
  212. package/dist/src/core/ast-utils.d.ts +7 -7
  213. package/dist/src/core/ast-utils.js +8 -8
  214. package/dist/src/core/branding.d.ts +5 -12
  215. package/dist/src/core/branding.js +6 -5
  216. package/dist/src/core/browser-wire.d.ts +1 -1
  217. package/dist/src/core/browser-wire.js +10 -7
  218. package/dist/src/core/build-audit-platform.d.ts +32 -3
  219. package/dist/src/core/build-audit-platform.js +153 -13
  220. package/dist/src/core/build-audit-registration.d.ts +5 -5
  221. package/dist/src/core/build-audit-registration.js +10 -9
  222. package/dist/src/core/build-audit-resolve.d.ts +5 -5
  223. package/dist/src/core/build-audit-resolve.js +6 -6
  224. package/dist/src/core/build-audit-skip.d.ts +57 -0
  225. package/dist/src/core/build-audit-skip.js +112 -0
  226. package/dist/src/core/build-audit-transforms.d.ts +2 -2
  227. package/dist/src/core/build-audit-transforms.js +3 -3
  228. package/dist/src/core/build-audit.d.ts +21 -8
  229. package/dist/src/core/build-audit.js +142 -40
  230. package/dist/src/core/build-baseline-types.d.ts +19 -18
  231. package/dist/src/core/build-baseline-types.js +1 -1
  232. package/dist/src/core/build-baseline.d.ts +48 -31
  233. package/dist/src/core/build-baseline.js +20 -43
  234. package/dist/src/core/build-jar-escalation.d.ts +8 -8
  235. package/dist/src/core/build-jar-escalation.js +18 -17
  236. package/dist/src/core/build-overwrite-guard.d.ts +4 -4
  237. package/dist/src/core/build-overwrite-guard.js +14 -14
  238. package/dist/src/core/build-prepare.d.ts +4 -12
  239. package/dist/src/core/build-prepare.js +22 -26
  240. package/dist/src/core/config-mutate.js +4 -4
  241. package/dist/src/core/config-paths.d.ts +2 -6
  242. package/dist/src/core/config-paths.js +4 -2
  243. package/dist/src/core/config-state.d.ts +0 -6
  244. package/dist/src/core/config-state.js +3 -21
  245. package/dist/src/core/config-validate-build-audit.d.ts +8 -0
  246. package/dist/src/core/config-validate-build-audit.js +80 -0
  247. package/dist/src/core/config-validate-file-size.d.ts +1 -1
  248. package/dist/src/core/config-validate-file-size.js +3 -3
  249. package/dist/src/core/config-validate-patch-policy.d.ts +2 -2
  250. package/dist/src/core/config-validate-patch-policy.js +3 -3
  251. package/dist/src/core/config-validate-test-toolchains.d.ts +2 -2
  252. package/dist/src/core/config-validate-test-toolchains.js +4 -5
  253. package/dist/src/core/config-validate.js +22 -12
  254. package/dist/src/core/config.d.ts +12 -12
  255. package/dist/src/core/config.js +21 -25
  256. package/dist/src/core/coverage-extend.d.ts +16 -16
  257. package/dist/src/core/coverage-extend.js +20 -20
  258. package/dist/src/core/destructive.d.ts +14 -14
  259. package/dist/src/core/destructive.js +9 -9
  260. package/dist/src/core/diff-hunks.d.ts +2 -2
  261. package/dist/src/core/diff-hunks.js +7 -7
  262. package/dist/src/core/discard-baseline.d.ts +10 -10
  263. package/dist/src/core/discard-baseline.js +22 -23
  264. package/dist/src/core/display-state.d.ts +11 -11
  265. package/dist/src/core/display-state.js +12 -12
  266. package/dist/src/core/engine-changes.d.ts +2 -2
  267. package/dist/src/core/engine-changes.js +2 -2
  268. package/dist/src/core/engine-precondition.d.ts +5 -13
  269. package/dist/src/core/engine-precondition.js +5 -10
  270. package/dist/src/core/engine-session-lock.d.ts +18 -18
  271. package/dist/src/core/engine-session-lock.js +50 -54
  272. package/dist/src/core/export-moved-code-shape.d.ts +7 -7
  273. package/dist/src/core/export-moved-code-shape.js +10 -10
  274. package/dist/src/core/file-lock-owner.d.ts +103 -0
  275. package/dist/src/core/file-lock-owner.js +259 -0
  276. package/dist/src/core/file-lock.d.ts +14 -19
  277. package/dist/src/core/file-lock.js +90 -128
  278. package/dist/src/core/firefox-cache.d.ts +13 -1
  279. package/dist/src/core/firefox-cache.js +61 -36
  280. package/dist/src/core/firefox-download.d.ts +15 -0
  281. package/dist/src/core/firefox-download.js +38 -22
  282. package/dist/src/core/firefox-extract.d.ts +8 -7
  283. package/dist/src/core/firefox-extract.js +45 -27
  284. package/dist/src/core/firefox.d.ts +34 -36
  285. package/dist/src/core/firefox.js +13 -44
  286. package/dist/src/core/furnace-apply-dry-run.d.ts +1 -6
  287. package/dist/src/core/furnace-apply-dry-run.js +2 -8
  288. package/dist/src/core/furnace-apply-ftl.d.ts +5 -5
  289. package/dist/src/core/furnace-apply-ftl.js +8 -8
  290. package/dist/src/core/furnace-apply-helpers.d.ts +9 -20
  291. package/dist/src/core/furnace-apply-helpers.js +28 -39
  292. package/dist/src/core/furnace-apply-output.js +1 -1
  293. package/dist/src/core/furnace-apply-overwrite-warn.d.ts +9 -9
  294. package/dist/src/core/furnace-apply-overwrite-warn.js +13 -11
  295. package/dist/src/core/furnace-apply-undeploy-actions.d.ts +1 -1
  296. package/dist/src/core/furnace-apply-undeploy-actions.js +1 -1
  297. package/dist/src/core/furnace-apply.d.ts +4 -4
  298. package/dist/src/core/furnace-apply.js +50 -29
  299. package/dist/src/core/furnace-checksum-utils.d.ts +5 -5
  300. package/dist/src/core/furnace-checksum-utils.js +5 -5
  301. package/dist/src/core/furnace-config-custom.d.ts +1 -1
  302. package/dist/src/core/furnace-config-custom.js +2 -2
  303. package/dist/src/core/furnace-config-order.js +1 -1
  304. package/dist/src/core/furnace-config-tokens.d.ts +3 -3
  305. package/dist/src/core/furnace-config-tokens.js +3 -3
  306. package/dist/src/core/furnace-config-validate.js +2 -2
  307. package/dist/src/core/furnace-config.d.ts +5 -5
  308. package/dist/src/core/furnace-config.js +40 -53
  309. package/dist/src/core/furnace-constants.d.ts +6 -6
  310. package/dist/src/core/furnace-constants.js +9 -8
  311. package/dist/src/core/furnace-css-fragments.d.ts +6 -6
  312. package/dist/src/core/furnace-css-fragments.js +11 -11
  313. package/dist/src/core/furnace-dir-entry.d.ts +20 -0
  314. package/dist/src/core/furnace-dir-entry.js +21 -0
  315. package/dist/src/core/furnace-jsconfig.d.ts +7 -7
  316. package/dist/src/core/furnace-jsconfig.js +22 -20
  317. package/dist/src/core/furnace-operation.d.ts +22 -19
  318. package/dist/src/core/furnace-operation.js +38 -34
  319. package/dist/src/core/furnace-precondition.d.ts +10 -10
  320. package/dist/src/core/furnace-precondition.js +8 -8
  321. package/dist/src/core/furnace-refresh.d.ts +18 -6
  322. package/dist/src/core/furnace-refresh.js +5 -8
  323. package/dist/src/core/furnace-registration-ast.d.ts +2 -3
  324. package/dist/src/core/furnace-registration-ast.js +9 -12
  325. package/dist/src/core/furnace-registration-remove.d.ts +4 -4
  326. package/dist/src/core/furnace-registration-remove.js +6 -6
  327. package/dist/src/core/furnace-registration-validate.d.ts +2 -2
  328. package/dist/src/core/furnace-registration-validate.js +2 -2
  329. package/dist/src/core/furnace-registration.d.ts +7 -6
  330. package/dist/src/core/furnace-registration.js +29 -36
  331. package/dist/src/core/furnace-rollback.d.ts +1 -1
  332. package/dist/src/core/furnace-rollback.js +5 -5
  333. package/dist/src/core/furnace-scanner.js +3 -6
  334. package/dist/src/core/furnace-stale-export.d.ts +17 -16
  335. package/dist/src/core/furnace-stale-export.js +16 -15
  336. package/dist/src/core/furnace-staleness.d.ts +2 -2
  337. package/dist/src/core/furnace-staleness.js +2 -2
  338. package/dist/src/core/furnace-state-persist.d.ts +12 -12
  339. package/dist/src/core/furnace-state-persist.js +10 -10
  340. package/dist/src/core/furnace-step-errors.d.ts +6 -6
  341. package/dist/src/core/furnace-step-errors.js +6 -6
  342. package/dist/src/core/furnace-validate-accessibility.js +14 -14
  343. package/dist/src/core/furnace-validate-compatibility.js +9 -9
  344. package/dist/src/core/furnace-validate-registration.d.ts +2 -2
  345. package/dist/src/core/furnace-validate-registration.js +18 -20
  346. package/dist/src/core/furnace-validate-structure.d.ts +1 -1
  347. package/dist/src/core/furnace-validate-structure.js +4 -4
  348. package/dist/src/core/furnace-validate.js +9 -9
  349. package/dist/src/core/furnace-version-drift.d.ts +5 -5
  350. package/dist/src/core/furnace-version-drift.js +5 -5
  351. package/dist/src/core/git-base.d.ts +6 -4
  352. package/dist/src/core/git-base.js +29 -7
  353. package/dist/src/core/git-diff-new-file.d.ts +40 -0
  354. package/dist/src/core/git-diff-new-file.js +119 -0
  355. package/dist/src/core/git-diff.d.ts +13 -13
  356. package/dist/src/core/git-diff.js +121 -189
  357. package/dist/src/core/git-file-ops.d.ts +6 -13
  358. package/dist/src/core/git-file-ops.js +11 -35
  359. package/dist/src/core/git-readonly-index.d.ts +12 -14
  360. package/dist/src/core/git-readonly-index.js +12 -16
  361. package/dist/src/core/git-status.d.ts +9 -2
  362. package/dist/src/core/git-status.js +23 -11
  363. package/dist/src/core/git.d.ts +3 -9
  364. package/dist/src/core/git.js +28 -57
  365. package/dist/src/core/harness-orphans.d.ts +17 -17
  366. package/dist/src/core/harness-orphans.js +28 -27
  367. package/dist/src/core/history-log.d.ts +19 -0
  368. package/dist/src/core/history-log.js +29 -0
  369. package/dist/src/core/license-headers.d.ts +19 -18
  370. package/dist/src/core/license-headers.js +29 -28
  371. package/dist/src/core/mach-build-artifacts.d.ts +21 -21
  372. package/dist/src/core/mach-build-artifacts.js +23 -23
  373. package/dist/src/core/mach-error-hints.d.ts +5 -10
  374. package/dist/src/core/mach-error-hints.js +14 -14
  375. package/dist/src/core/mach-known-noise-filter.d.ts +42 -38
  376. package/dist/src/core/mach-known-noise-filter.js +57 -56
  377. package/dist/src/core/mach-mozconfig.d.ts +6 -6
  378. package/dist/src/core/mach-mozconfig.js +17 -16
  379. package/dist/src/core/mach-python.d.ts +3 -0
  380. package/dist/src/core/mach-python.js +13 -7
  381. package/dist/src/core/mach-resource-shim.d.ts +24 -12
  382. package/dist/src/core/mach-resource-shim.js +124 -21
  383. package/dist/src/core/mach.d.ts +59 -73
  384. package/dist/src/core/mach.js +47 -115
  385. package/dist/src/core/marionette-port.d.ts +15 -30
  386. package/dist/src/core/marionette-port.js +46 -89
  387. package/dist/src/core/marionette-preflight.d.ts +6 -6
  388. package/dist/src/core/marionette-preflight.js +32 -50
  389. package/dist/src/core/markdown-table.d.ts +9 -9
  390. package/dist/src/core/markdown-table.js +14 -14
  391. package/dist/src/core/mochitest-server-port.d.ts +8 -8
  392. package/dist/src/core/mochitest-server-port.js +17 -17
  393. package/dist/src/core/module-resolution-preflight.d.ts +8 -8
  394. package/dist/src/core/module-resolution-preflight.js +11 -11
  395. package/dist/src/core/moz-manifest-helpers.d.ts +7 -7
  396. package/dist/src/core/moz-manifest-helpers.js +7 -7
  397. package/dist/src/core/moz-manifest-register.d.ts +1 -1
  398. package/dist/src/core/moz-manifest-register.js +2 -2
  399. package/dist/src/core/moz-manifest-rules.js +46 -42
  400. package/dist/src/core/moz-manifest-tokenizers.js +1 -1
  401. package/dist/src/core/ownership-table.d.ts +5 -5
  402. package/dist/src/core/ownership-table.js +7 -7
  403. package/dist/src/core/parser-fallback.d.ts +3 -3
  404. package/dist/src/core/parser-fallback.js +3 -3
  405. package/dist/src/core/patch-apply-fuzz.d.ts +5 -5
  406. package/dist/src/core/patch-apply-fuzz.js +13 -13
  407. package/dist/src/core/patch-apply.d.ts +13 -14
  408. package/dist/src/core/patch-apply.js +36 -42
  409. package/dist/src/core/patch-export-coverage.d.ts +0 -9
  410. package/dist/src/core/patch-export-coverage.js +1 -30
  411. package/dist/src/core/patch-export-update.d.ts +21 -4
  412. package/dist/src/core/patch-export-update.js +7 -6
  413. package/dist/src/core/patch-export.d.ts +20 -30
  414. package/dist/src/core/patch-export.js +55 -77
  415. package/dist/src/core/patch-files.d.ts +0 -4
  416. package/dist/src/core/patch-files.js +0 -11
  417. package/dist/src/core/patch-identifier-suggest.d.ts +1 -1
  418. package/dist/src/core/patch-identifier-suggest.js +4 -4
  419. package/dist/src/core/patch-lint-binary.d.ts +12 -18
  420. package/dist/src/core/patch-lint-cache.d.ts +18 -2
  421. package/dist/src/core/patch-lint-cache.js +16 -19
  422. package/dist/src/core/patch-lint-checkjs.d.ts +55 -38
  423. package/dist/src/core/patch-lint-checkjs.js +78 -64
  424. package/dist/src/core/patch-lint-chrome-jsdoc.d.ts +8 -9
  425. package/dist/src/core/patch-lint-chrome-jsdoc.js +10 -11
  426. package/dist/src/core/patch-lint-creators.d.ts +5 -9
  427. package/dist/src/core/patch-lint-creators.js +3 -3
  428. package/dist/src/core/patch-lint-cross.d.ts +27 -19
  429. package/dist/src/core/patch-lint-cross.js +67 -110
  430. package/dist/src/core/patch-lint-css.d.ts +1 -1
  431. package/dist/src/core/patch-lint-css.js +15 -11
  432. package/dist/src/core/patch-lint-diff-tag.d.ts +5 -5
  433. package/dist/src/core/patch-lint-diff-tag.js +5 -5
  434. package/dist/src/core/patch-lint-diff.d.ts +4 -4
  435. package/dist/src/core/patch-lint-diff.js +4 -4
  436. package/dist/src/core/patch-lint-file-size.d.ts +3 -3
  437. package/dist/src/core/patch-lint-file-size.js +6 -6
  438. package/dist/src/core/patch-lint-forward-registration.d.ts +58 -0
  439. package/dist/src/core/patch-lint-forward-registration.js +210 -0
  440. package/dist/src/core/patch-lint-jsdoc.d.ts +2 -2
  441. package/dist/src/core/patch-lint-jsdoc.js +46 -46
  442. package/dist/src/core/patch-lint-module-registration.d.ts +3 -9
  443. package/dist/src/core/patch-lint-module-registration.js +1 -1
  444. package/dist/src/core/patch-lint-mozbuild.d.ts +1 -1
  445. package/dist/src/core/patch-lint-mozbuild.js +10 -10
  446. package/dist/src/core/patch-lint-observer.d.ts +3 -3
  447. package/dist/src/core/patch-lint-observer.js +7 -7
  448. package/dist/src/core/patch-lint-ownership.d.ts +6 -6
  449. package/dist/src/core/patch-lint-ownership.js +6 -6
  450. package/dist/src/core/patch-lint-prettier.d.ts +6 -6
  451. package/dist/src/core/patch-lint-prettier.js +7 -7
  452. package/dist/src/core/patch-lint-queue-types.d.ts +60 -0
  453. package/dist/src/core/patch-lint-queue-types.js +12 -0
  454. package/dist/src/core/patch-lint-staged-registration.d.ts +61 -0
  455. package/dist/src/core/patch-lint-staged-registration.js +90 -0
  456. package/dist/src/core/patch-lint-unmanaged-companion.d.ts +23 -23
  457. package/dist/src/core/patch-lint-unmanaged-companion.js +26 -26
  458. package/dist/src/core/patch-lint.d.ts +41 -35
  459. package/dist/src/core/patch-lint.js +52 -49
  460. package/dist/src/core/patch-lock.d.ts +1 -1
  461. package/dist/src/core/patch-lock.js +11 -11
  462. package/dist/src/core/patch-manifest-consistency.d.ts +7 -7
  463. package/dist/src/core/patch-manifest-consistency.js +16 -17
  464. package/dist/src/core/patch-manifest-files-affected.d.ts +1 -1
  465. package/dist/src/core/patch-manifest-files-affected.js +3 -3
  466. package/dist/src/core/patch-manifest-io.d.ts +14 -14
  467. package/dist/src/core/patch-manifest-io.js +35 -34
  468. package/dist/src/core/patch-manifest-query.d.ts +1 -1
  469. package/dist/src/core/patch-manifest-query.js +4 -4
  470. package/dist/src/core/patch-manifest-resolve.d.ts +5 -5
  471. package/dist/src/core/patch-manifest-resolve.js +7 -7
  472. package/dist/src/core/patch-manifest-validate.js +3 -3
  473. package/dist/src/core/patch-manifest.d.ts +2 -2
  474. package/dist/src/core/patch-manifest.js +2 -2
  475. package/dist/src/core/patch-parse.d.ts +32 -21
  476. package/dist/src/core/patch-parse.js +40 -15
  477. package/dist/src/core/patch-policy.js +15 -27
  478. package/dist/src/core/patch-registration-refs.d.ts +4 -4
  479. package/dist/src/core/patch-registration-refs.js +7 -7
  480. package/dist/src/core/patch-source-metadata.d.ts +1 -3
  481. package/dist/src/core/patch-source-metadata.js +0 -4
  482. package/dist/src/core/patch-transform.d.ts +8 -16
  483. package/dist/src/core/patch-transform.js +13 -23
  484. package/dist/src/core/process-cpu-time.d.ts +1 -1
  485. package/dist/src/core/process-cpu-time.js +6 -6
  486. package/dist/src/core/rebase-session.d.ts +9 -15
  487. package/dist/src/core/rebase-session.js +13 -25
  488. package/dist/src/core/register-browser-content.js +3 -2
  489. package/dist/src/core/register-browser-test.js +2 -1
  490. package/dist/src/core/register-module.js +2 -1
  491. package/dist/src/core/register-result.d.ts +1 -1
  492. package/dist/src/core/register-result.js +1 -1
  493. package/dist/src/core/register-scaffold.d.ts +2 -2
  494. package/dist/src/core/register-scaffold.js +8 -7
  495. package/dist/src/core/register-shared-css.d.ts +3 -3
  496. package/dist/src/core/register-shared-css.js +6 -5
  497. package/dist/src/core/register-xpcshell-test.d.ts +2 -2
  498. package/dist/src/core/register-xpcshell-test.js +2 -2
  499. package/dist/src/core/run-log-redact.d.ts +38 -0
  500. package/dist/src/core/run-log-redact.js +69 -0
  501. package/dist/src/core/run-log.d.ts +21 -10
  502. package/dist/src/core/run-log.js +76 -27
  503. package/dist/src/core/shared-ftl.d.ts +2 -2
  504. package/dist/src/core/shared-ftl.js +6 -6
  505. package/dist/src/core/signal-critical.d.ts +2 -2
  506. package/dist/src/core/signal-critical.js +4 -6
  507. package/dist/src/core/smoke-patterns.d.ts +5 -6
  508. package/dist/src/core/smoke-patterns.js +15 -20
  509. package/dist/src/core/state-file.d.ts +15 -4
  510. package/dist/src/core/state-file.js +14 -1
  511. package/dist/src/core/status-binary.d.ts +8 -8
  512. package/dist/src/core/status-binary.js +12 -12
  513. package/dist/src/core/status-classify.d.ts +17 -17
  514. package/dist/src/core/status-classify.js +13 -12
  515. package/dist/src/core/test-changed-prefs.d.ts +12 -12
  516. package/dist/src/core/test-changed-prefs.js +40 -25
  517. package/dist/src/core/test-harness-crash.d.ts +39 -39
  518. package/dist/src/core/test-harness-crash.js +69 -69
  519. package/dist/src/core/test-harness-output.d.ts +7 -7
  520. package/dist/src/core/test-harness-output.js +7 -7
  521. package/dist/src/core/test-harness-verdict-notes.d.ts +13 -14
  522. package/dist/src/core/test-harness-verdict-notes.js +4 -4
  523. package/dist/src/core/test-path-scope.d.ts +8 -8
  524. package/dist/src/core/test-path-scope.js +11 -11
  525. package/dist/src/core/test-stale-check.d.ts +22 -23
  526. package/dist/src/core/test-stale-check.js +31 -30
  527. package/dist/src/core/test-stale-symlink.d.ts +1 -1
  528. package/dist/src/core/test-stale-symlink.js +1 -1
  529. package/dist/src/core/test-stall-triage.d.ts +9 -9
  530. package/dist/src/core/test-stall-triage.js +22 -22
  531. package/dist/src/core/test-xpcshell-retry.d.ts +26 -7
  532. package/dist/src/core/test-xpcshell-retry.js +14 -11
  533. package/dist/src/core/token-category.d.ts +35 -2
  534. package/dist/src/core/token-category.js +67 -58
  535. package/dist/src/core/token-coverage.js +4 -5
  536. package/dist/src/core/token-dark-mode.d.ts +9 -9
  537. package/dist/src/core/token-dark-mode.js +13 -25
  538. package/dist/src/core/token-docs.d.ts +1 -1
  539. package/dist/src/core/token-inventory.d.ts +56 -0
  540. package/dist/src/core/token-inventory.js +109 -0
  541. package/dist/src/core/token-manager.d.ts +4 -4
  542. package/dist/src/core/token-manager.js +22 -22
  543. package/dist/src/core/token-scaffold.d.ts +4 -4
  544. package/dist/src/core/token-scaffold.js +4 -4
  545. package/dist/src/core/token-variant.d.ts +14 -14
  546. package/dist/src/core/token-variant.js +52 -53
  547. package/dist/src/core/toolchain-preflight.d.ts +15 -15
  548. package/dist/src/core/toolchain-preflight.js +23 -23
  549. package/dist/src/core/tree-cow.d.ts +3 -5
  550. package/dist/src/core/tree-cow.js +8 -8
  551. package/dist/src/core/tree-guard.d.ts +3 -3
  552. package/dist/src/core/tree-guard.js +23 -23
  553. package/dist/src/core/tree-store.d.ts +15 -15
  554. package/dist/src/core/tree-store.js +39 -38
  555. package/dist/src/core/typecheck-shim.d.ts +16 -15
  556. package/dist/src/core/typecheck-shim.js +26 -25
  557. package/dist/src/core/typecheck.d.ts +12 -12
  558. package/dist/src/core/typecheck.js +33 -33
  559. package/dist/src/core/wire-destroy.d.ts +2 -2
  560. package/dist/src/core/wire-destroy.js +5 -5
  561. package/dist/src/core/wire-dom-fragment.d.ts +3 -3
  562. package/dist/src/core/wire-dom-fragment.js +12 -23
  563. package/dist/src/core/wire-init.d.ts +2 -2
  564. package/dist/src/core/wire-init.js +7 -7
  565. package/dist/src/core/wire-subscript.d.ts +1 -1
  566. package/dist/src/core/wire-subscript.js +3 -3
  567. package/dist/src/core/wire-utils.d.ts +9 -9
  568. package/dist/src/core/wire-utils.js +16 -28
  569. package/dist/src/core/xpcshell-appdir.d.ts +20 -20
  570. package/dist/src/core/xpcshell-appdir.js +28 -30
  571. package/dist/src/core/xpcshell-profile-dir.d.ts +3 -3
  572. package/dist/src/core/xpcshell-profile-dir.js +7 -7
  573. package/dist/src/errors/base.d.ts +69 -16
  574. package/dist/src/errors/base.js +95 -26
  575. package/dist/src/errors/build.d.ts +6 -6
  576. package/dist/src/errors/build.js +26 -34
  577. package/dist/src/errors/codes.d.ts +10 -10
  578. package/dist/src/errors/codes.js +10 -10
  579. package/dist/src/errors/config.d.ts +0 -14
  580. package/dist/src/errors/config.js +13 -34
  581. package/dist/src/errors/download.d.ts +13 -0
  582. package/dist/src/errors/download.js +53 -24
  583. package/dist/src/errors/furnace.d.ts +2 -2
  584. package/dist/src/errors/furnace.js +8 -9
  585. package/dist/src/errors/git.d.ts +9 -9
  586. package/dist/src/errors/git.js +21 -31
  587. package/dist/src/errors/patch.d.ts +3 -3
  588. package/dist/src/errors/patch.js +11 -13
  589. package/dist/src/errors/rebase.d.ts +1 -1
  590. package/dist/src/errors/rebase.js +8 -8
  591. package/dist/src/errors/run.d.ts +1 -1
  592. package/dist/src/errors/run.js +1 -1
  593. package/dist/src/index.d.ts +4 -4
  594. package/dist/src/index.js +4 -4
  595. package/dist/src/types/commands/options.d.ts +155 -200
  596. package/dist/src/types/commands/patches.d.ts +19 -19
  597. package/dist/src/types/commands/project.d.ts +3 -3
  598. package/dist/src/types/config.d.ts +52 -19
  599. package/dist/src/types/furnace.d.ts +17 -17
  600. package/dist/src/types/index.d.ts +0 -1
  601. package/dist/src/types/json.d.ts +3 -3
  602. package/dist/src/types/json.js +2 -2
  603. package/dist/src/types/typecheck.d.ts +3 -3
  604. package/dist/src/utils/assert.d.ts +4 -16
  605. package/dist/src/utils/assert.js +7 -24
  606. package/dist/src/utils/build-info.d.ts +6 -6
  607. package/dist/src/utils/build-info.js +6 -6
  608. package/dist/src/utils/child-env.d.ts +7 -6
  609. package/dist/src/utils/child-env.js +5 -5
  610. package/dist/src/utils/concurrency.d.ts +2 -2
  611. package/dist/src/utils/concurrency.js +2 -2
  612. package/dist/src/utils/elapsed.js +10 -1
  613. package/dist/src/utils/errors.d.ts +8 -8
  614. package/dist/src/utils/errors.js +8 -8
  615. package/dist/src/utils/fs.d.ts +1 -1
  616. package/dist/src/utils/fs.js +15 -20
  617. package/dist/src/utils/hash.d.ts +12 -0
  618. package/dist/src/utils/hash.js +16 -0
  619. package/dist/src/utils/line-dispatch.d.ts +15 -0
  620. package/dist/src/utils/line-dispatch.js +48 -0
  621. package/dist/src/utils/logger.d.ts +4 -4
  622. package/dist/src/utils/logger.js +11 -11
  623. package/dist/src/utils/machine-output.js +2 -2
  624. package/dist/src/utils/options.d.ts +14 -20
  625. package/dist/src/utils/options.js +26 -27
  626. package/dist/src/utils/package-root.js +5 -14
  627. package/dist/src/utils/paths.d.ts +4 -4
  628. package/dist/src/utils/paths.js +4 -4
  629. package/dist/src/utils/platform.d.ts +0 -4
  630. package/dist/src/utils/process-group.d.ts +10 -9
  631. package/dist/src/utils/process-group.js +37 -36
  632. package/dist/src/utils/process.d.ts +70 -55
  633. package/dist/src/utils/process.js +129 -179
  634. package/dist/src/utils/ps-duration.d.ts +4 -4
  635. package/dist/src/utils/ps-duration.js +9 -9
  636. package/dist/src/utils/regex.d.ts +4 -4
  637. package/dist/src/utils/regex.js +7 -7
  638. package/dist/src/utils/sleep.d.ts +26 -0
  639. package/dist/src/utils/sleep.js +31 -0
  640. package/dist/src/utils/stdio-drain.d.ts +7 -7
  641. package/dist/src/utils/stdio-drain.js +8 -8
  642. package/dist/src/utils/validation.d.ts +12 -49
  643. package/dist/src/utils/validation.js +26 -36
  644. package/docs/README.md +2 -2
  645. package/docs/configuration.md +163 -69
  646. package/docs/exit-codes.md +66 -49
  647. package/docs/furnace.md +20 -19
  648. package/docs/lifecycle-invariants.md +414 -247
  649. package/docs/machine-output.md +58 -34
  650. package/docs/patch-workflow.md +48 -44
  651. package/docs/run-logs.md +72 -28
  652. package/docs/testing.md +105 -98
  653. package/docs/verification-trees.md +23 -22
  654. package/package.json +7 -6
  655. package/dist/src/commands/rebase.d.ts +0 -4
  656. package/dist/src/commands/rebase.js +0 -5
  657. package/dist/src/core/patch-artifact-normalize.d.ts +0 -21
  658. package/dist/src/core/patch-artifact-normalize.js +0 -24
  659. package/dist/src/core/patch-lint-reexports.d.ts +0 -7
  660. package/dist/src/core/patch-lint-reexports.js +0 -8
  661. package/dist/src/core/wire-targets.d.ts +0 -7
  662. package/dist/src/core/wire-targets.js +0 -8
@@ -19,10 +19,20 @@ import { info, intro, outro, spinner } from '../utils/logger.js';
19
19
  import { addWaitLockOption, pickDefined, resolveWaitLockSeconds } from '../utils/options.js';
20
20
  import { renderDryRunPreview } from './export-flow.js';
21
21
  import { autoFixLicenseHeaders, promptExportPatchMetadata, runPatchLint, runSupersedeAndOverlapGates, } from './export-shared.js';
22
+ /**
23
+ * The engine paths an export-all entry owns: its current file plus, for a
24
+ * rename, the path it came from. Spelled once because three call sites had
25
+ * copied the same `filter((value): value is string => !!value)` narrowing.
26
+ * @param entry - Export entry carrying `file` and an optional `originalPath`.
27
+ * @returns Both paths when the entry was renamed, otherwise just `file`.
28
+ */
29
+ function ownedPaths(entry) {
30
+ return [entry.file, entry.originalPath].filter((value) => !!value);
31
+ }
22
32
  async function checkBrandingManagedFiles(paths, config) {
23
33
  const changedFiles = await getWorkingTreeStatus(paths.engine);
24
34
  const brandingManagedFiles = changedFiles
25
- .flatMap((entry) => [entry.file, entry.originalPath].filter((value) => !!value))
35
+ .flatMap((entry) => ownedPaths(entry))
26
36
  .filter((file) => isBrandingManagedPath(file, config.binaryName));
27
37
  if (brandingManagedFiles.length > 0) {
28
38
  throw new GeneralError('Export-all refuses to capture tool-managed branding changes by default.\n\n' +
@@ -46,13 +56,13 @@ async function resolveFurnaceExclusionPolicy(paths, projectRoot, excludeFurnace)
46
56
  if (prefixes.size === 0)
47
57
  return new Set();
48
58
  // Expand collapsed `?? dir/` entries before matching against Furnace
49
- // prefixes — otherwise a Furnace-introduced directory slips past the
59
+ // prefixes, otherwise a Furnace-introduced directory slips past the
50
60
  // filter and later lands in the non-Furnace path list that feeds the
51
61
  // aggregate diff, where `getDiffForFilesAgainstHead` crashes with EISDIR.
52
62
  const rawStatus = await getWorkingTreeStatus(paths.engine);
53
63
  const changedFiles = await expandUntrackedDirectoryEntries(paths.engine, rawStatus);
54
64
  const furnaceManagedFiles = changedFiles
55
- .flatMap((entry) => [entry.file, entry.originalPath].filter((value) => !!value))
65
+ .flatMap((entry) => ownedPaths(entry))
56
66
  .filter((file) => [...prefixes].some((prefix) => file.startsWith(prefix)));
57
67
  if (furnaceManagedFiles.length === 0)
58
68
  return new Set();
@@ -71,7 +81,7 @@ async function resolveFurnaceExclusionPolicy(paths, projectRoot, excludeFurnace)
71
81
  * `export-all --exclude-furnace` after `furnace create --localized
72
82
  * --with-tests` otherwise produces a patch that adds
73
83
  * `toolkit/content/widgets/<tag>/*` via jar.mn / customElements.js / locale
74
- * jar.mn while excluding the component source files themselves — a
84
+ * jar.mn while excluding the component source files themselves, a
75
85
  * structurally broken queue that `fireforge verify` stays silent about. The
76
86
  * operator is asked to either include the component sources (skip
77
87
  * `--exclude-furnace`) or revert the furnace changes before exporting.
@@ -124,7 +134,7 @@ async function checkDanglingFurnaceRegistrations(projectRoot, diff, furnaceExclu
124
134
  * path that some existing patch in the queue already creates. `verify`
125
135
  * detects this post-hoc via `collectNewFileCreatorsByPath`, but by the time
126
136
  * `verify` runs the operator has already landed a patch that irreversibly
127
- * sits atop the queue — resolving the conflict from there requires a
137
+ * sits atop the queue, and resolving the conflict from there requires a
128
138
  * `patch delete` or hand-surgery on `re-export --files`. Catching it here,
129
139
  * pre-write, keeps the queue clean and gives the operator a specific path
130
140
  * to narrow with `export` + explicit file scoping (which lets them drop
@@ -196,7 +206,7 @@ export async function exportAllCommand(projectRoot, options = {}) {
196
206
  const allChanged = await expandUntrackedDirectoryEntries(paths.engine, rawChanged);
197
207
  const nonFurnacePaths = [
198
208
  ...new Set(allChanged
199
- .flatMap((entry) => [entry.file, entry.originalPath].filter((value) => !!value))
209
+ .flatMap((entry) => ownedPaths(entry))
200
210
  .filter((file) => !furnaceExcluded.has(file))),
201
211
  ].sort();
202
212
  scopedExportPaths = nonFurnacePaths;
@@ -222,12 +232,12 @@ export async function exportAllCommand(projectRoot, options = {}) {
222
232
  await checkDuplicateNewFileCreations(paths, diff);
223
233
  // Dangling-furnace-registration preflight. Runs after the diff is
224
234
  // assembled so it can inspect the exact hunks the operator is about to
225
- // land, and BEFORE any write so a refusal leaves the patches directory
235
+ // land, and before any write so a refusal leaves the patches directory
226
236
  // untouched.
227
237
  await checkDanglingFurnaceRegistrations(projectRoot, diff, furnaceExcluded);
228
238
  // Check for non-interactive mode
229
239
  const isInteractive = stdioIsInteractive();
230
- // Auto-fix missing license headers on new files (interactive only;
240
+ // Auto-fix missing license headers on new files (interactive only, and
231
241
  // report-only under --dry-run so the preview never mutates engine/)
232
242
  const headersAdded = await autoFixLicenseHeaders(paths.engine, diff, config, isInteractive, isDryRun);
233
243
  if (headersAdded) {
@@ -241,7 +251,7 @@ export async function exportAllCommand(projectRoot, options = {}) {
241
251
  return;
242
252
  const { patchName, selectedCategory, description } = metadata;
243
253
  // Ensure patches directory exists. Skip during a dry-run so the command
244
- // is purely read-only — `--dry-run` callers should be safe to invoke
254
+ // is purely read-only. `--dry-run` callers should be safe to invoke
245
255
  // against a project that has never exported a patch without leaving the
246
256
  // empty `patches/` directory behind.
247
257
  if (!isDryRun) {
@@ -254,12 +264,19 @@ export async function exportAllCommand(projectRoot, options = {}) {
254
264
  const patchQueueCtx = (await pathExists(paths.patches))
255
265
  ? await buildPatchQueueContext(paths.patches)
256
266
  : undefined;
257
- await runPatchLint(paths.engine, filesAffected, diff, config, options.skipLint, patchQueueCtx);
267
+ await runPatchLint({
268
+ engineDir: paths.engine,
269
+ filesAffected,
270
+ diffContent: diff,
271
+ config,
272
+ skipLint: options.skipLint,
273
+ patchQueueCtx,
274
+ });
258
275
  // Dry-run: enumerate filename, metadata, and supersede coverage without
259
276
  // writing. Mirrors `fireforge export --dry-run` so the same preview
260
277
  // surface is available for both targeted and aggregate exports. Runs
261
- // AFTER lint so the operator sees the same lint output they would on
262
- // a real run; runs BEFORE the supersede confirmation prompt because
278
+ // after lint so the operator sees the same lint output they would on
279
+ // a real run. It runs before the supersede confirmation prompt because
263
280
  // confirming a dry-run is meaningless.
264
281
  if (isDryRun) {
265
282
  s.stop('Plan ready');
@@ -20,7 +20,7 @@ export interface PlacementPlan {
20
20
  renameMap: Map<string, PatchRenameEntry>;
21
21
  }
22
22
  /**
23
- * Structural equality for placement plans — used by placement-mode export
23
+ * Structural equality for placement plans. Used by placement-mode export
24
24
  * and `patch split` to verify the queue did not change between the
25
25
  * confirmed preview and the under-lock commit.
26
26
  */
@@ -40,14 +40,14 @@ export declare function computeExactPlacementPlan(manifestPatches: PatchMetadata
40
40
  /**
41
41
  * Resolves a placement plan from CLI flags against the current manifest.
42
42
  * When `config` is provided, positional plans (`--before`/`--after`) are
43
- * refused up front if their renumber would touch a reserved range — one
44
- * error for the whole shift instead of per-patch policy findings. The
43
+ * refused up front if their renumber would touch a reserved range, giving
44
+ * one error for the whole shift instead of per-patch policy findings. The
45
45
  * exact `--order` branch never renames, so it bypasses that gate.
46
46
  */
47
47
  export declare function resolvePlacementPlan(patchesDir: string, options: ExportOptions, category: PatchCategory, name: string, config?: FireForgeConfig): Promise<PlacementPlan>;
48
48
  /**
49
49
  * Projects the placement through cross-patch lint to detect forward-imports
50
- * the renumber would introduce *or* that the new patch itself would
50
+ * the renumber would introduce, or that the new patch itself would
51
51
  * introduce by landing earlier than one of its dependencies. Returns null
52
52
  * when the projection is clean.
53
53
  */
@@ -79,7 +79,7 @@ export interface CommitPlacementExportInput {
79
79
  * Optional post-commit hook that runs inside the patch directory lock,
80
80
  * after the mutation has succeeded but before the lock is released.
81
81
  * Intended for the caller's history-log append so the audit record
82
- * lands atomically with the mutation — a crash between mutation and
82
+ * lands atomically with the mutation. A crash between mutation and
83
83
  * hook leaves no room for another process's history record to sneak
84
84
  * in first.
85
85
  *
@@ -10,14 +10,12 @@
10
10
  import { join } from 'node:path';
11
11
  import {} from '../core/destructive.js';
12
12
  import { detectMovedCodeOverlaps, formatAdoptThenSplitRemedy, } from '../core/export-moved-code-shape.js';
13
- import { normalizePatchArtifact } from '../core/patch-artifact-normalize.js';
14
- import { findAllPatchesForFilesWithDetails, patchNameSlug, planExport, } from '../core/patch-export.js';
15
- import { buildModifiedFileAdditionsFromDiff, buildPatchQueueContext, lintPatchQueue, } from '../core/patch-lint.js';
13
+ import { buildPlanExportInput, findAllPatchesForFilesWithDetails, patchNameSlug, planExport, } from '../core/patch-export.js';
14
+ import { buildPatchQueueContext, lintPatchQueue } from '../core/patch-lint.js';
16
15
  import { withPatchDirectoryLock } from '../core/patch-lock.js';
17
16
  import { addPatchToManifest, loadPatchesManifest, loadPatchesManifestForWrite, renumberPatchesInManifest, resolvePatchIdentifier, savePatchesManifest, } from '../core/patch-manifest.js';
18
- import { requirePatchOrder } from '../core/patch-parse.js';
17
+ import { formatPatchOrder, requirePatchOrder } from '../core/patch-parse.js';
19
18
  import { applyRenameMapToManifest, buildProjectedManifest, enforcePatchPolicy, } from '../core/patch-policy.js';
20
- import { buildNewFileTextProjection } from '../core/patch-transform.js';
21
19
  import { GeneralError, InvalidArgumentError } from '../errors/base.js';
22
20
  import { toError } from '../utils/errors.js';
23
21
  import { pathExists, readText, removeFile, writeText } from '../utils/fs.js';
@@ -25,6 +23,8 @@ import { info, warn } from '../utils/logger.js';
25
23
  import { groupProjectedPlacementErrors } from './export-placement-conflicts.js';
26
24
  import { assertPlacementAvoidsReservedRanges } from './export-placement-policy.js';
27
25
  import { findPartialOwnershipOverlap } from './export-shared.js';
26
+ import { projectEntryBody } from './patch/entry-projection.js';
27
+ import { getSortedRenameEntries, renameMapsEqual } from './patch-rename-map.js';
28
28
  function buildFilenameForPlacement(category, name, order, width) {
29
29
  const padded = String(order).padStart(Math.max(3, width), '0');
30
30
  return `${padded}-${category}-${patchNameSlug(name, category)}.patch`;
@@ -35,11 +35,8 @@ function prefixWidthForPatches(manifestPatches, requestedOrder) {
35
35
  return Math.max(width, match?.[1]?.length ?? 3, String(requestedOrder).length);
36
36
  }, 3);
37
37
  }
38
- function getSortedRenameEntries(renameMap) {
39
- return Array.from(renameMap.entries()).sort((a, b) => a[1].newOrder - b[1].newOrder);
40
- }
41
38
  /**
42
- * Structural equality for placement plans — used by placement-mode export
39
+ * Structural equality for placement plans. Used by placement-mode export
43
40
  * and `patch split` to verify the queue did not change between the
44
41
  * confirmed preview and the under-lock commit.
45
42
  */
@@ -47,20 +44,7 @@ export function placementPlansEqual(left, right) {
47
44
  if (left.insertionOrder !== right.insertionOrder || left.newFilename !== right.newFilename) {
48
45
  return false;
49
46
  }
50
- const leftEntries = getSortedRenameEntries(left.renameMap);
51
- const rightEntries = getSortedRenameEntries(right.renameMap);
52
- if (leftEntries.length !== rightEntries.length) {
53
- return false;
54
- }
55
- return leftEntries.every(([leftFilename, leftEntry], index) => {
56
- const rightTuple = rightEntries[index];
57
- if (!rightTuple)
58
- return false;
59
- const [rightFilename, rightEntry] = rightTuple;
60
- return (leftFilename === rightFilename &&
61
- leftEntry.newFilename === rightEntry.newFilename &&
62
- leftEntry.newOrder === rightEntry.newOrder);
63
- });
47
+ return renameMapsEqual(left.renameMap, right.renameMap);
64
48
  }
65
49
  /**
66
50
  * Computes the shift map that moves existing patches out of the requested
@@ -72,13 +56,13 @@ export function computePlacementPlan(manifestPatches, newPatchCategory, newPatch
72
56
  // Failing fast here prevents a NaN requestedOrder from producing a
73
57
  // filename like "NaN-ui-foo.patch".
74
58
  if (!Number.isInteger(requestedOrder) || requestedOrder <= 0) {
75
- throw new InvalidArgumentError(`computePlacementPlan requires a positive integer order, got ${String(requestedOrder)}.`, 'requestedOrder');
59
+ throw new InvalidArgumentError(`computePlacementPlan requires a positive integer order, got ${requestedOrder}.`, 'requestedOrder');
76
60
  }
77
61
  const sorted = [...manifestPatches].sort((a, b) => a.order - b.order);
78
62
  const renameMap = new Map();
79
63
  const prefixWidth = prefixWidthForPatches(sorted, requestedOrder);
80
64
  // Patches at requestedOrder or later shift up by one, but only until the
81
- // cascade reaches a free ordinal — a gap absorbs the insert, so the tail
65
+ // cascade reaches a free ordinal. A gap absorbs the insert, so the tail
82
66
  // beyond it (including any reserved block) keeps its numbering.
83
67
  let cursor = requestedOrder;
84
68
  for (const patch of sorted) {
@@ -90,7 +74,7 @@ export function computePlacementPlan(manifestPatches, newPatchCategory, newPatch
90
74
  }
91
75
  const newOrder = cursor + 1;
92
76
  const currentRest = patch.filename.replace(/^\d+-/, '');
93
- const newFilename = `${String(newOrder).padStart(prefixWidth, '0')}-${currentRest}`;
77
+ const newFilename = `${formatPatchOrder(newOrder, prefixWidth)}-${currentRest}`;
94
78
  renameMap.set(patch.filename, { newOrder, newFilename });
95
79
  cursor = newOrder;
96
80
  }
@@ -109,11 +93,11 @@ export function computePlacementPlan(manifestPatches, newPatchCategory, newPatch
109
93
  */
110
94
  export function computeExactPlacementPlan(manifestPatches, newPatchCategory, newPatchName, requestedOrder) {
111
95
  if (!Number.isInteger(requestedOrder) || requestedOrder <= 0) {
112
- throw new InvalidArgumentError(`--order must be a positive integer, got ${String(requestedOrder)}.`, '--order');
96
+ throw new InvalidArgumentError(`--order must be a positive integer, got ${requestedOrder}.`, '--order');
113
97
  }
114
98
  const occupied = manifestPatches.find((patch) => patch.order === requestedOrder);
115
99
  if (occupied) {
116
- throw new InvalidArgumentError(`--order ${String(requestedOrder)} is already occupied by ${occupied.filename}. ` +
100
+ throw new InvalidArgumentError(`--order ${requestedOrder} is already occupied by ${occupied.filename}. ` +
117
101
  'Choose an unused order or use --before/--after for positional insertion.', '--order');
118
102
  }
119
103
  return {
@@ -125,22 +109,22 @@ export function computeExactPlacementPlan(manifestPatches, newPatchCategory, new
125
109
  /**
126
110
  * Resolves a placement plan from CLI flags against the current manifest.
127
111
  * When `config` is provided, positional plans (`--before`/`--after`) are
128
- * refused up front if their renumber would touch a reserved range — one
129
- * error for the whole shift instead of per-patch policy findings. The
112
+ * refused up front if their renumber would touch a reserved range, giving
113
+ * one error for the whole shift instead of per-patch policy findings. The
130
114
  * exact `--order` branch never renames, so it bypasses that gate.
131
115
  */
132
116
  export async function resolvePlacementPlan(patchesDir, options, category, name, config) {
133
- // ForWrite: placement planning feeds a manifest rewrite; a corrupt
117
+ // ForWrite: placement planning feeds a manifest rewrite. A corrupt
134
118
  // manifest read as empty would allocate colliding orders.
135
119
  const manifest = await loadPatchesManifestForWrite(patchesDir);
136
120
  const existingPatches = manifest?.patches ?? [];
137
121
  let targetOrder;
138
122
  if (options.order !== undefined) {
139
- // Defense-in-depth — argParser covers the CLI path, but this
123
+ // Defense-in-depth: argParser covers the CLI path, but this
140
124
  // function is called directly from the command body which could
141
125
  // reach here with a NaN/0/negative value passed in via test harness.
142
126
  if (!Number.isInteger(options.order) || options.order <= 0) {
143
- throw new InvalidArgumentError(`--order must be a positive integer, got ${String(options.order)}.`, '--order');
127
+ throw new InvalidArgumentError(`--order must be a positive integer, got ${options.order}.`, '--order');
144
128
  }
145
129
  return computeExactPlacementPlan(existingPatches, category, name, options.order);
146
130
  }
@@ -168,7 +152,7 @@ export async function resolvePlacementPlan(patchesDir, options, category, name,
168
152
  }
169
153
  /**
170
154
  * Projects the placement through cross-patch lint to detect forward-imports
171
- * the renumber would introduce *or* that the new patch itself would
155
+ * the renumber would introduce, or that the new patch itself would
172
156
  * introduce by landing earlier than one of its dependencies. Returns null
173
157
  * when the projection is clean.
174
158
  */
@@ -181,8 +165,8 @@ export async function projectPlacementForLint(patchesDir, plan, diff, config) {
181
165
  return { ...entry, filename: rename.newFilename, order: rename.newOrder };
182
166
  });
183
167
  // Synthetic entry for the pending patch, populated with both its new-file
184
- // content AND its added-line content for files it modifies, so the
185
- // forward-import rule can inspect imports the patch *itself* authors —
168
+ // content and its added-line content for files it modifies, so the
169
+ // forward-import rule can inspect imports the patch itself authors,
186
170
  // whether they live in a brand-new file or are added to an existing one.
187
171
  // Leaving either map empty lets a patch land before one of its own
188
172
  // dependencies and still pass the gate.
@@ -190,9 +174,7 @@ export async function projectPlacementForLint(patchesDir, plan, diff, config) {
190
174
  filename: plan.newFilename,
191
175
  order: plan.insertionOrder,
192
176
  metadata: null,
193
- diff,
194
- newFiles: buildNewFileTextProjection(diff),
195
- modifiedFileAdditions: buildModifiedFileAdditionsFromDiff(diff),
177
+ ...projectEntryBody(diff),
196
178
  });
197
179
  projectedEntries.sort((a, b) => a.order - b.order || a.filename.localeCompare(b.filename));
198
180
  const policyRest = baseCtx.patchPolicy ? { patchPolicy: baseCtx.patchPolicy } : {};
@@ -202,9 +184,9 @@ export async function projectPlacementForLint(patchesDir, plan, diff, config) {
202
184
  }).filter((i) => i.severity === 'error');
203
185
  if (projectedIssues.length === 0)
204
186
  return null;
205
- // Baseline lint over the UN-renumbered queue: an error present here is
206
- // pre-existing breakage, not a consequence of this placement — calling
207
- // it one would misattribute. Entries are already in memory,
187
+ // Baseline lint over the un-renumbered queue: an error present here is
188
+ // pre-existing breakage rather than a consequence of this placement, and
189
+ // calling it one would misattribute. Entries are already in memory,
208
190
  // so this second pass costs no additional IO.
209
191
  const baselineIssues = lintPatchQueue({
210
192
  entries: baseCtx.entries,
@@ -292,9 +274,9 @@ export async function commitPlacementExport(input) {
292
274
  await renumberPatchesInManifest(input.patchesDir, currentPlan.renameMap);
293
275
  renumberApplied = true;
294
276
  }
295
- // Normalize identically to commitExportedPatch — the two export
277
+ // Normalize identically to commitExportedPatch: the two export
296
278
  // paths must produce one artifact contract for the same diff.
297
- await writeText(patchPath, normalizePatchArtifact(input.diff));
279
+ await writeText(patchPath, input.diff);
298
280
  await addPatchToManifest(input.patchesDir, {
299
281
  ...input.metadata,
300
282
  filename: currentPlan.newFilename,
@@ -307,7 +289,7 @@ export async function commitPlacementExport(input) {
307
289
  catch (hookError) {
308
290
  // Mutation has already committed and is not reversible. Warn
309
291
  // so operators know the audit trail has a gap, but do not
310
- // re-throw — that would look like the export itself failed.
292
+ // re-throw, which would look like the export itself failed.
311
293
  warn(`History log append failed after export committed (export-order, ${currentPlan.newFilename}): ` +
312
294
  toError(hookError).message);
313
295
  }
@@ -380,19 +362,7 @@ export async function renderDryRunPreview(input) {
380
362
  const overlap = manifest !== null
381
363
  ? findPartialOwnershipOverlap(manifest, input.filesAffected, supersedingFilenames)
382
364
  : new Map();
383
- const plan = await planExport({
384
- patchesDir: input.patchesDir,
385
- category: input.category,
386
- name: input.name,
387
- description: input.description,
388
- filesAffected: input.filesAffected,
389
- sourceEsrVersion: input.sourceEsrVersion,
390
- ...(input.sourceProduct !== undefined ? { sourceProduct: input.sourceProduct } : {}),
391
- ...(input.sourceVersion !== undefined ? { sourceVersion: input.sourceVersion } : {}),
392
- ...(input.tier !== undefined ? { tier: input.tier } : {}),
393
- ...(input.lintIgnore !== undefined ? { lintIgnore: input.lintIgnore } : {}),
394
- ...(input.config !== undefined ? { config: input.config } : {}),
395
- });
365
+ const plan = await planExport(buildPlanExportInput(input));
396
366
  if (input.config !== undefined) {
397
367
  enforcePatchPolicy({
398
368
  config: input.config,
@@ -426,7 +396,7 @@ export async function renderDryRunPreview(input) {
426
396
  }
427
397
  if (overlap.size > 0) {
428
398
  const entries = [...overlap.entries()].sort(([a], [b]) => a.localeCompare(b));
429
- warn(`\n[dry-run] Would create cross-patch ownership overlap on ${String(entries.length)} file${entries.length === 1 ? '' : 's'}:`);
399
+ warn(`\n[dry-run] Would create cross-patch ownership overlap on ${entries.length} file${entries.length === 1 ? '' : 's'}:`);
430
400
  for (const [file, owners] of entries) {
431
401
  warn(` - ${file} already claimed by: ${owners.join(', ')}`);
432
402
  }
@@ -7,9 +7,9 @@ export interface PlacementAttributionPlan {
7
7
  renameMap: Map<string, PatchRenameEntry>;
8
8
  }
9
9
  /**
10
- * Partitions the projected placement errors into three labeled groups —
11
- * defects in the exported content, consequences of the renumbering, and
12
- * errors the queue already had — rendered as indented detail lines for
10
+ * Partitions the projected placement errors into three labeled groups
11
+ * (defects in the exported content, consequences of the renumbering, and
12
+ * errors the queue already had), rendered as indented detail lines for
13
13
  * {@link ConflictReport.details}. Grouping travels through the plain
14
14
  * `details: string[]`, so both refusal sites and confirmDestructive's
15
15
  * conflict printer show it without changes.
@@ -3,31 +3,31 @@
3
3
  * Attribution of projected placement lint errors, split out of
4
4
  * export-flow.ts for the line budget.
5
5
  *
6
- * A placement projection lints one merged queue — the renumbered existing
7
- * patches plus a synthetic entry for the pending patch — so a flat error
8
- * list reads as though the NEW patch caused every one of them. A renumbering
6
+ * A placement projection lints one merged queue (the renumbered existing
7
+ * patches plus a synthetic entry for the pending patch), so a flat error
8
+ * list reads as though the new patch caused every one of them. A renumbering
9
9
  * that re-evaluates pre-existing staged relationships (patch 455 importing a
10
10
  * module created by 456, legal only at their current ordinals) then sends
11
11
  * the operator auditing a perfectly fine export.
12
12
  *
13
- * Consumed by export-flow.ts; no top-level registrar is exported and none is
13
+ * Consumed by export-flow.ts. No top-level registrar is exported and none is
14
14
  * wanted.
15
15
  */
16
16
  import { formatPatchLintIssue } from '../core/patch-lint.js';
17
17
  /**
18
18
  * Identity for baseline comparison: check + site file + implicated
19
- * patches, with projected filenames mapped BACK through the rename map so
19
+ * patches, with projected filenames mapped back through the rename map so
20
20
  * a pre-existing error keeps its identity across the renumber. Never
21
- * parses the fingerprint — it is documented rename-sensitive.
21
+ * parses the fingerprint. It is documented rename-sensitive.
22
22
  */
23
23
  function issueKey(issue, mapBackToOldName) {
24
24
  const patches = (issue.patches ?? []).map(mapBackToOldName).sort((a, b) => a.localeCompare(b));
25
25
  return `${issue.check}|${issue.file}|${patches.join(',')}`;
26
26
  }
27
27
  /**
28
- * Partitions the projected placement errors into three labeled groups —
29
- * defects in the exported content, consequences of the renumbering, and
30
- * errors the queue already had — rendered as indented detail lines for
28
+ * Partitions the projected placement errors into three labeled groups
29
+ * (defects in the exported content, consequences of the renumbering, and
30
+ * errors the queue already had), rendered as indented detail lines for
31
31
  * {@link ConflictReport.details}. Grouping travels through the plain
32
32
  * `details: string[]`, so both refusal sites and confirmDestructive's
33
33
  * conflict printer show it without changes.
@@ -66,10 +66,10 @@ export function groupProjectedPlacementErrors(projectedErrors, baselineErrors, p
66
66
  details.push(` ${formatPatchLintIssue(issue)}`);
67
67
  }
68
68
  };
69
- pushGroup(`errors in the exported patch content (${String(exported.length)}):`, exported);
69
+ pushGroup(`errors in the exported patch content (${exported.length}):`, exported);
70
70
  pushGroup(`consequences of renumbering existing patches to make room at ordinal ` +
71
- `${String(plan.insertionOrder)} (${String(renumbering.length)}) — these come from ` +
71
+ `${plan.insertionOrder} (${renumbering.length}) — these come from ` +
72
72
  'renumbering, NOT from the exported content:', renumbering);
73
- pushGroup(`errors already present in the queue before this export (${String(preExisting.length)}):`, preExisting);
73
+ pushGroup(`errors already present in the queue before this export (${preExisting.length}):`, preExisting);
74
74
  return details;
75
75
  }
@@ -11,7 +11,7 @@ import { type PlacementPlan } from './export-flow.js';
11
11
  /**
12
12
  * Spreadable optional metadata (`tier`, `lintIgnore`) derived from the
13
13
  * export flags. Every manifest-row construction site in this command
14
- * shares this shape; with exactOptionalPropertyTypes the keys must be
14
+ * shares this shape. With exactOptionalPropertyTypes the keys must be
15
15
  * omitted entirely (not set to undefined) when the flags are absent.
16
16
  */
17
17
  export declare function patchMetadataExtras(options: ExportOptions): Partial<Pick<PatchMetadata, 'tier' | 'lintIgnore'>>;
@@ -22,7 +22,7 @@ export declare function patchMetadataExtras(options: ExportOptions): Partial<Pic
22
22
  * projected manifest, and routes destructive renumbers (or dry-runs)
23
23
  * through `confirmDestructive`. Returns the plan to commit, or `'stop'`
24
24
  * when the command should end here (dry-run rendered or operator
25
- * cancelled — the corresponding outro has already been printed).
25
+ * cancelled, and the corresponding outro has already been printed).
26
26
  */
27
27
  export declare function gatePlacementPlan(args: {
28
28
  patchesDir: string;
@@ -10,12 +10,12 @@ import { loadPatchesManifest } from '../core/patch-manifest.js';
10
10
  import { applyRenameMapToManifest, buildProjectedManifest, enforcePatchPolicy, } from '../core/patch-policy.js';
11
11
  import { buildPatchSourceMetadata } from '../core/patch-source-metadata.js';
12
12
  import { InvalidArgumentError } from '../errors/base.js';
13
- import { outro } from '../utils/logger.js';
13
+ import { proceedAfterDecision } from './destructive-decision.js';
14
14
  import { placementSummary, projectPlacementForLint, resolvePlacementPlan, } from './export-flow.js';
15
15
  /**
16
16
  * Spreadable optional metadata (`tier`, `lintIgnore`) derived from the
17
17
  * export flags. Every manifest-row construction site in this command
18
- * shares this shape; with exactOptionalPropertyTypes the keys must be
18
+ * shares this shape. With exactOptionalPropertyTypes the keys must be
19
19
  * omitted entirely (not set to undefined) when the flags are absent.
20
20
  */
21
21
  export function patchMetadataExtras(options) {
@@ -33,7 +33,7 @@ export function patchMetadataExtras(options) {
33
33
  * projected manifest, and routes destructive renumbers (or dry-runs)
34
34
  * through `confirmDestructive`. Returns the plan to commit, or `'stop'`
35
35
  * when the command should end here (dry-run rendered or operator
36
- * cancelled — the corresponding outro has already been printed).
36
+ * cancelled, and the corresponding outro has already been printed).
37
37
  */
38
38
  export async function gatePlacementPlan(args) {
39
39
  const { patchesDir, options, selectedCategory, patchName, description, filesAffected, diff, config, isDryRun, s, } = args;
@@ -41,7 +41,7 @@ export async function gatePlacementPlan(args) {
41
41
  throw new InvalidArgumentError('Placement flags (--order/--before/--after) cannot be combined with --supersede.', 'export placement');
42
42
  }
43
43
  // resolvePlacementPlan runs the reserved-range gate itself when config
44
- // is passed — one up-front error per run instead of per-patch findings.
44
+ // is passed: one up-front error per run instead of per-patch findings.
45
45
  const placementPlan = await resolvePlacementPlan(patchesDir, options, selectedCategory, patchName, config);
46
46
  const currentManifest = await loadPatchesManifest(patchesDir);
47
47
  const conflicts = await projectPlacementForLint(patchesDir, placementPlan, diff, config);
@@ -70,9 +70,9 @@ export async function gatePlacementPlan(args) {
70
70
  const summary = placementSummary(placementPlan);
71
71
  const renameCount = placementPlan.renameMap.size;
72
72
  // Route through confirmDestructive when the operation is destructive
73
- // enough to warrant a prompt (more than one rename) OR when the user asked
73
+ // enough to warrant a prompt (more than one rename) or when the user asked
74
74
  // for a dry-run. The dry-run branch must always print the placement
75
- // summary; otherwise single-rename and no-rename dry-runs exit silently
75
+ // summary. Otherwise single-rename and no-rename dry-runs exit silently
76
76
  // with no filename or projected layout.
77
77
  if (renameCount > 1 || isDryRun) {
78
78
  s.stop();
@@ -85,14 +85,8 @@ export async function gatePlacementPlan(args) {
85
85
  unsafeOverride: options.forceUnsafe === true,
86
86
  conflicts,
87
87
  });
88
- if (decision === 'dry-run') {
89
- outro('Dry run complete — no changes made');
88
+ if (!proceedAfterDecision(decision, 'Export cancelled'))
90
89
  return 'stop';
91
- }
92
- if (decision === 'declined') {
93
- outro('Export cancelled');
94
- return 'stop';
95
- }
96
90
  }
97
91
  else if (conflicts && options.forceUnsafe !== true) {
98
92
  s.stop();
@@ -12,7 +12,7 @@ export interface PlacementPolicyPlan {
12
12
  }
13
13
  /**
14
14
  * Refuses positional placement plans whose renumber would touch a
15
- * `patchPolicy.reservedRanges` block — either by moving a patch INTO a
15
+ * `patchPolicy.reservedRanges` block, either by moving a patch into a
16
16
  * reserved range or by moving a patch that currently sits inside one.
17
17
  * Throws a single up-front error for the first reserved range hit (the
18
18
  * per-patch alternative surfaced one confusing finding per shifted
@@ -2,10 +2,8 @@
2
2
  /**
3
3
  * Policy-aware checks for export placement plans.
4
4
  */
5
+ import { formatOrderRange, formatPatchOrder } from '../core/patch-parse.js';
5
6
  import { InvalidArgumentError } from '../errors/base.js';
6
- function reservedRangeLabel(range) {
7
- return `${String(range.from).padStart(3, '0')}-${String(range.to).padStart(3, '0')}`;
8
- }
9
7
  function findReservedRange(config, order) {
10
8
  return (config.patchPolicy?.reservedRanges?.find((range) => order >= range.from && order <= range.to) ??
11
9
  null);
@@ -25,7 +23,7 @@ function firstFreeOrderBelowReservedRange(patches, range) {
25
23
  }
26
24
  /**
27
25
  * Refuses positional placement plans whose renumber would touch a
28
- * `patchPolicy.reservedRanges` block — either by moving a patch INTO a
26
+ * `patchPolicy.reservedRanges` block, either by moving a patch into a
29
27
  * reserved range or by moving a patch that currently sits inside one.
30
28
  * Throws a single up-front error for the first reserved range hit (the
31
29
  * per-patch alternative surfaced one confusing finding per shifted
@@ -42,11 +40,11 @@ export function assertPlacementAvoidsReservedRanges(plan, manifestPatches, confi
42
40
  (oldOrder !== undefined ? findReservedRange(config, oldOrder) : null);
43
41
  if (reserved === null)
44
42
  continue;
45
- const label = reservedRangeLabel(reserved);
43
+ const label = formatOrderRange(reserved);
46
44
  const freeOrder = firstFreeOrderBelowReservedRange(manifestPatches, reserved);
47
45
  if (freeOrder !== null) {
48
46
  throw new InvalidArgumentError(`Positional insert would renumber the reserved range ${label}; ` +
49
- `pass --order ${String(freeOrder).padStart(3, '0')} (first free order below the ` +
47
+ `pass --order ${formatPatchOrder(freeOrder)} (first free order below the ` +
50
48
  'reserved block) to place the new patch without renumbering reserved patches.', 'export placement');
51
49
  }
52
50
  throw new InvalidArgumentError(`Positional insert would renumber the reserved range ${label}; ` +