@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
@@ -53,8 +53,7 @@ export declare function loadFurnaceConfig(root: string): Promise<FurnaceConfig>;
53
53
  * reset, rebase, rebase --abort): every applied checksum describes content
54
54
  * that no longer exists, but pendingRepair tracks authoring-side rollback
55
55
  * issues in the component WORKSPACE and must survive an engine refresh.
56
- * No-ops when the state file does not exist. Centralized because the same
57
- * reset logic had drifted into four separate command files.
56
+ * No-ops when the state file does not exist.
58
57
  */
59
58
  export declare function clearAppliedFurnaceState(root: string): Promise<void>;
60
59
  /**
@@ -65,20 +64,15 @@ export declare function clearAppliedFurnaceState(root: string): Promise<void>;
65
64
  export declare function writeFurnaceConfig(root: string, config: FurnaceConfig): Promise<void>;
66
65
  /**
67
66
  * Stamps every override's `baseVersion` to the supplied version. Used by
68
- * `fireforge rebase` after a successful patch re-export so a successful
69
- * ESR bump does not leave Furnace overrides in a doctor-failing drift
70
- * state. Returns the number of overrides stamped (zero if furnace.json
71
- * has no overrides, or if the file is missing).
67
+ * `fireforge rebase` after a successful patch re-export, so an ESR bump does
68
+ * not leave Furnace overrides in a doctor-failing drift state: `rebase`
69
+ * stamps patch `sourceEsrVersion` via `stampPatchVersions`, and without the
70
+ * matching override stamp `doctor` fails Furnace component validation on
71
+ * every override.
72
72
  *
73
- * Motivating case: a 140.9.0esr → 140.9.1esr rebase stamps patch
74
- * `sourceEsrVersion` via `stampPatchVersions`, but before 0.16.0 no
75
- * equivalent stamping ran for Furnace override `baseVersion`. `doctor`
76
- * then immediately failed Furnace component validation on every
77
- * override. The stamp is deliberately unconditional — `fireforge
78
- * furnace validate` is the right tool for "does this override still
79
- * apply", and rebase already attested that the patch layer re-validated
80
- * against the new ESR; the per-override health check belongs in a
81
- * separate pass, not inline with the stamp.
73
+ * The stamp is deliberately unconditional — `fireforge furnace validate` is
74
+ * the right tool for "does this override still apply", and rebase has
75
+ * already attested that the patch layer re-validated against the new ESR.
82
76
  *
83
77
  * @param root - Root directory of the project
84
78
  * @param version - Firefox version string to stamp onto every override
@@ -90,23 +84,20 @@ export declare function stampFurnaceOverrideBaseVersions(root: string, version:
90
84
  * Creates a default furnace configuration.
91
85
  *
92
86
  * When a `binaryName` is provided, the default config carries a
93
- * `tokenPrefix` derived as `--<binaryName>-`. Without that default,
94
- * `fireforge token coverage` on a fresh project reports `0 tokens` and
95
- * labels every custom-property reference as `unknown` — the scan has
96
- * no prefix to key off. The 2026-04-21 eval walked directly into this
97
- * state (`furnace init` → `token add` → `token coverage` → zero
98
- * tokens), and only recovered after hand-editing furnace.json. Deriving
99
- * the prefix from the binary name matches the convention the scaffolded
100
- * tokens CSS already uses for its `--<binaryName>-*` declarations.
87
+ * `tokenPrefix` derived as `--<binaryName>-`. Without it, `fireforge token
88
+ * coverage` on a fresh project reports `0 tokens` and labels every
89
+ * custom-property reference as `unknown`, because the scan has no prefix to
90
+ * key off. Deriving the prefix from the binary name matches the convention
91
+ * the scaffolded tokens CSS already uses for its `--<binaryName>-*`
92
+ * declarations.
101
93
  *
102
- * `validateFurnaceConfig` treats `tokenPrefix` as optional, so callers
103
- * on the legacy no-arg call shape (existing tests, programmatic callers
104
- * bootstrapping from a not-yet-loaded config) still get a valid config
105
- * without a prefix; the CLI init path always has a `binaryName` from
106
- * `fireforge.json` and always sets one.
94
+ * `validateFurnaceConfig` treats `tokenPrefix` as optional, so callers on
95
+ * the no-arg call shape still get a valid config without a prefix; the CLI
96
+ * init path always has a `binaryName` from `fireforge.json` and always sets
97
+ * one.
107
98
  *
108
- * @param options - Optional init context; pass `{ binaryName }` to
109
- * derive the token prefix.
99
+ * @param options - Optional init context; pass `{ binaryName }` to derive
100
+ * the token prefix.
110
101
  * @returns A valid FurnaceConfig
111
102
  */
