@hominis/fireforge 0.45.0 → 0.46.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (662) hide show
  1. package/CHANGELOG.md +409 -446
  2. package/dist/bin/fireforge.d.ts +1 -1
  3. package/dist/bin/fireforge.js +21 -15
  4. package/dist/build-info.json +4 -4
  5. package/dist/src/cli-usage-error.d.ts +46 -0
  6. package/dist/src/cli-usage-error.js +81 -0
  7. package/dist/src/cli.d.ts +7 -2
  8. package/dist/src/cli.js +47 -47
  9. package/dist/src/commands/bootstrap-checks.js +2 -1
  10. package/dist/src/commands/bootstrap.js +3 -4
  11. package/dist/src/commands/build.js +27 -17
  12. package/dist/src/commands/config.js +9 -9
  13. package/dist/src/commands/destructive-decision.d.ts +19 -0
  14. package/dist/src/commands/destructive-decision.js +31 -0
  15. package/dist/src/commands/discard.js +5 -5
  16. package/dist/src/commands/doctor-check-core.d.ts +4 -10
  17. package/dist/src/commands/doctor-check-core.js +0 -8
  18. package/dist/src/commands/doctor-external-toolchains.js +2 -2
  19. package/dist/src/commands/doctor-furnace-config-sync.d.ts +2 -2
  20. package/dist/src/commands/doctor-furnace-config-sync.js +20 -20
  21. package/dist/src/commands/doctor-furnace-jar.d.ts +1 -1
  22. package/dist/src/commands/doctor-furnace-jar.js +1 -1
  23. package/dist/src/commands/doctor-furnace.js +22 -22
  24. package/dist/src/commands/doctor-orphaned-harness.d.ts +10 -17
  25. package/dist/src/commands/doctor-orphaned-harness.js +14 -23
  26. package/dist/src/commands/doctor-patch-manifest.d.ts +2 -1
  27. package/dist/src/commands/doctor-patch-manifest.js +7 -6
  28. package/dist/src/commands/doctor-post-rebase-audit.js +3 -3
  29. package/dist/src/commands/doctor-source-pin.d.ts +12 -12
  30. package/dist/src/commands/doctor-source-pin.js +14 -14
  31. package/dist/src/commands/doctor-working-tree.d.ts +3 -3
  32. package/dist/src/commands/doctor-working-tree.js +3 -3
  33. package/dist/src/commands/doctor.d.ts +3 -1
  34. package/dist/src/commands/doctor.js +15 -16
  35. package/dist/src/commands/download.js +50 -37
  36. package/dist/src/commands/export-all.js +29 -12
  37. package/dist/src/commands/export-flow.d.ts +5 -5
  38. package/dist/src/commands/export-flow.js +29 -59
  39. package/dist/src/commands/export-placement-conflicts.d.ts +3 -3
  40. package/dist/src/commands/export-placement-conflicts.js +12 -12
  41. package/dist/src/commands/export-placement-gate.d.ts +2 -2
  42. package/dist/src/commands/export-placement-gate.js +7 -13
  43. package/dist/src/commands/export-placement-policy.d.ts +1 -1
  44. package/dist/src/commands/export-placement-policy.js +4 -6
  45. package/dist/src/commands/export-shared.d.ts +51 -32
  46. package/dist/src/commands/export-shared.js +17 -32
  47. package/dist/src/commands/export.js +14 -5
  48. package/dist/src/commands/furnace/apply.js +16 -16
  49. package/dist/src/commands/furnace/authoring-config.d.ts +13 -0
  50. package/dist/src/commands/furnace/authoring-config.js +19 -0
  51. package/dist/src/commands/furnace/chrome-doc-remove.d.ts +1 -1
  52. package/dist/src/commands/furnace/chrome-doc-remove.js +2 -2
  53. package/dist/src/commands/furnace/chrome-doc-templates.d.ts +14 -14
  54. package/dist/src/commands/furnace/chrome-doc-templates.js +17 -17
  55. package/dist/src/commands/furnace/chrome-doc-tests.d.ts +2 -2
  56. package/dist/src/commands/furnace/chrome-doc-tests.js +4 -4
  57. package/dist/src/commands/furnace/chrome-doc.d.ts +8 -8
  58. package/dist/src/commands/furnace/chrome-doc.js +18 -18
  59. package/dist/src/commands/furnace/create-browser-test.d.ts +1 -1
  60. package/dist/src/commands/furnace/create-browser-test.js +7 -12
  61. package/dist/src/commands/furnace/create-dry-run.d.ts +4 -4
  62. package/dist/src/commands/furnace/create-dry-run.js +6 -9
  63. package/dist/src/commands/furnace/create-features.d.ts +2 -2
  64. package/dist/src/commands/furnace/create-features.js +2 -2
  65. package/dist/src/commands/furnace/create-mochikit.d.ts +4 -4
  66. package/dist/src/commands/furnace/create-mochikit.js +7 -7
  67. package/dist/src/commands/furnace/create-templates.d.ts +31 -15
  68. package/dist/src/commands/furnace/create-templates.js +20 -19
  69. package/dist/src/commands/furnace/create-xpcshell.d.ts +5 -5
  70. package/dist/src/commands/furnace/create-xpcshell.js +8 -8
  71. package/dist/src/commands/furnace/create.d.ts +1 -1
  72. package/dist/src/commands/furnace/create.js +35 -29
  73. package/dist/src/commands/furnace/deploy.js +15 -6
  74. package/dist/src/commands/furnace/diff.js +7 -7
  75. package/dist/src/commands/furnace/index.js +1 -1
  76. package/dist/src/commands/furnace/init.js +17 -16
  77. package/dist/src/commands/furnace/list.js +2 -2
  78. package/dist/src/commands/furnace/override.d.ts +1 -1
  79. package/dist/src/commands/furnace/override.js +43 -34
  80. package/dist/src/commands/furnace/preview.js +17 -17
  81. package/dist/src/commands/furnace/refresh.js +15 -7
  82. package/dist/src/commands/furnace/remove-mutations.d.ts +9 -10
  83. package/dist/src/commands/furnace/remove-mutations.js +19 -19
  84. package/dist/src/commands/furnace/remove-state.d.ts +1 -1
  85. package/dist/src/commands/furnace/remove-state.js +1 -1
  86. package/dist/src/commands/furnace/remove.js +4 -8
  87. package/dist/src/commands/furnace/rename-browser-test.js +10 -15
  88. package/dist/src/commands/furnace/rename-xpcshell.d.ts +2 -2
  89. package/dist/src/commands/furnace/rename-xpcshell.js +3 -3
  90. package/dist/src/commands/furnace/rename.js +36 -36
  91. package/dist/src/commands/furnace/scan.js +3 -3
  92. package/dist/src/commands/furnace/status.js +19 -16
  93. package/dist/src/commands/furnace/sync.js +6 -6
  94. package/dist/src/commands/furnace/test-file-name.d.ts +28 -0
  95. package/dist/src/commands/furnace/test-file-name.js +39 -0
  96. package/dist/src/commands/furnace/validate.js +11 -12
  97. package/dist/src/commands/furnace/validation-output.d.ts +21 -9
  98. package/dist/src/commands/furnace/validation-output.js +3 -8
  99. package/dist/src/commands/import.js +22 -29
  100. package/dist/src/commands/lint-per-patch.d.ts +2 -2
  101. package/dist/src/commands/lint-per-patch.js +27 -12
  102. package/dist/src/commands/lint-per-run-checkjs.d.ts +14 -15
  103. package/dist/src/commands/lint-per-run-checkjs.js +14 -15
  104. package/dist/src/commands/lint-report.d.ts +3 -3
  105. package/dist/src/commands/lint-report.js +4 -4
  106. package/dist/src/commands/lint.d.ts +5 -4
  107. package/dist/src/commands/lint.js +36 -36
  108. package/dist/src/commands/manifest.d.ts +4 -4
  109. package/dist/src/commands/manifest.js +1 -1
  110. package/dist/src/commands/package.js +4 -6
  111. package/dist/src/commands/patch/compact.d.ts +2 -2
  112. package/dist/src/commands/patch/compact.js +19 -20
  113. package/dist/src/commands/patch/delete.d.ts +1 -1
  114. package/dist/src/commands/patch/delete.js +23 -33
  115. package/dist/src/commands/patch/entry-projection.d.ts +13 -0
  116. package/dist/src/commands/patch/entry-projection.js +24 -0
  117. package/dist/src/commands/patch/lint-ignore.d.ts +3 -12
  118. package/dist/src/commands/patch/lint-ignore.js +33 -44
  119. package/dist/src/commands/patch/move-files-create.d.ts +2 -2
  120. package/dist/src/commands/patch/move-files-create.js +29 -15
  121. package/dist/src/commands/patch/move-files-into.d.ts +2 -2
  122. package/dist/src/commands/patch/move-files-into.js +41 -37
  123. package/dist/src/commands/patch/move-files.js +5 -14
  124. package/dist/src/commands/patch/patch-context.d.ts +1 -1
  125. package/dist/src/commands/patch/rename.d.ts +4 -4
  126. package/dist/src/commands/patch/rename.js +35 -49
  127. package/dist/src/commands/patch/reorder.js +35 -48
  128. package/dist/src/commands/patch/split-plan.d.ts +7 -8
  129. package/dist/src/commands/patch/split-plan.js +10 -13
  130. package/dist/src/commands/patch/split.d.ts +2 -2
  131. package/dist/src/commands/patch/split.js +50 -48
  132. package/dist/src/commands/patch/staged-dependency-validate.d.ts +1 -1
  133. package/dist/src/commands/patch/staged-dependency-validate.js +3 -3
  134. package/dist/src/commands/patch/staged-dependency.d.ts +1 -1
  135. package/dist/src/commands/patch/staged-dependency.js +22 -28
  136. package/dist/src/commands/patch/tier.d.ts +2 -2
  137. package/dist/src/commands/patch/tier.js +20 -30
  138. package/dist/src/commands/patch-rename-map.d.ts +19 -0
  139. package/dist/src/commands/patch-rename-map.js +36 -0
  140. package/dist/src/commands/pending-resolution.d.ts +15 -0
  141. package/dist/src/commands/pending-resolution.js +25 -0
  142. package/dist/src/commands/re-export-adjacent.d.ts +25 -3
  143. package/dist/src/commands/re-export-adjacent.js +40 -24
  144. package/dist/src/commands/re-export-bulk-scan.d.ts +3 -3
  145. package/dist/src/commands/re-export-bulk-scan.js +23 -27
  146. package/dist/src/commands/re-export-drift.d.ts +10 -10
  147. package/dist/src/commands/re-export-drift.js +33 -33
  148. package/dist/src/commands/re-export-files.d.ts +2 -3
  149. package/dist/src/commands/re-export-files.js +52 -44
  150. package/dist/src/commands/re-export-lint.d.ts +29 -30
  151. package/dist/src/commands/re-export-lint.js +36 -29
  152. package/dist/src/commands/re-export-options.d.ts +1 -1
  153. package/dist/src/commands/re-export-options.js +1 -1
  154. package/dist/src/commands/re-export-register.d.ts +1 -1
  155. package/dist/src/commands/re-export-register.js +1 -1
  156. package/dist/src/commands/re-export-scan.d.ts +1 -1
  157. package/dist/src/commands/re-export-scan.js +12 -9
  158. package/dist/src/commands/re-export-single.d.ts +23 -4
  159. package/dist/src/commands/re-export-single.js +39 -31
  160. package/dist/src/commands/re-export.js +35 -17
  161. package/dist/src/commands/rebase/abort.js +9 -14
  162. package/dist/src/commands/rebase/continue.js +20 -19
  163. package/dist/src/commands/rebase/index.d.ts +1 -1
  164. package/dist/src/commands/rebase/index.js +5 -5
  165. package/dist/src/commands/rebase/patch-loop.d.ts +2 -2
  166. package/dist/src/commands/rebase/patch-loop.js +20 -24
  167. package/dist/src/commands/register.js +5 -5
  168. package/dist/src/commands/reset.js +1 -1
  169. package/dist/src/commands/resolve.d.ts +2 -2
  170. package/dist/src/commands/resolve.js +21 -13
  171. package/dist/src/commands/run.d.ts +0 -13
  172. package/dist/src/commands/run.js +38 -51
  173. package/dist/src/commands/setup-support.d.ts +16 -4
  174. package/dist/src/commands/setup-support.js +20 -20
  175. package/dist/src/commands/setup.js +4 -10
  176. package/dist/src/commands/source.js +9 -2
  177. package/dist/src/commands/status-check.d.ts +3 -3
  178. package/dist/src/commands/status-check.js +6 -6
  179. package/dist/src/commands/status-json.d.ts +14 -13
  180. package/dist/src/commands/status-json.js +9 -8
  181. package/dist/src/commands/status-output.d.ts +3 -3
  182. package/dist/src/commands/status-output.js +5 -5
  183. package/dist/src/commands/status-ownership.d.ts +3 -3
  184. package/dist/src/commands/status-ownership.js +3 -3
  185. package/dist/src/commands/status.js +25 -26
  186. package/dist/src/commands/test-build-phase.d.ts +3 -3
  187. package/dist/src/commands/test-build-phase.js +48 -24
  188. package/dist/src/commands/test-diagnose.d.ts +1 -1
  189. package/dist/src/commands/test-diagnose.js +20 -20
  190. package/dist/src/commands/test-modes.d.ts +4 -4
  191. package/dist/src/commands/test-modes.js +4 -5
  192. package/dist/src/commands/test-register.js +5 -3
  193. package/dist/src/commands/test-run.d.ts +11 -11
  194. package/dist/src/commands/test-run.js +40 -33
  195. package/dist/src/commands/test-stale-gate.d.ts +12 -12
  196. package/dist/src/commands/test-stale-gate.js +17 -17
  197. package/dist/src/commands/test-verdict.d.ts +19 -5
  198. package/dist/src/commands/test-verdict.js +26 -11
  199. package/dist/src/commands/test.d.ts +3 -3
  200. package/dist/src/commands/test.js +73 -36
  201. package/dist/src/commands/token-coverage.js +3 -3
  202. package/dist/src/commands/token-list.d.ts +26 -0
  203. package/dist/src/commands/token-list.js +153 -0
  204. package/dist/src/commands/token.js +26 -10
  205. package/dist/src/commands/tree.js +26 -21
  206. package/dist/src/commands/typecheck.d.ts +6 -6
  207. package/dist/src/commands/typecheck.js +16 -16
  208. package/dist/src/commands/verify.d.ts +3 -3
  209. package/dist/src/commands/verify.js +10 -10
  210. package/dist/src/commands/watch.js +11 -11
  211. package/dist/src/commands/wire.js +17 -16
  212. package/dist/src/core/ast-utils.d.ts +7 -7
  213. package/dist/src/core/ast-utils.js +8 -8
  214. package/dist/src/core/branding.d.ts +5 -12
  215. package/dist/src/core/branding.js +6 -5
  216. package/dist/src/core/browser-wire.d.ts +1 -1
  217. package/dist/src/core/browser-wire.js +10 -7
  218. package/dist/src/core/build-audit-platform.d.ts +32 -3
  219. package/dist/src/core/build-audit-platform.js +153 -13
  220. package/dist/src/core/build-audit-registration.d.ts +5 -5
  221. package/dist/src/core/build-audit-registration.js +10 -9
  222. package/dist/src/core/build-audit-resolve.d.ts +5 -5
  223. package/dist/src/core/build-audit-resolve.js +6 -6
  224. package/dist/src/core/build-audit-skip.d.ts +57 -0
  225. package/dist/src/core/build-audit-skip.js +112 -0
  226. package/dist/src/core/build-audit-transforms.d.ts +2 -2
  227. package/dist/src/core/build-audit-transforms.js +3 -3
  228. package/dist/src/core/build-audit.d.ts +21 -8
  229. package/dist/src/core/build-audit.js +142 -40
  230. package/dist/src/core/build-baseline-types.d.ts +19 -18
  231. package/dist/src/core/build-baseline-types.js +1 -1
  232. package/dist/src/core/build-baseline.d.ts +48 -31
  233. package/dist/src/core/build-baseline.js +20 -43
  234. package/dist/src/core/build-jar-escalation.d.ts +8 -8
  235. package/dist/src/core/build-jar-escalation.js +18 -17
  236. package/dist/src/core/build-overwrite-guard.d.ts +4 -4
  237. package/dist/src/core/build-overwrite-guard.js +14 -14
  238. package/dist/src/core/build-prepare.d.ts +4 -12
  239. package/dist/src/core/build-prepare.js +22 -26
  240. package/dist/src/core/config-mutate.js +4 -4
  241. package/dist/src/core/config-paths.d.ts +2 -6
  242. package/dist/src/core/config-paths.js +4 -2
  243. package/dist/src/core/config-state.d.ts +0 -6
  244. package/dist/src/core/config-state.js +3 -21
  245. package/dist/src/core/config-validate-build-audit.d.ts +8 -0
  246. package/dist/src/core/config-validate-build-audit.js +80 -0
  247. package/dist/src/core/config-validate-file-size.d.ts +1 -1
  248. package/dist/src/core/config-validate-file-size.js +3 -3
  249. package/dist/src/core/config-validate-patch-policy.d.ts +2 -2
  250. package/dist/src/core/config-validate-patch-policy.js +3 -3
  251. package/dist/src/core/config-validate-test-toolchains.d.ts +2 -2
  252. package/dist/src/core/config-validate-test-toolchains.js +4 -5
  253. package/dist/src/core/config-validate.js +22 -12
  254. package/dist/src/core/config.d.ts +12 -12
  255. package/dist/src/core/config.js +21 -25
  256. package/dist/src/core/coverage-extend.d.ts +16 -16
  257. package/dist/src/core/coverage-extend.js +20 -20
  258. package/dist/src/core/destructive.d.ts +14 -14
  259. package/dist/src/core/destructive.js +9 -9
  260. package/dist/src/core/diff-hunks.d.ts +2 -2
  261. package/dist/src/core/diff-hunks.js +7 -7
  262. package/dist/src/core/discard-baseline.d.ts +10 -10
  263. package/dist/src/core/discard-baseline.js +22 -23
  264. package/dist/src/core/display-state.d.ts +11 -11
  265. package/dist/src/core/display-state.js +12 -12
  266. package/dist/src/core/engine-changes.d.ts +2 -2
  267. package/dist/src/core/engine-changes.js +2 -2
  268. package/dist/src/core/engine-precondition.d.ts +5 -13
  269. package/dist/src/core/engine-precondition.js +5 -10
  270. package/dist/src/core/engine-session-lock.d.ts +18 -18
  271. package/dist/src/core/engine-session-lock.js +50 -54
  272. package/dist/src/core/export-moved-code-shape.d.ts +7 -7
  273. package/dist/src/core/export-moved-code-shape.js +10 -10
  274. package/dist/src/core/file-lock-owner.d.ts +103 -0
  275. package/dist/src/core/file-lock-owner.js +259 -0
  276. package/dist/src/core/file-lock.d.ts +14 -19
  277. package/dist/src/core/file-lock.js +90 -128
  278. package/dist/src/core/firefox-cache.d.ts +13 -1
  279. package/dist/src/core/firefox-cache.js +61 -36
  280. package/dist/src/core/firefox-download.d.ts +15 -0
  281. package/dist/src/core/firefox-download.js +38 -22
  282. package/dist/src/core/firefox-extract.d.ts +8 -7
  283. package/dist/src/core/firefox-extract.js +45 -27
  284. package/dist/src/core/firefox.d.ts +34 -36
  285. package/dist/src/core/firefox.js +13 -44
  286. package/dist/src/core/furnace-apply-dry-run.d.ts +1 -6
  287. package/dist/src/core/furnace-apply-dry-run.js +2 -8
  288. package/dist/src/core/furnace-apply-ftl.d.ts +5 -5
  289. package/dist/src/core/furnace-apply-ftl.js +8 -8
  290. package/dist/src/core/furnace-apply-helpers.d.ts +9 -20
  291. package/dist/src/core/furnace-apply-helpers.js +28 -39
  292. package/dist/src/core/furnace-apply-output.js +1 -1
  293. package/dist/src/core/furnace-apply-overwrite-warn.d.ts +9 -9
  294. package/dist/src/core/furnace-apply-overwrite-warn.js +13 -11
  295. package/dist/src/core/furnace-apply-undeploy-actions.d.ts +1 -1
  296. package/dist/src/core/furnace-apply-undeploy-actions.js +1 -1
  297. package/dist/src/core/furnace-apply.d.ts +4 -4
  298. package/dist/src/core/furnace-apply.js +50 -29
  299. package/dist/src/core/furnace-checksum-utils.d.ts +5 -5
  300. package/dist/src/core/furnace-checksum-utils.js +5 -5
  301. package/dist/src/core/furnace-config-custom.d.ts +1 -1
  302. package/dist/src/core/furnace-config-custom.js +2 -2
  303. package/dist/src/core/furnace-config-order.js +1 -1
  304. package/dist/src/core/furnace-config-tokens.d.ts +3 -3
  305. package/dist/src/core/furnace-config-tokens.js +3 -3
  306. package/dist/src/core/furnace-config-validate.js +2 -2
  307. package/dist/src/core/furnace-config.d.ts +5 -5
  308. package/dist/src/core/furnace-config.js +40 -53
  309. package/dist/src/core/furnace-constants.d.ts +6 -6
  310. package/dist/src/core/furnace-constants.js +9 -8
  311. package/dist/src/core/furnace-css-fragments.d.ts +6 -6
  312. package/dist/src/core/furnace-css-fragments.js +11 -11
  313. package/dist/src/core/furnace-dir-entry.d.ts +20 -0
  314. package/dist/src/core/furnace-dir-entry.js +21 -0
  315. package/dist/src/core/furnace-jsconfig.d.ts +7 -7
  316. package/dist/src/core/furnace-jsconfig.js +22 -20
  317. package/dist/src/core/furnace-operation.d.ts +22 -19
  318. package/dist/src/core/furnace-operation.js +38 -34
  319. package/dist/src/core/furnace-precondition.d.ts +10 -10
  320. package/dist/src/core/furnace-precondition.js +8 -8
  321. package/dist/src/core/furnace-refresh.d.ts +18 -6
  322. package/dist/src/core/furnace-refresh.js +5 -8
  323. package/dist/src/core/furnace-registration-ast.d.ts +2 -3
  324. package/dist/src/core/furnace-registration-ast.js +9 -12
  325. package/dist/src/core/furnace-registration-remove.d.ts +4 -4
  326. package/dist/src/core/furnace-registration-remove.js +6 -6
  327. package/dist/src/core/furnace-registration-validate.d.ts +2 -2
  328. package/dist/src/core/furnace-registration-validate.js +2 -2
  329. package/dist/src/core/furnace-registration.d.ts +7 -6
  330. package/dist/src/core/furnace-registration.js +29 -36
  331. package/dist/src/core/furnace-rollback.d.ts +1 -1
  332. package/dist/src/core/furnace-rollback.js +5 -5
  333. package/dist/src/core/furnace-scanner.js +3 -6
  334. package/dist/src/core/furnace-stale-export.d.ts +17 -16
  335. package/dist/src/core/furnace-stale-export.js +16 -15
  336. package/dist/src/core/furnace-staleness.d.ts +2 -2
  337. package/dist/src/core/furnace-staleness.js +2 -2
  338. package/dist/src/core/furnace-state-persist.d.ts +12 -12
  339. package/dist/src/core/furnace-state-persist.js +10 -10
  340. package/dist/src/core/furnace-step-errors.d.ts +6 -6
  341. package/dist/src/core/furnace-step-errors.js +6 -6
  342. package/dist/src/core/furnace-validate-accessibility.js +14 -14
  343. package/dist/src/core/furnace-validate-compatibility.js +9 -9
  344. package/dist/src/core/furnace-validate-registration.d.ts +2 -2
  345. package/dist/src/core/furnace-validate-registration.js +18 -20
  346. package/dist/src/core/furnace-validate-structure.d.ts +1 -1
  347. package/dist/src/core/furnace-validate-structure.js +4 -4
  348. package/dist/src/core/furnace-validate.js +9 -9
  349. package/dist/src/core/furnace-version-drift.d.ts +5 -5
  350. package/dist/src/core/furnace-version-drift.js +5 -5
  351. package/dist/src/core/git-base.d.ts +6 -4
  352. package/dist/src/core/git-base.js +29 -7
  353. package/dist/src/core/git-diff-new-file.d.ts +40 -0
  354. package/dist/src/core/git-diff-new-file.js +119 -0
  355. package/dist/src/core/git-diff.d.ts +13 -13
  356. package/dist/src/core/git-diff.js +121 -189
  357. package/dist/src/core/git-file-ops.d.ts +6 -13
  358. package/dist/src/core/git-file-ops.js +11 -35
  359. package/dist/src/core/git-readonly-index.d.ts +12 -14
  360. package/dist/src/core/git-readonly-index.js +12 -16
  361. package/dist/src/core/git-status.d.ts +9 -2
  362. package/dist/src/core/git-status.js +23 -11
  363. package/dist/src/core/git.d.ts +3 -9
  364. package/dist/src/core/git.js +28 -57
  365. package/dist/src/core/harness-orphans.d.ts +17 -17
  366. package/dist/src/core/harness-orphans.js +28 -27
  367. package/dist/src/core/history-log.d.ts +19 -0
  368. package/dist/src/core/history-log.js +29 -0
  369. package/dist/src/core/license-headers.d.ts +19 -18
  370. package/dist/src/core/license-headers.js +29 -28
  371. package/dist/src/core/mach-build-artifacts.d.ts +21 -21
  372. package/dist/src/core/mach-build-artifacts.js +23 -23
  373. package/dist/src/core/mach-error-hints.d.ts +5 -10
  374. package/dist/src/core/mach-error-hints.js +14 -14
  375. package/dist/src/core/mach-known-noise-filter.d.ts +42 -38
  376. package/dist/src/core/mach-known-noise-filter.js +57 -56
  377. package/dist/src/core/mach-mozconfig.d.ts +6 -6
  378. package/dist/src/core/mach-mozconfig.js +17 -16
  379. package/dist/src/core/mach-python.d.ts +3 -0
  380. package/dist/src/core/mach-python.js +13 -7
  381. package/dist/src/core/mach-resource-shim.d.ts +24 -12
  382. package/dist/src/core/mach-resource-shim.js +124 -21
  383. package/dist/src/core/mach.d.ts +59 -73
  384. package/dist/src/core/mach.js +47 -115
  385. package/dist/src/core/marionette-port.d.ts +15 -30
  386. package/dist/src/core/marionette-port.js +46 -89
  387. package/dist/src/core/marionette-preflight.d.ts +6 -6
  388. package/dist/src/core/marionette-preflight.js +32 -50
  389. package/dist/src/core/markdown-table.d.ts +9 -9
  390. package/dist/src/core/markdown-table.js +14 -14
  391. package/dist/src/core/mochitest-server-port.d.ts +8 -8
  392. package/dist/src/core/mochitest-server-port.js +17 -17
  393. package/dist/src/core/module-resolution-preflight.d.ts +8 -8
  394. package/dist/src/core/module-resolution-preflight.js +11 -11
  395. package/dist/src/core/moz-manifest-helpers.d.ts +7 -7
  396. package/dist/src/core/moz-manifest-helpers.js +7 -7
  397. package/dist/src/core/moz-manifest-register.d.ts +1 -1
  398. package/dist/src/core/moz-manifest-register.js +2 -2
  399. package/dist/src/core/moz-manifest-rules.js +46 -42
  400. package/dist/src/core/moz-manifest-tokenizers.js +1 -1
  401. package/dist/src/core/ownership-table.d.ts +5 -5
  402. package/dist/src/core/ownership-table.js +7 -7
  403. package/dist/src/core/parser-fallback.d.ts +3 -3
  404. package/dist/src/core/parser-fallback.js +3 -3
  405. package/dist/src/core/patch-apply-fuzz.d.ts +5 -5
  406. package/dist/src/core/patch-apply-fuzz.js +13 -13
  407. package/dist/src/core/patch-apply.d.ts +13 -14
  408. package/dist/src/core/patch-apply.js +36 -42
  409. package/dist/src/core/patch-export-coverage.d.ts +0 -9
  410. package/dist/src/core/patch-export-coverage.js +1 -30
  411. package/dist/src/core/patch-export-update.d.ts +21 -4
  412. package/dist/src/core/patch-export-update.js +7 -6
  413. package/dist/src/core/patch-export.d.ts +20 -30
  414. package/dist/src/core/patch-export.js +55 -77
  415. package/dist/src/core/patch-files.d.ts +0 -4
  416. package/dist/src/core/patch-files.js +0 -11
  417. package/dist/src/core/patch-identifier-suggest.d.ts +1 -1
  418. package/dist/src/core/patch-identifier-suggest.js +4 -4
  419. package/dist/src/core/patch-lint-binary.d.ts +12 -18
  420. package/dist/src/core/patch-lint-cache.d.ts +18 -2
  421. package/dist/src/core/patch-lint-cache.js +16 -19
  422. package/dist/src/core/patch-lint-checkjs.d.ts +55 -38
  423. package/dist/src/core/patch-lint-checkjs.js +78 -64
  424. package/dist/src/core/patch-lint-chrome-jsdoc.d.ts +8 -9
  425. package/dist/src/core/patch-lint-chrome-jsdoc.js +10 -11
  426. package/dist/src/core/patch-lint-creators.d.ts +5 -9
  427. package/dist/src/core/patch-lint-creators.js +3 -3
  428. package/dist/src/core/patch-lint-cross.d.ts +27 -19
  429. package/dist/src/core/patch-lint-cross.js +67 -110
  430. package/dist/src/core/patch-lint-css.d.ts +1 -1
  431. package/dist/src/core/patch-lint-css.js +15 -11
  432. package/dist/src/core/patch-lint-diff-tag.d.ts +5 -5
  433. package/dist/src/core/patch-lint-diff-tag.js +5 -5
  434. package/dist/src/core/patch-lint-diff.d.ts +4 -4
  435. package/dist/src/core/patch-lint-diff.js +4 -4
  436. package/dist/src/core/patch-lint-file-size.d.ts +3 -3
  437. package/dist/src/core/patch-lint-file-size.js +6 -6
  438. package/dist/src/core/patch-lint-forward-registration.d.ts +58 -0
  439. package/dist/src/core/patch-lint-forward-registration.js +210 -0
  440. package/dist/src/core/patch-lint-jsdoc.d.ts +2 -2
  441. package/dist/src/core/patch-lint-jsdoc.js +46 -46
  442. package/dist/src/core/patch-lint-module-registration.d.ts +3 -9
  443. package/dist/src/core/patch-lint-module-registration.js +1 -1
  444. package/dist/src/core/patch-lint-mozbuild.d.ts +1 -1
  445. package/dist/src/core/patch-lint-mozbuild.js +10 -10
  446. package/dist/src/core/patch-lint-observer.d.ts +3 -3
  447. package/dist/src/core/patch-lint-observer.js +7 -7
  448. package/dist/src/core/patch-lint-ownership.d.ts +6 -6
  449. package/dist/src/core/patch-lint-ownership.js +6 -6
  450. package/dist/src/core/patch-lint-prettier.d.ts +6 -6
  451. package/dist/src/core/patch-lint-prettier.js +7 -7
  452. package/dist/src/core/patch-lint-queue-types.d.ts +60 -0
  453. package/dist/src/core/patch-lint-queue-types.js +12 -0
  454. package/dist/src/core/patch-lint-staged-registration.d.ts +61 -0
  455. package/dist/src/core/patch-lint-staged-registration.js +90 -0
  456. package/dist/src/core/patch-lint-unmanaged-companion.d.ts +23 -23
  457. package/dist/src/core/patch-lint-unmanaged-companion.js +26 -26
  458. package/dist/src/core/patch-lint.d.ts +41 -35
  459. package/dist/src/core/patch-lint.js +52 -49
  460. package/dist/src/core/patch-lock.d.ts +1 -1
  461. package/dist/src/core/patch-lock.js +11 -11
  462. package/dist/src/core/patch-manifest-consistency.d.ts +7 -7
  463. package/dist/src/core/patch-manifest-consistency.js +16 -17
  464. package/dist/src/core/patch-manifest-files-affected.d.ts +1 -1
  465. package/dist/src/core/patch-manifest-files-affected.js +3 -3
  466. package/dist/src/core/patch-manifest-io.d.ts +14 -14
  467. package/dist/src/core/patch-manifest-io.js +35 -34
  468. package/dist/src/core/patch-manifest-query.d.ts +1 -1
  469. package/dist/src/core/patch-manifest-query.js +4 -4
  470. package/dist/src/core/patch-manifest-resolve.d.ts +5 -5
  471. package/dist/src/core/patch-manifest-resolve.js +7 -7
  472. package/dist/src/core/patch-manifest-validate.js +3 -3
  473. package/dist/src/core/patch-manifest.d.ts +2 -2
  474. package/dist/src/core/patch-manifest.js +2 -2
  475. package/dist/src/core/patch-parse.d.ts +32 -21
  476. package/dist/src/core/patch-parse.js +40 -15
  477. package/dist/src/core/patch-policy.js +15 -27
  478. package/dist/src/core/patch-registration-refs.d.ts +4 -4
  479. package/dist/src/core/patch-registration-refs.js +7 -7
  480. package/dist/src/core/patch-source-metadata.d.ts +1 -3
  481. package/dist/src/core/patch-source-metadata.js +0 -4
  482. package/dist/src/core/patch-transform.d.ts +8 -16
  483. package/dist/src/core/patch-transform.js +13 -23
  484. package/dist/src/core/process-cpu-time.d.ts +1 -1
  485. package/dist/src/core/process-cpu-time.js +6 -6
  486. package/dist/src/core/rebase-session.d.ts +9 -15
  487. package/dist/src/core/rebase-session.js +13 -25
  488. package/dist/src/core/register-browser-content.js +3 -2
  489. package/dist/src/core/register-browser-test.js +2 -1
  490. package/dist/src/core/register-module.js +2 -1
  491. package/dist/src/core/register-result.d.ts +1 -1
  492. package/dist/src/core/register-result.js +1 -1
  493. package/dist/src/core/register-scaffold.d.ts +2 -2
  494. package/dist/src/core/register-scaffold.js +8 -7
  495. package/dist/src/core/register-shared-css.d.ts +3 -3
  496. package/dist/src/core/register-shared-css.js +6 -5
  497. package/dist/src/core/register-xpcshell-test.d.ts +2 -2
  498. package/dist/src/core/register-xpcshell-test.js +2 -2
  499. package/dist/src/core/run-log-redact.d.ts +38 -0
  500. package/dist/src/core/run-log-redact.js +69 -0
  501. package/dist/src/core/run-log.d.ts +21 -10
  502. package/dist/src/core/run-log.js +76 -27
  503. package/dist/src/core/shared-ftl.d.ts +2 -2
  504. package/dist/src/core/shared-ftl.js +6 -6
  505. package/dist/src/core/signal-critical.d.ts +2 -2
  506. package/dist/src/core/signal-critical.js +4 -6
  507. package/dist/src/core/smoke-patterns.d.ts +5 -6
  508. package/dist/src/core/smoke-patterns.js +15 -20
  509. package/dist/src/core/state-file.d.ts +15 -4
  510. package/dist/src/core/state-file.js +14 -1
  511. package/dist/src/core/status-binary.d.ts +8 -8
  512. package/dist/src/core/status-binary.js +12 -12
  513. package/dist/src/core/status-classify.d.ts +17 -17
  514. package/dist/src/core/status-classify.js +13 -12
  515. package/dist/src/core/test-changed-prefs.d.ts +12 -12
  516. package/dist/src/core/test-changed-prefs.js +40 -25
  517. package/dist/src/core/test-harness-crash.d.ts +39 -39
  518. package/dist/src/core/test-harness-crash.js +69 -69
  519. package/dist/src/core/test-harness-output.d.ts +7 -7
  520. package/dist/src/core/test-harness-output.js +7 -7
  521. package/dist/src/core/test-harness-verdict-notes.d.ts +13 -14
  522. package/dist/src/core/test-harness-verdict-notes.js +4 -4
  523. package/dist/src/core/test-path-scope.d.ts +8 -8
  524. package/dist/src/core/test-path-scope.js +11 -11
  525. package/dist/src/core/test-stale-check.d.ts +22 -23
  526. package/dist/src/core/test-stale-check.js +31 -30
  527. package/dist/src/core/test-stale-symlink.d.ts +1 -1
  528. package/dist/src/core/test-stale-symlink.js +1 -1
  529. package/dist/src/core/test-stall-triage.d.ts +9 -9
  530. package/dist/src/core/test-stall-triage.js +22 -22
  531. package/dist/src/core/test-xpcshell-retry.d.ts +26 -7
  532. package/dist/src/core/test-xpcshell-retry.js +14 -11
  533. package/dist/src/core/token-category.d.ts +35 -2
  534. package/dist/src/core/token-category.js +67 -58
  535. package/dist/src/core/token-coverage.js +4 -5
  536. package/dist/src/core/token-dark-mode.d.ts +9 -9
  537. package/dist/src/core/token-dark-mode.js +13 -25
  538. package/dist/src/core/token-docs.d.ts +1 -1
  539. package/dist/src/core/token-inventory.d.ts +56 -0
  540. package/dist/src/core/token-inventory.js +109 -0
  541. package/dist/src/core/token-manager.d.ts +4 -4
  542. package/dist/src/core/token-manager.js +22 -22
  543. package/dist/src/core/token-scaffold.d.ts +4 -4
  544. package/dist/src/core/token-scaffold.js +4 -4
  545. package/dist/src/core/token-variant.d.ts +14 -14
  546. package/dist/src/core/token-variant.js +52 -53
  547. package/dist/src/core/toolchain-preflight.d.ts +15 -15
  548. package/dist/src/core/toolchain-preflight.js +23 -23
  549. package/dist/src/core/tree-cow.d.ts +3 -5
  550. package/dist/src/core/tree-cow.js +8 -8
  551. package/dist/src/core/tree-guard.d.ts +3 -3
  552. package/dist/src/core/tree-guard.js +23 -23
  553. package/dist/src/core/tree-store.d.ts +15 -15
  554. package/dist/src/core/tree-store.js +39 -38
  555. package/dist/src/core/typecheck-shim.d.ts +16 -15
  556. package/dist/src/core/typecheck-shim.js +26 -25
  557. package/dist/src/core/typecheck.d.ts +12 -12
  558. package/dist/src/core/typecheck.js +33 -33
  559. package/dist/src/core/wire-destroy.d.ts +2 -2
  560. package/dist/src/core/wire-destroy.js +5 -5
  561. package/dist/src/core/wire-dom-fragment.d.ts +3 -3
  562. package/dist/src/core/wire-dom-fragment.js +12 -23
  563. package/dist/src/core/wire-init.d.ts +2 -2
  564. package/dist/src/core/wire-init.js +7 -7
  565. package/dist/src/core/wire-subscript.d.ts +1 -1
  566. package/dist/src/core/wire-subscript.js +3 -3
  567. package/dist/src/core/wire-utils.d.ts +9 -9
  568. package/dist/src/core/wire-utils.js +16 -28
  569. package/dist/src/core/xpcshell-appdir.d.ts +20 -20
  570. package/dist/src/core/xpcshell-appdir.js +28 -30
  571. package/dist/src/core/xpcshell-profile-dir.d.ts +3 -3
  572. package/dist/src/core/xpcshell-profile-dir.js +7 -7
  573. package/dist/src/errors/base.d.ts +69 -16
  574. package/dist/src/errors/base.js +95 -26
  575. package/dist/src/errors/build.d.ts +6 -6
  576. package/dist/src/errors/build.js +26 -34
  577. package/dist/src/errors/codes.d.ts +10 -10
  578. package/dist/src/errors/codes.js +10 -10
  579. package/dist/src/errors/config.d.ts +0 -14
  580. package/dist/src/errors/config.js +13 -34
  581. package/dist/src/errors/download.d.ts +13 -0
  582. package/dist/src/errors/download.js +53 -24
  583. package/dist/src/errors/furnace.d.ts +2 -2
  584. package/dist/src/errors/furnace.js +8 -9
  585. package/dist/src/errors/git.d.ts +9 -9
  586. package/dist/src/errors/git.js +21 -31
  587. package/dist/src/errors/patch.d.ts +3 -3
  588. package/dist/src/errors/patch.js +11 -13
  589. package/dist/src/errors/rebase.d.ts +1 -1
  590. package/dist/src/errors/rebase.js +8 -8
  591. package/dist/src/errors/run.d.ts +1 -1
  592. package/dist/src/errors/run.js +1 -1
  593. package/dist/src/index.d.ts +4 -4
  594. package/dist/src/index.js +4 -4
  595. package/dist/src/types/commands/options.d.ts +155 -200
  596. package/dist/src/types/commands/patches.d.ts +19 -19
  597. package/dist/src/types/commands/project.d.ts +3 -3
  598. package/dist/src/types/config.d.ts +52 -19
  599. package/dist/src/types/furnace.d.ts +17 -17
  600. package/dist/src/types/index.d.ts +0 -1
  601. package/dist/src/types/json.d.ts +3 -3
  602. package/dist/src/types/json.js +2 -2
  603. package/dist/src/types/typecheck.d.ts +3 -3
  604. package/dist/src/utils/assert.d.ts +4 -16
  605. package/dist/src/utils/assert.js +7 -24
  606. package/dist/src/utils/build-info.d.ts +6 -6
  607. package/dist/src/utils/build-info.js +6 -6
  608. package/dist/src/utils/child-env.d.ts +7 -6
  609. package/dist/src/utils/child-env.js +5 -5
  610. package/dist/src/utils/concurrency.d.ts +2 -2
  611. package/dist/src/utils/concurrency.js +2 -2
  612. package/dist/src/utils/elapsed.js +10 -1
  613. package/dist/src/utils/errors.d.ts +8 -8
  614. package/dist/src/utils/errors.js +8 -8
  615. package/dist/src/utils/fs.d.ts +1 -1
  616. package/dist/src/utils/fs.js +15 -20
  617. package/dist/src/utils/hash.d.ts +12 -0
  618. package/dist/src/utils/hash.js +16 -0
  619. package/dist/src/utils/line-dispatch.d.ts +15 -0
  620. package/dist/src/utils/line-dispatch.js +48 -0
  621. package/dist/src/utils/logger.d.ts +4 -4
  622. package/dist/src/utils/logger.js +11 -11
  623. package/dist/src/utils/machine-output.js +2 -2
  624. package/dist/src/utils/options.d.ts +14 -20
  625. package/dist/src/utils/options.js +26 -27
  626. package/dist/src/utils/package-root.js +5 -14
  627. package/dist/src/utils/paths.d.ts +4 -4
  628. package/dist/src/utils/paths.js +4 -4
  629. package/dist/src/utils/platform.d.ts +0 -4
  630. package/dist/src/utils/process-group.d.ts +10 -9
  631. package/dist/src/utils/process-group.js +37 -36
  632. package/dist/src/utils/process.d.ts +70 -55
  633. package/dist/src/utils/process.js +129 -179
  634. package/dist/src/utils/ps-duration.d.ts +4 -4
  635. package/dist/src/utils/ps-duration.js +9 -9
  636. package/dist/src/utils/regex.d.ts +4 -4
  637. package/dist/src/utils/regex.js +7 -7
  638. package/dist/src/utils/sleep.d.ts +26 -0
  639. package/dist/src/utils/sleep.js +31 -0
  640. package/dist/src/utils/stdio-drain.d.ts +7 -7
  641. package/dist/src/utils/stdio-drain.js +8 -8
  642. package/dist/src/utils/validation.d.ts +12 -49
  643. package/dist/src/utils/validation.js +26 -36
  644. package/docs/README.md +2 -2
  645. package/docs/configuration.md +163 -69
  646. package/docs/exit-codes.md +66 -49
  647. package/docs/furnace.md +20 -19
  648. package/docs/lifecycle-invariants.md +414 -247
  649. package/docs/machine-output.md +58 -34
  650. package/docs/patch-workflow.md +48 -44
  651. package/docs/run-logs.md +72 -28
  652. package/docs/testing.md +105 -98
  653. package/docs/verification-trees.md +23 -22
  654. package/package.json +7 -6
  655. package/dist/src/commands/rebase.d.ts +0 -4
  656. package/dist/src/commands/rebase.js +0 -5
  657. package/dist/src/core/patch-artifact-normalize.d.ts +0 -21
  658. package/dist/src/core/patch-artifact-normalize.js +0 -24
  659. package/dist/src/core/patch-lint-reexports.d.ts +0 -7
  660. package/dist/src/core/patch-lint-reexports.js +0 -8
  661. package/dist/src/core/wire-targets.d.ts +0 -7
  662. package/dist/src/core/wire-targets.js +0 -8
