@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
@@ -9,7 +9,7 @@ import { BuildError } from '../errors/build.js';
9
9
  import { pathExists, readText, writeText } from '../utils/fs.js';
10
10
  import { escapeRegex } from '../utils/regex.js';
11
11
  import { asEstree, detectIndent, getNodeSource, parseScript, } from './ast-utils.js';
12
- import { withParserFallback } from './parser-fallback.js';
12
+ import { isInternalInvariantFailure, withParserFallback } from './parser-fallback.js';
13
13
  import { assertBraceBalancePreserved, coerceToCall, extractNameFromExpression, findInsertionAfterFireforgeBlocks, findMethodBody, findMethodBraceIndex, validateWireName, walkToTryBlockEnd, } from './wire-utils.js';
14
14
  const BROWSER_INIT_JS = 'browser/base/content/browser-init.js';
15
15
  /**
@@ -23,10 +23,9 @@ const DEFAULT_MARKER = 'FIREFORGE:';
23
23
  * the top of the method body when there is none.
24
24
  *
25
25
  * Both callers below — the `--after`-target-not-found fallthrough and the
26
- * no-`--after` default — ran a character-for-character copy of this ladder,
27
- * including both throw guards. `browser-init.js` is written through those two
28
- * independent paths and they MUST emit identical blocks, so having one
29
- * implementation enforces the invariant rather than merely tidying.
26
+ * no-`--after` default — must emit identical blocks, since `browser-init.js`
27
+ * is written through both paths. One implementation enforces that invariant
28
+ * rather than merely tidying.
30
29
  */