112
103
  export declare function createDefaultFurnaceConfig(options?: {
@@ -1,6 +1,7 @@
1
1
  // SPDX-License-Identifier: EUPL-1.2
2
2
  import { join } from 'node:path';
3
3
  import { FurnaceError } from '../errors/furnace.js';
4
+ import { FURNACE_PENDING_REPAIR_OPERATIONS } from '../types/furnace.js';
4
5
  import { toError } from '../utils/errors.js';
5
6
  import { pathExists, readJson, writeJson } from '../utils/fs.js';
6
7
  import { warn } from '../utils/logger.js';
@@ -128,9 +129,8 @@ export function validateFurnaceConfig(data) {
128
129
  // Warn when two custom components share a targetPath. Nothing technically
129
130
  // prevents co-location, but per-component removal and orphan detection
130
131
  // both reason about "files this component deployed into its directory" —
131
- // shared directories make those judgements ambiguous, and historically a
132
- // shared targetPath meant `furnace remove` of one component deleted the
133
- // other's deployed files.
132
+ // shared directories make those judgements ambiguous, and can lead to
133
+ // `furnace remove` of one component deleting the other's deployed files.
134
134
  const targetPathOwners = new Map();
135
135
  for (const [name, custom_] of Object.entries(custom)) {
136
136
  const owners = targetPathOwners.get(custom_.targetPath) ?? [];
@@ -166,18 +166,11 @@ function validateFurnaceState(data) {
166
166
  }
167
167
  return result.state;
168
168
  }
169
- const PENDING_REPAIR_OPERATIONS = [
170
- 'preview-teardown',
171
- 'apply-rollback',
172
- 'deploy-rollback',
173
- 'remove-rollback',
174
- 'create-rollback',
175
- 'chrome-doc-rollback',
176
- 'override-rollback',
177
- 'scan-rollback',
178
- 'rename-rollback',
179
- 'refresh-rollback',
180
- ];
169
+ // Single source of truth: the list the union is derived from. The copy
170
+ // this replaced was annotated, not linked — it caught a member REMOVED
171
+ // from the union but never one ADDED to it, and listed them in a
172
+ // different order.
173
+ const PENDING_REPAIR_OPERATIONS = FURNACE_PENDING_REPAIR_OPERATIONS;
181
174
  function parsePendingRepair(data) {
182
175
  if (!isObject(data)) {
183
176
  return { error: 'field "pendingRepair" must be an object' };
@@ -337,8 +330,7 @@ export async function loadFurnaceConfig(root) {
337
330
  * reset, rebase, rebase --abort): every applied checksum describes content
338
331
  * that no longer exists, but pendingRepair tracks authoring-side rollback
339
332
  * issues in the component WORKSPACE and must survive an engine refresh.
340
- * No-ops when the state file does not exist. Centralized because the same
341
- * reset logic had drifted into four separate command files.
333
+ * No-ops when the state file does not exist.
342
334
  */
343
335
  export async function clearAppliedFurnaceState(root) {
344
336
  const paths = getFurnacePaths(root);
@@ -374,20 +366,15 @@ export async function writeFurnaceConfig(root, config) {
374
366
  }
375
367
  /**
376
368
  * Stamps every override's `baseVersion` to the supplied version. Used by
377
- * `fireforge rebase` after a successful patch re-export so a successful
378
- * ESR bump does not leave Furnace overrides in a doctor-failing drift
379
- * state. Returns the number of overrides stamped (zero if furnace.json
380
- * has no overrides, or if the file is missing).
369
+ * `fireforge rebase` after a successful patch re-export, so an ESR bump does
370
+ * not leave Furnace overrides in a doctor-failing drift state: `rebase`
371
+ * stamps patch `sourceEsrVersion` via `stampPatchVersions`, and without the
372
+ * matching override stamp `doctor` fails Furnace component validation on
373
+ * every override.
381
374
  *
382
- * Motivating case: a 140.9.0esr → 140.9.1esr rebase stamps patch
383
- * `sourceEsrVersion` via `stampPatchVersions`, but before 0.16.0 no
384
- * equivalent stamping ran for Furnace override `baseVersion`. `doctor`
385
- * then immediately failed Furnace component validation on every
386
- * override. The stamp is deliberately unconditional — `fireforge
387
- * furnace validate` is the right tool for "does this override still
388
- * apply", and rebase already attested that the patch layer re-validated
389
- * against the new ESR; the per-override health check belongs in a
390
- * separate pass, not inline with the stamp.
375
+ * The stamp is deliberately unconditional — `fireforge furnace validate` is
376
+ * the right tool for "does this override still apply", and rebase has
377
+ * already attested that the patch layer re-validated against the new ESR.
391
378
  *
392
379
  * @param root - Root directory of the project
393
380
  * @param version - Firefox version string to stamp onto every override
@@ -414,23 +401,20 @@ export async function stampFurnaceOverrideBaseVersions(root, version) {
414
401
  * Creates a default furnace configuration.
415
402
  *
416
403
  * When a `binaryName` is provided, the default config carries a
417
- * `tokenPrefix` derived as `--<binaryName>-`. Without that default,
418
- * `fireforge token coverage` on a fresh project reports `0 tokens` and
419
- * labels every custom-property reference as `unknown` — the scan has
420
- * no prefix to key off. The 2026-04-21 eval walked directly into this
421
- * state (`furnace init` → `token add` → `token coverage` → zero
422
- * tokens), and only recovered after hand-editing furnace.json. Deriving
423
- * the prefix from the binary name matches the convention the scaffolded
424
- * tokens CSS already uses for its `--<binaryName>-*` declarations.
404
+ * `tokenPrefix` derived as `--<binaryName>-`. Without it, `fireforge token
405
+ * coverage` on a fresh project reports `0 tokens` and labels every
406
+ * custom-property reference as `unknown`, because the scan has no prefix to
407
+ * key off. Deriving the prefix from the binary name matches the convention
408
+ * the scaffolded tokens CSS already uses for its `--<binaryName>-*`
409
+ * declarations.
425
410
  *
426
- * `validateFurnaceConfig` treats `tokenPrefix` as optional, so callers
427
- * on the legacy no-arg call shape (existing tests, programmatic callers
428
- * bootstrapping from a not-yet-loaded config) still get a valid config
429
- * without a prefix; the CLI init path always has a `binaryName` from
430
- * `fireforge.json` and always sets one.
411
+ * `validateFurnaceConfig` treats `tokenPrefix` as optional, so callers on
412
+ * the no-arg call shape still get a valid config without a prefix; the CLI
413
+ * init path always has a `binaryName` from `fireforge.json` and always sets
414
+ * one.
431
415
  *
432
- * @param options - Optional init context; pass `{ binaryName }` to
433
- * derive the token prefix.
416
+ * @param options - Optional init context; pass `{ binaryName }` to derive
417
+ * the token prefix.
434
418
  * @returns A valid FurnaceConfig
435
419
  */
436
420
  export function createDefaultFurnaceConfig(options = {}) {
@@ -496,15 +480,9 @@ export async function updateFurnaceState(root, updates) {
496
480
  /**
497
481
  * Engine-relative path of the directory `furnace preview` writes its
498
482
  * generated Storybook story files into. Treated as Furnace-managed so
499
- * `status` does not flag them as unmanaged and `lint` does not fail on
500
- * their (intentionally bare) license headers.
501
- *
502
- * 2026-04-25 eval Finding 19: a successful `furnace preview` run synced
503
- * 23 stories under this prefix; afterwards `status` showed all 23 as
504
- * untracked unmanaged changes and aggregate `lint` failed with 23
505
- * `missing-license-header` errors. The files are tool output — operators
506
- * are not expected to commit or hand-edit them — so the right shape is
507
- * to bucket them with the rest of Furnace's managed material.
483
+ * `status` does not flag them as unmanaged and `lint` does not fail on their
484
+ * (intentionally bare) license headers — they are tool output, not files an
485
+ * operator commits or hand-edits.
508
486
  */
509
487
  const FURNACE_STORYBOOK_STORIES_PREFIX = 'browser/components/storybook/stories/furnace/';
510
488
  /**
@@ -2,6 +2,14 @@
2
2
  export declare const CUSTOM_ELEMENTS_JS = "toolkit/content/customElements.js";
3
3
  /** Path to jar.mn within the engine source tree (toolkit global) */
4
4
  export declare const JAR_MN = "toolkit/content/jar.mn";
5
+ /**
6
+ * Upstream home of the MozLitElement widget sources.
7
+ *
8
+ * The trailing slash is NOT included: `build-audit-transforms.ts` needs
9
+ * `${WIDGETS_DIR}/` and its ordered prefix table depends on that slash, so
10
+ * appending it at the one site that wants it keeps the others correct.
11
+ */
12
+ export declare const WIDGETS_DIR = "toolkit/content/widgets";
5
13
  /** Default Fluent localization directory for toolkit global components, relative to engine root */
6
14
  export declare const FTL_DIR = "toolkit/locales/en-US/toolkit/global";
7
15
  /**
@@ -3,14 +3,22 @@
3
3
  export const CUSTOM_ELEMENTS_JS = 'toolkit/content/customElements.js';
4
4
  /** Path to jar.mn within the engine source tree (toolkit global) */
5
5
  export const JAR_MN = 'toolkit/content/jar.mn';
6
+ /**
7
+ * Upstream home of the MozLitElement widget sources.
8
+ *
9
+ * The trailing slash is NOT included: `build-audit-transforms.ts` needs
10
+ * `${WIDGETS_DIR}/` and its ordered prefix table depends on that slash, so
11
+ * appending it at the one site that wants it keeps the others correct.
12
+ */
13
+ export const WIDGETS_DIR = 'toolkit/content/widgets';
6
14
  /** Default Fluent localization directory for toolkit global components, relative to engine root */
7
15
  export const FTL_DIR = 'toolkit/locales/en-US/toolkit/global';
8
16
  /**
9
17
  * Suffix for the per-binary xpcshell scaffold parent directory. Components
10
18
  * created with `furnace create --with-tests --xpcshell` land at
11
19
  * `browser/base/content/test/<binaryName>${XPCSHELL_TEST_DIR_SUFFIX}/<component>/`.
12
- * Centralised so `create` / `remove` / `rename` / `validate` all agree on
13
- * the path template (2026-04-24 eval Finding 5).
20
+ * Centralised so `create` / `remove` / `rename` / `validate` all agree on the
21
+ * path template.
14
22
  */
15
23
  const XPCSHELL_TEST_DIR_SUFFIX = '-xpcshell';
16
24
  /**
@@ -1,8 +1,8 @@
1
1
  /**
2
- * Shared CSS fragments for Furnace widgets (field report D2).
2
+ * Shared CSS fragments for Furnace widgets.
3
3
  *
4
4
  * Shadow-DOM isolation forces each widget stylesheet to carry its own copy
5
- * of genuinely shared CSS (keyframes, resets). Hand-syncing those copies
5
+ * of genuinely shared CSS (keyframes, resets), and hand-syncing those copies
6
6
  * drifts. Instead, a workspace stylesheet declares an include directive
7
7
  * (a CSS block comment on its own line):
8
8
  *
@@ -14,9 +14,9 @@
14
14
  * `@fireforge-end-include` marker so re-deploys can refresh it idempotently.
15
15
  *
16
16
  * Drift contract: the apply fast-path and `furnace validate` compare the
17
- * *expanded* workspace source against the engine copy, so editing a
18
- * fragment surfaces as ordinary component drift and the next deploy
19
- * refreshes every consuming widget.
17
+ * *expanded* workspace source against the engine copy, so editing a fragment
18
+ * surfaces as ordinary component drift and the next deploy refreshes every
19
+ * consuming widget.
20
20
  */
21
21
  import type { ValidationIssue } from '../types/furnace.js';
22
22
  export { SHARED_FRAGMENTS_DIR } from './furnace-config.js';
@@ -1,9 +1,9 @@
1
1
  // SPDX-License-Identifier: EUPL-1.2
2
2
  /**
3
- * Shared CSS fragments for Furnace widgets (field report D2).
3
+ * Shared CSS fragments for Furnace widgets.
4
4
  *
5
5
  * Shadow-DOM isolation forces each widget stylesheet to carry its own copy
6
- * of genuinely shared CSS (keyframes, resets). Hand-syncing those copies
6
+ * of genuinely shared CSS (keyframes, resets), and hand-syncing those copies
7
7
  * drifts. Instead, a workspace stylesheet declares an include directive
8
8
  * (a CSS block comment on its own line):
9
9
  *
@@ -15,9 +15,9 @@
15
15
  * `@fireforge-end-include` marker so re-deploys can refresh it idempotently.
16
16
  *
17
17
  * Drift contract: the apply fast-path and `furnace validate` compare the
18
- * *expanded* workspace source against the engine copy, so editing a
19
- * fragment surfaces as ordinary component drift and the next deploy
20
- * refreshes every consuming widget.
18
+ * *expanded* workspace source against the engine copy, so editing a fragment
19
+ * surfaces as ordinary component drift and the next deploy refreshes every
20
+ * consuming widget.
21
21
  */
22
22
  import { readdir } from 'node:fs/promises';
23
23
  import { join } from 'node:path';
@@ -1,23 +1,22 @@
1
1
  /**
2
- * Maintains `compilerOptions.paths` entries in a consumer-owned jsconfig
3
- * so typed cross-module imports of multi-file Furnace components work
4
- * (field report D3).
2
+ * Maintains `compilerOptions.paths` entries in a consumer-owned jsconfig so
3
+ * typed cross-module imports of multi-file Furnace components work.
5
4
  *
6
5
  * When a main widget imports a sibling helper via its deployed chrome URL
7
- * (`chrome://global/content/elements/<helper>.mjs`), a wildcard module
8
- * shim swallows the import: value imports degrade to `any` and
6
+ * (`chrome://global/content/elements/<helper>.mjs`), a wildcard module shim
7
+ * swallows the import: value imports degrade to `any` and
9
8
  * `import(...).SomeType` typedefs fail with TS2694. The fix is a `paths`
10
- * mapping from the chrome URL to the real workspace source. Furnace
11
- * already owns the jar.mn side of that mapping, so it can maintain the
12
- * jsconfig side automatically on every deploy.
9
+ * mapping from the chrome URL to the real workspace source. Furnace already
10
+ * owns the jar.mn side of that mapping, so it maintains the jsconfig side
11
+ * automatically on every deploy.
13
12
  *
14
13
  * Ownership contract: only entries whose key starts with
15
14
  * `chrome://global/content/elements/` AND whose mapped path resolves into
16
15
  * the Furnace custom-components workspace are managed (added, updated,
17
- * pruned). Everything else in the jsconfig — including hand-written
18
- * `paths` entries pointing elsewhere — is preserved verbatim. No
19
- * `baseUrl` is required or written: relative `paths` resolve against the
20
- * config file's directory.
16
+ * pruned). Everything else in the jsconfig — including hand-written `paths`
17
+ * entries pointing elsewhere — is preserved verbatim. No `baseUrl` is
18
+ * required or written: relative `paths` resolve against the config file's
19
+ * directory.
21
20
  */
22
21
  import type { FurnaceConfig } from '../types/furnace.js';
23
22
  /** Result summary of a jsconfig paths sync. */
@@ -1,24 +1,23 @@
1
1
  // SPDX-License-Identifier: EUPL-1.2
2
2
  /**
3
- * Maintains `compilerOptions.paths` entries in a consumer-owned jsconfig
4
- * so typed cross-module imports of multi-file Furnace components work
5
- * (field report D3).
3
+ * Maintains `compilerOptions.paths` entries in a consumer-owned jsconfig so
4
+ * typed cross-module imports of multi-file Furnace components work.
6
5
  *
7
6
  * When a main widget imports a sibling helper via its deployed chrome URL
8
- * (`chrome://global/content/elements/<helper>.mjs`), a wildcard module
9
- * shim swallows the import: value imports degrade to `any` and
7
+ * (`chrome://global/content/elements/<helper>.mjs`), a wildcard module shim
8
+ * swallows the import: value imports degrade to `any` and
10
9
  * `import(...).SomeType` typedefs fail with TS2694. The fix is a `paths`
11
- * mapping from the chrome URL to the real workspace source. Furnace
12
- * already owns the jar.mn side of that mapping, so it can maintain the
13
- * jsconfig side automatically on every deploy.
10
+ * mapping from the chrome URL to the real workspace source. Furnace already
11
+ * owns the jar.mn side of that mapping, so it maintains the jsconfig side
12
+ * automatically on every deploy.
14
13
  *
15
14
  * Ownership contract: only entries whose key starts with
16
15
  * `chrome://global/content/elements/` AND whose mapped path resolves into
17
16
  * the Furnace custom-components workspace are managed (added, updated,
18
- * pruned). Everything else in the jsconfig — including hand-written
19
- * `paths` entries pointing elsewhere — is preserved verbatim. No
20
- * `baseUrl` is required or written: relative `paths` resolve against the
21
- * config file's directory.
17
+ * pruned). Everything else in the jsconfig — including hand-written `paths`
18
+ * entries pointing elsewhere — is preserved verbatim. No `baseUrl` is
19
+ * required or written: relative `paths` resolve against the config file's
20
+ * directory.
22
21
  */
23
22
  import { readdir } from 'node:fs/promises';
24
23
  import { dirname, join, relative, resolve } from 'node:path';
@@ -1,14 +1,13 @@
1
1
  /**
2
2
  * Marker-comment resolution shared between furnace apply and deploy.
3
3
  *
4
- * 2026-04-26 eval Finding 6: when `markerComment` is unset in
5
- * fireforge.json, fall back to `binaryName.toUpperCase()` so the
6
- * patch-lint rule `lintModificationComments` (which keys on
7
- * `${binaryName.toUpperCase()}:`) accepts furnace-emitted edits on the
8
- * next `lint`/`export` round-trip. The helper tolerates the
9
- * undefined-config case (a project that hasn't run `fireforge setup`
10
- * yet) and the missing-binaryName case (test fixtures that mock
11
- * `loadConfig` with a partial shape).
4
+ * When `markerComment` is unset in fireforge.json, fall back to
5
+ * `binaryName.toUpperCase()` so the patch-lint rule
6
+ * `lintModificationComments` (which keys on `${binaryName.toUpperCase()}:`)
7
+ * accepts furnace-emitted edits on the next `lint`/`export` round-trip. The
8
+ * helper tolerates the undefined-config case (a project that has not run
9
+ * `fireforge setup` yet) and the missing-binaryName case (test fixtures that
10
+ * mock `loadConfig` with a partial shape).
12
11
  */
13
12
  export declare function resolveFurnaceMarkerComment(forgeConfig: {
14
13
  markerComment?: string;
@@ -2,14 +2,13 @@
2
2
  /**
3
3
  * Marker-comment resolution shared between furnace apply and deploy.
4
4
  *
5
- * 2026-04-26 eval Finding 6: when `markerComment` is unset in
6
- * fireforge.json, fall back to `binaryName.toUpperCase()` so the
7
- * patch-lint rule `lintModificationComments` (which keys on
8
- * `${binaryName.toUpperCase()}:`) accepts furnace-emitted edits on the
9
- * next `lint`/`export` round-trip. The helper tolerates the
10
- * undefined-config case (a project that hasn't run `fireforge setup`
11
- * yet) and the missing-binaryName case (test fixtures that mock
12
- * `loadConfig` with a partial shape).
5
+ * When `markerComment` is unset in fireforge.json, fall back to
6
+ * `binaryName.toUpperCase()` so the patch-lint rule
7
+ * `lintModificationComments` (which keys on `${binaryName.toUpperCase()}:`)
8
+ * accepts furnace-emitted edits on the next `lint`/`export` round-trip. The
9
+ * helper tolerates the undefined-config case (a project that has not run
10
+ * `fireforge setup` yet) and the missing-binaryName case (test fixtures that
11
+ * mock `loadConfig` with a partial shape).
13
12
  */
14
13
  export function resolveFurnaceMarkerComment(forgeConfig) {
15
14
  if (!forgeConfig)
@@ -86,6 +86,37 @@ export declare function rollbackActiveOperationsForSignal(signal: FurnaceShutdow
86
86
  * touch this directly.
87
87
  */
88
88
  export declare function getFurnaceLockPath(root: string): string;
89
+ /**
90
+ * Completes the rollback for a mutation body that owns its journal end to
91
+ * end, then rethrows. Never returns normally.
92
+ *
93
+ * Shaped as a catch-body handler rather than a `withJournalRollback(body)`
94
+ * wrapper on purpose: the eight calling bodies differ in early returns and
95
+ * in what they close over, and converting them to callbacks would
96
+ * restructure control flow through the engine's rollback path for a
97
+ * cosmetic gain.
98
+ *
99
+ * The ordering is the part worth centralising: `markRolledBack()` MUST run
100
+ * before the restore, so a restore that itself fails does not leave the
101
+ * lifecycle wrapper replaying the same journal on the way out. And the
102
+ * ORIGINAL error is rethrown unless the rollback is what failed — the
103
+ * operator needs to know what went wrong, and separately whether the engine
104
+ * could be put back.
105
+ *
106
+ * @param ctx - The furnace operation context from `runFurnaceMutation`
107
+ * @param journal - Rollback journal this body populated
108
+ * @param error - The error the body threw
109
+ * @param options - Project root, pending-repair tag, and message fragments
110
+ * @returns Never — always throws
111
+ */
112
+ export declare function completeJournalRollback(ctx: FurnaceOperationContext, journal: RollbackJournal, error: unknown, options: {
113
+ projectRoot: string;
114
+ operation: FurnacePendingRepairOperation;
115
+ /** Prefix for the restore failure, e.g. `Failed to override component "x"`. */
116
+ failureMessage: string;
117
+ /** Subject recorded on the pending-repair marker, e.g. `component "x"`. */
118
+ subject: string;
119
+ }): Promise<never>;
89
120
  /**
90
121
  * Forcibly removes the furnace lock directory for every active operation.
91
122
  *
@@ -1,14 +1,13 @@
1
1
  // SPDX-License-Identifier: EUPL-1.2
2
- import { rm } from 'node:fs/promises';
3
2
  import { join } from 'node:path';
4
3
  import { FurnaceError } from '../errors/furnace.js';
5
4
  import { assert } from '../utils/assert.js';
6
5
  import { toError } from '../utils/errors.js';
7
6
  import { verbose, warn } from '../utils/logger.js';
8
7
  import { FIREFORGE_DIR } from './config-paths.js';
9
- import { readLockStatus, withFileLock } from './file-lock.js';
8
+ import { readLockStatus, releaseLockIfOwned, withFileLock } from './file-lock.js';
10
9
  import { loadFurnaceState, updateFurnaceState } from './furnace-config.js';
11
- import { restoreRollbackJournal } from './furnace-rollback.js';
10
+ import { restoreRollbackJournal, restoreRollbackJournalOrThrow, } from './furnace-rollback.js';
12
11
  /** Sidecar lock filename used to serialize concurrent furnace mutations. */
13
12
  const FURNACE_LOCK_FILENAME = 'furnace.lock';
14
13
  /**
@@ -232,6 +231,42 @@ async function persistPendingRepair(root, operation, reason) {
232
231
  export function getFurnaceLockPath(root) {
233
232
  return join(root, FIREFORGE_DIR, FURNACE_LOCK_FILENAME);
234
233
  }
234
+ /**
235
+ * Completes the rollback for a mutation body that owns its journal end to
236
+ * end, then rethrows. Never returns normally.
237
+ *
238
+ * Shaped as a catch-body handler rather than a `withJournalRollback(body)`
239
+ * wrapper on purpose: the eight calling bodies differ in early returns and
240
+ * in what they close over, and converting them to callbacks would
241
+ * restructure control flow through the engine's rollback path for a
242
+ * cosmetic gain.
243
+ *
244
+ * The ordering is the part worth centralising: `markRolledBack()` MUST run
245
+ * before the restore, so a restore that itself fails does not leave the
246
+ * lifecycle wrapper replaying the same journal on the way out. And the
247
+ * ORIGINAL error is rethrown unless the rollback is what failed — the
248
+ * operator needs to know what went wrong, and separately whether the engine
249
+ * could be put back.
250
+ *
251
+ * @param ctx - The furnace operation context from `runFurnaceMutation`
252
+ * @param journal - Rollback journal this body populated
253
+ * @param error - The error the body threw
254
+ * @param options - Project root, pending-repair tag, and message fragments
255
+ * @returns Never — always throws
256
+ */
257
+ export async function completeJournalRollback(ctx, journal, error, options) {
258
+ // This body owns its rollback end to end, so tell the lifecycle wrapper
259
+ // not to restore the same journal again on the way out.
260
+ ctx.markRolledBack();
261
+ try {
262
+ await restoreRollbackJournalOrThrow(journal, options.failureMessage);
263
+ }
264
+ catch (rollbackError) {
265
+ await recordFurnaceRollbackFailure(options.projectRoot, options.operation, `${options.subject}: ${toError(rollbackError).message}`);
266
+ throw rollbackError;
267
+ }
268
+ throw error;
269
+ }
235
270
  /**
236
271
  * Forcibly removes the furnace lock directory for every active operation.
237
272
  *
@@ -251,13 +286,15 @@ export function getFurnaceLockPath(root) {
251
286
  export async function forceReleaseFurnaceLocksForActiveOperations() {
252
287
  const paths = new Set([...activeOperations.values()].map((op) => getFurnaceLockPath(op.root)));
253
288
  for (const lockPath of paths) {
254
- try {
255
- await rm(lockPath, { recursive: true, force: true });
256
- verbose(`Removed furnace lock at ${lockPath} during signal teardown`);
257
- }
258
- catch (error) {
259
- verbose(`Could not remove furnace lock at ${lockPath} during signal teardown: ${toError(error).message}`);
260
- }
289
+ // Ownership-checked, like every other release path. The bare `rm` this
290
+ // replaced would delete a lock a DIFFERENT process had acquired in the
291
+ // window between our operation dying and this sweep running — the exact
292
+ // race `releaseLock`'s PID verification was added to close, reopened
293
+ // here because the sweeper has no acquisition token to check.
294
+ const removed = await releaseLockIfOwned(lockPath);
295
+ verbose(removed
296
+ ? `Removed furnace lock at ${lockPath} during signal teardown`
297
+ : `Left furnace lock at ${lockPath} in place during signal teardown: it is not owned by this process`);
261
298
  }
262
299
  }
263
300
  /**
@@ -336,15 +373,15 @@ export async function runFurnaceMutation(root, kind, body, options = {}) {
336
373
  }
337
374
  catch (error) {
338
375
  // A thrown error leaves the engine mutated exactly as a signal does,
339
- // so it gets the same treatment. Before 0.43.0 this was a bare
340
- // finally: the throw path deregistered the operation and marked it
341
- // completed, which removed it from the signal handler's view too, so
342
- // a body that threw outside its own catch (notably anywhere in
343
- // `applyAllComponents` outside its two per-component try blocks) left
344
- // the checkout torn with no marker.
376
+ // so it gets the same treatment. A bare finally here would
377
+ // deregister the operation and mark it completed, removing it from
378
+ // the signal handler's view too, so a body that threw outside its
379
+ // own catch — notably anywhere in `applyAllComponents` outside its
380
+ // two per-component try blocks — would leave the checkout torn with
381
+ // no marker.
345
382
  //
346
383
  // This runs inside the withFileLock callback, so the furnace lock is
347
- // still held for the duration of the restore — a competing process
384
+ // still held for the duration of the restore: a competing process
348
385
  // cannot start mutating half-way through it.
349
386
  await rollbackOperationForThrow(operation);
350
387
  throw error;
@@ -0,0 +1,61 @@
1
+ /**
2
+ * Shared precondition ladder for the Furnace command family: engine exists,
3
+ * `furnace.json` exists.
4
+ *
5
+ * Kept separate from the `GeneralError` ladder in `engine-precondition.ts`
6
+ * because the error CLASS is load-bearing here, not cosmetic: `FurnaceError`
7
+ * carries its own `userMessage` and exit code 9, so a helper raising
8
+ * `GeneralError` would silently change both.
9
+ *
10
+ * Deliberately NOT routed through this helper — each informs rather than
11
+ * refuses, and each says so at its own site: `furnace list`,
12
+ * `furnace status`, `furnace init`, and `verify`. `furnace validate`
13
+ * refusing is the intended line between inspecting and validating.
14
+ */
15
+ import type { FurnaceConfig } from '../types/furnace.js';
16
+ import type { ProjectPaths } from '../types/index.js';
17
+ /** Options shared by the Furnace precondition assertions. */
18
+ export interface FurnacePreconditionOptions {
19
+ /**
20
+ * Appended to the engine-missing refusal, e.g.
21
+ * `' to scaffold a chrome-doc.'`. The base message ends WITHOUT
22
+ * punctuation so the suffix reads as one sentence; callers passing nothing
23
+ * get a plain full stop.
24
+ */
25
+ engineMissingSuffix?: string;
26
+ }
27
+ /**
28
+ * Asserts that a specific engine directory exists, raising a `FurnaceError`.
29
+ *
30
+ * The path-taking form, for core helpers that already hold `engineDir` and
31
+ * have no project root to derive it from.
32
+ *
33
+ * @param engineDir - Absolute path to the engine checkout
34
+ * @param options - Optional message tailoring
35
+ */
36
+ export declare function assertFurnaceEngineDirReady(engineDir: string, options?: FurnacePreconditionOptions): Promise<void>;
37
+ /**
38
+ * Asserts that the engine checkout exists, raising a `FurnaceError`.
39
+ *
40
+ * The engine rung on its own, for the Furnace commands that scaffold or
41
+ * mutate component sources without needing `furnace.json` to exist yet.
42
+ *
43
+ * @param projectRoot - Project root directory
44
+ * @param options - Optional message tailoring
45
+ * @returns Resolved project paths, so callers do not re-derive them
46
+ */
47
+ export declare function assertFurnaceEngineReady(projectRoot: string, options?: FurnacePreconditionOptions): Promise<{
48
+ paths: ProjectPaths;
49
+ }>;
50
+ /**
51
+ * Asserts the full Furnace ladder — engine checkout, then `furnace.json` —
52
+ * and returns the loaded config so callers do not read it a second time.
53
+ *
54
+ * @param projectRoot - Project root directory
55
+ * @param options - Optional message tailoring
56
+ * @returns Resolved project paths and the loaded furnace config
57
+ */
58
+ export declare function assertFurnaceReady(projectRoot: string, options?: FurnacePreconditionOptions): Promise<{
59
+ paths: ProjectPaths;
60
+ config: FurnaceConfig;
61
+ }>;