@hominis/fireforge 0.43.1 → 0.44.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 (478) hide show
  1. package/CHANGELOG.md +153 -0
  2. package/README.md +3 -3
  3. package/dist/bin/fireforge.d.ts +4 -9
  4. package/dist/bin/fireforge.js +42 -40
  5. package/dist/build-info.json +4 -4
  6. package/dist/src/cli.js +74 -8
  7. package/dist/src/commands/bootstrap.js +17 -20
  8. package/dist/src/commands/build.js +25 -32
  9. package/dist/src/commands/config.js +34 -41
  10. package/dist/src/commands/discard.js +8 -9
  11. package/dist/src/commands/doctor-check-core.d.ts +13 -18
  12. package/dist/src/commands/doctor-check-core.js +8 -35
  13. package/dist/src/commands/doctor-external-toolchains.js +2 -2
  14. package/dist/src/commands/doctor-furnace-config-sync.d.ts +18 -0
  15. package/dist/src/commands/{doctor-furnace-manifest-sync.js → doctor-furnace-config-sync.js} +27 -26
  16. package/dist/src/commands/doctor-furnace-jar.d.ts +7 -9
  17. package/dist/src/commands/doctor-furnace-jar.js +7 -9
  18. package/dist/src/commands/doctor-furnace.js +21 -24
  19. package/dist/src/commands/doctor-orphaned-harness.d.ts +16 -20
  20. package/dist/src/commands/doctor-orphaned-harness.js +18 -44
  21. package/dist/src/commands/doctor-patch-manifest.d.ts +8 -0
  22. package/dist/src/commands/doctor-patch-manifest.js +155 -0
  23. package/dist/src/commands/doctor-post-rebase-audit.d.ts +2 -0
  24. package/dist/src/commands/{doctor/post-rebase-audit.js → doctor-post-rebase-audit.js} +3 -3
  25. package/dist/src/commands/doctor-working-tree.d.ts +10 -12
  26. package/dist/src/commands/doctor-working-tree.js +11 -18
  27. package/dist/src/commands/doctor.d.ts +1 -1
  28. package/dist/src/commands/doctor.js +64 -96
  29. package/dist/src/commands/download.js +32 -48
  30. package/dist/src/commands/export-all.js +29 -33
  31. package/dist/src/commands/export-flow.js +6 -6
  32. package/dist/src/commands/export-placement-conflicts.js +10 -9
  33. package/dist/src/commands/export-placement-gate.js +5 -5
  34. package/dist/src/commands/export-shared.d.ts +30 -33
  35. package/dist/src/commands/export-shared.js +45 -43
  36. package/dist/src/commands/export.js +21 -27
  37. package/dist/src/commands/furnace/apply.js +14 -23
  38. package/dist/src/commands/furnace/chrome-doc-remove.js +14 -21
  39. package/dist/src/commands/furnace/chrome-doc-templates.d.ts +23 -23
  40. package/dist/src/commands/furnace/chrome-doc-templates.js +23 -23
  41. package/dist/src/commands/furnace/chrome-doc-tests.js +26 -29
  42. package/dist/src/commands/furnace/chrome-doc.d.ts +16 -17
  43. package/dist/src/commands/furnace/chrome-doc.js +31 -41
  44. package/dist/src/commands/furnace/create-browser-test.d.ts +4 -4
  45. package/dist/src/commands/furnace/create-browser-test.js +8 -8
  46. package/dist/src/commands/furnace/create-mochikit.d.ts +6 -7
  47. package/dist/src/commands/furnace/create-mochikit.js +8 -9
  48. package/dist/src/commands/furnace/create-readback.d.ts +12 -13
  49. package/dist/src/commands/furnace/create-readback.js +12 -13
  50. package/dist/src/commands/furnace/create-templates.d.ts +22 -28
  51. package/dist/src/commands/furnace/create-templates.js +35 -30
  52. package/dist/src/commands/furnace/create-xpcshell.js +2 -2
  53. package/dist/src/commands/furnace/create.js +33 -23
  54. package/dist/src/commands/furnace/deploy.js +16 -24
  55. package/dist/src/commands/furnace/diff.js +15 -10
  56. package/dist/src/commands/furnace/init.js +33 -36
  57. package/dist/src/commands/furnace/override.js +23 -25
  58. package/dist/src/commands/furnace/preview.js +47 -67
  59. package/dist/src/commands/furnace/refresh.js +12 -16
  60. package/dist/src/commands/furnace/remove-mutations.d.ts +3 -6
  61. package/dist/src/commands/furnace/remove-mutations.js +14 -17
  62. package/dist/src/commands/furnace/remove-state.js +1 -1
  63. package/dist/src/commands/furnace/remove.js +33 -38
  64. package/dist/src/commands/furnace/rename-xpcshell.d.ts +8 -11
  65. package/dist/src/commands/furnace/rename-xpcshell.js +8 -11
  66. package/dist/src/commands/furnace/rename.js +59 -69
  67. package/dist/src/commands/furnace/scan.js +19 -33
  68. package/dist/src/commands/furnace/status.js +12 -9
  69. package/dist/src/commands/furnace/sync.js +9 -16
  70. package/dist/src/commands/furnace/validate.js +20 -20
  71. package/dist/src/commands/import.js +48 -37
  72. package/dist/src/commands/lint-per-patch.js +15 -10
  73. package/dist/src/commands/lint-per-run-checkjs.d.ts +13 -13
  74. package/dist/src/commands/lint-per-run-checkjs.js +13 -13
  75. package/dist/src/commands/lint-report.js +6 -7
  76. package/dist/src/commands/lint.d.ts +15 -16
  77. package/dist/src/commands/lint.js +86 -102
  78. package/dist/src/commands/package.js +6 -11
  79. package/dist/src/commands/patch/compact.js +1 -1
  80. package/dist/src/commands/patch/delete.js +24 -33
  81. package/dist/src/commands/patch/index.d.ts +5 -6
  82. package/dist/src/commands/patch/index.js +10 -12
  83. package/dist/src/commands/patch/lint-ignore.js +14 -13
  84. package/dist/src/commands/patch/move-files-create.d.ts +6 -6
  85. package/dist/src/commands/patch/move-files-create.js +8 -8
  86. package/dist/src/commands/patch/move-files-into.d.ts +6 -6
  87. package/dist/src/commands/patch/move-files-into.js +8 -8
  88. package/dist/src/commands/patch/patch-context.d.ts +2 -3
  89. package/dist/src/commands/patch/patch-context.js +2 -3
  90. package/dist/src/commands/patch/rename.d.ts +10 -11
  91. package/dist/src/commands/patch/rename.js +11 -12
  92. package/dist/src/commands/patch/reorder.js +8 -9
  93. package/dist/src/commands/patch/split-plan.js +1 -1
  94. package/dist/src/commands/patch/split.d.ts +8 -10
  95. package/dist/src/commands/patch/split.js +9 -11
  96. package/dist/src/commands/patch/staged-dependency-validate.js +8 -8
  97. package/dist/src/commands/patch/staged-dependency.js +7 -3
  98. package/dist/src/commands/patch/tier.d.ts +9 -9
  99. package/dist/src/commands/patch/tier.js +18 -15
  100. package/dist/src/commands/re-export-adjacent.js +9 -8
  101. package/dist/src/commands/re-export-bulk-scan.d.ts +9 -9
  102. package/dist/src/commands/re-export-bulk-scan.js +22 -21
  103. package/dist/src/commands/re-export-drift.js +10 -10
  104. package/dist/src/commands/re-export-files.d.ts +6 -7
  105. package/dist/src/commands/re-export-files.js +34 -44
  106. package/dist/src/commands/re-export-lint.d.ts +10 -13
  107. package/dist/src/commands/re-export-lint.js +16 -14
  108. package/dist/src/commands/re-export-options.d.ts +6 -6
  109. package/dist/src/commands/re-export-options.js +6 -6
  110. package/dist/src/commands/re-export-register.d.ts +4 -10
  111. package/dist/src/commands/re-export-register.js +5 -11
  112. package/dist/src/commands/re-export-scan.js +1 -1
  113. package/dist/src/commands/re-export-single.d.ts +3 -3
  114. package/dist/src/commands/re-export-single.js +33 -25
  115. package/dist/src/commands/re-export.js +13 -21
  116. package/dist/src/commands/rebase/abort.js +3 -3
  117. package/dist/src/commands/rebase/confirm.js +2 -1
  118. package/dist/src/commands/rebase/continue.d.ts +1 -1
  119. package/dist/src/commands/rebase/continue.js +14 -9
  120. package/dist/src/commands/rebase/index.js +11 -11
  121. package/dist/src/commands/rebase/patch-loop.d.ts +7 -1
  122. package/dist/src/commands/rebase/patch-loop.js +60 -39
  123. package/dist/src/commands/rebase/summary.js +1 -1
  124. package/dist/src/commands/register.js +5 -7
  125. package/dist/src/commands/reset.js +2 -1
  126. package/dist/src/commands/resolve.d.ts +16 -13
  127. package/dist/src/commands/resolve.js +30 -33
  128. package/dist/src/commands/run.js +33 -35
  129. package/dist/src/commands/setup-support.js +15 -19
  130. package/dist/src/commands/setup.js +13 -9
  131. package/dist/src/commands/status-check.d.ts +6 -6
  132. package/dist/src/commands/status-json.d.ts +6 -6
  133. package/dist/src/commands/status-json.js +5 -0
  134. package/dist/src/commands/status-output.d.ts +5 -5
  135. package/dist/src/commands/status-output.js +6 -6
  136. package/dist/src/commands/status-ownership.d.ts +16 -14
  137. package/dist/src/commands/status-ownership.js +16 -14
  138. package/dist/src/commands/status.js +42 -34
  139. package/dist/src/commands/test-build-phase.js +26 -13
  140. package/dist/src/commands/test-diagnose.js +44 -44
  141. package/dist/src/commands/test-register.js +1 -0
  142. package/dist/src/commands/test-run.d.ts +14 -16
  143. package/dist/src/commands/test-run.js +21 -13
  144. package/dist/src/commands/test-stale-gate.d.ts +15 -16
  145. package/dist/src/commands/test-stale-gate.js +15 -16
  146. package/dist/src/commands/test-verdict.d.ts +20 -3
  147. package/dist/src/commands/test-verdict.js +30 -0
  148. package/dist/src/commands/test.js +83 -76
  149. package/dist/src/commands/token-coverage.js +3 -4
  150. package/dist/src/commands/token.js +16 -18
  151. package/dist/src/commands/tree.js +47 -31
  152. package/dist/src/commands/typecheck.d.ts +10 -12
  153. package/dist/src/commands/typecheck.js +24 -27
  154. package/dist/src/commands/verify.js +13 -15
  155. package/dist/src/commands/watch.js +21 -23
  156. package/dist/src/commands/wire.js +52 -62
  157. package/dist/src/core/ast-utils.d.ts +8 -7
  158. package/dist/src/core/ast-utils.js +8 -7
  159. package/dist/src/core/branding.d.ts +9 -14
  160. package/dist/src/core/branding.js +7 -11
  161. package/dist/src/core/browser-wire.d.ts +1 -1
  162. package/dist/src/core/browser-wire.js +14 -19
  163. package/dist/src/core/build-audit-platform.js +25 -33
  164. package/dist/src/core/build-audit-registration.js +17 -25
  165. package/dist/src/core/build-audit-resolve.d.ts +15 -17
  166. package/dist/src/core/build-audit-resolve.js +39 -36
  167. package/dist/src/core/build-audit-transforms.js +18 -19
  168. package/dist/src/core/build-audit.js +28 -42
  169. package/dist/src/core/build-baseline-types.d.ts +29 -35
  170. package/dist/src/core/build-baseline.d.ts +5 -4
  171. package/dist/src/core/build-baseline.js +14 -14
  172. package/dist/src/core/build-overwrite-guard.d.ts +7 -14
  173. package/dist/src/core/build-overwrite-guard.js +17 -27
  174. package/dist/src/core/build-prepare.d.ts +2 -2
  175. package/dist/src/core/build-prepare.js +8 -9
  176. package/dist/src/core/config-mutate.js +20 -19
  177. package/dist/src/core/config-state.js +12 -4
  178. package/dist/src/core/config-validate.js +8 -5
  179. package/dist/src/core/config.d.ts +5 -8
  180. package/dist/src/core/config.js +7 -16
  181. package/dist/src/core/coverage-extend.d.ts +15 -13
  182. package/dist/src/core/coverage-extend.js +15 -13
  183. package/dist/src/core/destructive.d.ts +31 -9
  184. package/dist/src/core/destructive.js +29 -26
  185. package/dist/src/core/diff-hunks.js +10 -12
  186. package/dist/src/core/discard-baseline.d.ts +8 -8
  187. package/dist/src/core/discard-baseline.js +16 -15
  188. package/dist/src/core/display-state.d.ts +12 -14
  189. package/dist/src/core/display-state.js +12 -14
  190. package/dist/src/core/engine-changes.d.ts +2 -4
  191. package/dist/src/core/engine-changes.js +2 -4
  192. package/dist/src/core/engine-precondition.d.ts +28 -13
  193. package/dist/src/core/engine-precondition.js +25 -10
  194. package/dist/src/core/engine-session-lock.d.ts +47 -21
  195. package/dist/src/core/engine-session-lock.js +168 -33
  196. package/dist/src/core/export-moved-code-shape.d.ts +10 -10
  197. package/dist/src/core/export-moved-code-shape.js +10 -10
  198. package/dist/src/core/file-lock.d.ts +62 -5
  199. package/dist/src/core/file-lock.js +196 -59
  200. package/dist/src/core/firefox-cache.js +1 -3
  201. package/dist/src/core/firefox-extract.js +10 -14
  202. package/dist/src/core/firefox.d.ts +7 -5
  203. package/dist/src/core/firefox.js +4 -5
  204. package/dist/src/core/furnace-apply-dry-run.d.ts +2 -2
  205. package/dist/src/core/furnace-apply-dry-run.js +3 -2
  206. package/dist/src/core/furnace-apply-ftl.d.ts +7 -9
  207. package/dist/src/core/furnace-apply-ftl.js +16 -13
  208. package/dist/src/core/furnace-apply-helpers.d.ts +7 -7
  209. package/dist/src/core/furnace-apply-helpers.js +30 -21
  210. package/dist/src/core/furnace-apply-overwrite-warn.d.ts +8 -9
  211. package/dist/src/core/furnace-apply-overwrite-warn.js +8 -9
  212. package/dist/src/core/furnace-apply-undeploy-actions.d.ts +3 -4
  213. package/dist/src/core/furnace-apply-undeploy-actions.js +3 -4
  214. package/dist/src/core/furnace-apply.d.ts +5 -8
  215. package/dist/src/core/furnace-apply.js +19 -24
  216. package/dist/src/core/furnace-checksum-utils.d.ts +14 -0
  217. package/dist/src/core/furnace-checksum-utils.js +16 -0
  218. package/dist/src/core/furnace-config.d.ts +21 -30
  219. package/dist/src/core/furnace-config.js +32 -54
  220. package/dist/src/core/furnace-constants.d.ts +8 -0
  221. package/dist/src/core/furnace-constants.js +10 -2
  222. package/dist/src/core/furnace-css-fragments.d.ts +5 -5
  223. package/dist/src/core/furnace-css-fragments.js +5 -5
  224. package/dist/src/core/furnace-jsconfig.d.ts +11 -12
  225. package/dist/src/core/furnace-jsconfig.js +11 -12
  226. package/dist/src/core/furnace-marker.d.ts +7 -8
  227. package/dist/src/core/furnace-marker.js +7 -8
  228. package/dist/src/core/furnace-operation.d.ts +31 -0
  229. package/dist/src/core/furnace-operation.js +54 -17
  230. package/dist/src/core/furnace-precondition.d.ts +61 -0
  231. package/dist/src/core/furnace-precondition.js +67 -0
  232. package/dist/src/core/furnace-registration-remove.d.ts +5 -6
  233. package/dist/src/core/furnace-registration-remove.js +6 -7
  234. package/dist/src/core/furnace-registration-validate.d.ts +13 -0
  235. package/dist/src/core/furnace-registration-validate.js +20 -1
  236. package/dist/src/core/furnace-registration.d.ts +5 -6
  237. package/dist/src/core/furnace-registration.js +10 -12
  238. package/dist/src/core/furnace-rollback.js +7 -7
  239. package/dist/src/core/furnace-scanner.d.ts +1 -0
  240. package/dist/src/core/furnace-scanner.js +1 -2
  241. package/dist/src/core/furnace-stale-export.d.ts +10 -10
  242. package/dist/src/core/furnace-stale-export.js +10 -10
  243. package/dist/src/core/furnace-state-persist.d.ts +6 -8
  244. package/dist/src/core/furnace-state-persist.js +6 -8
  245. package/dist/src/core/furnace-validate-accessibility.d.ts +22 -0
  246. package/dist/src/core/furnace-validate-accessibility.js +310 -1
  247. package/dist/src/core/furnace-validate-compatibility.js +141 -1
  248. package/dist/src/core/furnace-validate-helpers.d.ts +5 -116
  249. package/dist/src/core/furnace-validate-helpers.js +0 -491
  250. package/dist/src/core/furnace-validate-registration.d.ts +7 -0
  251. package/dist/src/core/furnace-validate-registration.js +115 -41
  252. package/dist/src/core/furnace-validate.d.ts +16 -0
  253. package/dist/src/core/furnace-validate.js +188 -145
  254. package/dist/src/core/furnace-version-drift.d.ts +10 -11
  255. package/dist/src/core/furnace-version-drift.js +10 -11
  256. package/dist/src/core/git-base.d.ts +21 -9
  257. package/dist/src/core/git-base.js +24 -9
  258. package/dist/src/core/git-diff.d.ts +20 -9
  259. package/dist/src/core/git-diff.js +148 -63
  260. package/dist/src/core/git-file-ops.d.ts +19 -19
  261. package/dist/src/core/git-file-ops.js +19 -19
  262. package/dist/src/core/git-readonly-index.d.ts +53 -19
  263. package/dist/src/core/git-readonly-index.js +75 -31
  264. package/dist/src/core/git-status.d.ts +5 -6
  265. package/dist/src/core/git-status.js +5 -6
  266. package/dist/src/core/git.d.ts +9 -10
  267. package/dist/src/core/git.js +57 -71
  268. package/dist/src/core/license-headers.d.ts +17 -23
  269. package/dist/src/core/license-headers.js +17 -23
  270. package/dist/src/core/mach-build-artifacts.d.ts +9 -9
  271. package/dist/src/core/mach-build-artifacts.js +57 -19
  272. package/dist/src/core/mach-error-hints.js +42 -29
  273. package/dist/src/core/mach-known-noise-filter.d.ts +15 -16
  274. package/dist/src/core/mach-known-noise-filter.js +18 -20
  275. package/dist/src/core/mach-mozconfig.d.ts +14 -0
  276. package/dist/src/core/mach-mozconfig.js +30 -0
  277. package/dist/src/core/mach-resource-shim.d.ts +43 -58
  278. package/dist/src/core/mach-resource-shim.js +50 -67
  279. package/dist/src/core/mach.d.ts +37 -41
  280. package/dist/src/core/mach.js +50 -51
  281. package/dist/src/core/marionette-port.d.ts +36 -1
  282. package/dist/src/core/marionette-port.js +96 -31
  283. package/dist/src/core/marionette-preflight.d.ts +8 -12
  284. package/dist/src/core/marionette-preflight.js +86 -52
  285. package/dist/src/core/mochitest-server-port.d.ts +42 -0
  286. package/dist/src/core/mochitest-server-port.js +119 -0
  287. package/dist/src/core/module-resolution-preflight.d.ts +9 -11
  288. package/dist/src/core/module-resolution-preflight.js +9 -11
  289. package/dist/src/core/moz-manifest-helpers.d.ts +79 -0
  290. package/dist/src/core/moz-manifest-helpers.js +163 -0
  291. package/dist/src/core/{manifest-register.d.ts → moz-manifest-register.d.ts} +1 -1
  292. package/dist/src/core/{manifest-register.js → moz-manifest-register.js} +13 -28
  293. package/dist/src/core/{manifest-rules.d.ts → moz-manifest-rules.d.ts} +10 -1
  294. package/dist/src/core/{manifest-rules.js → moz-manifest-rules.js} +31 -24
  295. package/dist/src/core/{manifest-tokenizers.d.ts → moz-manifest-tokenizers.d.ts} +3 -5
  296. package/dist/src/core/{manifest-tokenizers.js → moz-manifest-tokenizers.js} +9 -12
  297. package/dist/src/core/ownership-table.d.ts +14 -16
  298. package/dist/src/core/ownership-table.js +14 -16
  299. package/dist/src/core/parser-fallback.d.ts +15 -1
  300. package/dist/src/core/parser-fallback.js +22 -3
  301. package/dist/src/core/patch-apply-fuzz.d.ts +10 -12
  302. package/dist/src/core/patch-apply-fuzz.js +15 -18
  303. package/dist/src/core/patch-apply.d.ts +13 -34
  304. package/dist/src/core/patch-apply.js +16 -76
  305. package/dist/src/core/patch-artifact-normalize.d.ts +13 -15
  306. package/dist/src/core/patch-artifact-normalize.js +13 -15
  307. package/dist/src/core/patch-export-metadata.d.ts +12 -2
  308. package/dist/src/core/patch-export-metadata.js +13 -4
  309. package/dist/src/core/patch-export-update.d.ts +13 -1
  310. package/dist/src/core/patch-export-update.js +25 -8
  311. package/dist/src/core/patch-export.d.ts +15 -8
  312. package/dist/src/core/patch-export.js +10 -11
  313. package/dist/src/core/patch-files.d.ts +5 -6
  314. package/dist/src/core/patch-files.js +5 -6
  315. package/dist/src/core/patch-identifier-suggest.d.ts +7 -12
  316. package/dist/src/core/patch-identifier-suggest.js +14 -19
  317. package/dist/src/core/patch-lint-binary.d.ts +51 -0
  318. package/dist/src/core/patch-lint-binary.js +39 -0
  319. package/dist/src/core/{lint-cache.d.ts → patch-lint-cache.d.ts} +5 -5
  320. package/dist/src/core/{lint-cache.js → patch-lint-cache.js} +21 -23
  321. package/dist/src/core/patch-lint-checkjs.d.ts +16 -16
  322. package/dist/src/core/patch-lint-checkjs.js +41 -20
  323. package/dist/src/core/patch-lint-chrome-jsdoc.d.ts +6 -9
  324. package/dist/src/core/patch-lint-chrome-jsdoc.js +10 -14
  325. package/dist/src/core/patch-lint-creators.d.ts +8 -8
  326. package/dist/src/core/patch-lint-creators.js +8 -8
  327. package/dist/src/core/patch-lint-cross.d.ts +17 -20
  328. package/dist/src/core/patch-lint-cross.js +16 -16
  329. package/dist/src/core/patch-lint-css.d.ts +3 -5
  330. package/dist/src/core/patch-lint-css.js +17 -22
  331. package/dist/src/core/patch-lint-diff-tag.d.ts +14 -16
  332. package/dist/src/core/patch-lint-diff-tag.js +14 -16
  333. package/dist/src/core/patch-lint-jsdoc.d.ts +7 -8
  334. package/dist/src/core/patch-lint-jsdoc.js +26 -19
  335. package/dist/src/core/patch-lint-mozbuild.js +20 -20
  336. package/dist/src/core/patch-lint-observer.d.ts +7 -7
  337. package/dist/src/core/patch-lint-observer.js +7 -7
  338. package/dist/src/core/patch-lint.d.ts +38 -29
  339. package/dist/src/core/patch-lint.js +89 -121
  340. package/dist/src/core/patch-lock.d.ts +1 -1
  341. package/dist/src/core/patch-lock.js +45 -9
  342. package/dist/src/core/patch-manifest-consistency.d.ts +57 -6
  343. package/dist/src/core/patch-manifest-consistency.js +111 -40
  344. package/dist/src/core/patch-manifest-files-affected.d.ts +43 -0
  345. package/dist/src/core/patch-manifest-files-affected.js +77 -0
  346. package/dist/src/core/patch-manifest-io.js +14 -18
  347. package/dist/src/core/patch-manifest-resolve.d.ts +9 -12
  348. package/dist/src/core/patch-manifest-resolve.js +9 -12
  349. package/dist/src/core/patch-manifest-validate.d.ts +6 -1
  350. package/dist/src/core/patch-manifest-validate.js +25 -13
  351. package/dist/src/core/patch-manifest.d.ts +2 -1
  352. package/dist/src/core/patch-manifest.js +2 -1
  353. package/dist/src/core/patch-parse.d.ts +24 -13
  354. package/dist/src/core/patch-parse.js +19 -14
  355. package/dist/src/core/patch-policy.d.ts +2 -2
  356. package/dist/src/core/patch-policy.js +2 -2
  357. package/dist/src/core/patch-registration-refs.d.ts +7 -8
  358. package/dist/src/core/patch-registration-refs.js +9 -9
  359. package/dist/src/core/process-cpu-time.d.ts +12 -0
  360. package/dist/src/core/process-cpu-time.js +52 -0
  361. package/dist/src/core/rebase-session.d.ts +38 -26
  362. package/dist/src/core/rebase-session.js +55 -28
  363. package/dist/src/core/register-browser-content.js +9 -74
  364. package/dist/src/core/{register-test-manifest.js → register-browser-test.js} +7 -42
  365. package/dist/src/core/register-module.js +10 -43
  366. package/dist/src/core/register-scaffold.d.ts +8 -8
  367. package/dist/src/core/register-scaffold.js +10 -10
  368. package/dist/src/core/register-shared-css.d.ts +9 -12
  369. package/dist/src/core/register-shared-css.js +17 -87
  370. package/dist/src/core/register-xpcshell-test.d.ts +6 -7
  371. package/dist/src/core/register-xpcshell-test.js +7 -8
  372. package/dist/src/core/shared-ftl.js +12 -4
  373. package/dist/src/core/state-file.d.ts +45 -0
  374. package/dist/src/core/state-file.js +34 -0
  375. package/dist/src/core/status-binary.d.ts +18 -11
  376. package/dist/src/core/status-binary.js +19 -12
  377. package/dist/src/core/status-classify.d.ts +30 -36
  378. package/dist/src/core/status-classify.js +21 -26
  379. package/dist/src/core/test-changed-prefs.d.ts +30 -0
  380. package/dist/src/core/test-changed-prefs.js +78 -0
  381. package/dist/src/core/test-harness-crash.d.ts +25 -63
  382. package/dist/src/core/test-harness-crash.js +121 -142
  383. package/dist/src/core/test-harness-signature.d.ts +18 -0
  384. package/dist/src/core/test-harness-signature.js +13 -0
  385. package/dist/src/core/test-path-scope.d.ts +12 -15
  386. package/dist/src/core/test-path-scope.js +15 -18
  387. package/dist/src/core/test-stale-check.d.ts +17 -17
  388. package/dist/src/core/test-stale-check.js +50 -43
  389. package/dist/src/core/test-stall-triage.d.ts +51 -0
  390. package/dist/src/core/test-stall-triage.js +126 -0
  391. package/dist/src/core/token-category.js +66 -14
  392. package/dist/src/core/token-coverage.js +9 -9
  393. package/dist/src/core/token-dark-mode.d.ts +9 -11
  394. package/dist/src/core/token-dark-mode.js +29 -13
  395. package/dist/src/core/token-docs.d.ts +2 -0
  396. package/dist/src/core/token-docs.js +3 -1
  397. package/dist/src/core/token-manager.d.ts +10 -2
  398. package/dist/src/core/token-manager.js +17 -8
  399. package/dist/src/core/token-scaffold.d.ts +7 -7
  400. package/dist/src/core/token-scaffold.js +7 -7
  401. package/dist/src/core/token-variant.d.ts +4 -4
  402. package/dist/src/core/token-variant.js +28 -6
  403. package/dist/src/core/toolchain-preflight.d.ts +20 -21
  404. package/dist/src/core/toolchain-preflight.js +28 -31
  405. package/dist/src/core/tree-guard.js +12 -2
  406. package/dist/src/core/tree-store.d.ts +41 -27
  407. package/dist/src/core/tree-store.js +68 -43
  408. package/dist/src/core/typecheck-shim.d.ts +23 -24
  409. package/dist/src/core/typecheck-shim.js +23 -24
  410. package/dist/src/core/typecheck.js +15 -9
  411. package/dist/src/core/wire-destroy.d.ts +3 -3
  412. package/dist/src/core/wire-destroy.js +7 -15
  413. package/dist/src/core/wire-dom-fragment.d.ts +9 -17
  414. package/dist/src/core/wire-dom-fragment.js +11 -44
  415. package/dist/src/core/wire-init.d.ts +2 -3
  416. package/dist/src/core/wire-init.js +8 -19
  417. package/dist/src/core/wire-subscript.d.ts +2 -3
  418. package/dist/src/core/wire-subscript.js +4 -13
  419. package/dist/src/core/wire-utils.d.ts +7 -8
  420. package/dist/src/core/wire-utils.js +7 -8
  421. package/dist/src/core/xpcshell-appdir.d.ts +38 -45
  422. package/dist/src/core/xpcshell-appdir.js +38 -45
  423. package/dist/src/errors/base.d.ts +37 -16
  424. package/dist/src/errors/base.js +37 -16
  425. package/dist/src/errors/build.d.ts +13 -1
  426. package/dist/src/errors/build.js +14 -2
  427. package/dist/src/errors/codes.d.ts +16 -0
  428. package/dist/src/errors/codes.js +16 -0
  429. package/dist/src/errors/furnace.d.ts +4 -4
  430. package/dist/src/errors/git.d.ts +6 -10
  431. package/dist/src/errors/git.js +6 -10
  432. package/dist/src/errors/patch.d.ts +7 -7
  433. package/dist/src/errors/patch.js +7 -7
  434. package/dist/src/errors/rebase.d.ts +4 -4
  435. package/dist/src/errors/rebase.js +4 -4
  436. package/dist/src/index.d.ts +7 -1
  437. package/dist/src/index.js +5 -0
  438. package/dist/src/types/commands/index.d.ts +2 -2
  439. package/dist/src/types/commands/options.d.ts +111 -70
  440. package/dist/src/types/commands/patches.d.ts +24 -34
  441. package/dist/src/types/commands/project.d.ts +5 -34
  442. package/dist/src/types/config.d.ts +25 -23
  443. package/dist/src/types/config.js +6 -1
  444. package/dist/src/types/furnace.d.ts +37 -13
  445. package/dist/src/types/furnace.js +19 -1
  446. package/dist/src/types/index.d.ts +3 -3
  447. package/dist/src/utils/build-info.d.ts +7 -8
  448. package/dist/src/utils/build-info.js +12 -11
  449. package/dist/src/utils/errors.d.ts +6 -8
  450. package/dist/src/utils/errors.js +6 -8
  451. package/dist/src/utils/logger.d.ts +27 -10
  452. package/dist/src/utils/logger.js +28 -16
  453. package/dist/src/utils/machine-output.d.ts +12 -0
  454. package/dist/src/utils/machine-output.js +33 -0
  455. package/dist/src/utils/options.d.ts +31 -14
  456. package/dist/src/utils/options.js +86 -30
  457. package/dist/src/utils/paths.d.ts +10 -8
  458. package/dist/src/utils/paths.js +10 -8
  459. package/dist/src/utils/platform.d.ts +0 -25
  460. package/dist/src/utils/platform.js +1 -42
  461. package/dist/src/utils/process-group.d.ts +9 -4
  462. package/dist/src/utils/process-group.js +19 -5
  463. package/dist/src/utils/process.d.ts +42 -7
  464. package/dist/src/utils/process.js +44 -17
  465. package/dist/src/utils/ps-duration.d.ts +31 -0
  466. package/dist/src/utils/ps-duration.js +70 -0
  467. package/dist/src/utils/regex.d.ts +9 -10
  468. package/dist/src/utils/regex.js +9 -10
  469. package/dist/src/utils/validation.d.ts +58 -28
  470. package/dist/src/utils/validation.js +60 -33
  471. package/package.json +3 -3
  472. package/dist/src/commands/doctor/post-rebase-audit.d.ts +0 -2
  473. package/dist/src/commands/doctor-furnace-manifest-sync.d.ts +0 -18
  474. package/dist/src/core/manifest-helpers.d.ts +0 -38
  475. package/dist/src/core/manifest-helpers.js +0 -120
  476. /package/dist/src/core/{lint-projection.d.ts → patch-lint-projection.d.ts} +0 -0
  477. /package/dist/src/core/{lint-projection.js → patch-lint-projection.js} +0 -0
  478. /package/dist/src/core/{register-test-manifest.d.ts → register-browser-test.d.ts} +0 -0
