@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
@@ -5,51 +5,16 @@
5
5
  import { join } from 'node:path';
6
6
  import { GeneralError } from '../errors/base.js';
7
7
  import { pathExists, readText, writeText } from '../utils/fs.js';
8
- import { findAlphabeticalMozBuildPosition, findAlphabeticalPosition } from './manifest-helpers.js';
9
- import { tokenizeMozBuildList } from './manifest-tokenizers.js';
10
- import { withParserFallback } from './parser-fallback.js';
8
+ import { insertMozBuildListEntry } from './moz-manifest-helpers.js';
11
9
  /**
12
10
  * Tokenizer-based implementation for test manifest registration.
13
11
  */
14
12
  function registerTestManifestTokenized(content, testDir, entry) {
15
- const lines = content.split('\n');
16
- const listResult = tokenizeMozBuildList(lines, /BROWSER_CHROME_MANIFESTS/);
17
- if (!listResult) {
18
- throw new GeneralError('Could not find BROWSER_CHROME_MANIFESTS in browser/base/moz.build');
19
- }
20
- const { insertIndex, previousEntry } = findAlphabeticalMozBuildPosition(listResult.tokens, `content/test/${testDir}/browser.toml`);
21
- lines.splice(insertIndex, 0, entry);
22
- return { result: lines.join('\n'), previousEntry };
23
- }
24
- /**
25
- * Legacy line-based implementation preserved as fallback.
26
- */
27
- function legacyRegisterTestManifest(content, testDir, entry) {
28
- const lines = content.split('\n');
29
- const extractKey = (line) => {
30
- // Nested manifests (`content/test/a/b/browser.toml`) are supported —
31
- // capture the whole directory chain, not just one segment.
32
- const match = /"content\/test\/(.+)\/browser\.toml"/.exec(line);
33
- return match?.[1];
34
- };
35
- let sectionStart = -1;
36
- let sectionEnd = lines.length;
37
- for (let i = 0; i < lines.length; i++) {
38
- const line = lines[i];
39
- if (line === undefined)
40
- continue;
41
- if (/^\s+"content\/test\/.*browser\.toml"/.test(line)) {
42
- if (sectionStart === -1)
43
- sectionStart = i;
44
- sectionEnd = i + 1;
45
- }
46
- }
47
- if (sectionStart === -1) {
48
- throw new GeneralError('Could not find test manifest section in browser/base/moz.build');
49
- }
50
- const { insertIndex, previousEntry } = findAlphabeticalPosition(lines, sectionStart, sectionEnd, testDir, extractKey);
51
- lines.splice(insertIndex, 0, entry);
52
- return { result: lines.join('\n'), previousEntry };
13
+ return insertMozBuildListEntry(content, entry, {
14
+ listPattern: /BROWSER_CHROME_MANIFESTS/,
15
+ sortKey: `content/test/${testDir}/browser.toml`,
16
+ missingListMessage: 'Could not find BROWSER_CHROME_MANIFESTS in browser/base/moz.build',
17
+ });
53
18
  }
54
19
  /**
55
20
  * Registers a test manifest (browser.toml) in browser/base/moz.build.
@@ -69,7 +34,7 @@ export async function registerTestManifest(engineDir, testDir, dryRun = false) {
69
34
  if (content.includes(`content/test/${testDir}/browser.toml`)) {
70
35
  return { manifest, entry, skipped: true };
71
36
  }
72
- const { value } = withParserFallback(() => registerTestManifestTokenized(content, testDir, entry), () => legacyRegisterTestManifest(content, testDir, entry), manifest);
37
+ const value = registerTestManifestTokenized(content, testDir, entry);
73
38
  if (!dryRun) {
74
39
  await writeText(manifestPath, value.result);
75
40
  }
@@ -5,50 +5,17 @@
5
5
  import { join } from 'node:path';
6
6
  import { GeneralError } from '../errors/base.js';
7
7
  import { pathExists, readText, writeText } from '../utils/fs.js';
8
- import { findAlphabeticalMozBuildPosition, findAlphabeticalPosition } from './manifest-helpers.js';
9
- import { tokenizeMozBuildList } from './manifest-tokenizers.js';
10
- import { withParserFallback } from './parser-fallback.js';
8
+ import { insertMozBuildListEntry } from './moz-manifest-helpers.js';
11
9
  import { scaffoldModuleMozBuild } from './register-scaffold.js';
12
10
  /**
13
11
  * Tokenizer-based implementation for module registration.
14
12
  */