31
30
  function resolveDefaultInsertion(content, body, fireforgeBlocks) {
32
31
  if (fireforgeBlocks.length > 0) {
@@ -49,9 +48,8 @@ function resolveDefaultInsertion(content, body, fireforgeBlocks) {
49
48
  *
50
49
  * `marker` is prepended (uppercased) to the generated comment line so the
51
50
  * emitted block carries the patch-lint `// <MARKER>:` signature that
52
- * `lintModificationComments` looks for. Otherwise the first export after
53
- * `wire` trips `missing-modification-comment` on wire-generated edits —
54
- * exactly the eval 1 Finding #9 regression.
51
+ * `lintModificationComments` looks for; otherwise the first export after
52
+ * `wire` trips `missing-modification-comment` on wire-generated edits.
55
53
  */
56
54
  export function addInitAST(content, expression, after, marker = DEFAULT_MARKER) {
57
55
  const name = extractNameFromExpression(expression);
@@ -206,22 +204,13 @@ export async function addInitToBrowserInit(engineDir, expression, after, marker
206
204
  const content = await readText(filePath);
207
205
  // Idempotency check — look for the coerced (call) form because that is
208
206
  // what the emitter writes. Matching against the raw input would miss a
209
- // previous `EvalStartup.init` invocation that the 0.16.0 coercion
210
- // already persisted as `EvalStartup.init()`.
207
+ // bare `X.init` invocation that coercion already persisted as `X.init()`.
211
208
  const callExpression = coerceToCall(expression);
212
209
  const initPattern = new RegExp(`(?:^|\\W)${escapeRegex(callExpression)}\\s*;?\\s*$`, 'm');
213
210
  if (initPattern.test(content)) {
214
211
  return false;
215
212
  }
216
- const { value, usedFallback } = withParserFallback(() => addInitAST(content, expression, after, marker), () => legacyAddInit(content, expression, after, marker), BROWSER_INIT_JS,
217
- // Rethrow only the internal-invariant GeneralErrors ("Unexpected empty
218
- // …array"): those are programming bugs, and retrying the legacy scanner
219
- // cannot fix a broken invariant — it just buries the stack. Everything
220
- // else still falls back, which is load-bearing: the AST path raises a raw
221
- // acorn SyntaxError on chrome sources acorn cannot parse (preprocessor
222
- // directives), and BuildError when the file's shape is unexpected. Both
223
- // are exactly what the legacy scanner is here to handle.
224
- (error) => error instanceof GeneralError);
213
+ const { value, usedFallback } = withParserFallback(() => addInitAST(content, expression, after, marker), () => legacyAddInit(content, expression, after, marker), BROWSER_INIT_JS, isInternalInvariantFailure);
225
214
  if (usedFallback) {
226
215
  assertBraceBalancePreserved(content, value, BROWSER_INIT_JS);
227
216
  }
@@ -5,9 +5,8 @@
5
5
  * AST-based implementation: finds the last try/catch containing
6
6
  * `loadSubScript` and inserts a new try/catch block after it.
7
7
  *
8
- * The inserted block carries a `// <MARKER>: wire-subscript ...` comment
9
- * so the emitted edit satisfies `lintModificationComments` (eval 1
10
- * Finding #9).
8
+ * The inserted block carries a `// <MARKER>: wire-subscript ...` comment so
9
+ * the emitted edit satisfies `lintModificationComments`.
11
10
  */
12
11
  export declare function addSubscriptAST(content: string, name: string, marker?: string): string;
13
12
  /**
@@ -8,7 +8,7 @@ import { GeneralError } from '../errors/base.js';
8
8
  import { BuildError } from '../errors/build.js';
9
9
  import { pathExists, readText, writeText } from '../utils/fs.js';
10
10
  import { asEstree, detectIndent, getNodeSource, parseScript, walkAST, } from './ast-utils.js';
11
- import { withParserFallback } from './parser-fallback.js';
11
+ import { isInternalInvariantFailure, withParserFallback } from './parser-fallback.js';
12
12
  import { assertBraceBalancePreserved, findNearestTryLine, validateWireName, walkToTryBlockEnd, } from './wire-utils.js';
13
13
  const BROWSER_MAIN_JS = 'browser/base/content/browser-main.js';
14
14
  const DEFAULT_MARKER = 'FIREFORGE:';
@@ -16,9 +16,8 @@ const DEFAULT_MARKER = 'FIREFORGE:';
16
16
  * AST-based implementation: finds the last try/catch containing
17
17
  * `loadSubScript` and inserts a new try/catch block after it.
18
18
  *
19
- * The inserted block carries a `// <MARKER>: wire-subscript ...` comment
20
- * so the emitted edit satisfies `lintModificationComments` (eval 1
21
- * Finding #9).
19
+ * The inserted block carries a `// <MARKER>: wire-subscript ...` comment so
20
+ * the emitted edit satisfies `lintModificationComments`.
22
21
  */
23
22
  export function addSubscriptAST(content, name, marker = DEFAULT_MARKER) {
24
23
  const ast = parseScript(content);
@@ -137,15 +136,7 @@ export async function addSubscriptToBrowserMain(engineDir, name, marker = DEFAUL
137
136
  if (content.includes(`content/${name}.js"`)) {
138
137
  return false;
139
138
  }
140
- const { value, usedFallback } = withParserFallback(() => addSubscriptAST(content, name, marker), () => legacyAddSubscript(content, name, marker), BROWSER_MAIN_JS,
141
- // Rethrow only the internal-invariant GeneralErrors ("Unexpected empty
142
- // …array"): those are programming bugs, and retrying the legacy scanner
143
- // cannot fix a broken invariant — it just buries the stack. Everything
144
- // else still falls back, which is load-bearing: the AST path raises a raw
145
- // acorn SyntaxError on chrome sources acorn cannot parse (preprocessor
146
- // directives), and BuildError when the file's shape is unexpected. Both
147
- // are exactly what the legacy scanner is here to handle.
148
- (error) => error instanceof GeneralError);
139
+ const { value, usedFallback } = withParserFallback(() => addSubscriptAST(content, name, marker), () => legacyAddSubscript(content, name, marker), BROWSER_MAIN_JS, isInternalInvariantFailure);
149
140
  if (usedFallback) {
150
141
  assertBraceBalancePreserved(content, value, BROWSER_MAIN_JS);
151
142
  }
@@ -9,15 +9,14 @@ export declare function validateWireName(value: string, label: string): void;
9
9
  * Coerces an init/destroy expression into a function call by appending `()`
10
10
  * when the caller passed a bare property chain. Idempotent: an expression
11
11
  * already ending in `()` is returned unchanged, so operators can pass either
12
- * `EvalStartup.init` or `EvalStartup.init()` and get the same wired output.
12
+ * `Startup.init` or `Startup.init()` and get the same wired output.
13
13
  *
14
- * Motivation (eval finding 8): `validateWireName` accepts both shapes, but
15
- * the generated block interpolated the expression verbatim inside
16
- * `${expression};`. When a caller passed `EvalStartup.init`, the emitted
17
- * code was `EvalStartup.init;` — a plain property reference that never
18
- * invoked the lifecycle hook. The symptom was silent: `wire` reported
19
- * success and the browser-init block looked plausible, but the hook
20
- * never fired at runtime. Coercion at the template site closes that gap.
14
+ * `validateWireName` accepts both shapes, but the generated block
15
+ * interpolates the expression verbatim inside `${expression};` — so a bare
16
+ * `Startup.init` emits `Startup.init;`, a plain property reference that
17
+ * never invokes the lifecycle hook. The symptom is silent: `wire` reports
18
+ * success and the browser-init block looks plausible, but the hook never
19
+ * fires at runtime.
21
20
  */
22
21
  export declare function coerceToCall(expression: string): string;
23
22
  /**
@@ -21,15 +21,14 @@ export function validateWireName(value, label) {
21
21
  * Coerces an init/destroy expression into a function call by appending `()`
22
22
  * when the caller passed a bare property chain. Idempotent: an expression
23
23
  * already ending in `()` is returned unchanged, so operators can pass either
24
- * `EvalStartup.init` or `EvalStartup.init()` and get the same wired output.
24
+ * `Startup.init` or `Startup.init()` and get the same wired output.
25
25
  *
26
- * Motivation (eval finding 8): `validateWireName` accepts both shapes, but
27
- * the generated block interpolated the expression verbatim inside
28
- * `${expression};`. When a caller passed `EvalStartup.init`, the emitted
29
- * code was `EvalStartup.init;` — a plain property reference that never
30
- * invoked the lifecycle hook. The symptom was silent: `wire` reported
31
- * success and the browser-init block looked plausible, but the hook
32
- * never fired at runtime. Coercion at the template site closes that gap.
26
+ * `validateWireName` accepts both shapes, but the generated block
27
+ * interpolates the expression verbatim inside `${expression};` — so a bare
28
+ * `Startup.init` emits `Startup.init;`, a plain property reference that
29
+ * never invokes the lifecycle hook. The symptom is silent: `wire` reports
30
+ * success and the browser-init block looks plausible, but the hook never
31
+ * fires at runtime.
33
32
  */
34
33
  export function coerceToCall(expression) {
35
34
  return expression.endsWith('()') ? expression : `${expression}()`;
@@ -8,33 +8,32 @@
8
8
  * The upstream xpcshell harness computes the manifest key for the appdir
9
9
  * override as `mozInfo["appname"] + "-appdir"`. On a stock Firefox build the
10
10
  * key is `firefox-appdir`, so the very common `firefox-appdir = "browser"`
11
- * directive is honoured. On a rebranded fork (appname=`mybrowser`, …) the
12
- * harness looks for `mybrowser-appdir`
13
- * — the literal `firefox-appdir` line is silently ignored, `appPath` falls
14
- * back to `xrePath`, and every `resource:///modules/…` import throws
15
- * `Failed to load resource:///modules/<name>.sys.mjs` because xpcshell now
16
- * resolves the `resource:///` prefix one level above the real app root.
11
+ * directive is honoured. On a rebranded fork (appname=`mybrowser`) the
12
+ * harness looks for `mybrowser-appdir` — the literal `firefox-appdir` line
13
+ * is silently ignored, `appPath` falls back to `xrePath`, and every
14
+ * `resource:///modules/…` import throws `Failed to load
15
+ * resource:///modules/<name>.sys.mjs` because xpcshell resolves the
16
+ * `resource:///` prefix one level above the real app root.
17
17
  *
18
18
  * ## Strategy
19
19
  *
20
20
  * 1. For each test path the operator handed us, find the nearest
21
21
  * `xpcshell.toml`. If none exists, the test is not an xpcshell test and
22
- * nothing to inject.
22
+ * there is nothing to inject.
23
23
  * 2. Read the manifest's `[DEFAULT]` section. Look for `<appname>-appdir`
24
- * first — if present, the harness already finds it and there's nothing to
25
- * do. Fall back to `firefox-appdir`. This ordering matches upstream
26
- * precedence and avoids overriding an operator who already migrated.
24
+ * first — if present, the harness already finds it. Fall back to
25
+ * `firefox-appdir`. This ordering matches upstream precedence and avoids
26
+ * overriding an operator who already migrated.
27
27
  * 3. If only `firefox-appdir` is present and `appname != "firefox"`, compute
28
- * the absolute app dir path against the active `obj-X/dist` tree
29
- * (probing `dist/bin/<value>` first, then any `dist/<bundle>.app/Contents/
30
- * Resources/<value>` for the macOS packaged layout) and return it as
31
- * the value to pass to `--app-path`.
32
- * 4. If multiple test paths disagree on the resolved value (e.g. one
33
- * manifest sets `browser`, another sets `xulrunner`), refuse injection
28
+ * the absolute app dir path against the active `obj-X/dist` tree (probing
29
+ * `dist/bin/<value>` first, then any
30
+ * `dist/<bundle>.app/Contents/Resources/<value>` for the macOS packaged
31
+ * layout) and return it as the value to pass to `--app-path`.
32
+ * 4. If multiple test paths disagree on the resolved value, refuse injection
34
33
  * and return null — the operator can drop down to `--mach-arg`.
35
34
  *
36
- * Operator escape hatches: `--mach-arg=--app-path=…` always wins (handled in
37
- * test.ts; we skip injection when `--app-path=` already appears in the
35
+ * Operator escape hatch: `--mach-arg=--app-path=…` always wins (handled in
36
+ * test.ts, which skips injection when `--app-path=` already appears in the
38
37
  * forwarded args).
39
38
  */
40
39
  /**
@@ -75,15 +74,14 @@ export declare function parseAppdirFromToml(tomlText: string, key: string): {
75
74
  * returns the absolute path of the first sibling `xpcshell.toml` found.
76
75
  * Stops at `engineDir` (inclusive) and returns null on miss.
77
76
  *
78
- * Special-cases `startPath` itself when it already ends with
79
- * `xpcshell.toml` — operators sometimes pass a manifest path directly.
77
+ * Special-cases `startPath` itself when it already ends with `xpcshell.toml`
78
+ * — operators sometimes pass a manifest path directly.
80
79
  *
81
80
  * When `startPath` is a DIRECTORY, the walk starts at the directory itself
82
- * (checking `<dir>/xpcshell.toml` first) rather than at its parent. Field
83
- * report (0.34.0 cycle): a directory whose own manifest is an
84
- * `xpcshell.toml` was classified non-xpcshell — the walk began at the
85
- * parent, missed the manifest, and `fireforge test <dir>` dispatched to
86
- * the mochitest runner, which found no mochitests.
81
+ * (checking `<dir>/xpcshell.toml` first) rather than at its parent.
82
+ * Starting at the parent misses a directory's own manifest, so
83
+ * `fireforge test <dir>` classifies it non-xpcshell and dispatches to the
84
+ * mochitest runner, which finds no mochitests.
87
85
  */
88
86
  export declare function findNearestXpcshellManifest(engineDir: string, startPath: string): Promise<string | null>;
89
87
  /**
@@ -96,32 +94,27 @@ export declare function findNearestXpcshellManifest(engineDir: string, startPath
96
94
  */
97
95
  export declare function readMozinfoAppname(objDirPath: string): Promise<string>;
98
96
  /**
99
- * Probes the obj-dir's `dist/` subtree for the absolute path that the
100
- * harness would have computed if the manifest key had been honoured.
101
- * Returns null when no candidate exists — better to skip injection
102
- * silently than to point the harness at a path that doesn't exist
103
- * (which fails with a different error than the original `firefox-appdir`
104
- * symptom and confuses triage).
97
+ * Probes the obj-dir's `dist/` subtree for the absolute path the harness
98
+ * would have computed if the manifest key had been honoured. Returns null
99
+ * when no candidate exists — better to skip injection silently than to point
100
+ * the harness at a path that does not exist, which fails with a different
101
+ * error than the original symptom and confuses triage.
105
102
  *
106
103
  * Probe order differs by host platform:
107
104
  *
108
- * - **macOS (`darwin`)**: prefer `<objDir>/dist/<App>.app/Contents/Resources/
109
- * <value>` FIRST, then fall back to `<objDir>/dist/bin/<value>`.
110
- * 2026-04-24 eval Finding 8: on macOS `dist/bin` is symlinked to
105
+ * - **macOS (`darwin`)**: prefer
106
+ * `<objDir>/dist/<App>.app/Contents/Resources/<value>` FIRST, then fall
107
+ * back to `<objDir>/dist/bin/<value>`. On macOS `dist/bin` is symlinked to
111
108
  * `dist/<App>.app/Contents/MacOS/` (the *binaries* directory), so
112
- * `dist/bin/browser` actually resolves to `<App>.app/Contents/MacOS/
113
- * browser/`. That is NOT where `resource:///modules/` is rooted — on
114
- * macOS, `-a` for xpcshell must point at the `.app/Contents/Resources/
115
- * <value>` subtree where modules / chrome.manifest live. Returning
116
- * `dist/bin/browser` caused the injected `--app-path` to look
117
- * successful (the info log showed it) but pointed at a directory
118
- * without the modules tree, so every `resource:///modules/…` import
119
- * still threw.
120
- * - **non-macOS**: keep the historical order — `dist/bin/<value>` first,
109
+ * `dist/bin/browser` resolves to `<App>.app/Contents/MacOS/browser/` —
110
+ * NOT where `resource:///modules/` is rooted. Injecting that path looks
111
+ * successful in the log but points at a directory with no modules tree, so
112
+ * every `resource:///modules/…` import still throws.
113
+ * - **non-macOS**: `dist/bin/<value>` first,
121
114
  * `.app/Contents/Resources/<value>` as fallback.
122
115
  *
123
- * On both platforms the final `.app` fallback iterates every `*.app`
124
- * entry because a rebranded fork may pick an arbitrary app name.
116
+ * On both platforms the final `.app` fallback iterates every `*.app` entry
117
+ * because a rebranded fork may pick an arbitrary app name.
125
118
  */
126
119
  export declare function resolveAbsoluteAppPath(objDirAbs: string, relativeAppdir: string): Promise<string | null>;
127
120
  /**
@@ -9,33 +9,32 @@
9
9
  * The upstream xpcshell harness computes the manifest key for the appdir
10
10
  * override as `mozInfo["appname"] + "-appdir"`. On a stock Firefox build the
11
11
  * key is `firefox-appdir`, so the very common `firefox-appdir = "browser"`
12
- * directive is honoured. On a rebranded fork (appname=`mybrowser`, …) the
13
- * harness looks for `mybrowser-appdir`
14
- * — the literal `firefox-appdir` line is silently ignored, `appPath` falls
15
- * back to `xrePath`, and every `resource:///modules/…` import throws
16
- * `Failed to load resource:///modules/<name>.sys.mjs` because xpcshell now
17
- * resolves the `resource:///` prefix one level above the real app root.
12
+ * directive is honoured. On a rebranded fork (appname=`mybrowser`) the
13
+ * harness looks for `mybrowser-appdir` — the literal `firefox-appdir` line
14
+ * is silently ignored, `appPath` falls back to `xrePath`, and every
15
+ * `resource:///modules/…` import throws `Failed to load
16
+ * resource:///modules/<name>.sys.mjs` because xpcshell resolves the
17
+ * `resource:///` prefix one level above the real app root.
18
18
  *
19
19
  * ## Strategy
20
20
  *
21
21
  * 1. For each test path the operator handed us, find the nearest
22
22
  * `xpcshell.toml`. If none exists, the test is not an xpcshell test and
23
- * nothing to inject.
23
+ * there is nothing to inject.
24
24
  * 2. Read the manifest's `[DEFAULT]` section. Look for `<appname>-appdir`
25
- * first — if present, the harness already finds it and there's nothing to
26
- * do. Fall back to `firefox-appdir`. This ordering matches upstream
27
- * precedence and avoids overriding an operator who already migrated.
25
+ * first — if present, the harness already finds it. Fall back to
26
+ * `firefox-appdir`. This ordering matches upstream precedence and avoids
27
+ * overriding an operator who already migrated.
28
28
  * 3. If only `firefox-appdir` is present and `appname != "firefox"`, compute
29
- * the absolute app dir path against the active `obj-X/dist` tree
30
- * (probing `dist/bin/<value>` first, then any `dist/<bundle>.app/Contents/
31
- * Resources/<value>` for the macOS packaged layout) and return it as
32
- * the value to pass to `--app-path`.
33
- * 4. If multiple test paths disagree on the resolved value (e.g. one
34
- * manifest sets `browser`, another sets `xulrunner`), refuse injection
29
+ * the absolute app dir path against the active `obj-X/dist` tree (probing
30
+ * `dist/bin/<value>` first, then any
31
+ * `dist/<bundle>.app/Contents/Resources/<value>` for the macOS packaged
32
+ * layout) and return it as the value to pass to `--app-path`.
33
+ * 4. If multiple test paths disagree on the resolved value, refuse injection
35
34
  * and return null — the operator can drop down to `--mach-arg`.
36
35
  *
37
- * Operator escape hatches: `--mach-arg=--app-path=…` always wins (handled in
38
- * test.ts; we skip injection when `--app-path=` already appears in the
36
+ * Operator escape hatch: `--mach-arg=--app-path=…` always wins (handled in
37
+ * test.ts, which skips injection when `--app-path=` already appears in the
39
38
  * forwarded args).
40
39
  */
41
40
  import { readdir, stat } from 'node:fs/promises';
@@ -106,15 +105,14 @@ function stripQuotes(raw) {
106
105
  * returns the absolute path of the first sibling `xpcshell.toml` found.
107
106
  * Stops at `engineDir` (inclusive) and returns null on miss.
108
107
  *
109
- * Special-cases `startPath` itself when it already ends with
110
- * `xpcshell.toml` — operators sometimes pass a manifest path directly.
108
+ * Special-cases `startPath` itself when it already ends with `xpcshell.toml`
109
+ * — operators sometimes pass a manifest path directly.
111
110
  *
112
111
  * When `startPath` is a DIRECTORY, the walk starts at the directory itself
113
- * (checking `<dir>/xpcshell.toml` first) rather than at its parent. Field
114
- * report (0.34.0 cycle): a directory whose own manifest is an
115
- * `xpcshell.toml` was classified non-xpcshell — the walk began at the
116
- * parent, missed the manifest, and `fireforge test <dir>` dispatched to
117
- * the mochitest runner, which found no mochitests.
112
+ * (checking `<dir>/xpcshell.toml` first) rather than at its parent.
113
+ * Starting at the parent misses a directory's own manifest, so
114
+ * `fireforge test <dir>` classifies it non-xpcshell and dispatches to the
115
+ * mochitest runner, which finds no mochitests.
118
116
  */
119
117
  export async function findNearestXpcshellManifest(engineDir, startPath) {
120
118
  const absStart = resolve(engineDir, startPath);
@@ -164,32 +162,27 @@ export async function readMozinfoAppname(objDirPath) {
164
162
  return 'firefox';
165
163
  }
166
164
  /**
167
- * Probes the obj-dir's `dist/` subtree for the absolute path that the
168
- * harness would have computed if the manifest key had been honoured.
169
- * Returns null when no candidate exists — better to skip injection
170
- * silently than to point the harness at a path that doesn't exist
171
- * (which fails with a different error than the original `firefox-appdir`
172
- * symptom and confuses triage).
165
+ * Probes the obj-dir's `dist/` subtree for the absolute path the harness
166
+ * would have computed if the manifest key had been honoured. Returns null
167
+ * when no candidate exists — better to skip injection silently than to point
168
+ * the harness at a path that does not exist, which fails with a different
169
+ * error than the original symptom and confuses triage.
173
170
  *
174
171
  * Probe order differs by host platform:
175
172
  *
176
- * - **macOS (`darwin`)**: prefer `<objDir>/dist/<App>.app/Contents/Resources/
177
- * <value>` FIRST, then fall back to `<objDir>/dist/bin/<value>`.
178
- * 2026-04-24 eval Finding 8: on macOS `dist/bin` is symlinked to
173
+ * - **macOS (`darwin`)**: prefer
174
+ * `<objDir>/dist/<App>.app/Contents/Resources/<value>` FIRST, then fall
175
+ * back to `<objDir>/dist/bin/<value>`. On macOS `dist/bin` is symlinked to
179
176
  * `dist/<App>.app/Contents/MacOS/` (the *binaries* directory), so
180
- * `dist/bin/browser` actually resolves to `<App>.app/Contents/MacOS/
181
- * browser/`. That is NOT where `resource:///modules/` is rooted — on
182
- * macOS, `-a` for xpcshell must point at the `.app/Contents/Resources/
183
- * <value>` subtree where modules / chrome.manifest live. Returning
184
- * `dist/bin/browser` caused the injected `--app-path` to look
185
- * successful (the info log showed it) but pointed at a directory
186
- * without the modules tree, so every `resource:///modules/…` import
187
- * still threw.
188
- * - **non-macOS**: keep the historical order — `dist/bin/<value>` first,
177
+ * `dist/bin/browser` resolves to `<App>.app/Contents/MacOS/browser/` —
178
+ * NOT where `resource:///modules/` is rooted. Injecting that path looks
179
+ * successful in the log but points at a directory with no modules tree, so
180
+ * every `resource:///modules/…` import still throws.
181
+ * - **non-macOS**: `dist/bin/<value>` first,
189
182
  * `.app/Contents/Resources/<value>` as fallback.
190
183
  *
191
- * On both platforms the final `.app` fallback iterates every `*.app`
192
- * entry because a rebranded fork may pick an arbitrary app name.
184
+ * On both platforms the final `.app` fallback iterates every `*.app` entry
185
+ * because a rebranded fork may pick an arbitrary app name.
193
186
  */
194
187
  export async function resolveAbsoluteAppPath(objDirAbs, relativeAppdir) {
195
188
  const distBinCandidate = join(objDirAbs, 'dist', 'bin', relativeAppdir);
@@ -79,13 +79,10 @@ export declare class InvalidArgumentError extends FireForgeError {
79
79
  * Error thrown when a spawned command exceeds its `timeout` option.
80
80
  *
81
81
  * Every `exec*` helper in `src/utils/process.ts` rejects with this type
82
- * (instead of Node's bare `AbortError: The operation was aborted`) when the
83
- * caller-supplied timeout fires. The bare AbortError bit an operator during
84
- * the 2026-04-24 eval (see {@link GitIndexingTimeoutError} in errors/git.ts):
85
- * an 854 s git indexing pass died with no command name, no elapsed time, and
86
- * no hint that a timeout — not git — was responsible. The git path gained a
87
- * site-local typed error then; this class extends the same courtesy to every
88
- * other `timeout` caller.
82
+ * instead of Node's bare `AbortError: The operation was aborted`, which
83
+ * carries no command name, no elapsed time, and no hint that a timeout —
84
+ * not the command — was responsible. See {@link GitIndexingTimeoutError} in
85
+ * errors/git.ts for the git-specific variant.
89
86
  */
90
87
  export declare class ExecTimeoutError extends FireForgeError {
91
88
  /** Executable that was spawned (argv[0]). */
@@ -105,23 +102,47 @@ export declare class ExecTimeoutError extends FireForgeError {
105
102
  get userMessage(): string;
106
103
  }
107
104
  /**
108
- * Error thrown when a file-lock wait times out because another process
109
- * holds the lock.
105
+ * Error thrown when a file-lock wait times out because another process holds
106
+ * the lock.
110
107
  *
111
108
  * Dedicated subclass so the CLI boundary renders lock contention as the
112
- * one-line reason-first/remedy-second refusal it is — before this, the
113
- * timeout surfaced as a plain `Error`, which `withErrorHandling` treats
114
- * as an internal failure and prints with a five-frame stack. The refusal
115
- * was always correct; the presentation made it look like a crash.
109
+ * one-line reason-first/remedy-second refusal it is. As a plain `Error` it
110
+ * is treated by `withErrorHandling` as an internal failure and printed with
111
+ * a five-frame stack — a correct refusal that looks like a crash.
112
+ *
113
+ * Exit code 15, not 1: the run never started. A script that retries on
114
+ * failure wants to re-queue this one, not treat it as a failure of the work
115
+ * it asked for. Every lock in FireForge shares the class and therefore the
116
+ * code — the fact is the same whichever lock was contended.
116
117
  */
117
118
  export declare class LockContentionError extends FireForgeError {
118
- readonly code: 1;
119
+ readonly code: 15;
120
+ }
121
+ /**
122
+ * Error thrown when a test run completed but its verdict cannot be trusted,
123
+ * because `engine/` changed (or stopped being probeable) while the harness
124
+ * was running.
125
+ *
126
+ * Dedicated subclass for its exit code alone: as a `GeneralError` this
127
+ * refusal exited 1 beside real test failures' 5, and a summary line reading
128
+ * `FAIL — exit 1` next to `FAIL — exit 5` invites treating them as the same
129
+ * kind of fact. They are opposites — one suite failed, the other's result
130
+ * was discarded — and only a distinct code makes "unknown, re-run"
131
+ * mechanically separable from "red".
132
+ */
133
+ export declare class InconclusiveVerdictError extends FireForgeError {
134
+ readonly code: 14;
119
135
  }
120
136
  /**
121
- * Error thrown when the user cancels an interactive prompt.
137
+ * Error thrown when the user INTERRUPTS an interactive prompt — Esc or
138
+ * Ctrl+C, i.e. `isCancel(...)`.
139
+ *
140
+ * Not for a prompt the operator deliberately answered "no" to: 130 is
141
+ * 128+SIGINT, which claims an interrupt. A declined confirmation is a
142
+ * successful run that chose not to proceed, and exits 0.
122
143
  */
123
144
  export declare class CancellationError extends FireForgeError {
124
- readonly code: 1;
145
+ readonly code: 130;
125
146
  constructor();
126
147
  }
127
148
  /**
@@ -113,13 +113,10 @@ export class InvalidArgumentError extends FireForgeError {
113
113
  * Error thrown when a spawned command exceeds its `timeout` option.
114
114
  *
115
115
  * Every `exec*` helper in `src/utils/process.ts` rejects with this type
116
- * (instead of Node's bare `AbortError: The operation was aborted`) when the
117
- * caller-supplied timeout fires. The bare AbortError bit an operator during
118
- * the 2026-04-24 eval (see {@link GitIndexingTimeoutError} in errors/git.ts):
119
- * an 854 s git indexing pass died with no command name, no elapsed time, and
120
- * no hint that a timeout — not git — was responsible. The git path gained a
121
- * site-local typed error then; this class extends the same courtesy to every
122
- * other `timeout` caller.
116
+ * instead of Node's bare `AbortError: The operation was aborted`, which
117
+ * carries no command name, no elapsed time, and no hint that a timeout —
118
+ * not the command — was responsible. See {@link GitIndexingTimeoutError} in
119
+ * errors/git.ts for the git-specific variant.
123
120
  */
124
121
  export class ExecTimeoutError extends FireForgeError {
125
122
  command;
@@ -145,23 +142,47 @@ export class ExecTimeoutError extends FireForgeError {
145
142
  }
146
143
  }
147
144
  /**
148
- * Error thrown when a file-lock wait times out because another process
149
- * holds the lock.
145
+ * Error thrown when a file-lock wait times out because another process holds
146
+ * the lock.
150
147
  *
151
148
  * Dedicated subclass so the CLI boundary renders lock contention as the
152
- * one-line reason-first/remedy-second refusal it is — before this, the
153
- * timeout surfaced as a plain `Error`, which `withErrorHandling` treats
154
- * as an internal failure and prints with a five-frame stack. The refusal
155
- * was always correct; the presentation made it look like a crash.
149
+ * one-line reason-first/remedy-second refusal it is. As a plain `Error` it
150
+ * is treated by `withErrorHandling` as an internal failure and printed with
151
+ * a five-frame stack — a correct refusal that looks like a crash.
152
+ *
153
+ * Exit code 15, not 1: the run never started. A script that retries on
154
+ * failure wants to re-queue this one, not treat it as a failure of the work
155
+ * it asked for. Every lock in FireForge shares the class and therefore the
156
+ * code — the fact is the same whichever lock was contended.
156
157
  */
157
158
  export class LockContentionError extends FireForgeError {
158
- code = ExitCode.GENERAL_ERROR;
159
+ code = ExitCode.LOCK_TIMEOUT;
160
+ }
161
+ /**
162
+ * Error thrown when a test run completed but its verdict cannot be trusted,
163
+ * because `engine/` changed (or stopped being probeable) while the harness
164
+ * was running.
165
+ *
166
+ * Dedicated subclass for its exit code alone: as a `GeneralError` this
167
+ * refusal exited 1 beside real test failures' 5, and a summary line reading
168
+ * `FAIL — exit 1` next to `FAIL — exit 5` invites treating them as the same
169
+ * kind of fact. They are opposites — one suite failed, the other's result
170
+ * was discarded — and only a distinct code makes "unknown, re-run"
171
+ * mechanically separable from "red".
172
+ */
173
+ export class InconclusiveVerdictError extends FireForgeError {
174
+ code = ExitCode.INCONCLUSIVE;
159
175
  }
160
176
  /**
161
- * Error thrown when the user cancels an interactive prompt.
177
+ * Error thrown when the user INTERRUPTS an interactive prompt — Esc or
178
+ * Ctrl+C, i.e. `isCancel(...)`.
179
+ *
180
+ * Not for a prompt the operator deliberately answered "no" to: 130 is
181
+ * 128+SIGINT, which claims an interrupt. A declined confirmation is a
182
+ * successful run that chose not to proceed, and exits 0.
162
183
  */
163
184
  export class CancellationError extends FireForgeError {
164
- code = ExitCode.GENERAL_ERROR;
185
+ code = ExitCode.USER_CANCELLED;
165
186
  constructor() {
166
187
  super('cancelled');
167
188
  }
@@ -47,6 +47,18 @@ export declare class MozconfigError extends BuildError {
47
47
  */
48
48
  export declare class AmbiguousBuildArtifactsError extends BuildError {
49
49
  readonly objDirs: string[];
50
- constructor(objDirs: string[]);
50
+ /**
51
+ * Objdir the active mozconfig declared, when one was declared and did
52
+ * not resolve to exactly one candidate. Reported because a declaration
53
+ * that names something the scan cannot see is the diagnosis, not noise.
54
+ */
55
+ readonly declaredObjDir?: string | undefined;
56
+ constructor(objDirs: string[],
57
+ /**
58
+ * Objdir the active mozconfig declared, when one was declared and did
59
+ * not resolve to exactly one candidate. Reported because a declaration
60
+ * that names something the scan cannot see is the diagnosis, not noise.
61
+ */
62
+ declaredObjDir?: string | undefined);
51
63
  get userMessage(): string;
52
64
  }
@@ -97,17 +97,29 @@ export class MozconfigError extends BuildError {
97
97
  */
98
98
  export class AmbiguousBuildArtifactsError extends BuildError {
99
99
  objDirs;
100
- constructor(objDirs) {
100
+ declaredObjDir;
101
+ constructor(objDirs,
102
+ /**
103
+ * Objdir the active mozconfig declared, when one was declared and did
104
+ * not resolve to exactly one candidate. Reported because a declaration
105
+ * that names something the scan cannot see is the diagnosis, not noise.
106
+ */
107
+ declaredObjDir) {
101
108
  super(`Multiple build artifact directories found: ${objDirs.join(', ')}`);
102
109
  this.objDirs = objDirs;
110
+ this.declaredObjDir = declaredObjDir;
103
111
  }
104
112
  get userMessage() {
113
+ const declared = this.declaredObjDir !== undefined
114
+ ? `The mozconfig declares MOZ_OBJDIR=${this.declaredObjDir}, which does not match exactly one of these candidates — so it could not settle the choice.\n\n`
115
+ : '';
105
116
  return ('Build Error: Multiple build artifact directories were found.\n\n' +
106
117
  `Candidates: ${this.objDirs.join(', ')}\n\n` +
118
+ declared +
107
119
  'FireForge will not guess which build output to use.\n\n' +
108
120
  'To fix this:\n' +
109
121
  ' 1. Remove stale obj-* directories you no longer need\n' +
110
- ' 2. Keep only the active build output directory\n' +
122
+ ' 2. Keep only the active build output directory, or name it with MOZ_OBJDIR in the mozconfig\n' +
111
123
  ' 3. Run the command again');
112
124
  }
113
125
  }