@@ -1,9 +1,9 @@
1
1
  // SPDX-License-Identifier: EUPL-1.2
2
2
  import { join } from 'node:path';
3
- import { getProjectPaths } from '../../core/config.js';
4
3
  import { applyAllComponents } from '../../core/furnace-apply.js';
5
- import { furnaceConfigExists, loadFurnaceConfig, updateFurnaceState, } from '../../core/furnace-config.js';
4
+ import { updateFurnaceState } from '../../core/furnace-config.js';
6
5
  import { runFurnaceMutation } from '../../core/furnace-operation.js';
6
+ import { assertFurnaceReady } from '../../core/furnace-precondition.js';
7
7
  import { restoreRollbackJournal } from '../../core/furnace-rollback.js';
8
8
  import { countEntriesWithBlockingStepErrors } from '../../core/furnace-step-errors.js';
9
9
  import { cleanStories, syncStories } from '../../core/furnace-stories.js';
@@ -49,14 +49,11 @@ async function runPreviewTeardown(engineDir, storiesCleanupRequired, journal) {
49
49
  return errors;
50
50
  }
51
51
  /**
52
- * Reports staging failures (component-level errors and per-step errors) to the
53
- * user and throws a single FurnaceError summarising the failure count.
54
- * Extracted from `furnacePreviewCommand` to keep that function under the
55
- * `max-lines-per-function` threshold and to colocate the failure-reporting
56
- * contract in one place.
52
+ * Reports staging failures (component-level errors and per-step errors) to
53
+ * the user and throws a single FurnaceError summarising the failure count.
57
54
  *
58
- * @returns The total failure count if there were any (always non-zero when
59
- * this returns; the function throws after logging).
55
+ * Never returns: it always throws after logging, which is what the `never`
56
+ * return type states.
60
57
  */