15
13
  function registerFireForgeModuleTokenized(content, fileName, entry) {
16
- const lines = content.split('\n');
17
- const listResult = tokenizeMozBuildList(lines, /EXTRA_JS_MODULES/);
18
- if (!listResult) {
19
- throw new GeneralError('Could not find EXTRA_JS_MODULES in moz.build');
20
- }
21
- const { insertIndex, previousEntry } = findAlphabeticalMozBuildPosition(listResult.tokens, fileName);
22
- lines.splice(insertIndex, 0, entry);
23
- return { result: lines.join('\n'), previousEntry };
24
- }
25
- /**
26
- * Legacy line-based implementation preserved as fallback.
27
- */
28
- function legacyRegisterFireForgeModule(content, fileName, entry, moduleDir) {
29
- const lines = content.split('\n');
30
- const extractKey = (line) => {
31
- const match = /^\s+"([^"]+\.sys\.mjs)"/.exec(line);
32
- return match?.[1];
33
- };
34
- let sectionStart = -1;
35
- let sectionEnd = lines.length;
36
- for (let i = 0; i < lines.length; i++) {
37
- const line = lines[i];
38
- if (line === undefined)
39
- continue;
40
- if (/^\s+"[^"]+\.sys\.mjs"/.test(line)) {
41
- if (sectionStart === -1)
42
- sectionStart = i;
43
- sectionEnd = i + 1;
44
- }
45
- }
46
- if (sectionStart === -1) {
47
- throw new GeneralError(`Could not find module list section in ${moduleDir}/moz.build`);
48
- }
49
- const { insertIndex, previousEntry } = findAlphabeticalPosition(lines, sectionStart, sectionEnd, fileName, extractKey);
50
- lines.splice(insertIndex, 0, entry);
51
- return { result: lines.join('\n'), previousEntry };
14
+ return insertMozBuildListEntry(content, entry, {
15
+ listPattern: /EXTRA_JS_MODULES/,
16
+ sortKey: fileName,
17
+ missingListMessage: 'Could not find EXTRA_JS_MODULES in moz.build',
18
+ });
52
19
  }