@@ -25,17 +25,7 @@ import { explainMachError } from './mach-error-hints.js';
25
25
  /** Path fragments of files whose edits invalidate the recursive-make backend. */
26
26
  const BACKEND_INVALIDATING_SUFFIXES = ['moz.build', 'moz.configure', 'Makefile.in'];
27
27
  /**
28
- * Packaging manifests whose graph/destination directories MAY need a full
29
- * build. Path-shape only: {@link evaluateJarManifestEscalation} decides
30
- * whether a given changed manifest actually forces one (a new manifest, or
31
- * one that redirects its install base directory), so an entry added to an
32
- * existing `dist/bin` manifest no longer costs a ~10-minute build.
33
- */
34
- export function requiresFullBuildForIncrementalTest(path) {
35
- return isJarManifestPath(path);
36
- }
37
- /**
38
- * Build-input manifests changed since the last SUCCESSFUL build — not
28
+ * Build-input manifests changed since the last successful build, not
39
29
  * merely dirty against HEAD. `collectChangedEnginePaths` unions the
40
30
  * baseline-to-HEAD diff with every worktree modification, and a fork's
41
31
  * worktree is permanently dirty (imported patches, Furnace-applied
@@ -43,8 +33,8 @@ export function requiresFullBuildForIncrementalTest(path) {
43
33
  * `moz.build` as changed on every run: `mach configure` re-ran and the
44
34
  * pre-test build escalated to a full `mach build` after each full build
45
35
  * that had already consumed exactly this content. The baseline's
46
- * `buildInputFingerprints` say what the last successful build saw;
47
- * anything byte-identical to that is dropped here. A baseline without the
36
+ * `buildInputFingerprints` say what the last successful build saw.
37
+ * Anything byte-identical to that is dropped here. A baseline without the
48
38
  * field (written before it existed) keeps every dirty input, which is the
49
39
  * old behaviour.
50
40
  *
@@ -66,8 +56,9 @@ async function collectChangedBuildInputs(engineDir, baseline) {
66
56
  * Extracts the tail of captured `mach configure` output so the underlying
67
57
  * mozbuild failure (e.g. `mozbuild.util.UnsortedError: ... is not in sorted
68
58
  * order`) is carried into the thrown `BuildError` instead of being reduced to
69
- * a bare exit code. mozbuild writes the error and its traceback to stderr;
70
- * stdout is included as a fallback for shells that interleave the streams.
59
+ * a bare exit code. mozbuild writes the error and its traceback to stderr,
60
+ * and stdout is included as a fallback for shells that interleave the
61
+ * streams.
71
62
  * Returns an empty string when nothing useful was captured.
72
63
  */