61
58
  function reportPreviewStagingFailures(stageResult) {
62
59
  for (const err of stageResult.errors) {
@@ -76,13 +73,12 @@ function reportPreviewStagingFailures(stageResult) {
76
73
  /**
77
74
  * Filenames emitted by the Firefox build backend (not by Storybook's npm
78
75
  * package set) — their absence means `mach build` has not produced its
79
- * post-configure artifacts, which is a different failure mode from a
80
- * missing Storybook workspace dependency tree. The eval log for finding
81
- * #11 reported `FileNotFoundError: [...] chrome-map.json` *after* a
82
- * successful Storybook `npm install`, and the pre-0.16 heuristic
83
- * misdiagnosed it as a dep failure and sent the operator back to
84
- * `--install`. Pattern list is narrow on purpose so we only surface the
85
- * backend-rebuild hint when we are confident.
76
+ * post-configure artifacts, which is a different failure mode from a missing
77
+ * Storybook workspace dependency tree. A
78
+ * `FileNotFoundError: [...] chrome-map.json` AFTER a successful Storybook
79
+ * `npm install` is the case a dep-focused heuristic misdiagnoses, sending
80
+ * the operator back to `--install`. The pattern list is narrow on purpose so
81
+ * the backend-rebuild hint only fires when it is confident.
86
82
  */
87
83
  const BACKEND_ARTIFACT_PATTERNS = [
88
84
  /chrome-map\.json/i,
@@ -124,17 +120,14 @@ export function buildStorybookFailureMessage(output, installRequested) {
124
120
  }
125
121
  /**
126
122
  * Preflights the Firefox build + toolchain prerequisites `mach storybook`
127
- * quietly assumes. Pre-0.16.0 the preview staged components and launched
128
- * a ~1000-package `mach storybook upgrade` npm install before the
129
- * backend surfaced a "missing chrome-map.json" / Cargo-config failure;
130
- * the preflight below refuses fast and leaves the workspace untouched.
131
- *
132
- * Extracted from `furnacePreviewCommand` so the main function stays
133
- * under the per-function LOC budget as the preflight list grows.
123
+ * quietly assumes. Without it, preview stages components and launches a
124
+ * ~1000-package `mach storybook upgrade` npm install before the backend
125
+ * surfaces a "missing chrome-map.json" / Cargo-config failure; this refuses
126
+ * fast and leaves the workspace untouched.
134
127
  *
135
128
  * @param engineDir - Resolved engine directory
136
- * @throws FurnaceError when the Firefox build hasn't produced dist/, or
137
- * when `.cargo/config.toml` is absent
129
+ * @throws FurnaceError when the Firefox build has not produced dist/, or
130
+ * when `.cargo/config.toml` is absent
138
131
  */
139
132
  async function assertPreviewPrerequisites(engineDir) {
140
133
  const buildCheck = await hasBuildArtifacts(engineDir);
@@ -146,14 +139,12 @@ async function assertPreviewPrerequisites(engineDir) {
146
139
  }
147
140
  // Accept either `.cargo/config.toml` (post-configure) or
148
141
  // `.cargo/config.toml.in` (post-bootstrap template, consumed at
149
- // `mach configure` time). Pre-0.16.0 the preflight insisted on the
150
- // plain file, but `fireforge bootstrap` alone produces only `.in` —
151
- // operators who followed the remediation instruction ("run bootstrap
152
- // then rerun preview") hit the same refusal on the retry. Either name
153
- // is sufficient to prove the Rust toolchain is registered; the stronger
154
- // `hasBuildArtifacts` check above already guards against a completely
155
- // un-configured tree, so relaxing this to an OR-check does not weaken
156
- // the signal we care about.
142
+ // `mach configure` time). Insisting on the plain file makes operators who
143
+ // follow the remediation instruction ("run bootstrap then rerun preview")
144
+ // hit the same refusal on the retry, because `fireforge bootstrap` alone
145
+ // produces only `.in`. Either name is sufficient to prove the Rust
146
+ // toolchain is registered; the stronger `hasBuildArtifacts` check above
147
+ // already guards against a completely un-configured tree.
157
148
  const cargoConfigPath = join(engineDir, '.cargo', 'config.toml');
158
149
  const cargoConfigInPath = join(engineDir, '.cargo', 'config.toml.in');
159
150
  const cargoConfigPresent = (await pathExists(cargoConfigPath)) || (await pathExists(cargoConfigInPath));
@@ -165,15 +156,14 @@ async function assertPreviewPrerequisites(engineDir) {
165
156
  }
166
157
  }
167
158
  /**
168
- * Emits a framing banner when the Storybook workspace has not yet had
169
- * its npm dependencies installed. `mach storybook` will drive the
170
- * install internally and print ELSPROBLEMS / UNMET DEPENDENCY lines
171
- * verbatim; without this banner operators reliably read the npm output
172
- * as a failure (2026-04-24 eval Finding 13).
159
+ * Emits a framing banner when the Storybook workspace has not yet had its npm
160
+ * dependencies installed. `mach storybook` drives the install internally and
161
+ * prints ELSPROBLEMS / UNMET DEPENDENCY lines verbatim; without this banner
162
+ * operators reliably read the npm output as a failure.
173
163
  *
174
- * Skipped when `--install` was explicitly requested — that path already
175
- * runs `mach storybook upgrade` before the preview launches, so the npm
176
- * output for the subsequent `mach storybook` invocation is a no-op.
164
+ * Skipped when `--install` was explicitly requested — that path already runs
165
+ * `mach storybook upgrade` before the preview launches, so the npm output
166
+ * for the subsequent `mach storybook` invocation is a no-op.
177
167
  */
178
168
  async function announceStorybookFirstRunIfNeeded(engineDir, installRequested) {
179
169
  if (installRequested)
@@ -203,16 +193,7 @@ function announceStorybookCleanExitIfApplicable(exitCode) {
203
193
  */
204
194
  export async function furnacePreviewCommand(projectRoot, options = {}) {
205
195
  intro('Furnace Preview (Storybook)');
206
- // Verify engine exists
207
- const paths = getProjectPaths(projectRoot);
208
- if (!(await pathExists(paths.engine))) {
209
- throw new FurnaceError('Engine directory not found. Run "fireforge download" first.');
210
- }
211
- // Load furnace config
212
- if (!(await furnaceConfigExists(projectRoot))) {
213
- throw new FurnaceError('No furnace.json found. Run "fireforge furnace create" or "fireforge furnace override" to get started.');
214
- }
215
- const config = await loadFurnaceConfig(projectRoot);
196
+ const { paths, config } = await assertFurnaceReady(projectRoot);
216
197
  const stockCount = config.stock.length;
217
198
  const overrideCount = Object.keys(config.overrides).length;
218
199
  const customCount = Object.keys(config.custom).length;
@@ -226,8 +207,8 @@ export async function furnacePreviewCommand(projectRoot, options = {}) {
226
207
  if (!(await pathExists(storybookRoot))) {
227
208
  throw new FurnaceError('This Firefox checkout does not contain browser/components/storybook. Furnace preview requires the upstream Storybook workspace to exist before stories can be synced.');
228
209
  }
229
- // Build + toolchain preflight (Finding #9). Extracted into a helper so
230
- // the function below stays under the per-function LOC budget.
210
+ // Build + toolchain preflight, extracted into a helper so the function
211
+ // below stays under the per-function LOC budget.
231
212
  await assertPreviewPrerequisites(paths.engine);
232
213
  let previewResult;
233
214
  // True once we are about to (or have) written to engine/.../stories/furnace.
@@ -302,10 +283,8 @@ export async function furnacePreviewCommand(projectRoot, options = {}) {
302
283
  }
303
284
  installSpinner.stop('Storybook dependencies reinstalled');
304
285
  }
305
- // 2026-04-24 eval Finding 13: frame the npm noise that `mach
306
- // storybook` emits on first-run as expected progress rather than a
307
- // failure. The banner-before / banner-after helpers are extracted
308
- // so the command body stays under the per-function LOC budget.
286
+ // Frame the npm noise `mach storybook` emits on first run as expected
287
+ // progress rather than a failure.
309
288
  await announceStorybookFirstRunIfNeeded(paths.engine, options.install ?? false);
310
289
  // Start Storybook
311
290
  info('Starting Storybook...');
@@ -317,16 +296,17 @@ export async function furnacePreviewCommand(projectRoot, options = {}) {
317
296
  primaryError = error;
318
297
  }
319
298
  // Teardown runs unconditionally and never short-circuits: a failure in
320
- // cleanStories must not prevent the journal restore, and vice versa. The
321
- // previous implementation ran teardown in a `finally` block that called
322
- // `restoreRollbackJournalOrThrow`, which threw synchronously — that throw
323
- // bypassed the primary error and, worse, skipped downstream handling so
324
- // the engine was left with staged files and the user got a teardown
325
- // message with no guidance. We now collect both failures and, if anything
326
- // went wrong, persist a `pendingRepair` marker that `fireforge doctor`
327
- // consumes to finish the reconciliation.
328
- // Teardown restores the journal itself, so the lifecycle wrapper must not
329
- // restore it again when the throw below propagates out of this body.
299
+ // cleanStories must not prevent the journal restore, and vice versa.
300
+ // Running teardown in a `finally` that calls
301
+ // `restoreRollbackJournalOrThrow` throws synchronously, bypassing the
302
+ // primary error and skipping downstream handling — the engine is left
303
+ // with staged files and the user gets a teardown message with no
304
+ // guidance. Both failures are collected instead and, if anything went
305
+ // wrong, a `pendingRepair` marker is persisted for `fireforge doctor` to
306
+ // finish the reconciliation.
307
+ //
308
+ // Teardown restores the journal itself, so the lifecycle wrapper must
309
+ // not restore it again when the throw below propagates out of this body.
330
310
  ctx.markRolledBack();
331
311
  const teardownErrors = await runPreviewTeardown(paths.engine, storiesCleanupRequired, previewJournal);
332
312
  if (teardownErrors.length > 0) {
@@ -6,9 +6,10 @@ import { getOverrideEngineTargetPath } from '../../core/furnace-apply-helpers.js
6
6
  import { getFurnacePaths, loadFurnaceConfig, writeFurnaceConfig, } from '../../core/furnace-config.js';
7
7
  import { resolveFtlDir } from '../../core/furnace-constants.js';
8
8
  import { isComponentSourceFile } from '../../core/furnace-constants.js';
9
- import { recordFurnaceRollbackFailure, runFurnaceMutation } from '../../core/furnace-operation.js';
9
+ import { completeJournalRollback, runFurnaceMutation } from '../../core/furnace-operation.js';
10
+ import { assertFurnaceEngineReady } from '../../core/furnace-precondition.js';
10
11
  import { refreshOverrideFile } from '../../core/furnace-refresh.js';
11
- import { createRollbackJournal, restoreRollbackJournal, restoreRollbackJournalOrThrow, snapshotDir, snapshotFile, } from '../../core/furnace-rollback.js';
12
+ import { createRollbackJournal, restoreRollbackJournal, snapshotDir, snapshotFile, } from '../../core/furnace-rollback.js';
12
13
  import { getHead } from '../../core/git.js';
13
14
  import { FurnaceError } from '../../errors/furnace.js';
14
15
  import { toError } from '../../utils/errors.js';
@@ -144,17 +145,15 @@ async function refreshSingleOverride(projectRoot, name, options = {}) {
144
145
  return fileResults;
145
146
  }
146
147
  catch (error) {
148
+ // A dry run wrote nothing, so there is no journal to restore — it
149
+ // rethrows without touching the lifecycle wrapper.
147
150
  if (!dryRun) {
148
- // This body owns its rollback end to end, so tell the lifecycle
149
- // wrapper not to restore the same journal again on the way out.
150
- ctx.markRolledBack();
151
- try {
152
- await restoreRollbackJournalOrThrow(journal, `Failed to refresh override "${name}"`);
153
- }
154
- catch (rollbackError) {
155
- await recordFurnaceRollbackFailure(projectRoot, 'refresh-rollback', `override "${name}": ${toError(rollbackError).message}`);
156
- throw rollbackError;
157
- }
151
+ return await completeJournalRollback(ctx, journal, error, {
152
+ projectRoot,
153
+ operation: 'refresh-rollback',
154
+ failureMessage: `Failed to refresh override "${name}"`,
155
+ subject: `override "${name}"`,
156
+ });
158
157
  }
159
158
  throw error;
160
159
  }
@@ -228,10 +227,7 @@ export async function furnaceRefreshCommand(projectRoot, name, options = {}) {
228
227
  // Verify engine exists — refresh reads engine files for three-way merge
229
228
  // and --reset-base reads engine HEAD. Without this check, the user gets
230
229
  // an obscure git error instead of a clear precondition message.
231
- const paths = getProjectPaths(projectRoot);
232
- if (!(await pathExists(paths.engine))) {
233
- throw new FurnaceError('Engine directory not found. Run "fireforge download" first.');
234
- }
230
+ await assertFurnaceEngineReady(projectRoot);
235
231
  const dryRun = options.dryRun ?? false;
236
232
  if (name) {
237
233
  intro('Furnace Refresh');
@@ -5,12 +5,9 @@ import type { FurnaceState } from '../../types/furnace.js';
5
5
  /**
6
6
  * Engine-side and workspace-side removal for an OVERRIDE component.
7
7
  *
8
- * Extracted in 0.41.0: this and its custom-component sibling were the only
9
- * large inline blocks in the furnace subsystem never wrapped in a
10
- * `perform*Mutations` helper, and together they held `remove.ts` at 496/500
11
- * file lines with `furnaceRemoveCommand` at 149/150 — one line from a build
12
- * failure. Both run inside the caller's rollback journal rather than opening
13
- * their own, so a failure anywhere still restores the whole operation.
8
+ * Runs inside the caller's rollback journal rather than opening its own, so
9
+ * a failure anywhere in the remove still restores the whole operation as a
10
+ * single unit.
14
11
  */
15
12
  export declare function performOverrideRemovalMutations(args: {
16
13
  name: string;
@@ -2,12 +2,10 @@
2
2
  /**
3
3
  * Engine-side and workspace-side mutation bodies for `furnace remove`.
4
4
  *
5
- * Split out of `remove.ts` in 0.41.0. The two `perform*RemovalMutations`
6
- * functions were the only large inline blocks in the furnace subsystem never
7
- * wrapped in a helper, and together they held `remove.ts` at 496/500 file
8
- * lines with `furnaceRemoveCommand` at 149/150 — one line from a build
9
- * failure. Extracting them inside the same file traded a function-length
10
- * problem for a file-length one, so they live here instead.
5
+ * Split out of `remove.ts`, where the two `perform*RemovalMutations`
6
+ * functions held the file at the per-file line cap with
7
+ * `furnaceRemoveCommand` at the per-function cap. Extracting them inside the
8
+ * same file would trade a function-length problem for a file-length one.
11
9
  *
12
10
  * Both run inside the CALLER's rollback journal rather than opening their
13
11
  * own, so a failure anywhere in the remove still restores the whole
@@ -25,6 +23,7 @@ import { isGitRepository } from '../../core/git.js';
25
23
  import { FurnaceError } from '../../errors/furnace.js';
26
24
  import { pathExists, removeDir, removeFile } from '../../utils/fs.js';
27
25
  import { info } from '../../utils/logger.js';
26
+ import { normalizePathSlashes } from '../../utils/paths.js';
28
27
  import { removeDeployedCustomFiles } from './remove-state.js';
29
28
  /**
30
29
  * Restores every override-deployed file in `engine/` to its pristine HEAD
@@ -84,12 +83,9 @@ async function restoreOverrideEngineFiles(engineDir, overrideDir, overrideConfig
84
83
  /**
85
84
  * Engine-side and workspace-side removal for an OVERRIDE component.
86
85
  *
87
- * Extracted in 0.41.0: this and its custom-component sibling were the only
88
- * large inline blocks in the furnace subsystem never wrapped in a
89
- * `perform*Mutations` helper, and together they held `remove.ts` at 496/500
90
- * file lines with `furnaceRemoveCommand` at 149/150 — one line from a build
91
- * failure. Both run inside the caller's rollback journal rather than opening
92
- * their own, so a failure anywhere still restores the whole operation.
86
+ * Runs inside the caller's rollback journal rather than opening its own, so
87
+ * a failure anywhere in the remove still restores the whole operation as a
88
+ * single unit.
93
89
  */
94
90
  export async function performOverrideRemovalMutations(args) {
95
91
  const { name, paths, furnacePaths, freshConfig, freshState, ftlDir, journal } = args;
@@ -158,14 +154,15 @@ export async function performCustomRemovalMutations(args) {
158
154
  if (await pathExists(ftlPath)) {
159
155
  await snapshotFile(journal, ftlPath);
160
156
  await removeFile(ftlPath);
161
- info(`Deleted localized file engine/${ftlRel}`);
157
+ // `ftlRel` is a native join, so on Windows an interpolated
158
+ // `engine/${ftlRel}` renders as `engine/toolkit\locales\...` — one
159
+ // message with both separators. Print the engine-relative form.
160
+ info(`Deleted localized file engine/${normalizePathSlashes(ftlRel)}`);
162
161
  }
163
162
  // Drop the locale jar.mn chrome registration that `applyCustomFtlFile`
164
163
  // wrote during deploy — otherwise the engine is left with a
165
- // `locale/.../${name}.ftl` entry pointing at a file we just
166
- // deleted. 2026-04-21 eval (Finding #1): `furnace remove` left
167
- // `browser/locales/jar.mn` referencing the missing FTL, which
168
- // would break the next package-manifest validation.
164
+ // `locale/.../${name}.ftl` entry pointing at a file just deleted, which
165
+ // breaks the next package-manifest validation.
169
166
  await removeCustomFtlJarMnEntry(paths.engine, `${name}.ftl`, ftlDir, customConfig, journal);
170
167
  }
171
168
  }
@@ -1,4 +1,5 @@
1
1
  // SPDX-License-Identifier: EUPL-1.2
2
+ import { readdir } from 'node:fs/promises';
2
3
  import { join } from 'node:path';
3
4
  import { loadFurnaceState } from '../../core/furnace-config.js';
4
5
  import { snapshotFile } from '../../core/furnace-rollback.js';
@@ -52,7 +53,6 @@ export async function removeDeployedCustomFiles(projectRoot, engineDir, name, ta
52
53
  if (deletedCount > 0) {
53
54
  info(`Deleted ${deletedCount} deployed file(s) from engine/${targetPath}/`);
54
55
  }
55
- const { readdir } = await import('node:fs/promises');
56
56
  if ((await readdir(engineTargetDir)).length === 0) {
57
57
  await removeDir(engineTargetDir);
58
58
  info(`Removed now-empty engine/${targetPath}/`);
@@ -3,12 +3,13 @@ import { readdir, unlink } from 'node:fs/promises';
3
3
  import { join } from 'node:path';
4
4
  import { confirm } from '@clack/prompts';
5
5
  import { getProjectPaths, loadConfig } from '../../core/config.js';
6
+ import { stdioIsInteractive } from '../../core/destructive.js';
6
7
  import { getFurnacePaths, loadFurnaceConfig, loadFurnaceState, updateFurnaceState, writeFurnaceConfig, } from '../../core/furnace-config.js';
7
8
  import { resolveFtlDir, xpcshellTestParentDir } from '../../core/furnace-constants.js';
8
- import { recordFurnaceRollbackFailure, runFurnaceMutation } from '../../core/furnace-operation.js';
9
- import { createRollbackJournal, restoreRollbackJournalOrThrow, snapshotDir, snapshotFile, } from '../../core/furnace-rollback.js';
9
+ import { completeJournalRollback, runFurnaceMutation } from '../../core/furnace-operation.js';
10
+ import { createRollbackJournal, snapshotDir, snapshotFile, } from '../../core/furnace-rollback.js';
10
11
  import { isGitRepository } from '../../core/git.js';
11
- import { deregisterTestManifest } from '../../core/manifest-register.js';
12
+ import { deregisterTestManifest } from '../../core/moz-manifest-register.js';
12
13
  import { FurnaceError } from '../../errors/furnace.js';
13
14
  import { toError } from '../../utils/errors.js';
14
15
  import { pathExists, readText, removeDir, writeText } from '../../utils/fs.js';
@@ -157,23 +158,23 @@ async function cleanupCustomTestFiles(name, projectRoot, journal) {
157
158
  return { partialFailures };
158
159
  }
159
160
  /**
160
- * Removes the MochiKit test scaffold a `furnace create --with-tests
161
- * --test-style mochikit` produced for the component (matches the rename
162
- * counterpart in `rename.ts`). The test file is `test_<name>.html` under
163
- * `engine/toolkit/content/tests/widgets/` and the registration is the
164
- * `["test_<name>.html"]` entry in the same directory's `chrome.toml`.
161
+ * Removes the MochiKit test scaffold a
162
+ * `furnace create --with-tests --test-style mochikit` produced for the
163
+ * component (matches the rename counterpart in `rename.ts`). The test file is
164
+ * `test_<name>.html` under `engine/toolkit/content/tests/widgets/` and the
165
+ * registration is the `["test_<name>.html"]` entry in the same directory's
166
+ * `chrome.toml`.
165
167
  *
166
- * 2026-04-25 eval Finding 13: the prior cleanup only handled the
167
- * browser-chrome mochitest layout under `browser/base/content/test/
168
- * <binary>/`, which left mochikit-style scaffolds and their toml entries
169
- * orphaned after `furnace remove`. The post-rename name passed in here
170
- * is the canonical one written to disk by deploy/rename, so the file
171
- * basenames match without needing to re-derive from the old name.
168
+ * Cleanup that only handles the browser-chrome mochitest layout under
169
+ * `browser/base/content/test/<binary>/` leaves mochikit-style scaffolds and
170
+ * their toml entries orphaned after `furnace remove`. The post-rename name
171
+ * passed in here is the canonical one written to disk by deploy/rename, so
172
+ * the file basenames match without re-deriving from the old name.
172
173
  *
173
- * Best-effort: each step warns on failure rather than throwing so the
174
- * rest of the remove transaction proceeds. The journal still snapshots
175
- * touched files so the outer rollback can restore them on a later
176
- * failure in the same operation.
174
+ * Best-effort: each step warns on failure rather than throwing so the rest
175
+ * of the remove transaction proceeds. The journal still snapshots touched
176
+ * files so the outer rollback can restore them on a later failure in the
177
+ * same operation.
177
178
  */
178
179
  async function cleanupCustomMochikitTestFiles(name, projectRoot, journal) {
179
180
  const partialFailures = [];
@@ -216,14 +217,13 @@ async function cleanupCustomMochikitTestFiles(name, projectRoot, journal) {
216
217
  }
217
218
  /**
218
219
  * Removes generated xpcshell test scaffolds associated with a custom
219
- * component. 2026-04-24 eval Finding 5: `furnace remove` handled
220
- * browser mochitests via `cleanupCustomTestFiles` but never touched the
221
- * xpcshell scaffold tree, so an operator who ran
222
- * `furnace create --with-tests --xpcshell` followed by `furnace remove`
223
- * was left with orphan `xpcshell.toml` + `test_<name>_packaged.js`
224
- * files still referencing the removed component. This cleanup pass
225
- * mirrors the mochitest one — snapshot before removal, warn-and-
226
- * continue semantics, explicit summary when partial failures occur.
220
+ * component. Cleanup that handles browser mochitests via
221
+ * `cleanupCustomTestFiles` but never touches the xpcshell scaffold tree
222
+ * leaves an operator who ran `furnace create --with-tests --xpcshell`
223
+ * followed by `furnace remove` with orphan `xpcshell.toml` +
224
+ * `test_<name>_packaged.js` files still referencing the removed component.
225
+ * This pass mirrors the mochitest one — snapshot before removal,
226
+ * warn-and-continue semantics, explicit summary on partial failures.
227
227
  */
228
228
  async function cleanupCustomXpcshellTestFiles(name, projectRoot, journal) {
229
229
  const partialFailures = [];
@@ -328,7 +328,7 @@ async function requireGitEngineForRemove(type, name, engineDir) {
328
328
  * @param options - CLI options
329
329
  */
330
330
  export async function furnaceRemoveCommand(projectRoot, name, options = {}) {
331
- const isInteractive = process.stdin.isTTY && process.stdout.isTTY;
331
+ const isInteractive = stdioIsInteractive();
332
332
  intro('Furnace Remove');
333
333
  const config = await loadFurnaceConfig(projectRoot);
334
334
  const furnacePaths = getFurnacePaths(projectRoot);
@@ -405,17 +405,12 @@ export async function furnaceRemoveCommand(projectRoot, name, options = {}) {
405
405
  }
406
406
  }
407
407
  catch (error) {
408
- // This body owns its rollback end to end, so tell the lifecycle wrapper
409
- // not to restore the same journal again on the way out.
410
- ctx.markRolledBack();
411
- try {
412
- await restoreRollbackJournalOrThrow(journal, `Failed to remove component "${name}"`);
413
- }
414
- catch (rollbackError) {
415
- await recordFurnaceRollbackFailure(projectRoot, 'remove-rollback', `component "${name}": ${toError(rollbackError).message}`);
416
- throw rollbackError;
417
- }
418
- throw error;
408
+ return await completeJournalRollback(ctx, journal, error, {
409
+ projectRoot: projectRoot,
410
+ operation: 'remove-rollback',
411
+ failureMessage: `Failed to remove component "${name}"`,
412
+ subject: `component "${name}"`,
413
+ });
419
414
  }
420
415
  });
421
416
  info(`Removed "${name}" from furnace.json`);
@@ -1,18 +1,15 @@
1
1
  /**
2
2
  * xpcshell scaffold rename helper extracted from `rename.ts`.
3
3
  *
4
- * 2026-04-24 eval Finding 5: `furnace create --with-tests --xpcshell`
5
- * writes a scaffold at `browser/base/content/test/<binary>-xpcshell/
6
- * <name>/` and `furnace rename` did not update it. The helper below
7
- * renames the directory, updates the test filename, rewrites the
8
- * `xpcshell.toml` section header, and re-writes the test body so word-
9
- * boundary occurrences of the old tag / underscored name map to the new
10
- * ones.
4
+ * `furnace create --with-tests --xpcshell` writes a scaffold at
5
+ * `browser/base/content/test/<binary>-xpcshell/<name>/`, which a rename must
6
+ * follow. This helper renames the directory, updates the test filename,
7
+ * rewrites the `xpcshell.toml` section header, and re-writes the test body
8
+ * so word-boundary occurrences of the old tag / underscored name map to the
9
+ * new ones.
11
10
  *
12
- * Extracted to keep `rename.ts` under the per-file LOC budget —
13
- * `rename.ts` already carries mochikit + browser-mochitest + FTL
14
- * handling, and tacking xpcshell onto that tree pushed the file past
15
- * the limit.
11
+ * Extracted to keep `rename.ts` under the per-file LOC budget — it already
12
+ * carries mochikit + browser-mochitest + FTL handling.
16
13
  */
17
14
  import { type RollbackJournal } from '../../core/furnace-rollback.js';
18
15
  /**
@@ -2,18 +2,15 @@
2
2
  /**
3
3
  * xpcshell scaffold rename helper extracted from `rename.ts`.
4
4
  *
5
- * 2026-04-24 eval Finding 5: `furnace create --with-tests --xpcshell`
6
- * writes a scaffold at `browser/base/content/test/<binary>-xpcshell/
7
- * <name>/` and `furnace rename` did not update it. The helper below
8
- * renames the directory, updates the test filename, rewrites the
9
- * `xpcshell.toml` section header, and re-writes the test body so word-
10
- * boundary occurrences of the old tag / underscored name map to the new
11
- * ones.
5
+ * `furnace create --with-tests --xpcshell` writes a scaffold at
6
+ * `browser/base/content/test/<binary>-xpcshell/<name>/`, which a rename must
7
+ * follow. This helper renames the directory, updates the test filename,
8
+ * rewrites the `xpcshell.toml` section header, and re-writes the test body
9
+ * so word-boundary occurrences of the old tag / underscored name map to the
10
+ * new ones.
12
11
  *
13
- * Extracted to keep `rename.ts` under the per-file LOC budget —
14
- * `rename.ts` already carries mochikit + browser-mochitest + FTL
15
- * handling, and tacking xpcshell onto that tree pushed the file past
16
- * the limit.
12
+ * Extracted to keep `rename.ts` under the per-file LOC budget — it already
13
+ * carries mochikit + browser-mochitest + FTL handling.
17
14
  */
18
15
  import { readdir } from 'node:fs/promises';
19
16
  import { join } from 'node:path';