@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
@@ -17,8 +17,8 @@ import { stripEnginePrefix } from '../utils/paths.js';
17
17
  */
18
18
  export async function registerCommand(projectRoot, filePath, options = {}) {
19
19
  intro('Register');
20
- // --after is matched as a substring against existing manifest lines;
21
- // guard against control characters / line terminators that would either
20
+ // --after is matched as a substring against existing manifest lines.
21
+ // Guard against control characters / line terminators that would either
22
22
  // break the match logic or, worse, inject a second line if the value
23
23
  // is ever echoed back to a manifest writer. Null bytes are explicitly
24
24
  // rejected to mirror the hardening already applied to other user-
@@ -31,7 +31,7 @@ export async function registerCommand(projectRoot, filePath, options = {}) {
31
31
  }
32
32
  }
33
33
  // Accept either repo-root-relative (`engine/browser/...`) or
34
- // engine-relative (`browser/...`) inputs — operators frequently paste
34
+ // engine-relative (`browser/...`) inputs. Operators frequently paste
35
35
  // the former from the output of tab completion or `git status`, and
36
36
  // the mismatch used to produce a "File not found" error that named
37
37
  // the original path with no hint that dropping `engine/` would fix it.
@@ -49,8 +49,8 @@ export async function registerCommand(projectRoot, filePath, options = {}) {
49
49
  });