53
20
  /**
54
21
  * Registers a module in browser/modules/{binaryName}/moz.build.
@@ -61,9 +28,9 @@ export async function registerFireForgeModule(engineDir, fileName, moduleDir, dr
61
28
  const manifestPath = join(engineDir, manifest);
62
29
  if (!(await pathExists(manifestPath))) {
63
30
  if (createManifest) {
64
- // 0.34.0 field report: registering a module under a directory with
65
- // no moz.build failed with "Manifest not found". Scaffold the
66
- // directory manifest and wire the parent DIRS chain.
31
+ // Registering a module under a directory with no moz.build otherwise
32
+ // fails with "Manifest not found". Scaffold the directory manifest and
33
+ // wire the parent DIRS chain.
67
34
  const scaffoldActions = await scaffoldModuleMozBuild(engineDir, moduleDir, fileName, dryRun);
68
35
  return {
69
36
  manifest,
@@ -80,7 +47,7 @@ export async function registerFireForgeModule(engineDir, fileName, moduleDir, dr
80
47
  if (content.includes(`"${fileName}"`)) {
81
48
  return { manifest, entry, skipped: true };
82
49
  }
83
- const { value } = withParserFallback(() => registerFireForgeModuleTokenized(content, fileName, entry), () => legacyRegisterFireForgeModule(content, fileName, entry, moduleDir), manifest);
50
+ const value = registerFireForgeModuleTokenized(content, fileName, entry);
84
51
  if (!dryRun) {
85
52
  await writeText(manifestPath, value.result);
86
53
  }
@@ -1,13 +1,13 @@
1
1
  /**
2
- * Manifest scaffolding for `fireforge register --create-manifest`
3
- * (0.34.0 field report): registering a module under a directory with no
4
- * moz.build used to fail with "Manifest not found" because `register`
5
- * only inserts into EXISTING manifests. This module owns the two
6
- * scaffolding primitives:
2
+ * Manifest scaffolding for `fireforge register --create-manifest`.
7
3
  *
8
- * - creating a directory `moz.build` (license header + the requested
9
- * list directive) and wiring the parent chain's `DIRS` entries up to
10
- * the nearest existing moz.build;
4
+ * `register` only inserts into EXISTING manifests, so registering a module
5
+ * under a directory with no moz.build fails with "Manifest not found". This
6
+ * module owns the two scaffolding primitives:
7
+ *
8
+ * - creating a directory `moz.build` (license header + the requested list
9
+ * directive) and wiring the parent chain's `DIRS` entries up to the
10
+ * nearest existing moz.build;
11
11
  * - wiring an `XPCSHELL_TESTS_MANIFESTS` entry for a (possibly freshly
12
12
  * created) `xpcshell.toml` into the nearest existing moz.build.
13
13
  *
@@ -1,14 +1,14 @@
1
1
  // SPDX-License-Identifier: EUPL-1.2
2
2
  /**
3
- * Manifest scaffolding for `fireforge register --create-manifest`
4
- * (0.34.0 field report): registering a module under a directory with no
5
- * moz.build used to fail with "Manifest not found" because `register`
6
- * only inserts into EXISTING manifests. This module owns the two
7
- * scaffolding primitives:
3
+ * Manifest scaffolding for `fireforge register --create-manifest`.
8
4
  *
9
- * - creating a directory `moz.build` (license header + the requested
10
- * list directive) and wiring the parent chain's `DIRS` entries up to
11
- * the nearest existing moz.build;
5
+ * `register` only inserts into EXISTING manifests, so registering a module
6
+ * under a directory with no moz.build fails with "Manifest not found". This
7
+ * module owns the two scaffolding primitives:
8
+ *
9
+ * - creating a directory `moz.build` (license header + the requested list
10
+ * directive) and wiring the parent chain's `DIRS` entries up to the
11
+ * nearest existing moz.build;
12
12
  * - wiring an `XPCSHELL_TESTS_MANIFESTS` entry for a (possibly freshly
13
13
  * created) `xpcshell.toml` into the nearest existing moz.build.
14
14
  *
@@ -20,8 +20,8 @@ import { dirname, join } from 'node:path';
20
20
  import { GeneralError } from '../errors/base.js';
21
21
  import { pathExists, readText, writeText } from '../utils/fs.js';
22
22
  import { getLicenseHeader } from './license-headers.js';
23
- import { findAlphabeticalMozBuildPosition } from './manifest-helpers.js';
24
- import { tokenizeMozBuildList } from './manifest-tokenizers.js';
23
+ import { findAlphabeticalMozBuildPosition } from './moz-manifest-helpers.js';
24
+ import { tokenizeMozBuildList } from './moz-manifest-tokenizers.js';
25
25
  /**
26
26
  * moz.build files use Firefox's canonical MPL-2.0 hash-comment header
27
27
  * regardless of the fork's own project license — they live in the engine
@@ -3,19 +3,16 @@
3
3
  */
4
4
  import type { RegisterResult } from './register-result.js';
5
5
  /**
6
- * Measures the column at which the `(source)` parenthesis opens in
7
- * adjacent `skin/classic/browser/<x>.css (...)` entries inside an
8
- * existing jar.inc.mn body, and returns the maximum so a newly inserted
9
- * entry can align its source column to match.
6
+ * Measures the column at which the `(source)` parenthesis opens in adjacent
7
+ * `skin/classic/browser/<x>.css (...)` entries inside an existing
8
+ * jar.inc.mn body, and returns the maximum so a newly inserted entry can
9
+ * align its source column to match.
10
10
  *
11
- * 2026-04-26 eval Finding 3: pre-fix `registerSharedCSS` always emitted
12
- * a four-space gap between the target path and the parenthesis,
13
- * regardless of how the rest of the file was aligned. Adjacent Firefox
14
- * entries are typically padded to a wider column, so a freshly
15
- * registered file landed at the wrong column and produced avoidable
16
- * formatting churn. Returns `undefined` when no existing entries
17
- * provide an alignment signal — callers fall back to the four-space
18
- * default in that case.
11
+ * A fixed four-space gap regardless of the surrounding alignment lands a
12
+ * freshly registered file at the wrong column and produces avoidable
13
+ * formatting churn, since adjacent Firefox entries are typically padded to a
14
+ * wider column. Returns `undefined` when no existing entries provide an
15
+ * alignment signal — callers fall back to the four-space default.
19
16
  */
