@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
@@ -21,16 +21,16 @@ import { lintPerPatch } from './lint-per-patch.js';
21
21
  /**
22
22
  * Resolves the diff the lint command should run against. Returns `null` when
23
23
  * there is nothing to lint (no matching files, clean tree, or empty diff
24
- * content) — callers treat that as the early-exit signal and stop.
24
+ * content). Callers treat that as the early-exit signal and stop.
25
25
  *
26
26
  * Extracted from {@link lintCommand} so that function stays under the
27
- * per-function LOC budget; the two file-mode and aggregate-mode branches
27
+ * per-function LOC budget. The two file-mode and aggregate-mode branches
28
28
  * share no state with the post-lint reporting pipeline.
29
29
  *
30
30
  * When `binaryName` is provided, the aggregate-mode branch (no explicit file
31
31
  * list) excludes paths under `browser/branding/<binaryName>/` from the diff.
32
- * `status` classifies those paths as `branding` — tool-managed material the
33
- * operator did not author directly — and without the exclusion
32
+ * `status` classifies those paths as `branding`, tool-managed material the
33
+ * operator did not author directly, and without the exclusion
34
34
  * `fireforge lint` on a fresh project immediately fails `large-patch-lines`
35
35
  * / `large-patch-files` / `missing-license-header` on the generated branding
36
36
  * tree. File-list mode (explicit paths) is unaffected: passing a branding
@@ -97,7 +97,7 @@ async function resolveLintDiff(engineDir, files, binaryName, furnacePrefixes) {
97
97
  return null;
98
98
  }
99
99
  // Aggregate-mode branding exclusion. A fresh-setup workspace carries a
100
- // large tool-managed branding diff the operator did not author; running
100
+ // large tool-managed branding diff the operator did not author. Running
101
101
  // the default lint against it fires size and license-header rules on
102
102
  // content that was never intended to survive in the patch queue as-is. The
103
103
  // exclusion mirrors the `branding` bucket in `fireforge status` so the two
@@ -119,7 +119,7 @@ async function resolveLintDiff(engineDir, files, binaryName, furnacePrefixes) {
119
119
  // stories) that the operator did not author and never intended to land
120
120
  // on the patch queue. Without the carve-out, a post-`furnace preview`
121
121
  // aggregate `lint` fails with one `missing-license-header` error per
122
- // generated story file — each is intentionally header-less because it is
122
+ // generated story file. Each is header-less on purpose because it is
123
123
  // re-generated from component metadata on every preview run.
124
124
  const filteredPaths = furnacePrefixes
125
125
  ? nonBrandingPaths.filter((path) => ![...furnacePrefixes].some((p) => path.startsWith(p)))
@@ -176,9 +176,9 @@ function buildMaxWarningsMessage(count, maxWarnings, scope) {
176
176
  * attribute via `issue.file`, which is the offending site and is owned by
177
177
  * some patch.
178
178
  *
179
- * Multiple owners: an issue is dropped if **any** owning patch waived the
180
- * rule. Conservative — never adds new findings, only drops already-waived
181
- * ones.
179
+ * Multiple owners: an issue is dropped if any owning patch waived the
180
+ * rule. This is conservative: it never adds new findings, only drops
181
+ * already-waived ones.
182
182
  *
183
183
  * @param issues - Issues collected from the aggregate lint run.
184
184
  * @param ctx - Patch queue context used to attribute file → patch.
@@ -208,7 +208,7 @@ export function applyAggregateLintIgnoreSuppression(issues, ctx) {
208
208
  }
209
209
  /**
210
210
  * Up-front flag validation for `lintCommand`: rejects `--only-introduced`
211
- * without `--since` and non-integer `--max-warnings` — each a
211
+ * without `--since` and non-integer `--max-warnings`, each a
212
212
  * misconfiguration that should fail loud rather than silently narrow the
213
213
  * result. Positional arguments in per-patch mode are patch selectors
214
214
  * and are validated downstream by `selectPatchSubset`.
@@ -216,7 +216,7 @@ export function applyAggregateLintIgnoreSuppression(issues, ctx) {
216
216
  function validateLintFlags(options) {
217
217
  // `--only-introduced` scopes the exit code to `--since`-tagged issues, so
218
218
  // without a revision to anchor the diff there is no "introduced" subset
219
- // to scope to — reject the combination up-front so a misconfigured CI
219
+ // to scope to. Reject the combination up-front so a misconfigured CI
220
220
  // invocation fails loud instead of silently treating every error as
221
221
  // cumulative and passing.
222
222
  if (options.onlyIntroduced && !options.since) {
@@ -226,13 +226,13 @@ function validateLintFlags(options) {
226
226
  (!Number.isInteger(options.maxWarnings) || options.maxWarnings < 0)) {
227
227
  throw new InvalidArgumentError('--max-warnings must be a non-negative integer.', '--max-warnings');
228
228
  }
229
- // `--patches` only means something in per-patch mode (it filters the
230
- // queue); in aggregate/file-list mode there is no patch loop to narrow.
229
+ // `--patches` only means something in per-patch mode, where it filters
230
+ // the queue. In aggregate/file-list mode there is no patch loop to narrow.
231
231
  if (options.patches !== undefined && !options.perPatch) {
232
232
  throw new InvalidArgumentError('--patches requires --per-patch.', '--patches');
233
233
  }
234
234
  // The JSON report is a per-patch artifact (per-patch size metrics and
235
- // suppressed issues); aggregate mode has no per-patch rows to report.
235
+ // suppressed issues). Aggregate mode has no per-patch rows to report.
236
236
  if (options.report !== undefined && !options.perPatch) {
237
237
  throw new InvalidArgumentError('--report requires --per-patch.', '--report');
238
238
  }
@@ -242,7 +242,7 @@ function validateLintFlags(options) {
242
242
  * applied patch summed (no explicit file scope, multi-patch queue), the
243
243
  * `large-patch-lines` / `large-patch-files` counts are an artefact of
244
244
  * aggregation rather than a property of any one patch. Surface the
245
- * `--per-patch` hint and downgrade those two rules to warnings; per-patch
245
+ * `--per-patch` hint and downgrade those two rules to warnings. Per-patch
246
246
  * mode keeps them as errors.
247
247
  */