50
50
  if (options.dryRun) {
51
51
  // Dry-run must surface the idempotency decision too. Always saying
52
- // "Would register" — even when the rule already knows the entry is
53
- // present — makes automation read the plan as "work to do" while the
52
+ // "Would register", even when the rule already knows the entry is
53
+ // present, makes automation read the plan as "work to do" while the
54
54
  // following real run reports "Already registered".
55
55
  if (result.skipped) {
56
56
  info(`[dry-run] Already registered: ${engineRelativePath} in ${result.manifest}`);
@@ -70,7 +70,7 @@ export async function resetCommand(projectRoot, options) {
70
70
  await clearAppliedFurnaceState(projectRoot);
71
71
  s.stop('Changes reset');
72
72
  // The reset may have moved components.conf away from what the last full
73
- // build compiled in — surface that now instead of at the next test
73
+ // build compiled in, so surface that now instead of at the next test
74
74
  // refusal.
75
75
  await warnIfStaticComponentsStale(projectRoot, paths.engine);
76
76
  outro('Working tree restored to clean state');
@@ -15,7 +15,7 @@ export interface ResolveCommandOptions {
15
15
  * and the command proceeds straight to the patch-refresh + state-clear
16
16
  * path.
17
17
  *
18
- * The guard without `--yes` is preserved — running `resolve` with no TTY
18
+ * The guard without `--yes` is preserved: running `resolve` with no TTY
19
19
  * and no `--yes` still refuses, so an accidental pipe-into invocation does
20
20
  * not silently commit whatever the engine happens to contain.
21
21
  */
@@ -29,7 +29,7 @@ export interface ResolveCommandOptions {
29
29
  /**
30
30
  * Runs the resolve command to fix broken patches.
31
31
  * @param projectRoot - Root directory of the project
32
- * @param options - Optional flags; see {@link ResolveCommandOptions}.
32
+ * @param options - Optional flags. See {@link ResolveCommandOptions}.
33
33
  */
34
34
  export declare function resolveCommand(projectRoot: string, options?: ResolveCommandOptions): Promise<void>;
35
35
  /** Registers the resolve command on the CLI program. */
@@ -2,7 +2,7 @@
2
2
  import { join } from 'node:path';
3
3
  import { confirm } from '@clack/prompts';
4
4
  import { Command } from 'commander';
5
- import { getProjectPaths, loadConfig, loadState, updateState } from '../core/config.js';
5
+ import { getProjectPaths, loadConfig, loadState } from '../core/config.js';
6
6
  import { stdioIsInteractive } from '../core/destructive.js';
7
7
  import { assertEngineGitReady } from '../core/engine-precondition.js';
8
8
  import { getStagedDiffForFiles } from '../core/git-diff.js';
@@ -16,10 +16,11 @@ import { toError } from '../utils/errors.js';
16
16
  import { pathExists } from '../utils/fs.js';
17
17
  import { error as logError, info, intro, isCancel, outro, spinner, success, } from '../utils/logger.js';
18
18
  import { addWaitLockOption, resolveWaitLockSeconds } from '../utils/options.js';
19
+ import { clearPendingResolution } from './pending-resolution.js';
19
20
  /**
20
21
  * Runs the resolve command to fix broken patches.
21
22
  * @param projectRoot - Root directory of the project
22
- * @param options - Optional flags; see {@link ResolveCommandOptions}.
23
+ * @param options - Optional flags. See {@link ResolveCommandOptions}.
23
24
  */
24
25
  export async function resolveCommand(projectRoot, options = {}) {
25
26
  intro('FireForge Resolve');
@@ -36,7 +37,7 @@ export async function resolveCommand(projectRoot, options = {}) {
36
37
  // Non-interactive mode requires an explicit `--yes`: the operator is
37
38
  // asserting the manual merge is complete and the refreshed diff is the one
38
39
  // to record. Without it, an accidental pipe or CI shell could commit
39
- // whatever the engine currently contains — but an unconditional TTY
40
+ // whatever the engine currently contains, but an unconditional TTY
40
41
  // refusal dead-ends a scripted recovery flow.
41
42
  if (!stdioIsInteractive() && !options.yes) {
42
43
  throw new GeneralError('Cannot run "fireforge resolve" in non-interactive mode. Use a terminal with TTY support, or pass "--yes" to skip the interactive confirmation once the manual merge is complete.');
@@ -63,7 +64,7 @@ export async function resolveCommand(projectRoot, options = {}) {
63
64
  // Refuse to proceed if the patch file was deleted between the conflict
64
65
  // and the resolve. Without this check, `updatePatchAndMetadata` would
65
66
  // throw a less actionable "patch file is missing" error from inside
66
- // the lock; the explicit precondition lets us point the user at the
67
+ // the lock. The explicit precondition lets us point the user at the
67
68
  // exact recovery path.
68
69
  const patchPath = join(paths.patches, patchFilename);
69
70
  if (!(await pathExists(patchPath))) {
@@ -123,20 +124,27 @@ export async function resolveCommand(projectRoot, options = {}) {
123
124
  // here keeps resolve in agreement with every other writer.
124
125
  const diffFilesAffected = extractAffectedFiles(diffContent);
125
126
  const config = await loadConfig(projectRoot);
126
- await updatePatchAndMetadata(paths.patches, patchFilename, diffContent, {
127
- filesAffected: diffFilesAffected,
128
- ...buildPatchSourceMetadata(config.firefox),
129
- }, undefined, undefined, { waitLockSeconds: resolveWaitLockSeconds(options.waitLock), command: 'resolve' });
127
+ await updatePatchAndMetadata({
128
+ patchesDir: paths.patches,
129
+ filename: patchFilename,
130
+ newContent: diffContent,
131
+ updates: {
132
+ filesAffected: diffFilesAffected,
133
+ ...buildPatchSourceMetadata(config.firefox),
134
+ },
135
+ onCommitted: undefined,
136
+ policyGate: undefined,
137
+ lockOptions: {
138
+ waitLockSeconds: resolveWaitLockSeconds(options.waitLock),
139
+ command: 'resolve',
140
+ },
141
+ });
130
142
  // Clear pendingResolution from state.json transactionally so a
131
143
  // concurrent update to unrelated keys (another command writing buildMode
132
144
  // or baseCommit between our load and save) is not clobbered. The updater
133
145
  // runs inside the state-file lock with the freshest on-disk state, so
134
146
  // only pendingResolution is affected.
135
- await updateState(projectRoot, (current) => {
136
- const next = { ...current };
137
- delete next.pendingResolution;
138
- return next;
139
- });
147
+ await clearPendingResolution(projectRoot);
140
148
  s.stop(`Updated ${patchFilename}`);
141
149
  success('Patch updated successfully and resolution state cleared.');
142
150
  info('Patch updated. Run "fireforge import" next to resume the queue from this point — resolve only refreshes the one broken patch, it does not continue applying the remaining patches itself.');
@@ -1,19 +1,6 @@
1
1
  import { Command } from 'commander';
2
2
  import type { CommandContext } from '../types/cli.js';
3
3
  import type { RunOptions } from '../types/commands/index.js';
4
- /**
5
- * Exit code returned by smoke-run mode when the captured console stream
6
- * produced one or more error lines that did NOT match the operator's
7
- * allowlist.
8
- */
9
- export declare const SMOKE_EXIT_FAILURE: 12;
10
- /**
11
- * Exit code returned by smoke-run mode when the browser itself exited
12
- * with a non-clean status before the smoke window elapsed — i.e. a
13
- * launch-side failure we could NOT observe as a console error line
14
- * (crash before console wiring, missing profile, etc.).
15
- */
16
- export declare const SMOKE_LAUNCH_FAILURE: 13;
17
4
  /**
18
5
  * Runs the run command to launch the built browser.
19
6
  * @param projectRoot - Root directory of the project
@@ -17,19 +17,6 @@ import { toError } from '../utils/errors.js';
17
17
  import { pathExists, removeDir, removeFile } from '../utils/fs.js';
18
18
  import { info, intro, verbose, warn } from '../utils/logger.js';
19
19
  import { commanderArgParser, pickDefined, stringListOption } from '../utils/options.js';
20
- /**
21
- * Exit code returned by smoke-run mode when the captured console stream
22
- * produced one or more error lines that did NOT match the operator's
23
- * allowlist.
24
- */
25
- export const SMOKE_EXIT_FAILURE = ExitCode.SMOKE_EXIT_FAILURE;
26
- /**
27
- * Exit code returned by smoke-run mode when the browser itself exited
28
- * with a non-clean status before the smoke window elapsed — i.e. a
29
- * launch-side failure we could NOT observe as a console error line
30
- * (crash before console wiring, missing profile, etc.).
31
- */
32
- export const SMOKE_LAUNCH_FAILURE = ExitCode.SMOKE_LAUNCH_FAILURE;
33
20
  /** Recommendation surfaced when the smoke window is shorter than a typical cold start. */
34
21
  const SMOKE_COLD_START_THRESHOLD_MS = 30_000;
35
22
  /** Maximum number of unallowed error lines to surface in the terminal summary. */
@@ -38,10 +25,10 @@ const SMOKE_UNALLOWED_PREVIEW_MAX = 10;
38
25
  * Cleans the dev profile to prevent stale-state startup failures.
39
26
  *
40
27
  * Removes two things:
41
- * 1. **startupCache/** — Firefox caches compiled chrome JS bytecode here.
28
+ * 1. `startupCache/`: Firefox caches compiled chrome JS bytecode here.
42
29
  * When chrome scripts change between builds, the stale cache causes silent
43
30
  * crashes on startup.
44
- * 2. **.parentlock** — A zero-byte lock file that persists if the previous
31
+ * 2. `.parentlock`: a zero-byte lock file that persists if the previous
45
32
  * session was killed (Ctrl-C, crash, `kill`). Firefox checks this on
46
33
  * startup and silently exits if it exists, assuming another instance owns
47
34
  * the profile.
@@ -87,13 +74,13 @@ export async function runCommand(projectRoot, options = {}) {
87
74
  remediation: "Run 'fireforge build' first, then rerun 'fireforge run'.",
88
75
  requireExisting: true,
89
76
  });
90
- // `hasBuildArtifacts` only checks for an `obj-*/dist/` directory; a build
77
+ // `hasBuildArtifacts` only checks for an `obj-*/dist/` directory. A build
91
78
  // that configured but has not yet produced the launchable binary passes
92
79
  // that check, and `mach run` then fails on the missing binary path.
93
80
  // `hasRunnableBundle` narrows the probe to the actual executable so
94
81
  // `fireforge run` refuses with a targeted message before handing control
95
82
  // to mach. `fireforge watch` stays permissive and surfaces the same
96
- // information as a banner suffix; watch exists to drive rebuilds of
83
+ // information as a banner suffix. Watch exists to drive rebuilds of
97
84
  // partially-built trees, so blocking there would defeat it.
98
85
  if (buildCheck.objDir) {
99
86
  const config = await loadConfig(projectRoot);
@@ -117,12 +104,12 @@ export async function runCommand(projectRoot, options = {}) {
117
104
  info('Launching browser...\n');
118
105
  const exitCode = await run(paths.engine, options.headless ? ['--headless'] : []);
119
106
  // Exit-code whitelist:
120
- // 0 — clean shutdown
121
- // 130 — SIGINT (Ctrl+C), user-initiated termination
122
- // 143 — SIGTERM, graceful-shutdown termination
123
- // SIGKILL (137) and other signal-induced codes are intentionally NOT
124
- // whitelisted: those indicate abnormal termination the operator should
125
- // see surface as a build-time error.
107
+ // 0: clean shutdown
108
+ // 130: SIGINT (Ctrl+C), user-initiated termination
109
+ // 143: SIGTERM, graceful-shutdown termination
110
+ // SIGKILL (137) and other signal-induced codes are not whitelisted: those
111
+ // indicate abnormal termination the operator should see surface as a
112
+ // build-time error.
126
113
  if (exitCode !== 0 && exitCode !== 130 && exitCode !== 143) {
127
114
  throw new BuildError(`Browser exited with code ${exitCode}`, 'mach run');
128
115
  }
@@ -154,10 +141,10 @@ async function runSmokeExit(engineDir, options) {
154
141
  }
155
142
  const smokeTimeoutMs = smokeExit * 1000;
156
143
  if (smokeTimeoutMs < SMOKE_COLD_START_THRESHOLD_MS) {
157
- // Not an error — cold starts just tend to exceed the window. Surfacing
144
+ // Not an error. Cold starts just tend to exceed the window. Surfacing
158
145
  // the hint here instead of failing lets agents run shorter windows
159
146
  // intentionally (e.g. warm-cache smoke checks).
160
- verbose(`Smoke window is ${String(smokeExit)}s; cold starts on slow machines often exceed 30s.`);
147
+ verbose(`Smoke window is ${smokeExit}s; cold starts on slow machines often exceed 30s.`);
161
148
  }
162
149
  const allowlist = await buildAllowlist(options);
163
150
  const captureStream = options.captureConsole
@@ -166,9 +153,9 @@ async function runSmokeExit(engineDir, options) {
166
153
  // createWriteStream opens the fd asynchronously, so ENOENT / EACCES /
167
154
  // EISDIR / EROFS surface as an 'error' event *after* the constructor
168
155
  // returns. Without a listener Node re-throws as uncaughtException and
169
- // kills the CLI mid-smoke-run — orphaning the mach → python → firefox
156
+ // kills the CLI mid-smoke-run, orphaning the mach → python → firefox
170
157
  // tree because the deadline timer never fires. Swallow the event into a
171
- // warning so the smoke run still terminates cleanly; subsequent mirror
158
+ // warning so the smoke run still terminates cleanly. Subsequent mirror
172
159
  // writes on the errored stream are silent no-ops.
173
160
  captureStream?.on('error', (err) => {
174
161
  warn(`--capture-console stream error: ${err.message}`);
@@ -184,10 +171,10 @@ async function runSmokeExit(engineDir, options) {
184
171
  const sink = stream === 'stdout' ? process.stdout : process.stderr;
185
172
  sink.write(`${line}\n`);
186
173
  // Count allowlist hits up-front, regardless of error-pattern match.
187
- // Incrementing only when the line ALSO matches an error pattern makes an
174
+ // Incrementing only when the line also matches an error pattern makes an
188
175
  // allowlist regex that visibly matches `console.warn: RSLoader:` report 0
189
- // hits, because `console.warn:` is not a smoke error class — confusing
190
- // for operators tuning their allowlist. Two numbers are surfaced: the
176
+ // hits, because `console.warn:` is not a smoke error class, which
177
+ // confuses operators tuning their allowlist. Two numbers are surfaced: the
191
178
  // total set of allowlisted lines (what the operator sees in the console)
192
179
  // and the subset that were error-class (what the smoke exit contract
193
180
  // cares about). The exit contract itself is unchanged.
@@ -206,8 +193,8 @@ async function runSmokeExit(engineDir, options) {
206
193
  findings.push({ stream, line });
207
194
  };
208
195
  // A headed smoke window on a developer desktop absorbs live input: a human
209
- // interacting with the window mid-run can trigger console errors — a
210
- // password-manager import scan probing an unreadable profile dir, say —
196
+ // interacting with the window mid-run can trigger console errors (a
197
+ // password-manager import scan probing an unreadable profile dir, say)
211
198
  // that fail the smoke run looking like a product regression. CI hosts (CI
212
199
  // env var set) are assumed display-free and unattended, so the notice
213
200
  // stays quiet there.
@@ -216,7 +203,7 @@ async function runSmokeExit(engineDir, options) {
216
203
  'console capture and can fail the run. Pass --headless (or run on an unattended host) ' +
217
204
  'for reliable smoke checks.');
218
205
  }
219
- info(`Launching browser (smoke-exit after ${String(smokeExit)}s)...\n`);
206
+ info(`Launching browser (smoke-exit after ${smokeExit}s)...\n`);
220
207
  const startedAt = Date.now();
221
208
  let result;
222
209
  try {
@@ -248,22 +235,22 @@ async function runSmokeExit(engineDir, options) {
248
235
  });
249
236
  // Exit contract (precedence: unallowed errors dominate timed-out).
250
237
  if (findings.length > 0) {
251
- throw new SmokeRunError(`Smoke run observed ${String(findings.length)} unallowed console error(s).`, SMOKE_EXIT_FAILURE);
238
+ throw new SmokeRunError(`Smoke run observed ${findings.length} unallowed console error(s).`, ExitCode.SMOKE_EXIT_FAILURE);
252
239
  }
253
240
  if (result.timedOut) {
254
- // Clean window — SIGTERM from us. Treat as success.
241
+ // Clean window: SIGTERM came from us. Treat as success.
255
242
  return;
256
243
  }
257
244
  if (result.exitCode === 0 || result.exitCode === 130 || result.exitCode === 143) {
258
245
  return;
259
246
  }
260
- throw new SmokeRunError(`Browser exited with code ${String(result.exitCode)} before smoke-exit window elapsed.`, SMOKE_LAUNCH_FAILURE);
247
+ throw new SmokeRunError(`Browser exited with code ${result.exitCode} before smoke-exit window elapsed.`, ExitCode.SMOKE_LAUNCH_FAILURE);
261
248
  }
262
249
  /**
263
250
  * Compiles the active allowlist from `--console-allow` CLI values and
264
- * the optional `--console-allow-file`. Fails fast on a bad regex —
265
- * better to surface the typo at parse time than to silently let it
266
- * match nothing and turn every allowed hit into a smoke failure.
251
+ * the optional `--console-allow-file`. Fails fast on a bad regex, so the
252
+ * typo surfaces at parse time instead of silently matching nothing and
253
+ * turning every allowed hit into a smoke failure.
267
254
  */
268
255
  async function buildAllowlist(options) {
269
256
  const allow = [];
@@ -298,36 +285,36 @@ function reportSmokeSummary(args) {
298
285
  const suffix = args.timedOut ? ' (deadline fired — SIGTERM sent to process group)' : '';
299
286
  info('');
300
287
  info(`Smoke run complete: ${seconds}s elapsed of ${windowSeconds}s window${suffix}`);
301
- info(` Unallowed errors: ${String(args.findings.length)}`);
302
- // The "suppressed errors" count is what the exit contract cares about — the
288
+ info(` Unallowed errors: ${args.findings.length}`);
289
+ // The "suppressed errors" count is what the exit contract cares about: the
303
290
  // subset of allowlisted hits that would otherwise have been tallied as
304
291
  // findings. The "all allowlisted lines" count answers the operator's mental
305
292
  // model ("my --console-allow pattern matched N console lines"), without
306
293
  // which a visibly matching regex reports 0 hits.
307
- info(` Allowlisted error hits (suppressed): ${String(args.allowlistedErrorHits)}`);
308
- info(` Allowlisted lines total: ${String(args.allowlistedTotalHits)}`);
309
- info(` Child exit code: ${String(args.exitCode)}`);
310
- // Per-entry attribution: first-match credit per line, with
311
- // zero-hit entries always visible — an allowlist entry whose suppressed
312
- // shape changed upstream is only detectable as a 0× row.
294
+ info(` Allowlisted error hits (suppressed): ${args.allowlistedErrorHits}`);
295
+ info(` Allowlisted lines total: ${args.allowlistedTotalHits}`);
296
+ info(` Child exit code: ${args.exitCode}`);
297
+ // Per-entry attribution: first-match credit per line, with zero-hit
298
+ // entries always visible, since an allowlist entry whose suppressed shape
299
+ // changed upstream is only detectable as a 0× row.
313
300
  if (args.allowlist.length > 0) {
314
301
  info(' Allowlist attribution (first matching entry per line):');
315
302
  args.allowlist.forEach((entry, index) => {
316
303
  const hits = args.allowlistHits[index] ?? 0;
317
304
  const zeroSuffix = hits === 0 ? ' (never matched — candidate for removal)' : '';
318
- info(` ${String(hits)}× ${entry.origin} ${entry.source}${zeroSuffix}`);
305
+ info(` ${hits}× ${entry.origin} ${entry.source}${zeroSuffix}`);
319
306
  });
320
307
  }
321
308
  if (args.findings.length === 0)
322
309
  return;
323
310
  warn('');
324
- warn(`Unallowed console errors (first ${String(SMOKE_UNALLOWED_PREVIEW_MAX)}):`);
311
+ warn(`Unallowed console errors (first ${SMOKE_UNALLOWED_PREVIEW_MAX}):`);
325
312
  args.findings.slice(0, SMOKE_UNALLOWED_PREVIEW_MAX).forEach((finding, index) => {
326
- warn(` ${String(index + 1)}. [${finding.stream}] ${finding.line}`);
313
+ warn(` ${index + 1}. [${finding.stream}] ${finding.line}`);
327
314
  });
328
315
  if (args.findings.length > SMOKE_UNALLOWED_PREVIEW_MAX) {
329
316
  const remaining = args.findings.length - SMOKE_UNALLOWED_PREVIEW_MAX;
330
- warn(` …and ${String(remaining)} more.`);
317
+ warn(` …and ${remaining} more.`);
331
318
  }
332
319
  }
333
320
  /** Registers the run command on the CLI program. */
@@ -9,10 +9,22 @@ export interface ResolvedSetupInputs {
9
9
  finalProduct: FirefoxProduct;
10
10
  finalLicense: ProjectLicense;
11
11
  }
12
- /** Parses an optional Firefox product flag into a typed product value. */
13
- export declare function parseFirefoxProductOption(product: string | undefined): FirefoxProduct | undefined;
14
- /** Parses an optional license flag into a validated SPDX identifier. */
15
- export declare function parseProjectLicenseOption(license: string | undefined): ProjectLicense | undefined;
12
+ /**
13
+ * Narrows a raw CLI or prompt value to a supported Firefox product.
14
+ * @param value - Raw value from `--product` or the setup prompt.
15
+ * @param field - Field name quoted in the refusal (e.g. `--product`).
16
+ * @returns The validated product.
17
+ * @throws {@link InvalidArgumentError} when the value names no supported product.
18
+ */
19
+ export declare function resolveFirefoxProduct(value: unknown, field: string): FirefoxProduct;
20
+ /**
21
+ * Narrows a raw CLI or prompt value to a supported SPDX licence identifier.
22
+ * @param value - Raw value from `--license` or the setup prompt.
23
+ * @param field - Field name quoted in the refusal (e.g. `--license`).
24
+ * @returns The validated licence identifier.
25
+ * @throws {@link InvalidArgumentError} when the value names no supported licence.
26
+ */
27
+ export declare function resolveProjectLicense(value: unknown, field: string): ProjectLicense;
16
28
  /** Validates non-interactive setup options before project scaffolding begins. */
17
29
  export declare function validateSetupOptions(options: SetupOptions): void;
18
30
  /** Resolves setup inputs from CLI flags and optional interactive prompts. */
@@ -18,35 +18,35 @@ function renderLicenseTemplate(license, template, vendor, now = new Date()) {
18
18
  }
19
19
  return template.replace(/\[year\]/g, String(now.getFullYear())).replace(/\[fullname\]/g, vendor);
20
20
  }
21
- function resolveFirefoxProduct(value, field) {
21
+ /**
22
+ * Narrows a raw CLI or prompt value to a supported Firefox product.
23
+ * @param value - Raw value from `--product` or the setup prompt.
24
+ * @param field - Field name quoted in the refusal (e.g. `--product`).
25
+ * @returns The validated product.
26
+ * @throws {@link InvalidArgumentError} when the value names no supported product.
27
+ */
28
+ export function resolveFirefoxProduct(value, field) {
22
29
  // Matches the sibling `resolveProjectLicense`, which already delegates to
23
- // its guard. The `||` chain this replaced spelled the member list twice —
30
+ // its guard. The `||` chain this replaced spelled the member list twice,
24
31
  // once as the predicate and once in the message.
25
32
  if (typeof value === 'string' && isValidFirefoxProduct(value)) {
26
33
  return value;
27
34
  }
28
35
  throw new InvalidArgumentError(`Invalid product (use: ${FIREFOX_PRODUCTS.join(', ')})`, field);
29
36
  }
30
- function resolveProjectLicense(value, field) {
37
+ /**
38
+ * Narrows a raw CLI or prompt value to a supported SPDX licence identifier.
39
+ * @param value - Raw value from `--license` or the setup prompt.
40
+ * @param field - Field name quoted in the refusal (e.g. `--license`).
41
+ * @returns The validated licence identifier.
42
+ * @throws {@link InvalidArgumentError} when the value names no supported licence.
43
+ */
44
+ export function resolveProjectLicense(value, field) {
31
45
  if (typeof value === 'string' && isValidProjectLicense(value)) {
32
46
  return value;
33
47
  }
34
48
  throw new InvalidArgumentError('Invalid license (use: EUPL-1.2, MPL-2.0, 0BSD, GPL-2.0-or-later)', field);
35
49
  }
36
- /** Parses an optional Firefox product flag into a typed product value. */
37
- export function parseFirefoxProductOption(product) {
38
- if (product === undefined) {
39
- return undefined;
40
- }
41
- return resolveFirefoxProduct(product, '--product');
42
- }
43
- /** Parses an optional license flag into a validated SPDX identifier. */
44
- export function parseProjectLicenseOption(license) {
45
- if (license === undefined) {
46
- return undefined;
47
- }
48
- return resolveProjectLicense(license, '--license');
49
- }
50
50
  /** Validates non-interactive setup options before project scaffolding begins. */
51
51
  export function validateSetupOptions(options) {
52
52
  if (options.name !== undefined) {
@@ -194,7 +194,7 @@ function finalizePromptedSetupInputs(project) {
194
194
  // Project names that contain no ASCII alphanumerics (e.g. "----", "漢字",
195
195
  // emoji-only) collapse to an empty sanitised slug, which would silently
196
196
  // produce an invalid `appId` ("org..browser") and an empty `binaryName`.
197
- // Refuse to derive defaults from such names — the user must supply
197
+ // Refuse to derive defaults from such names. The user must supply
198
198
  // explicit appId / binaryName values instead.
199
199
  const explicitAppId = typeof project.appId === 'string' ? project.appId.trim() : '';
200
200
  const explicitBinaryName = typeof project.binaryName === 'string' ? project.binaryName.trim() : '';
@@ -270,7 +270,7 @@ export function buildSetupConfig(inputs) {
270
270
  /**
271
271
  * Creates or updates the root `package.json` so its `license` field matches
272
272
  * the project license selected during setup. When the file already exists
273
- * ONLY the `license` field is touched — preserving `name`, `description`,
273
+ * only the `license` field is touched, preserving `name`, `description`,
274
274
  * `dependencies`, `scripts`, and every other author-editorial field. Without
275
275
  * this sync, a `fireforge setup --force` that picks a new license leaves the
276
276
  * old one in `package.json`, so the two files describe different projects.
@@ -296,7 +296,7 @@ async function syncRootPackageJson(projectRoot, license) {
296
296
  }
297
297
  catch {
298
298
  // Malformed package.json is the operator's editorial responsibility to
299
- // repair; rewriting it would risk clobbering hand-authored content that
299
+ // repair. Rewriting it would risk clobbering hand-authored content that
300
300
  // the parser happens to reject. Leave the file alone and rely on the
301
301
  // doctor / lint paths that already surface invalid JSON.
302
302
  return;
@@ -8,7 +8,7 @@ import { ConfigError } from '../errors/config.js';
8
8
  import { cancel, intro, isCancel, note, outro, spinner } from '../utils/logger.js';
9
9
  import { pickDefined } from '../utils/options.js';
10
10
  import { FIREFOX_PRODUCTS, PROJECT_LICENSES } from '../utils/validation.js';
11
- import { buildSetupConfig, parseFirefoxProductOption, parseProjectLicenseOption, resolveSetupInputs, validateSetupOptions, writeSetupProjectFiles, } from './setup-support.js';
11
+ import { buildSetupConfig, resolveFirefoxProduct, resolveProjectLicense, resolveSetupInputs, validateSetupOptions, writeSetupProjectFiles, } from './setup-support.js';
12
12
  /**
13
13
  * Runs the setup command.
14
14
  * @param projectRoot - Root directory for the project
@@ -73,7 +73,7 @@ export function registerSetup(program, { withErrorHandling }) {
73
73
  .option('-f, --force', 'Overwrite existing configuration without prompting')
74
74
  // `--yes` is a plain alias here: `setup`'s only bypass is the overwrite
75
75
  // prompt, so the two flags mean exactly the same thing. Seventeen other
76
- // commands spell this bypass `--yes`; accepting it means a scripted
76
+ // commands spell this bypass `--yes`. Accepting it means a scripted
77
77
  // sequence can use one spelling throughout.
78
78
  .option('-y, --yes', 'Alias for --force: skip the overwrite confirmation')
79
79
  .action(withErrorHandling(async (options) => {
@@ -83,16 +83,10 @@ export function registerSetup(program, { withErrorHandling }) {
83
83
  if (yes === true)
84
84
  setupOptions.force = true;
85
85
  if (product !== undefined) {
86
- const parsedProduct = parseFirefoxProductOption(product);
87
- if (parsedProduct !== undefined) {
88
- setupOptions.product = parsedProduct;
89
- }
86
+ setupOptions.product = resolveFirefoxProduct(product, '--product');
90
87
  }
91
88
  if (license !== undefined) {
92
- const parsedLicense = parseProjectLicenseOption(license);
93
- if (parsedLicense !== undefined) {
94
- setupOptions.license = parsedLicense;
95
- }
89
+ setupOptions.license = resolveProjectLicense(license, '--license');
96
90
  }
97
91
  await setupCommand(resolve(process.cwd()), setupOptions);
98
92
  }));
@@ -10,7 +10,7 @@ function cloneRawConfig(raw) {
10
10
  if (!isObject(cloned)) {
11
11
  throw new GeneralError('Cannot update fireforge.json: config clone was not an object.');
12
12
  }
13
- // A structured clone of a JSON document is itself a JSON document; the
13
+ // A structured clone of a JSON document is itself a JSON document. The
14
14
  // object check above is the only invariant left to establish.
15
15
  return cloned;
16
16
  }
@@ -87,7 +87,14 @@ export async function sourceSetCommand(projectRoot, options) {
87
87
  }
88
88
  /** Registers the source command on the CLI program. */
89
89
  export function registerSource(program, { getProjectRoot, withErrorHandling }) {
90
- const source = program.command('source').description('Manage Firefox source configuration');
90
+ const source = program
91
+ .command('source')
92
+ .description('Manage Firefox source configuration')
93
+ // No-subcommand contract shared with `patch`/`token`/`furnace`: help on
94
+ // stdout, exit 0 (see `handleParseError` for the groups without an action).
95
+ .action(() => {
96
+ source.outputHelp();
97
+ });
91
98
  source
92
99
  .command('set')
93
100
  .description('Atomically set Firefox source version, product, and optional checksum')
@@ -4,8 +4,8 @@
4
4
  * classification outside {patch-backed, branding, furnace}, and
5
5
  * `--fail-on <class,...>` replaces that set for finer control.
6
6
  *
7
- * Helper module consumed by status.ts (which sits at the max-lines budget);
8
- * no top-level registrar is exported and none is wanted.
7
+ * Helper module consumed by status.ts, which sits at the max-lines budget.
8
+ * No top-level registrar is exported and none is wanted.
9
9
  */
10
10
  import type { ClassifiedFile, FileClassification } from '../core/status-classify.js';
11
11
  /** Resolved `--check`/`--fail-on` policy for one status invocation. */
@@ -15,7 +15,7 @@ export interface StatusCheckPolicy {
15
15
  }
16
16
  /**
17
17
  * Resolves the enforcement policy from the raw flags: `--fail-on` implies
18
- * `--check` and replaces the default set; both are refused alongside the
18
+ * `--check` and replaces the default set. Both are refused alongside the
19
19
  * modes that skip (or elide) classification.
20
20
  */
21
21
  export declare function resolveStatusCheckPolicy(options: {
@@ -10,9 +10,9 @@ const ALL_CLASSIFICATIONS = [
10
10
  ];
11
11
  /**
12
12
  * Default `--check` policy: everything outside {patch-backed, branding,
13
- * furnace, binary-unsupported} fails. `binary-unsupported` is deliberately
14
- * excluded — an honest "cannot compare" must not keep the gate permanently
15
- * red; strict CI can opt in via `--fail-on binary-unsupported`.
13
+ * furnace, binary-unsupported} fails. `binary-unsupported` is excluded so
14
+ * an honest "cannot compare" does not keep the gate permanently red.
15
+ * Strict CI can opt in via `--fail-on binary-unsupported`.
16
16
  */
17
17
  const DEFAULT_FAIL_CLASSIFICATIONS = [
18
18
  'unmanaged',
@@ -21,7 +21,7 @@ const DEFAULT_FAIL_CLASSIFICATIONS = [
21
21
  ];
22
22
  /**
23
23
  * Resolves the enforcement policy from the raw flags: `--fail-on` implies
24
- * `--check` and replaces the default set; both are refused alongside the
24
+ * `--check` and replaces the default set. Both are refused alongside the
25
25
  * modes that skip (or elide) classification.
26
26
  */
27
27
  export function resolveStatusCheckPolicy(options) {
@@ -95,9 +95,9 @@ export function runStatusCheck(classified, policy) {
95
95
  const offending = collectStatusCheckOffenders(classified, policy).map((offender) => {
96
96
  const preview = offender.files.slice(0, CHECK_FILE_PREVIEW_MAX).join(', ');
97
97
  const more = offender.count > CHECK_FILE_PREVIEW_MAX
98
- ? `, +${String(offender.count - CHECK_FILE_PREVIEW_MAX)} more`
98
+ ? `, +${offender.count - CHECK_FILE_PREVIEW_MAX} more`
99
99
  : '';
100
- return `${String(offender.count)} ${offender.classification} (${preview}${more})`;
100
+ return `${offender.count} ${offender.classification} (${preview}${more})`;
101
101
  });
102
102
  if (offending.length === 0)
103
103
  return;
@@ -1,31 +1,32 @@
1
1
  /**
2
2
  * `status --json` payload rendering (schemaVersion 1). Helper module
3
- * consumed by status.ts (which sits at the max-lines budget); no top-level
3
+ * consumed by status.ts (which sits at the max-lines budget). No top-level
4
4
  * registrar is exported and none is wanted.
5
5
  *
6
6
  * Two shapes share one counting pass:
7
- * - the full payload (`renderJsonStatus`) with the per-file `files[]` list;
7
+ * - the full payload (`renderJsonStatus`) with the per-file `files[]` list,
8
8
  * - the `--summary` gate payload (`renderJsonSummaryStatus`), which omits
9
- * `files[]` entirely — engine-clean gates need the verdict, per-class
10
- * counts, and offender names, not a payload that grows with the queue
11
- * (175 KB+ on a large one).
9
+ * `files[]` entirely, because engine-clean gates need the verdict,
10
+ * per-class counts, and offender names, not a payload that grows with
11
+ * the queue (175 KB+ on a large one).
12
12
  */
13
13
  import type { ClassifiedFile } from '../core/status-classify.js';
14
14
  import { type StatusCheckPolicy } from './status-check.js';
15
15
  import type { OwnershipJsonBlock } from './status-ownership.js';
16
16
  /**
17
- * Full `--json` payload: summary plus the per-file `files[]` list, and —
18
- * under `--include-ownership` — the additive `ownership` block.
17
+ * Full `--json` payload: summary plus the per-file `files[]` list, and,
18
+ * under `--include-ownership`, the additive `ownership` block.
19
19
  * Additive within schemaVersion 1: a consumer that does not ask for the
20
20
  * block never sees the key.
21
21
  */
22
22
  export declare function renderJsonStatus(classified: readonly ClassifiedFile[], ownership?: OwnershipJsonBlock): void;
23
23
  /**
24
- * Summary-only `--json --summary` payload: counts always; when the
25
- * `--check`/`--fail-on` policy is active, a `check` block with the active
26
- * fail set, the verdict, and the offending files per fail-set
27
- * classification (sourced from the same collector as the human `--check`
28
- * message, so the two views can never disagree). The absent `files[]` is
29
- * the mode signal within schemaVersion 1 — consumers opt in via the flag.
24
+ * Summary-only `--json --summary` payload. Counts are always present. When
25
+ * the `--check`/`--fail-on` policy is active, the payload adds a `check`
26
+ * block with the active fail set, the verdict, and the offending files per
27
+ * fail-set classification (sourced from the same collector as the human
28
+ * `--check` message, so the two views can never disagree). The absent
29
+ * `files[]` is the mode signal within schemaVersion 1. Consumers opt in via
30
+ * the flag.
30
31
  */
31
32
  export declare function renderJsonSummaryStatus(classified: readonly ClassifiedFile[], policy: StatusCheckPolicy, ownership?: OwnershipJsonBlock): void;