20
17
  export declare function measureSourceColumn(content: string): number | undefined;
21
18
  /**
@@ -5,101 +5,31 @@
5
5
  import { basename, join } from 'node:path';
6
6
  import { GeneralError } from '../errors/base.js';
7
7
  import { pathExists, readText, writeText } from '../utils/fs.js';
8
- import { escapeRegex } from '../utils/regex.js';
9
- import { findAlphabeticalPosition, findAlphabeticalTokenPosition } from './manifest-helpers.js';
10
- import { tokenizeJarMn } from './manifest-tokenizers.js';
11
- import { withParserFallback } from './parser-fallback.js';
8
+ import { insertJarMnEntry } from './moz-manifest-helpers.js';
12
9
  /**
13
10
  * Tokenizer-based implementation for shared CSS registration.
14
11
  */
15
12
  function registerSharedCSSTokenized(content, name, entry, after) {
16
- const lines = content.split('\n');
17
- const tokens = tokenizeJarMn(lines);
18
- let afterFallback = false;
19
- let insertIndex;
20
- let previousEntry;
21
- if (after) {
22
- const afterPattern = new RegExp(`(?:^|/)${escapeRegex(after)}(?:\\s|\\)|$)`);
23
- const afterToken = tokens.find((t) => afterPattern.test(t.raw));
24
- if (afterToken) {
25
- insertIndex = afterToken.lineIndex + 1;
26
- previousEntry = afterToken.raw.trim();
27
- }
28
- else {
29
- afterFallback = true;
30
- ({ insertIndex, previousEntry } = findAlphabeticalTokenPosition(tokens, /skin\/classic\/browser\/([^.]+)\.css/, name));
31
- }
32
- }
33
- else {
34
- ({ insertIndex, previousEntry } = findAlphabeticalTokenPosition(tokens, /skin\/classic\/browser\/([^.]+)\.css/, name));
35
- }
36
- if (insertIndex === -1) {
37
- throw new GeneralError('Could not find skin/classic/browser/ section in jar.inc.mn');
38
- }
39
- lines.splice(insertIndex, 0, entry);
40
- return { result: lines.join('\n'), insertIndex, previousEntry, afterFallback };
41
- }
42
- /**
43
- * Legacy line-based implementation preserved as fallback.
44
- */
45
- function legacyRegisterSharedCSS(content, name, entry, after) {
46
- const lines = content.split('\n');
47
- let afterFallback = false;
48
- const extractKey = (line) => {
49
- const match = /skin\/classic\/browser\/([^.]+)\.css/.exec(line);
50
- return match?.[1];
51
- };
52
- let insertIndex;
53
- let previousEntry;
54
- // Find skin/classic/browser/ section boundaries
55
- let sectionStart = -1;
56
- let sectionEnd = lines.length;
57
- for (let i = 0; i < lines.length; i++) {
58
- const line = lines[i];
59
- if (line === undefined)
60
- continue;
61
- if (/skin\/classic\/browser\//.test(line)) {
62
- if (sectionStart === -1)
63
- sectionStart = i;
64
- sectionEnd = i + 1;
65
- }
66
- }
67
- if (sectionStart === -1) {
68
- throw new GeneralError('Could not find skin/classic/browser/ section in jar.inc.mn');
69
- }
70
- if (after) {
71
- const afterLineIdx = lines.findIndex((l) => l.includes(after));
72
- if (afterLineIdx !== -1) {
73
- insertIndex = afterLineIdx + 1;
74
- previousEntry = lines[afterLineIdx]?.trim();
75
- }
76
- else {
77
- afterFallback = true;
78
- ({ insertIndex, previousEntry } = findAlphabeticalPosition(lines, sectionStart, sectionEnd, name, extractKey));
79
- }
80
- }
81
- else {
82
- ({ insertIndex, previousEntry } = findAlphabeticalPosition(lines, sectionStart, sectionEnd, name, extractKey));
83
- }
84
- lines.splice(insertIndex, 0, entry);
85
- return { result: lines.join('\n'), previousEntry, afterFallback };
13
+ return insertJarMnEntry(content, entry, {
14
+ sortPattern: /skin\/classic\/browser\/([^.]+)\.css/,
15
+ sortKey: name,
16
+ missingSectionMessage: 'Could not find skin/classic/browser/ section in jar.inc.mn',
17
+ after,
18
+ });
86
19
  }