248
248
  function downgradeAggregateSizeRules(issues, files, ctx) {
@@ -260,8 +260,8 @@ function downgradeAggregateSizeRules(issues, files, ctx) {
260
260
  }
261
261
  /**
262
262
  * Evaluates the patch-size rules (`large-patch-files` / `large-patch-lines`)
263
- * for an ad-hoc explicit-file-list lint, scoped to each file's **owning
264
- * patch** rather than the combined file list.
263
+ * for an ad-hoc explicit-file-list lint, scoped to each file's owning
264
+ * patch rather than the combined file list.
265
265
  *
266
266
  * Feeding every passed file to `lintExportedPatch` as one synthetic patch
267
267
  * makes a cross-patch selection of eight files belonging to four patches
@@ -269,7 +269,7 @@ function downgradeAggregateSizeRules(issues, files, ctx) {
269
269
  * oversized. This helper groups the affected files by their owning patch
270
270
  * (via the manifest's `filesAffected`), then runs `lintPatchSize` against
271
271
  * each owner's real file count + diff, honouring that owner's `tier` and
272
- * `lintIgnore` — so `lint <files>`, `lint --per-patch`, and
272
+ * `lintIgnore`, so `lint <files>`, `lint --per-patch`, and
273
273
  * `re-export --dry-run` agree on the same size findings for the same files.
274
274
  * Files no patch claims are evaluated together as one prospective new patch,
275
275
  * preserving the pre-export oversized-change warning.
@@ -338,9 +338,9 @@ async function lintOwningPatchSizes(engineDir, filesAffected, ctx) {
338
338
  */
339
339
  async function reportLintOutcome(engineDir, issues, options) {
340
340
  // Diff-scoping: tag each issue as introduced-in-current-task vs
341
- // cumulative-pre-existing-drift. Never filters — full set still prints
342
- // and exit code semantics are unchanged — but the per-line prefix and
343
- // summary make triage trivial on a large patch series.
341
+ // cumulative-pre-existing-drift. Nothing is filtered (the full set still
342
+ // prints and exit code semantics are unchanged), but the per-line prefix
343
+ // and summary make triage easier on a large patch series.
344
344
  const sinceActive = Boolean(options.since);
345
345
  if (options.since) {
346
346
  const diffFiles = await collectDiffFilePaths(engineDir, options.since);
@@ -371,8 +371,8 @@ async function reportLintOutcome(engineDir, issues, options) {
371
371
  }
372
372
  // Exit-code scope: `--only-introduced` narrows the failure criterion to
373
373
  // issues tagged `introduced`. Cumulative errors still print so the
374
- // operator sees the full queue state, but do not fail lint — the
375
- // case this serves is a branch whose own diff is clean but whose repo
374
+ // operator sees the full queue state, but do not fail lint. The case
375
+ // this serves is a branch whose own diff is clean but whose repo
376
376
  // already carries pre-existing queue errors from older patches.
377
377
  const failingErrors = options.onlyIntroduced
378
378
  ? errors.filter((i) => i.tag === 'introduced')
@@ -388,7 +388,7 @@ async function reportLintOutcome(engineDir, issues, options) {
388
388
  outro('Lint failed');
389
389
  throw new GeneralError(buildMaxWarningsMessage(warnings.length, options.maxWarnings));
390
390
  }
391
- // Notices are advisory and do not count as warnings — emitting "passed
391
+ // Notices are advisory and do not count as warnings: emitting "passed
392
392
  // with warnings" when only notices fired contradicts the preceding
393
393
  // `0 warning(s)` summary line and reads as a regression. Errors suppressed
394
394
  // by --only-introduced still warrant the "with warnings" outro: they print
@@ -417,10 +417,10 @@ export async function lintCommand(projectRoot, files, options = {}) {
417
417
  const paths = getProjectPaths(projectRoot);
418
418
  await assertEngineGitReady(paths.engine);
419
419
  if (options.perPatch) {
420
- // Positional arguments in per-patch mode select PATCHES through the
421
- // same alias resolution as --patches — a non-matching
422
- // positional fails loud against the queue listing, so an engine path
423
- // can never silently lint. Explicit --patches entries come first.
420
+ // Positional arguments in per-patch mode select patches through the
421
+ // same alias resolution as --patches. A non-matching positional fails
422
+ // loud against the queue listing, so an engine path can never silently
423
+ // lint. Explicit --patches entries come first.
424
424
  const perPatchOptions = files.length > 0 ? { ...options, patches: [...(options.patches ?? []), ...files] } : options;
425
425
  await lintPerPatch(projectRoot, paths, perPatchOptions);
426
426
  return;
@@ -429,7 +429,7 @@ export async function lintCommand(projectRoot, files, options = {}) {
429
429
  // into the aggregate-mode branding exclusion in `resolveLintDiff`.
430
430
  const config = await loadConfig(projectRoot);
431
431
  // Pull the Furnace-managed prefix set up-front so aggregate lint can
432
- // mirror the branding exclusion for Furnace material — without it,
432
+ // mirror the branding exclusion for Furnace material. Without it,
433
433
  // preview-generated stories under `browser/components/storybook/
434
434
  // stories/furnace/` show up as license-header errors on every
435
435
  // post-preview lint run.
@@ -446,7 +446,7 @@ export async function lintCommand(projectRoot, files, options = {}) {
446
446
  }
447
447
  // Ad-hoc explicit-file-list mode evaluates the patch-size rules per
448
448
  // owning patch (see `lintOwningPatchSizes`), so suppress the synthetic
449
- // combined-list size check in the shared pass — otherwise a cross-patch
449
+ // combined-list size check in the shared pass. Otherwise a cross-patch
450
450
  // selection synthesises a phantom oversized patch from the file count.
451
451
  const fileListMode = files.length > 0 && ctx !== undefined;
452
452
  let issues = [
@@ -459,15 +459,15 @@ export async function lintCommand(projectRoot, files, options = {}) {
459
459
  issues.push(...(await lintOwningPatchSizes(paths.engine, filesAffected, ctx)));
460
460
  }
461
461
  // Cross-patch rules operate over the whole queue, so run them whenever a
462
- // patches directory exists — they surface duplicate /dev/null creations
462
+ // patches directory exists. They surface duplicate /dev/null creations
463
463
  // and forward-import chains that the per-patch orchestrator cannot see.
464
464
  if (ctx) {
465
465
  issues.push(...lintPatchQueue(ctx));
466
466
  }
467
467
  // Honor per-patch `lintIgnore` in aggregate mode by attributing each
468
468
  // issue's file to its owning patches via the manifest's `filesAffected`.
469
- // Per-patch mode threads `lintIgnore` directly into `lintExportedPatch`;
470
- // aggregate mode has no patch-level scope to consult, so a check an
469
+ // Per-patch mode threads `lintIgnore` directly into `lintExportedPatch`.
470
+ // Aggregate mode has no patch-level scope to consult, so a check an
471
471
  // operator explicitly waived in `patches.json` re-surfaces on every
472
472
  // `--since` run (the CI default).
473
473
  if (ctx) {
@@ -495,7 +495,7 @@ export function registerLint(program, { getProjectRoot, withErrorHandling }) {
495
495
  .option('--since <git-rev>', 'Tag issues as [introduced] or [cumulative] based on whether the file changed since <git-rev> (e.g. HEAD, a branch, a SHA)')
496
496
  .option('--only-introduced', 'Fail only on issues tagged [introduced] (requires --since). Cumulative errors still print but do not set a non-zero exit.')
497
497
  .option('--per-patch', "Lint each patch in the queue as its own isolated diff. Rescopes patch-size rules so they fire against individual patches rather than the aggregate. Honours each patch's `lintIgnore` entries.")
498
- .option('--patches <names...>', 'With --per-patch, lint only the named patches. Accepts repeated flags, comma lists, full filenames/stems, manifest names, category-prefixed slugs, or bare slugs. Positional arguments after --per-patch are treated the same way.')
498
+ .option('--patches <names...>', 'With --per-patch, lint only the named patches. Accepts repeated flags, comma lists, full filenames/stems, bare order numbers, manifest names, category-prefixed slugs, or bare slugs. Positional arguments after --per-patch are treated the same way.')
499
499
  .option('--max-warnings <n>', 'Fail when lint reports more than <n> warning(s); use 0 for warning-clean release gates.')
500
500
  .option('--no-cache', 'Bypass per-patch lint result cache reads and writes.')
501
501
  .option('--report <path>', 'With --per-patch, write a machine-readable JSON report (per-patch size metrics, tier, thresholds, issues, and lintIgnore-suppressed issues) to <path>.')
@@ -533,8 +533,8 @@ export function registerLint(program, { getProjectRoot, withErrorHandling }) {
533
533
  .description('Manage the per-patch lint result cache')
534
534
  // Commander routes `fireforge lint cache` here even when the operator
535
535
  // meant to lint an engine directory literally named `cache`. A bare
536
- // `lint cache` (no subcommand) used to silently do nothing — make the
537
- // ambiguity explicit instead of doing the wrong operation quietly.
536
+ // `lint cache` (no subcommand) used to silently do nothing, so make
537
+ // the ambiguity explicit instead of doing the wrong operation quietly.
538
538
  .action(withErrorHandling(() => {
539
539
  info('Nothing to do: "lint cache" manages the lint result cache (try "lint cache clear"). ' +
540
540
  'To lint a directory named cache/, disambiguate with a trailing slash: "fireforge lint cache/".');
@@ -8,8 +8,8 @@
8
8
  * of commands to enumerate.
9
9
  *
10
10
  * The order of entries in {@link COMMAND_MANIFEST} is the order commands
11
- * appear in `fireforge --help`; it is intentional, not alphabetical, and
12
- * groups related commands together.
11
+ * appear in `fireforge --help`. The order is chosen rather than
12
+ * alphabetical, and groups related commands together.
13
13
  */
14
14
  import type { CommandRegistrar } from '../types/cli.js';
15
15
  /**
@@ -18,9 +18,9 @@ import type { CommandRegistrar } from '../types/cli.js';
18
18
  export interface CommandManifestEntry {
19
19
  /**
20
20
  * Human-readable command name, matching the first token of the
21
- * command line (e.g. `build`, `furnace`). Informational only — the
21
+ * command line (e.g. `build`, `furnace`). Informational only, since the
22
22
  * authoritative command string lives inside each registrar's
23
- * `.command(...)` call — but useful for documentation, manifest
23
+ * `.command(...)` call, but useful for documentation, manifest
24
24
  * introspection, and test assertions.
25
25
  */
26
26
  name: string;
@@ -12,7 +12,7 @@ import { registerLint } from './lint.js';
12
12
  import { registerPackage } from './package.js';
13
13
  import { registerPatch } from './patch/index.js';
14
14
  import { registerReExport } from './re-export-register.js';
15
- import { registerRebase } from './rebase.js';
15
+ import { registerRebase } from './rebase/index.js';
16
16
  import { registerRegister } from './register.js';
17
17
  import { registerReset } from './reset.js';
18
18
  import { registerResolve } from './resolve.js';
@@ -8,6 +8,7 @@ import { hasBuildArtifacts, machPackageCapture } from '../core/mach.js';
8
8
  import { assertBuildArtifacts } from '../core/mach-build-artifacts.js';
9
9
  import { explainMachError } from '../core/mach-error-hints.js';
10
10
  import { BuildError } from '../errors/build.js';
11
+ import { elapsedSince } from '../utils/elapsed.js';
11
12
  import { error, info, intro, outro, verbose } from '../utils/logger.js';
12
13
  import { pickDefined } from '../utils/options.js';
13
14
  /**
@@ -44,8 +45,8 @@ export async function packageCommand(projectRoot, options) {
44
45
  const startTime = Date.now();
45
46
  let result;
46
47
  try {
47
- // `machPackageCapture` streams output live AND captures the tail for
48
- // post-run diagnostics; an inherit-only dispatch leaves the hint
48
+ // `machPackageCapture` streams output live and captures the tail for
49
+ // post-run diagnostics. An inherit-only dispatch leaves the hint
49
50
  // translator unable to see the failure text. The captured stderr is fed
50
51
  // through `explainMachError` below so recognised failure modes get an
51
52
  // actionable hint prepended to the raw mach output.
@@ -54,10 +55,7 @@ export async function packageCommand(projectRoot, options) {
54
55
  catch (error) {
55
56
  throw new BuildError('Package process failed to start', 'mach package', error instanceof Error ? error : undefined);
56
57
  }
57
- const duration = Date.now() - startTime;
58
- const minutes = Math.floor(duration / 60000);
59
- const seconds = Math.floor((duration % 60000) / 1000);
60
- const timeStr = minutes > 0 ? `${minutes}m ${seconds}s` : `${seconds}s`;
58
+ const timeStr = elapsedSince(startTime);
61
59
  if (result.exitCode !== 0) {
62
60
  error(`Packaging failed after ${timeStr}`);
63
61
  const combinedOutput = `${result.stdout}\n${result.stderr}`;
@@ -1,10 +1,10 @@
1
1
  /**
2
- * `fireforge patch compact` — closes ordinal gaps in the patch queue.
2
+ * `fireforge patch compact`: closes ordinal gaps in the patch queue.
3
3
  *
4
4
  * After deletes or splits, patch ordinals may have gaps (e.g. 1, 3, 7).
5
5
  * This command renumbers patches to close those gaps in a single atomic
6
6
  * operation, preserving relative order. Without a patch policy the whole
7
- * queue is renumbered from 1; with `patchPolicy.ranges` configured the
7
+ * queue is renumbered from 1. With `patchPolicy.ranges` configured the
8
8
  * compaction is range-aware (each category range compacts independently,
9
9
  * reserved ranges and out-of-range strays are left untouched).
10
10
  */
@@ -1,24 +1,26 @@
1
1
  // SPDX-License-Identifier: EUPL-1.2
2
2
  /**
3
- * `fireforge patch compact` — closes ordinal gaps in the patch queue.
3
+ * `fireforge patch compact`: closes ordinal gaps in the patch queue.
4
4
  *
5
5
  * After deletes or splits, patch ordinals may have gaps (e.g. 1, 3, 7).
6
6
  * This command renumbers patches to close those gaps in a single atomic
7
7
  * operation, preserving relative order. Without a patch policy the whole
8
- * queue is renumbered from 1; with `patchPolicy.ranges` configured the
8
+ * queue is renumbered from 1. With `patchPolicy.ranges` configured the
9
9
  * compaction is range-aware (each category range compacts independently,
10
10
  * reserved ranges and out-of-range strays are left untouched).
11
11
  */
12
12
  import { Command } from 'commander';
13
13
  import { loadConfig } from '../../core/config.js';
14
- import { appendHistory, confirmDestructive } from '../../core/destructive.js';
14
+ import { confirmDestructive } from '../../core/destructive.js';
15
+ import { appendHistoryBestEffort } from '../../core/history-log.js';
15
16
  import { withPatchDirectoryLock } from '../../core/patch-lock.js';
16
17
  import { loadPatchesManifest, renumberPatchesInManifest, } from '../../core/patch-manifest.js';
17
18
  import { applyRenameMapToManifest, enforcePatchPolicy } from '../../core/patch-policy.js';
18
19
  import { GeneralError } from '../../errors/base.js';
19
- import { toError } from '../../utils/errors.js';
20
20
  import { info, intro, outro, warn } from '../../utils/logger.js';
21
21
  import { addWaitLockOption, pickDefined, resolveWaitLockSeconds } from '../../utils/options.js';
22
+ import { proceedAfterDecision } from '../destructive-decision.js';
23
+ import { renameMapsEqual } from '../patch-rename-map.js';
22
24
  import { requirePatchQueue } from './patch-context.js';
23
25
  import { rebuildFilenameForOrder } from './reorder.js';
24
26
  /** True when `order` falls inside a configured reserved range. */
@@ -30,9 +32,9 @@ function isReservedOrder(policyCfg, order) {
30
32
  *
31
33
  * Without a patch policy, all patches are renumbered to 1, 2, 3, … in
32
34
  * current sort order (historical behaviour). With `patchPolicy.ranges`
33
- * configured, compaction happens *within* each category range instead:
35
+ * configured, compaction happens within each category range instead:
34
36
  * each range's members are renumbered consecutively starting at the
35
- * range's first occupied ordinal, skipping reserved orders — mirroring
37
+ * range's first occupied ordinal, skipping reserved orders, mirroring
36
38
  * what `evaluateGaps` treats as gapless under `allowGaps: false`.
37
39
  * Reserved-range patches and patches outside their category's range are
38
40
  * never moved (a global renumber would project them across range
@@ -84,7 +86,7 @@ function computeCompactRenameMap(patches, policyCfg) {
84
86
  /**
85
87
  * Patches a range-aware compact leaves in place because they sit outside
86
88
  * their category's configured range (or outside all ranges) without a
87
- * reserved-range exception. They already violate `category-range`; moving
89
+ * reserved-range exception. They already violate `category-range`. Moving
88
90
  * them is a policy decision compact must not make silently.
89
91
  */
90
92
  function findCompactStrays(patches, policyCfg) {
@@ -139,14 +141,8 @@ export async function patchCompactCommand(projectRoot, options = {}) {
139
141
  dryRun: options.dryRun === true,
140
142
  unsafeOverride: options.forceUnsafe === true,
141
143
  });
142
- if (decision === 'dry-run') {
143
- outro('Dry run complete — no changes made');
144
+ if (!proceedAfterDecision(decision, 'Compact cancelled'))
144
145
  return;
145
- }
146
- if (decision === 'declined') {
147
- outro('Compact cancelled');
148
- return;
149
- }
150
146
  await withPatchDirectoryLock(paths.patches, async () => {
151
147
  const currentManifest = await loadPatchesManifest(paths.patches);
152
148
  if (!currentManifest) {
@@ -157,6 +153,14 @@ export async function patchCompactCommand(projectRoot, options = {}) {
157
153
  info('Patch queue was compacted by another process. Nothing to do.');
158
154
  return;
159
155
  }
156
+ // The operator confirmed a specific plan. A queue that changed between
157
+ // the prompt and the lock (an export landing a new patch, a delete)
158
+ // yields a different plan whose renames were never shown, so refuse
159
+ // rather than commit them under a history entry that says "ok". This
160
+ // is the same gate `patch reorder` applies.
161
+ if (!renameMapsEqual(renameMap, currentRenameMap)) {
162
+ throw new GeneralError('Patch queue changed while waiting for confirmation. Re-run compact to recompute the rename plan.');
163
+ }
160
164
  enforcePatchPolicy({
161
165
  config,
162
166
  manifest: applyRenameMapToManifest(currentManifest, currentRenameMap),
@@ -179,12 +183,7 @@ export async function patchCompactCommand(projectRoot, options = {}) {
179
183
  ...(options.forceUnsafe === true ? { unsafeOverride: true } : {}),
180
184
  result: 'ok',
181
185
  };
182
- try {
183
- await appendHistory(paths.patches, historyEntry);
184
- }
185
- catch (historyError) {
186
- warn(`History log append failed after patch compact committed: ${toError(historyError).message}`);
187
- }
186
+ await appendHistoryBestEffort(paths.patches, historyEntry, `patch compact committed`);
188
187
  }, { waitLockSeconds: resolveWaitLockSeconds(options.waitLock), command: 'patch compact' });
189
188
  info(`Compacted ${renameMap.size} patch(es).`);
190
189
  outro('Compact complete');
@@ -1,5 +1,5 @@
1
1
  /**
2
- * `fireforge patch delete <name>` — removes a patch from the queue.
2
+ * `fireforge patch delete <name>`: removes a patch from the queue.
3
3
  *
4
4
  * Destructive: refuses when a later patch imports a module owned by the
5
5
  * target (that would leave a dangling forward import), prompts for
@@ -1,6 +1,6 @@
1
1
  // SPDX-License-Identifier: EUPL-1.2
2
2
  /**
3
- * `fireforge patch delete <name>` — removes a patch from the queue.
3
+ * `fireforge patch delete <name>`: removes a patch from the queue.
4
4
  *
5
5
  * Destructive: refuses when a later patch imports a module owned by the
6
6
  * target (that would leave a dangling forward import), prompts for
@@ -9,13 +9,14 @@
9
9
  */
10
10
  import { basename } from 'node:path';
11
11
  import { Command } from 'commander';
12
- import { appendHistory, confirmDestructive } from '../../core/destructive.js';
12
+ import { confirmDestructive } from '../../core/destructive.js';
13
+ import { appendHistoryBestEffort } from '../../core/history-log.js';
13
14
  import { buildPatchQueueContext, extractImportSpecifiersWithLines, findForwardImportIgnoreLines, isForwardImportableFile, } from '../../core/patch-lint.js';
14
15
  import { withPatchDirectoryLock } from '../../core/patch-lock.js';
15
16
  import { removePatchFileAndManifest } from '../../core/patch-manifest.js';
16
- import { toError } from '../../utils/errors.js';
17
17
  import { info, intro, outro, warn } from '../../utils/logger.js';
18
18
  import { addWaitLockOption, pickDefined, resolveWaitLockSeconds } from '../../utils/options.js';
19
+ import { proceedAfterDecision } from '../destructive-decision.js';
19
20
  import { requirePatchQueue, requirePatchTarget } from './patch-context.js';
20
21
  /**
21
22
  * Runs the `patch delete` command: removes a patch file and its manifest
@@ -35,7 +36,7 @@ export async function patchDeleteCommand(projectRoot, identifier, options = {})
35
36
  // Build the full queue context once so we can scan each patch's newFiles
36
37
  // without re-parsing for the dependency check below.
37
38
  const baseCtx = await buildPatchQueueContext(paths.patches);
38
- // Hard refusal: an import owned by a LATER patch that points at any of
39
+ // Hard refusal: an import owned by a later patch that points at any of
39
40
  // the target's newly-created files is a dependency on the target. That
40
41
  // check is built directly from `baseCtx` rather than by diffing lint runs
41
42
  // over a projected state.
@@ -46,10 +47,10 @@ export async function patchDeleteCommand(projectRoot, identifier, options = {})
46
47
  targetNewFileLeaves.add(basename(fullPath));
47
48
  }
48
49
  }
49
- // Scan every later patch's new files AND its added lines on pre-existing
50
+ // Scan every later patch's new files and its added lines on pre-existing
50
51
  // files for import specifiers that resolve to a leaf owned by the target.
51
52
  // Uses the shared specifier extractor so dynamic `import()` and
52
- // `ChromeUtils.defineESModuleGetters` are picked up — the forward-import
53
+ // `ChromeUtils.defineESModuleGetters` are picked up: the forward-import
53
54
  // lint rule already covers those forms, and delete safety must match the
54
55
  // same set or it silently drops dependencies.
55
56
  //
@@ -109,14 +110,14 @@ export async function patchDeleteCommand(projectRoot, identifier, options = {})
109
110
  }
110
111
  const conflicts = dependents.length > 0
111
112
  ? {
112
- // Wording deliberately clarifies the *runtime* impact: `git apply`
113
+ // The wording spells out the runtime impact: `git apply`
113
114
  // does not resolve imports and succeeds even when a later patch
114
115
  // imports a file the target created, so the queue re-imports
115
116
  // cleanly. The breakage surfaces at browser startup when
116
117
  // `ChromeUtils.importESModule` cannot locate the deleted module.
117
- // Operators who deliberately plan to re-introduce the imported
118
- // files (rename, refactor) need to know this is the impact model,
119
- // not a patch-application failure.
118
+ // Operators who plan to re-introduce the imported files (rename,
119
+ // refactor) need to know this is the impact model rather than a
120
+ // patch-application failure.
120
121
  reason: `${dependents.length} later patch(es) contain import statements that reference files created by ${target.filename}. Patch application itself will still succeed, but runtime imports will fail at browser startup until those files are re-introduced.`,
121
122
  details: dependents,
122
123
  }
@@ -138,14 +139,8 @@ export async function patchDeleteCommand(projectRoot, identifier, options = {})
138
139
  unsafeOverride: options.forceUnsafe === true,
139
140
  conflicts,
140
141
  });
141
- if (decision === 'dry-run') {
142
- outro('Dry run complete — no changes made');
142
+ if (!proceedAfterDecision(decision, 'Delete cancelled'))
143
143
  return;
144
- }
145
- if (decision === 'declined') {
146
- outro('Delete cancelled');
147
- return;
148
- }
149
144
  // Proceed: remove under the patch directory lock so concurrent exports
150
145
  // cannot race us into the same manifest row. The history append lives
151
146
  // inside the same lock so two concurrent deletes cannot interleave history
@@ -156,22 +151,17 @@ export async function patchDeleteCommand(projectRoot, identifier, options = {})
156
151
  // failure to the caller would mislead.
157
152
  await withPatchDirectoryLock(paths.patches, async () => {
158
153
  await removePatchFileAndManifest(paths.patches, target.filename);
159
- try {
160
- await appendHistory(paths.patches, {
161
- operation: 'patch-delete',
162
- args: {
163
- filename: target.filename,
164
- order: target.order,
165
- filesAffected: target.filesAffected,
166
- },
167
- ...(options.yes === true ? { yes: true } : {}),
168
- ...(options.forceUnsafe === true ? { unsafeOverride: true } : {}),
169
- result: 'ok',
170
- });
171
- }
172
- catch (historyError) {
173
- warn(`History log append failed after patch delete committed (${target.filename}): ${toError(historyError).message}`);
174
- }
154
+ await appendHistoryBestEffort(paths.patches, {
155
+ operation: 'patch-delete',
156
+ args: {
157
+ filename: target.filename,
158
+ order: target.order,
159
+ filesAffected: target.filesAffected,
160
+ },
161
+ ...(options.yes === true ? { yes: true } : {}),
162
+ ...(options.forceUnsafe === true ? { unsafeOverride: true } : {}),
163
+ result: 'ok',
164
+ }, `patch delete committed (${target.filename})`);
175
165
  }, { waitLockSeconds: resolveWaitLockSeconds(options.waitLock), command: 'patch delete' });
176
166
  info(`Deleted ${target.filename}.`);
177
167
  outro('Delete complete');
@@ -0,0 +1,13 @@
1
+ import type { PatchQueueEntry } from '../../core/patch-lint.js';
2
+ /**
3
+ * Projects a rewritten patch body into the three fields cross-patch lint reads
4
+ * off a queue entry.
5
+ *
6
+ * `patch split` and `patch move-files` each had a byte-identical copy of this
7
+ * (`buildEntryProjection` / `projectEntryBody`). Both feed the same linter, so
8
+ * a change to what the projection carries has to reach both or the two
9
+ * commands start refusing different things for the same queue.
10
+ * @param diff - The rewritten patch body.
11
+ * @returns The diff plus its derived new-file and modified-file projections.
12
+ */
13
+ export declare function projectEntryBody(diff: string): Pick<PatchQueueEntry, 'diff' | 'newFiles' | 'createdFiles' | 'modifiedFileAdditions'>;
@@ -0,0 +1,24 @@
1
+ import { buildModifiedFileAdditionsFromDiff } from '../../core/patch-lint.js';
2
+ import { detectNewFilesInDiff } from '../../core/patch-lint-diff.js';
3
+ import { buildNewFileTextProjection } from '../../core/patch-transform.js';
4
+ /**
5
+ * Projects a rewritten patch body into the three fields cross-patch lint reads
6
+ * off a queue entry.
7
+ *
8
+ * `patch split` and `patch move-files` each had a byte-identical copy of this
9
+ * (`buildEntryProjection` / `projectEntryBody`). Both feed the same linter, so
10
+ * a change to what the projection carries has to reach both or the two
11
+ * commands start refusing different things for the same queue.
12
+ * @param diff - The rewritten patch body.
13
+ * @returns The diff plus its derived new-file and modified-file projections.
14
+ */
15
+ export function projectEntryBody(diff) {
16
+ const newFiles = buildNewFileTextProjection(diff);
17
+ return {
18
+ diff,
19
+ newFiles,
20
+ // Body-kind agnostic: a binary creation is still a creation.
21
+ createdFiles: detectNewFilesInDiff(diff),
22
+ modifiedFileAdditions: buildModifiedFileAdditionsFromDiff(diff),
23
+ };
24
+ }
@@ -1,10 +1,9 @@
1
1
  /**
2
- * `fireforge patch lint-ignore <name>` — adds, removes, or clears entries
2
+ * `fireforge patch lint-ignore <name>`: adds, removes, or clears entries
3
3
  * in `PatchMetadata.lintIgnore` without rewriting the `.patch` file body.
4
4
  *
5
5
  * Companion to `fireforge re-export <name> --lint-ignore <id>` (which is
6
- * append-only). Existence is justified by the cases re-export cannot
7
- * express:
6
+ * append-only). It exists for the cases re-export cannot express:
8
7
  * - Removing a single entry without dropping the rest of the list.
9
8
  * - Clearing the entire list when the operator wants the rule(s) to
10
9
  * start firing again.
@@ -15,19 +14,12 @@
15
14
  * `--clear` must be supplied per invocation. The read-modify-write
16
15
  * happens inside the patch directory lock via {@link mutatePatchMetadata}
17
16
  * so a concurrent writer cannot interleave between the read and the
18
- * write — important when an operator scripts repeated invocations or
17
+ * write, which matters when an operator scripts repeated invocations or
19
18
  * runs `--add` and `--remove` back-to-back.
20
19
  */
21
20
  import { Command } from 'commander';
22
21
  import type { CommandContext } from '../../types/cli.js';
23
22
  import type { PatchLintIgnoreOptions } from '../../types/commands/index.js';
24
- type LintIgnoreMode = 'add' | 'remove' | 'clear';
25
- /**
26
- * Renders a one-line summary of the planned change for use in
27
- * `info()` / dry-run / history args. Exported for unit-testing the
28
- * message format directly without mocking the logger transport.
29
- */
30
- export declare function describeChange(before: ReadonlyArray<string>, after: ReadonlyArray<string>, mode: LintIgnoreMode, values: ReadonlyArray<string>): string;
31
23
  /**
32
24
  * Runs the `patch lint-ignore` command: reads the patch's existing
33
25
  * `lintIgnore`, applies the requested mode, and writes the manifest.
@@ -44,4 +36,3 @@ export declare function patchLintIgnoreCommand(projectRoot: string, identifier:
44
36
  * @param context - Shared CLI registration context
45
37
  */
46
38
  export declare function registerPatchLintIgnore(parent: Command, context: CommandContext): void;
47
- export {};