73
64
  function extractMachConfigureError(result) {
@@ -79,7 +70,7 @@ function extractMachConfigureError(result) {
79
70
  /**
80
71
  * Describes an exit code in the shell's 128+N signal convention. Truncated
81
72
  * configure/build logs with a signal-shaped exit (e.g. 144 = 128+16, SIGURG
82
- * on macOS) are environmental interruptions, not compiler failures — naming
73
+ * on macOS) are environmental interruptions, not compiler failures. Naming
83
74
  * that in the failure text saves the operator a fruitless log hunt.
84
75
  * Returns undefined for codes <= 128 (regular failures) and
85
76
  * for codes past the conventional signal range, so callers append nothing.
@@ -101,7 +92,7 @@ export function describeSignalShapedExit(exitCode) {
101
92
  * Builds the `BuildError` for a non-zero auto-configure exit: the output
102
93
  * tail (so the underlying mozbuild failure survives), any matched
103
94
  * mach-error hints (so e.g. a toolchain minimum that moved with a source
104
- * hop names `fireforge bootstrap` on this path too, exactly like the
95
+ * hop names `fireforge bootstrap` on this path too, just like the
105
96
  * protected build dispatch), and the stop rationale.
106
97
  */
107
98
  function buildConfigureFailureError(captured) {
@@ -126,9 +117,14 @@ function buildConfigureFailureError(captured) {
126
117
  * @param baseline - Last successful build's baseline
127
118
  */
128
119
  async function decideJarEscalation(engineDir, changed, baseline) {
129
- const decision = await evaluateJarManifestEscalation(engineDir, changed.filter(requiresFullBuildForIncrementalTest), baseline);
120
+ // Packaging manifests whose graph/destination directories may need a full
121
+ // build. Path-shape only: `evaluateJarManifestEscalation` decides whether a
122
+ // given changed manifest actually forces one (a new manifest, or one that
123
+ // redirects its install base directory), so an entry added to an existing
124
+ // `dist/bin` manifest no longer costs a ~10-minute build.
125
+ const decision = await evaluateJarManifestEscalation(engineDir, changed.filter(isJarManifestPath), baseline);
130
126
  if (decision.cleared.length > 0) {
131
- verbose(`jar escalation: ${String(decision.cleared.length)} changed jar.mn add entries to an existing dist/bin manifest; not escalating for ${decision.cleared.join(', ')}.`);
127
+ verbose(`jar escalation: ${decision.cleared.length} changed jar.mn add entries to an existing dist/bin manifest; not escalating for ${decision.cleared.join(', ')}.`);
132
128
  }
133
129
  return decision.escalate ? formatJarEscalationNotice(decision) : undefined;
134
130
  }
@@ -144,10 +140,10 @@ export function isBackendInvalidatingFile(path) {
144
140
  return false;
145
141
  }
146
142
  /**
147
- * Loud before the overwrite, not silent after it.
143
+ * Warns before the overwrite rather than after it.
148
144
  *
149
- * Every write `prepareBuildEnvironment` performs — branding, Furnace
150
- * components, `mozconfig` — rewrites engine files from a FireForge-owned
145
+ * Every write `prepareBuildEnvironment` performs (branding, Furnace
146
+ * components, `mozconfig`) rewrites engine files from a FireForge-owned
151
147
  * source. Content recorded in neither a patch body nor the pristine baseline
152
148
  * is destroyed by that, and on a multi-session checkout the destruction is
153
149
  * what lets a later re-export capture a half-reverted hybrid that every gate
@@ -220,9 +216,9 @@ export async function prepareBuildEnvironment(projectRoot, paths, config, option
220
216
  const exitCode = captured.exitCode;
221
217
  if (exitCode !== 0) {
222
218
  configureSpinner.error(`mach configure failed with exit code ${exitCode}`);
223
- // Surface the underlying mozbuild error (e.g. UnsortedError) instead
224
- // of a bare exit code — the generic message hid the actual cause —
225
- // plus any matched mach-error hints (see the helper).
219
+ // Surface the underlying mozbuild error (e.g. UnsortedError)
220
+ // instead of a bare exit code, since the generic message hid the
221
+ // actual cause, plus any matched mach-error hints (see the helper).
226
222
  throw buildConfigureFailureError(captured);
227
223
  }
228
224
  else {
@@ -246,7 +242,7 @@ export async function prepareBuildEnvironment(projectRoot, paths, config, option
246
242
  // Set up custom branding directory and patch moz.configure. Thread the
247
243
  // project license through so `buildConfigureScriptContent` /
248
244
  // `buildBrandPropertiesContent` / `buildBrandFtlContent` stamp the
249
- // generated files with a matching SPDX header — otherwise `patch-lint`
245
+ // generated files with a matching SPDX header. Otherwise `patch-lint`
250
246
  // flags them with `missing-license-header` on every subsequent export when
251
247
  // the project is not MPL-2.0.
252
248
  const brandingConfig = {
@@ -18,10 +18,10 @@ function cloneConfigDocument(config) {
18
18
  return cloned;
19
19
  }
20
20
  /**
21
- * The error every sentinel-segment refusal raises. Only the MESSAGE lives
21
+ * The error every sentinel-segment refusal raises. Only the message lives
22
22
  * here: the comparison itself is spelled inline at each write site, because
23
23
  * that is what both a reader and CodeQL's `js/prototype-pollution-utility`
24
- * barrier detection need — the latter is not interprocedural, so a check
24
+ * barrier detection need. That detection is not interprocedural, so a check
25
25
  * hidden behind a helper leaves the descent below looking unguarded.
26
26
  */
27
27
  function sentinelSegmentError(key, part) {
@@ -41,8 +41,8 @@ function getOrCreateChildRecord(parent, key) {
41
41
  export function mutateConfig(config, key, value, skipValidation = false) {
42
42
  const parts = key.split('.');
43
43
  const raw = cloneConfigDocument(config);
44
- // Every segment is checked at the point it is USED as a property name —
45
- // the descent below and the leaf assignment — rather than once up front,
44
+ // Every segment is checked at the point it is used as a property name
45
+ // (the descent below and the leaf assignment) rather than once up front,
46
46
  // so `--force` cannot be used to mutate Object.prototype and neither write
47
47
  // can drift out from behind the guard. `raw` is a private clone, so a
48
48
  // refusal here has mutated nothing the caller can observe.
@@ -2,16 +2,12 @@
2
2
  * Project path derivation from a root directory.
3
3
  */
4
4
  import type { ProjectPaths } from '../types/config.js';
5
- /** Name of the configuration file */
6
- export declare const CONFIG_FILENAME = "fireforge.json";
7
5
  /** Name of the fireforge data directory */
8
6
  export declare const FIREFORGE_DIR = ".fireforge";
9
- /** Name of the state file */
10
- export declare const STATE_FILENAME = "state.json";
11
7
  /** Supported top-level fireforge.json keys backed by the current schema. */
12
- export declare const SUPPORTED_CONFIG_ROOT_KEYS: readonly ["name", "vendor", "appId", "binaryName", "firefox", "build", "test", "externalToolchains", "license", "wire", "patchLint", "patchPolicy", "typecheck", "markerComment"];
8
+ export declare const SUPPORTED_CONFIG_ROOT_KEYS: readonly ["name", "vendor", "appId", "binaryName", "firefox", "build", "buildAudit", "test", "externalToolchains", "license", "wire", "patchLint", "patchPolicy", "typecheck", "markerComment"];
13
9
  /** Supported config paths that can be read or set without --force. */
14
- export declare const SUPPORTED_CONFIG_PATHS: readonly ["name", "vendor", "appId", "binaryName", "license", "firefox", "firefox.version", "firefox.product", "firefox.sha256", "firefox.candidate", "build", "build.jobs", "test", "test.canaryPath", "test.canaryTimeoutSeconds", "externalToolchains", "wire", "wire.subscriptDir", "patchLint", "patchLint.checkJs", "patchLint.checkJsStrict", "patchLint.checkJsCompilerOptions", "patchLint.checkJsExtraShim", "patchLint.checkJsTestFiles", "patchLint.checkJsTestShim", "patchLint.rawColorAllowlist", "patchLint.jsdocClassMethods", "patchLint.testAssertionFloor", "patchLint.chromeScriptJsDoc", "patchPolicy", "typecheck", "typecheck.projects", "typecheck.extraShim", "markerComment"];
10
+ export declare const SUPPORTED_CONFIG_PATHS: readonly ["name", "vendor", "appId", "binaryName", "license", "firefox", "firefox.version", "firefox.product", "firefox.sha256", "firefox.candidate", "firefox.allowUnverifiedDownload", "build", "build.jobs", "test", "test.canaryPath", "test.canaryTimeoutSeconds", "externalToolchains", "wire", "wire.subscriptDir", "patchLint", "patchLint.checkJs", "patchLint.checkJsStrict", "patchLint.checkJsCompilerOptions", "patchLint.checkJsExtraShim", "patchLint.checkJsTestFiles", "patchLint.checkJsTestShim", "patchLint.rawColorAllowlist", "patchLint.jsdocClassMethods", "patchLint.testAssertionFloor", "patchLint.chromeScriptJsDoc", "patchPolicy", "typecheck", "typecheck.projects", "typecheck.extraShim", "markerComment"];
15
11
  /**
16
12
  * Gets all project paths based on a root directory.
17
13
  * @param root - Root directory of the project
@@ -4,11 +4,11 @@
4
4
  */
5
5
  import { join } from 'node:path';
6
6
  /** Name of the configuration file */
7
- export const CONFIG_FILENAME = 'fireforge.json';
7
+ const CONFIG_FILENAME = 'fireforge.json';
8
8
  /** Name of the fireforge data directory */
9
9
  export const FIREFORGE_DIR = '.fireforge';
10
10
  /** Name of the state file */
11
- export const STATE_FILENAME = 'state.json';
11
+ const STATE_FILENAME = 'state.json';
12
12
  /** Name of the engine directory */
13
13
  const ENGINE_DIR = 'engine';
14
14
  /** Name of the patches directory */
@@ -25,6 +25,7 @@ export const SUPPORTED_CONFIG_ROOT_KEYS = [
25
25
  'binaryName',
26
26
  'firefox',
27
27
  'build',
28
+ 'buildAudit',
28
29
  'test',
29
30
  'externalToolchains',
30
31
  'license',
@@ -46,6 +47,7 @@ export const SUPPORTED_CONFIG_PATHS = [
46
47
  'firefox.product',
47
48
  'firefox.sha256',
48
49
  'firefox.candidate',
50
+ 'firefox.allowUnverifiedDownload',
49
51
  'build',
50
52
  'build.jobs',
51
53
  'test',
@@ -8,12 +8,6 @@ import type { FireForgeState } from '../types/config.js';
8
8
  * @returns FireForge state
9
9
  */
10
10
  export declare function loadState(root: string): Promise<FireForgeState>;
11
- /**
12
- * Saves the fireforge state.
13
- * @param root - Root directory of the project
14
- * @param state - State to save
15
- */
16
- export declare function saveState(root: string, state: FireForgeState): Promise<void>;
17
11
  /**
18
12
  * Updates specific fields in the fireforge state.
19
13
  * @param root - Root directory of the project
@@ -24,13 +24,7 @@ function sanitizeProjectState(data) {
24
24
  const state = {};
25
25
  const issues = [];
26
26
  const recoveredFields = [];
27
- const stringFields = [
28
- 'brand',
29
- 'buildMode',
30
- 'lastBuild',
31
- 'downloadedVersion',
32
- 'baseCommit',
33
- ];
27
+ const stringFields = ['brand', 'buildMode', 'downloadedVersion', 'baseCommit'];
34
28
  for (const key of stringFields) {
35
29
  const value = data[key];
36
30
  if (value === undefined) {
@@ -41,9 +35,9 @@ function sanitizeProjectState(data) {
41
35
  continue;
42
36
  }
43
37
  if (key === 'buildMode') {
44
- // Validate and assign in ONE block so the predicate's narrowing reaches
38
+ // Validate and assign in one block so the predicate's narrowing reaches
45
39
  // the assignment. Split across two `key === 'buildMode'` guards,
46
- // TypeScript cannot correlate them and the assignment needed a cast —
40
+ // TypeScript cannot correlate them and the assignment needed a cast,
47
41
  // which is what let the untyped allowlist drift from the union.
48
42
  if (!isBuildMode(value)) {
49
43
  issues.push(`field "buildMode" must be one of: ${BUILD_MODES.join(', ')}`);
@@ -132,18 +126,6 @@ export async function loadState(root) {
132
126
  const paths = getProjectPaths(root);
133
127
  return loadStateFromPath(paths.state);
134
128
  }
135
- /**
136
- * Saves the fireforge state.
137
- * @param root - Root directory of the project
138
- * @param state - State to save
139
- */
140
- export async function saveState(root, state) {
141
- const paths = getProjectPaths(root);
142
- const validatedState = validateFireForgeState(state);
143
- await withStateFileLock(paths.state, async () => {
144
- await writeJson(paths.state, validatedState);
145
- });
146
- }
147
129
  /**
148
130
  * Updates specific fields in the fireforge state.
149
131
  * @param root - Root directory of the project
@@ -0,0 +1,8 @@
1
+ import type { BuildAuditConfig } from '../types/config.js';
2
+ /**
3
+ * Parses the `buildAudit` block.
4
+ *
5
+ * @param raw - The raw `buildAudit` value from fireforge.json
6
+ * @returns The validated block
7
+ */
8
+ export declare function parseBuildAuditConfig(raw: unknown): BuildAuditConfig;
@@ -0,0 +1,80 @@
1
+ // SPDX-License-Identifier: EUPL-1.2
2
+ /**
3
+ * Validation for the `buildAudit` block.
4
+ *
5
+ * Split out of `config-validate.ts`, which is at its per-file line budget,
6
+ * following the `config-validate-file-size.ts` precedent.
7
+ *
8
+ * The rules here are stricter than the schema strictly needs, on purpose:
9
+ * every entry is a standing suppression of a warning the
10
+ * audit would otherwise raise. A malformed one must fail loudly at config
11
+ * load rather than quietly admit nothing (leaving the operator believing a
12
+ * path is carved out) or quietly admit everything.
13
+ */
14
+ import { ConfigError } from '../errors/config.js';
15
+ import { isContainedRelativePath } from '../utils/paths.js';
16
+ import { isObject } from '../utils/validation.js';
17
+ /** Parses one `buildAudit.unpackaged[]` entry. */
18
+ function parseUnpackagedEntry(raw, field) {
19
+ if (!isObject(raw)) {
20
+ throw new ConfigError(`Config field "${field}" must be a plain object with "path" and "reason"`);
21
+ }
22
+ for (const key of Object.keys(raw)) {
23
+ if (key !== 'path' && key !== 'reason') {
24
+ throw new ConfigError(`Config field "${field}" has unknown key "${key}"`);
25
+ }
26
+ }
27
+ const path = raw['path'];
28
+ if (typeof path !== 'string' || path.trim().length === 0) {
29
+ throw new ConfigError(`Config field "${field}.path" must be a non-empty string`);
30
+ }
31
+ if (!isContainedRelativePath(path)) {
32
+ throw new ConfigError(`Config field "${field}.path" must be an engine-relative path`);
33
+ }
34
+ if (path.includes('**')) {
35
+ // A `**` carve-out admits an entire subtree, which is how a reviewed
36
+ // exception quietly becomes a blanket one. `*` inside a single segment
37
+ // is enough for the shapes this exists for.
38
+ throw new ConfigError(`Config field "${field}.path" must not use "**" — a carve-out may glob within one path segment only`);
39
+ }
40
+ const reason = raw['reason'];
41
+ if (typeof reason !== 'string' || reason.trim().length === 0) {
42
+ // Required on purpose: this is the one audit class FireForge cannot
43
+ // derive from the tree, so the declaration is the evidence.
44
+ throw new ConfigError(`Config field "${field}.reason" must be a non-empty string explaining why the file is never packaged`);
45
+ }
46
+ return { path, reason };
47
+ }
48
+ /**
49
+ * Parses the `buildAudit` block.
50
+ *
51
+ * @param raw - The raw `buildAudit` value from fireforge.json
52
+ * @returns The validated block
53
+ */
54
+ export function parseBuildAuditConfig(raw) {
55
+ if (!isObject(raw)) {
56
+ throw new ConfigError('Config field "buildAudit" must be a plain object');
57
+ }
58
+ for (const key of Object.keys(raw)) {
59
+ if (key !== 'unpackaged') {
60
+ throw new ConfigError(`Config field "buildAudit" has unknown key "${key}"`);
61
+ }
62
+ }
63
+ const unpackaged = raw['unpackaged'];
64
+ if (unpackaged === undefined)
65
+ return {};
66
+ if (!Array.isArray(unpackaged)) {
67
+ throw new ConfigError('Config field "buildAudit.unpackaged" must be an array');
68
+ }
69
+ const entries = unpackaged.map((entry, index) => parseUnpackagedEntry(entry, `buildAudit.unpackaged[${String(index)}]`));
70
+ const seen = new Set();
71
+ for (const entry of entries) {
72
+ if (seen.has(entry.path)) {
73
+ // Two rows for one path means one of the two reasons is not the
74
+ // operative one, and nothing says which.
75
+ throw new ConfigError(`Config field "buildAudit.unpackaged" declares "${entry.path}" more than once`);
76
+ }
77
+ seen.add(entry.path);
78
+ }
79
+ return { unpackaged: entries };
80
+ }
@@ -6,7 +6,7 @@
6
6
  import type { PatchLintFileSizeThresholds } from '../types/config.js';
7
7
  /**
8
8
  * Parses the `patchLint.fileSizeThresholds` block. Ordering is validated
9
- * against the MERGED triple (overrides on top of the defaults), so setting
9
+ * against the merged triple (overrides on top of the defaults), so setting
10
10
  * only `warning` cannot land below the default `notice`.
11
11
  */
12
12
  export declare function parsePatchLintFileSizeThresholds(raw: unknown): PatchLintFileSizeThresholds;
@@ -9,7 +9,7 @@ import { isObject } from '../utils/validation.js';
9
9
  import { DEFAULT_FILE_SIZE_THRESHOLDS } from './patch-lint-file-size.js';
10
10
  /**
11
11
  * Parses one `patchLint.fileSizeThresholds.<tier>` triple. Every field is
12
- * optional and merges over the built-in default; values must be positive
12
+ * optional and merges over the built-in default. Values must be positive
13
13
  * integers and stay ordered `notice <= warning <= error`, because an
14
14
  * out-of-order triple would silently disable a band instead of failing.
15
15
  */
@@ -36,7 +36,7 @@ function parseFileSizeTier(raw, field) {
36
36
  }
37
37
  /**
38
38
  * Parses the `patchLint.fileSizeThresholds` block. Ordering is validated
39
- * against the MERGED triple (overrides on top of the defaults), so setting
39
+ * against the merged triple (overrides on top of the defaults), so setting
40
40
  * only `warning` cannot land below the default `notice`.
41
41
  */
42
42
  export function parsePatchLintFileSizeThresholds(raw) {
@@ -52,7 +52,7 @@ export function parsePatchLintFileSizeThresholds(raw) {
52
52
  const merged = { ...DEFAULT_FILE_SIZE_THRESHOLDS[tier], ...parsed };
53
53
  if (merged.notice > merged.warning || merged.warning > merged.error) {
54
54
  throw new ConfigError(`Config field "patchLint.fileSizeThresholds.${tier}" must satisfy notice <= warning <= error ` +
55
- `(resolved: ${String(merged.notice)}/${String(merged.warning)}/${String(merged.error)})`);
55
+ `(resolved: ${merged.notice}/${merged.warning}/${merged.error})`);
56
56
  }
57
57
  out[tier] = parsed;
58
58
  }
@@ -2,6 +2,6 @@
2
2
  * Validation helpers for `fireforge.json#patchPolicy`.
3
3
  */
4
4
  import type { PatchPolicyConfig } from '../types/config.js';
5
- import { parseObject } from '../utils/parse.js';
5
+ import { type ParsedRecord } from '../utils/parse.js';
6
6
  /** Parses and validates the optional patch policy config block. */
7
- export declare function parsePatchPolicyBlock(rec: ReturnType<typeof parseObject>): PatchPolicyConfig;
7
+ export declare function parsePatchPolicyBlock(rec: ParsedRecord): PatchPolicyConfig;
@@ -108,7 +108,7 @@ function parsePatchPolicyReservedRange(raw, label) {
108
108
  return {
109
109
  from,
110
110
  to,
111
- allowed: allowedRaw.map((entry, index) => parseReservedAllowedPatch(entry, `${label}.allowed[${String(index)}]`)),
111
+ allowed: allowedRaw.map((entry, index) => parseReservedAllowedPatch(entry, `${label}.allowed[${index}]`)),
112
112
  };
113
113
  }
114
114
  function assertPolicyRangesDoNotOverlap(ranges, label) {
@@ -160,14 +160,14 @@ export function parsePatchPolicyBlock(rec) {
160
160
  if (!Array.isArray(rangesRaw) || rangesRaw.length === 0) {
161
161
  throw new ConfigError('Config field "patchPolicy.ranges" must be a non-empty array');
162
162
  }
163
- out.ranges = rangesRaw.map((entry, index) => parsePatchPolicyRange(entry, `patchPolicy.ranges[${String(index)}]`));
163
+ out.ranges = rangesRaw.map((entry, index) => parsePatchPolicyRange(entry, `patchPolicy.ranges[${index}]`));
164
164
  assertPolicyRangesDoNotOverlap(out.ranges, 'patchPolicy.ranges');
165
165
  const reservedRangesRaw = rec.raw('reservedRanges');
166
166
  if (reservedRangesRaw !== undefined) {
167
167
  if (!Array.isArray(reservedRangesRaw)) {
168
168
  throw new ConfigError('Config field "patchPolicy.reservedRanges" must be an array');
169
169
  }
170
- out.reservedRanges = reservedRangesRaw.map((entry, index) => parsePatchPolicyReservedRange(entry, `patchPolicy.reservedRanges[${String(index)}]`));
170
+ out.reservedRanges = reservedRangesRaw.map((entry, index) => parsePatchPolicyReservedRange(entry, `patchPolicy.reservedRanges[${index}]`));
171
171
  assertPolicyRangesDoNotOverlap(out.reservedRanges, 'patchPolicy.reservedRanges');
172
172
  }
173
173
  return out;
@@ -1,6 +1,6 @@
1
1
  import type { FireForgeConfig } from '../types/config.js';
2
- import { parseObject } from '../utils/parse.js';
3
- type ConfigRecord = ReturnType<typeof parseObject>;
2
+ import type { ParsedRecord } from '../utils/parse.js';
3
+ type ConfigRecord = ParsedRecord;
4
4
  /** Parses the optional `test` block. */
5
5
  export declare function parseTestBlock(rec: ConfigRecord, config: FireForgeConfig): void;
6
6
  /** Parses optional project-specific external toolchain doctor probes. */
@@ -1,6 +1,5 @@
1
1
  // SPDX-License-Identifier: EUPL-1.2
2
2
  import { ConfigError } from '../errors/config.js';
3
- import { parseObject } from '../utils/parse.js';
4
3
  import { isContainedRelativePath } from '../utils/paths.js';
5
4
  import { isObject } from '../utils/validation.js';
6
5
  function optionalConfigString(rec, key, label) {
@@ -58,16 +57,16 @@ export function parseExternalToolchainsBlock(rec, config) {
58
57
  }
59
58
  config.externalToolchains = raw.map((entry, index) => {
60
59
  if (!isObject(entry)) {
61
- throw new ConfigError(`Config field "externalToolchains[${String(index)}]" must be an object`);
60
+ throw new ConfigError(`Config field "externalToolchains[${index}]" must be an object`);
62
61
  }
63
62
  const item = entry;
64
63
  const name = item['name'];
65
64
  if (typeof name !== 'string' || name.trim() === '') {
66
- throw new ConfigError(`Config field "externalToolchains[${String(index)}].name" must be a non-empty string`);
65
+ throw new ConfigError(`Config field "externalToolchains[${index}].name" must be a non-empty string`);
67
66
  }
68
67
  const tools = item['tools'];
69
68
  if (!Array.isArray(tools) || tools.length === 0) {
70
- throw new ConfigError(`Config field "externalToolchains[${String(index)}].tools" must be a non-empty array`);
69
+ throw new ConfigError(`Config field "externalToolchains[${index}].tools" must be a non-empty array`);
71
70
  }
72
71
  return {
73
72
  name,
@@ -76,7 +75,7 @@ export function parseExternalToolchainsBlock(rec, config) {
76
75
  });
77
76
  }
78
77
  function parseExternalToolRequirement(tool, index, toolIndex) {
79
- const label = `externalToolchains[${String(index)}].tools[${String(toolIndex)}]`;
78
+ const label = `externalToolchains[${index}].tools[${toolIndex}]`;
80
79
  if (!isObject(tool)) {
81
80
  throw new ConfigError(`Config field "${label}" must be an object`);
82
81
  }
@@ -8,6 +8,7 @@ import { parseObject } from '../utils/parse.js';
8
8
  import { isContainedRelativePath, isExplicitAbsolutePath } from '../utils/paths.js';
9
9
  import { describeProductVersionIncompatibility, FIREFOX_PRODUCTS, isObject, isValidAppId, isValidFirefoxCandidate, isValidFirefoxProduct, isValidFirefoxVersion, isValidProjectLicense, PROJECT_LICENSES, } from '../utils/validation.js';
10
10
  import { SUPPORTED_CONFIG_ROOT_KEYS } from './config-paths.js';
11
+ import { parseBuildAuditConfig } from './config-validate-build-audit.js';
11
12
  import { parsePatchLintFileSizeThresholds } from './config-validate-file-size.js';
12
13
  import { parsePatchPolicyBlock } from './config-validate-patch-policy.js';
13
14
  import { parseExternalToolchainsBlock, parseTestBlock } from './config-validate-test-toolchains.js';
@@ -20,7 +21,7 @@ import { parseExternalToolchainsBlock, parseTestBlock } from './config-validate-
20
21
  function parseIdentityFields(rec) {
21
22
  // Empty strings would technically pass the
22
23
  // typeof-check below but are never valid for any of these identifier
23
- // fields — rejecting them here prevents downstream code (Firefox build,
24
+ // fields. Rejecting them here prevents downstream code (Firefox build,
24
25
  // launcher binary lookup, AppID assertions) from failing with confusing
25
26
  // errors much later.
26
27
  const name = requireConfigString(rec, 'name');
@@ -54,7 +55,8 @@ function parseIdentityFields(rec) {
54
55
  /**
55
56
  * Parses and validates the required `firefox` block: version shape,
56
57
  * product allowlist, product/version cross-compatibility, and the
57
- * optional sha256 digest (normalized to lowercase).
58
+ * optional sha256 digest (normalized to lowercase), optional
59
+ * `allowUnverifiedDownload` opt-out, optional candidate directory.
58
60
  */
59
61
  function parseFirefoxBlock(rec) {
60
62
  let firefoxRec;
@@ -70,7 +72,7 @@ function parseFirefoxBlock(rec) {
70
72
  }
71
73
  const firefoxProduct = requireConfigString(firefoxRec, 'product', 'firefox.product');
72
74
  // Uses the shared guard rather than a fourth copy of the member list. This
73
- // is the fireforge.json READ path: a product added to the union but not to
75
+ // is the fireforge.json read path: a product added to the union but not to
74
76
  // the copy that used to live here would have been silently rejected from
75
77
  // every project config.
76
78
  if (!isValidFirefoxProduct(firefoxProduct)) {
@@ -85,6 +87,10 @@ function parseFirefoxBlock(rec) {
85
87
  if (firefoxSha256 !== undefined && !/^[a-f0-9]{64}$/i.test(firefoxSha256)) {
86
88
  throw new ConfigError('Config field "firefox.sha256" must be a 64-character SHA-256 hex digest');
87
89
  }
90
+ const allowUnverifiedDownload = firefoxRec.raw('allowUnverifiedDownload');
91
+ if (allowUnverifiedDownload !== undefined && typeof allowUnverifiedDownload !== 'boolean') {
92
+ throw new ConfigError('Config field "firefox.allowUnverifiedDownload" must be a boolean');
93
+ }
88
94
  const firefoxCandidate = optionalConfigString(firefoxRec, 'candidate', 'firefox.candidate');
89
95
  if (firefoxCandidate !== undefined && !isValidFirefoxCandidate(firefoxCandidate)) {
90
96
  throw new ConfigError('Config field "firefox.candidate" must look like "buildN" (e.g. "build2")');
@@ -93,6 +99,7 @@ function parseFirefoxBlock(rec) {
93
99
  version: firefoxVersion,
94
100
  product: firefoxProduct,
95
101
  ...(firefoxSha256 !== undefined ? { sha256: firefoxSha256.toLowerCase() } : {}),
102
+ ...(allowUnverifiedDownload !== undefined ? { allowUnverifiedDownload } : {}),
96
103
  ...(firefoxCandidate !== undefined ? { candidate: firefoxCandidate } : {}),
97
104
  };
98
105
  }
@@ -155,11 +162,15 @@ export function validateConfig(data) {
155
162
  const firefox = parseFirefoxBlock(rec);
156
163
  const config = { ...identity, firefox };
157
164
  parseBuildBlock(rec, config);
165
+ const buildAuditRaw = rec.raw('buildAudit');
166
+ if (buildAuditRaw !== undefined) {
167
+ config.buildAudit = parseBuildAuditConfig(buildAuditRaw);
168
+ }
158
169
  parseTestBlock(rec, config);
159
170
  parseExternalToolchainsBlock(rec, config);
160
171
  parseWireBlock(rec, config);
161
172
  parseLicenseField(rec, config);
162
- // Marker comment — appended to lines FireForge writes into upstream files.
173
+ // Marker comment, appended to lines FireForge writes into upstream files.
163
174
  const markerComment = parseMarkerComment(rec.raw('markerComment'));
164
175
  if (markerComment !== undefined) {
165
176
  config.markerComment = markerComment;
@@ -174,7 +185,7 @@ export function validateConfig(data) {
174
185
  if (patchPolicyRec) {
175
186
  config.patchPolicy = parsePatchPolicyBlock(patchPolicyRec);
176
187
  }
177
- // Typecheck (top-level, distinct from patchLint — see TypecheckConfig docs).
188
+ // Typecheck (top-level, distinct from patchLint). See TypecheckConfig docs.
178
189
  const typecheckRec = optionalConfigObject(rec, 'typecheck');
179
190
  if (typecheckRec) {
180
191
  config.typecheck = parseTypecheckBlock(typecheckRec);
@@ -389,10 +400,9 @@ function parsePatchLintBlock(rec) {
389
400
  * file. Shared between `patchLint.checkJsExtraShim` and
390
401
  * `typecheck.extraShim` so both fields reject the same absolute-path /
391
402
  * traversal / empty-string inputs with consistent error messages. The
392
- * file's existence is intentionally not checked here — that lives at
393
- * the engine layer where a missing file produces a typed runtime error
394
- * pointing at the actual command, rather than blocking config reads
395
- * for unrelated commands.
403
+ * file's existence is not checked here. That lives at the engine layer,
404
+ * where a missing file produces a typed runtime error pointing at the
405
+ * actual command, rather than blocking config reads for unrelated commands.
396
406
  */
397
407
  function parseShimPath(raw, label) {
398
408
  if (typeof raw !== 'string' || raw.trim() === '') {
@@ -406,7 +416,7 @@ function parseShimPath(raw, label) {
406
416
  /**
407
417
  * Validates the optional top-level `typecheck` block. Empty `projects`
408
418
  * is rejected because a silent no-op for `fireforge typecheck` is a
409
- * footgun — operators set the block expecting it to do something. Each
419
+ * footgun, since operators set the block expecting it to do something. Each
410
420
  * project path must be a contained relative path so `--project` / CLI
411
421
  * scripts can't escape the project root.
412
422
  */
@@ -425,10 +435,10 @@ function parseTypecheckBlock(rec) {
425
435
  for (let i = 0; i < projectsRaw.length; i++) {
426
436
  const entry = projectsRaw[i];
427
437
  if (typeof entry !== 'string' || entry.trim() === '') {
428
- throw new ConfigError(`Config field "typecheck.projects[${String(i)}]" must be a non-empty string`);
438
+ throw new ConfigError(`Config field "typecheck.projects[${i}]" must be a non-empty string`);
429
439
  }
430
440
  if (!isContainedRelativePath(entry)) {
431
- throw new ConfigError(`Config field "typecheck.projects[${String(i)}]" must be a project-relative path`);
441
+ throw new ConfigError(`Config field "typecheck.projects[${i}]" must be a project-relative path`);
432
442
  }
433
443
  projects.push(entry);
434
444
  }
@@ -1,17 +1,17 @@
1
1
  /**
2
- * Project configuration — barrel module.
2
+ * Project configuration barrel module.
3
3
  *
4
4
  * Re-exports from focused sub-modules:
5
- * config-paths.ts — constants and project path derivation
6
- * config-validate.ts — fireforge.json schema validation
7
- * config-mutate.ts — immutable config mutation
8
- * config-state.ts — state file management
5
+ * config-paths.ts: constants and project path derivation
6
+ * config-validate.ts: fireforge.json schema validation
7
+ * config-mutate.ts: immutable config mutation
8
+ * config-state.ts: state file management
9
9
  */
10
10
  import type { FireForgeConfig } from '../types/config.js';
11
11
  import type { JsonObject } from '../types/json.js';
12
12
  export { mutateConfig } from './config-mutate.js';
13
- export { CONFIG_FILENAME, FIREFORGE_DIR, getProjectPaths, STATE_FILENAME, SUPPORTED_CONFIG_PATHS, SUPPORTED_CONFIG_ROOT_KEYS, } from './config-paths.js';
14
- export { loadState, saveState, updateState } from './config-state.js';
13
+ export { FIREFORGE_DIR, getProjectPaths, SUPPORTED_CONFIG_PATHS, SUPPORTED_CONFIG_ROOT_KEYS, } from './config-paths.js';
14
+ export { loadState, updateState } from './config-state.js';
15
15
  export { validateConfig } from './config-validate.js';
16
16
  /**
17
17
  * Checks if a fireforge.json exists in the given directory.
@@ -28,12 +28,12 @@ export declare function configExists(root: string): Promise<boolean>;
28
28
  export declare function loadConfig(root: string): Promise<FireForgeConfig>;
29
29
  /**
30
30
  * Reads the raw `fireforge.json` document without running it through
31
- * {@link validateConfig}. Returns every persisted key — including keys
31
+ * {@link validateConfig}. Returns every persisted key, including keys
32
32
  * written via `fireforge config <key> --force` that `validateConfig`
33
33
  * would strip from the typed result.
34
34
  *
35
35
  * Callers that need the validated, typed shape must still use
36
- * {@link loadConfig}; this helper exists specifically for the `config`
36
+ * {@link loadConfig}. This helper exists specifically for the `config`
37
37
  * read path so `fireforge config <key>` can surface keys the write path
38
38
  * accepted under `--force`.
39
39
  *
@@ -67,9 +67,9 @@ export declare function writeConfigDocument(root: string, config: FireForgeConfi
67
67
  * Runs an operation while holding a sidecar lock on `fireforge.json`.
68
68
  *
69
69
  * Two concurrent `fireforge config <key> <value>` invocations each run
70
- * load → mutate → writeJson against the same document; without this lock the
71
- * second rename lands after the first and silently drops the first writer's
72
- * key, with both commands exiting 0.
70
+ * load → mutate → writeJson against the same document. Without this lock
71
+ * the second rename lands after the first and silently drops the first
72
+ * writer's key, with both commands exiting 0.
73
73
  *
74
74
  * Reads (`loadConfig`, `loadRawConfigDocument`) stay lock-free: writers
75
75
  * always use `writeJson`'s atomic temp-file + rename, so a reader observes