87
20
  /** Minimum gap between the target path and the source parenthesis. */
88
21
  const MIN_SOURCE_GAP = 4;
89
22
  /**
90
- * Measures the column at which the `(source)` parenthesis opens in
91
- * adjacent `skin/classic/browser/<x>.css (...)` entries inside an
92
- * existing jar.inc.mn body, and returns the maximum so a newly inserted
93
- * entry can align its source column to match.
23
+ * Measures the column at which the `(source)` parenthesis opens in adjacent
24
+ * `skin/classic/browser/<x>.css (...)` entries inside an existing
25
+ * jar.inc.mn body, and returns the maximum so a newly inserted entry can
26
+ * align its source column to match.
94
27
  *
95
- * 2026-04-26 eval Finding 3: pre-fix `registerSharedCSS` always emitted
96
- * a four-space gap between the target path and the parenthesis,
97
- * regardless of how the rest of the file was aligned. Adjacent Firefox
98
- * entries are typically padded to a wider column, so a freshly
99
- * registered file landed at the wrong column and produced avoidable
100
- * formatting churn. Returns `undefined` when no existing entries
101
- * provide an alignment signal — callers fall back to the four-space
102
- * default in that case.
28
+ * A fixed four-space gap regardless of the surrounding alignment lands a
29
+ * freshly registered file at the wrong column and produces avoidable
30
+ * formatting churn, since adjacent Firefox entries are typically padded to a
31
+ * wider column. Returns `undefined` when no existing entries provide an
32
+ * alignment signal — callers fall back to the four-space default.
103
33
  */
104
34
  export function measureSourceColumn(content) {
105
35
  const lines = content.split('\n');
@@ -167,7 +97,7 @@ export async function registerSharedCSS(engineDir, fileName, after, dryRun = fal
167
97
  content.includes(`content/browser/${name}.css`)) {
168
98
  return { manifest, entry, skipped: true };
169
99
  }
170
- const { value } = withParserFallback(() => registerSharedCSSTokenized(content, name, entry, after), () => legacyRegisterSharedCSS(content, name, entry, after), manifest);
100
+ const value = registerSharedCSSTokenized(content, name, entry, after);
171
101
  if (!dryRun) {
172
102
  await writeText(manifestPath, value.result);
173
103
  }
@@ -1,11 +1,10 @@
1
1
  /**
2
- * xpcshell test-file registration (0.34.0 field report): xpcshell test
3
- * files (e.g. `<module-dir>/test/unit/test_*.js`) were rejected by
4
- * `fireforge register` as "Unknown file pattern". This writer inserts the
5
- * `["test_*.js"]` section into the directory's `xpcshell.toml`
6
- * (alphabetically, idempotently) and — with `--create-manifest` — creates
7
- * the manifest and wires `XPCSHELL_TESTS_MANIFESTS` into the nearest
8
- * moz.build.
2
+ * xpcshell test-file registration. Without it, xpcshell test files (e.g.
3
+ * `<module-dir>/test/unit/test_*.js`) are rejected by `fireforge register`
4
+ * as "Unknown file pattern". This writer inserts the `["test_*.js"]` section
5
+ * into the directory's `xpcshell.toml` (alphabetically, idempotently) and —
6
+ * with `--create-manifest` — creates the manifest and wires
7
+ * `XPCSHELL_TESTS_MANIFESTS` into the nearest moz.build.
9
8
  */
10
9
  import type { RegisterResult } from './register-result.js';
11
10
  /**
@@ -1,17 +1,16 @@
1
1
  // SPDX-License-Identifier: EUPL-1.2
2
2
  /**
3
- * xpcshell test-file registration (0.34.0 field report): xpcshell test
4
- * files (e.g. `<module-dir>/test/unit/test_*.js`) were rejected by
5
- * `fireforge register` as "Unknown file pattern". This writer inserts the
6
- * `["test_*.js"]` section into the directory's `xpcshell.toml`
7
- * (alphabetically, idempotently) and — with `--create-manifest` — creates
8
- * the manifest and wires `XPCSHELL_TESTS_MANIFESTS` into the nearest
9
- * moz.build.
3
+ * xpcshell test-file registration. Without it, xpcshell test files (e.g.
4
+ * `<module-dir>/test/unit/test_*.js`) are rejected by `fireforge register`
5
+ * as "Unknown file pattern". This writer inserts the `["test_*.js"]` section
6
+ * into the directory's `xpcshell.toml` (alphabetically, idempotently) and —
7
+ * with `--create-manifest` — creates the manifest and wires
8
+ * `XPCSHELL_TESTS_MANIFESTS` into the nearest moz.build.
10
9
  */
11
10
  import { join } from 'node:path';
12
11
  import { GeneralError } from '../errors/base.js';
13
12
  import { pathExists, readText, writeText } from '../utils/fs.js';
14
- import { mozbuildSortCompare } from './manifest-helpers.js';
13
+ import { mozbuildSortCompare } from './moz-manifest-helpers.js';
15
14
  import { ensureXpcshellManifestWiring } from './register-scaffold.js';
16
15
  function manifestMissingError(manifestRel) {
17
16
  return new GeneralError(`Manifest not found: ${manifestRel}. ` +
@@ -8,11 +8,19 @@
8
8
  * template generator assume the value is safe to interpolate verbatim.
9
9
  */
10
10
  /**
11
- * Characters that must not appear in `sharedFtl`:
12
- * - Backticks close the MJS template literal the scaffold writes.
11
+ * Characters that must not appear in `sharedFtl`.
12
+ *
13
+ * A POLICY rule about what a sensible FTL path looks like, not the safety
14
+ * boundary for the generated `.mjs`: the scaffold escapes the value at its
15
+ * sink with `JSON.stringify` (`commands/furnace/create-templates.ts`), which
16
+ * is what actually makes interpolation safe and what covers the two inputs
17
+ * this rule never catches — a `"` and a raw newline.
18
+ *
19
+ * Kept because each remains a real sign of a malformed path:
13
20
  * - `\` is a path-escape we do not want to interpret.
14
- * - `${` opens a template expression and turns the FTL path into
15
- * executable code.
21
+ * - Backticks and `${` are inert in the current double-quoted sink, but a
22
+ * template-literal sink is one refactor away and they are not valid in a
23
+ * chrome:// FTL path regardless.
16
24
  */
17
25
  const UNSAFE_CHARS = /[`\\]|\$\{/;
18
26
  /**
@@ -2,3 +2,48 @@
2
2
  export declare function withStateFileLock<T>(statePath: string, operation: () => Promise<T>): Promise<T>;
3
3
  /** Renames a state file out of the way while preserving it for later inspection. */
4
4
  export declare function quarantineStateFile(statePath: string, reason?: string): Promise<string | undefined>;
5
+ /**
6
+ * Outcome of a version check on a persisted FireForge document.
7
+ *
8
+ * The distinction that matters is `newer` vs `corrupt`. A document written
9
+ * by a NEWER FireForge is not damaged — the operator simply needs to upgrade
10
+ * — but a check that collapses the two offers destructive remedies. The
11
+ * sharpest case is the tree marker, whose `schemaVersion` check inside a
12
+ * boolean type guard makes a `schemaVersion: 2` marker read as "missing or
13
+ * mistypes a required field"; `tree-guard.ts` is default-deny on corrupt, so
14
+ * a newer FireForge would lock the operator out of every mutating command
15
+ * inside that tree.
16
+ *
17
+ * `furnace.json` is the pattern the rest should follow: it refuses a newer
18
+ * version by name and tells the operator to upgrade (`migrateFurnaceConfig`
19
+ * in `furnace-config.ts`).
20
+ */
21
+ export type DocumentVersionCheck = {
22
+ kind: 'current';
23
+ } | {
24
+ kind: 'older';
25
+ found: number;
26
+ } | {
27
+ kind: 'newer';
28
+ found: number;
29
+ } | {
30
+ kind: 'malformed';
31
+ };
32
+ /**
33
+ * Classifies a persisted document's `version`/`schemaVersion` field.
34
+ *
35
+ * @param raw - The parsed document
36
+ * @param field - Version field name, e.g. `schemaVersion`
37
+ * @param supported - Version this build writes and understands
38
+ * @returns Whether the document is current, older, newer, or malformed
39
+ */
40
+ export declare function checkDocumentVersion(raw: unknown, field: string, supported: number): DocumentVersionCheck;
41
+ /**
42
+ * The refusal shown for a document this build is too old to read.
43
+ *
44
+ * @param label - Operator-facing document name, e.g. `tree marker`
45
+ * @param found - Version found on disk
46
+ * @param supported - Version this build understands
47
+ * @returns A message naming both versions and the remedy
48
+ */
49
+ export declare function describeNewerDocument(label: string, found: number, supported: number): string;
@@ -22,3 +22,37 @@ export async function quarantineStateFile(statePath, reason = 'corrupt') {
22
22
  await rename(statePath, quarantinedPath);
23
23
  return basename(quarantinedPath);
24
24
  }
25
+ /**
26
+ * Classifies a persisted document's `version`/`schemaVersion` field.
27
+ *
28
+ * @param raw - The parsed document
29
+ * @param field - Version field name, e.g. `schemaVersion`
30
+ * @param supported - Version this build writes and understands
31
+ * @returns Whether the document is current, older, newer, or malformed
32
+ */
33
+ export function checkDocumentVersion(raw, field, supported) {
34
+ if (typeof raw !== 'object' || raw === null)
35
+ return { kind: 'malformed' };
36
+ const found = raw[field];
37
+ if (typeof found !== 'number' || !Number.isInteger(found) || found < 1) {
38
+ return { kind: 'malformed' };
39
+ }
40
+ if (found > supported)
41
+ return { kind: 'newer', found };
42
+ if (found < supported)
43
+ return { kind: 'older', found };
44
+ return { kind: 'current' };
45
+ }
46
+ /**
47
+ * The refusal shown for a document this build is too old to read.
48
+ *
49
+ * @param label - Operator-facing document name, e.g. `tree marker`
50
+ * @param found - Version found on disk
51
+ * @param supported - Version this build understands
52
+ * @returns A message naming both versions and the remedy
53
+ */
54
+ export function describeNewerDocument(label, found, supported) {
55
+ return (`the ${label} was written by a newer FireForge (schema version ${found}; ` +
56
+ `this build understands ${supported}). Upgrade FireForge to read it — the file is ` +
57
+ 'not damaged, so do not delete it.');
58
+ }
@@ -2,20 +2,27 @@
2
2
  * Binary-aware drift classification for patch-owned files.
3
3
  *
4
4
  * The text classifier compares utf-8 decoded content against
5
- * `computePatchedContent`, which cannot apply `GIT binary patch` bodies —
6
- * so a binary file exported into a patch classified as `patch-owned-drift`
5
+ * `computePatchedContent`, which cannot apply `GIT binary patch` bodies — so
6
+ * a binary file exported into a patch classifies as `patch-owned-drift`
7
7
  * forever, keeping the engine-clean gate permanently red with nothing
8
- * actually un-durable. Binary sections DO carry the ground truth, though:
9
- * `git diff --binary` always records full blob hashes on the section's
8
+ * actually un-durable. A `GIT binary patch` section DOES carry the ground
9
+ * truth: `git diff --binary` always records full blob hashes on the section's
10
10
  * `index <old>..<new>` line. Comparing the live file's `git hash-object`
11
- * against the last owning section's new-side hash settles the
12
- * classification exactly. Bodies without a usable hash (hand-written
13
- * diffs, `Binary files … differ`) classify as `binary-unsupported` —
14
- * an honest "cannot compare" instead of a false "not durable".
11
+ * against the last owning section's new-side hash settles the classification
12
+ * exactly. Bodies without a usable hash (hand-written diffs) classify as
13
+ * `binary-unsupported` — an honest "cannot compare" instead of a false "not
14
+ * durable".
15
15
  *
16
- * Lives in its own module (not `status-classify.ts`) so the classifier
17
- * stays within the per-file line budget and this module never has to
18
- * import it back (dpdm-clean: the dependency edge points one way).
16
+ * That hash is trusted ONLY when the section carries a replayable payload
17
+ * (`hasBinaryDelta`). A `Binary files … differ` stub carries a correct index
18
+ * line too, so hashing against it reports `patch-backed` for a body that
19
+ * cannot rebuild the file at all — precisely the dishonesty this module
20
+ * exists to avoid. Such a body is `binary-unsupported` here, and an error
21
+ * from the `binary-body-not-reconstructable` queue lint.
22
+ *
23
+ * Lives in its own module (not `status-classify.ts`) so the classifier stays
24
+ * within the per-file line budget and this module never has to import it
25
+ * back: the dependency edge points one way, which keeps dpdm clean.
19
26
  */
20
27
  import type { PatchedContentContext } from './patch-apply.js';
21
28
  /** Batched patch lookup, injected by callers that classify many files. */
@@ -3,20 +3,27 @@
3
3
  * Binary-aware drift classification for patch-owned files.
4
4
  *
5
5
  * The text classifier compares utf-8 decoded content against
6
- * `computePatchedContent`, which cannot apply `GIT binary patch` bodies —
7
- * so a binary file exported into a patch classified as `patch-owned-drift`
6
+ * `computePatchedContent`, which cannot apply `GIT binary patch` bodies — so
7
+ * a binary file exported into a patch classifies as `patch-owned-drift`
8
8
  * forever, keeping the engine-clean gate permanently red with nothing
9
- * actually un-durable. Binary sections DO carry the ground truth, though:
10
- * `git diff --binary` always records full blob hashes on the section's
9
+ * actually un-durable. A `GIT binary patch` section DOES carry the ground
10
+ * truth: `git diff --binary` always records full blob hashes on the section's
11
11
  * `index <old>..<new>` line. Comparing the live file's `git hash-object`
12
- * against the last owning section's new-side hash settles the
13
- * classification exactly. Bodies without a usable hash (hand-written
14
- * diffs, `Binary files … differ`) classify as `binary-unsupported` —
15
- * an honest "cannot compare" instead of a false "not durable".
12
+ * against the last owning section's new-side hash settles the classification
13
+ * exactly. Bodies without a usable hash (hand-written diffs) classify as
14
+ * `binary-unsupported` — an honest "cannot compare" instead of a false "not
15
+ * durable".
16
16
  *
17
- * Lives in its own module (not `status-classify.ts`) so the classifier
18
- * stays within the per-file line budget and this module never has to
19
- * import it back (dpdm-clean: the dependency edge points one way).
17
+ * That hash is trusted ONLY when the section carries a replayable payload
18
+ * (`hasBinaryDelta`). A `Binary files … differ` stub carries a correct index
19
+ * line too, so hashing against it reports `patch-backed` for a body that
20
+ * cannot rebuild the file at all — precisely the dishonesty this module
21
+ * exists to avoid. Such a body is `binary-unsupported` here, and an error
22
+ * from the `binary-body-not-reconstructable` queue lint.
23
+ *
24
+ * Lives in its own module (not `status-classify.ts`) so the classifier stays
25
+ * within the per-file line budget and this module never has to import it
26
+ * back: the dependency edge points one way, which keeps dpdm clean.
20
27
  */
21
28
  import { join } from 'node:path';
22
29
  import { toError } from '../utils/errors.js';
@@ -102,7 +109,7 @@ export async function classifyBinaryOwnedFile(args) {
102
109
  // The last binary section expects the file to exist.
103
110
  return { ...entry, classification: 'patch-owned-drift', owner };
104
111
  }
105
- if (section.indexNewHash !== undefined) {
112
+ if (section.hasBinaryDelta && section.indexNewHash !== undefined) {
106
113
  const fullPath = join(engineDir, entry.file);
107
114
  const live = (await hashObjectBatch(engineDir, [fullPath])).get(fullPath);
108
115
  if (live !== undefined) {