@hominis/fireforge 0.43.1 → 0.44.0

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 (470) hide show
  1. package/CHANGELOG.md +126 -0
  2. package/README.md +10 -1
  3. package/dist/bin/fireforge.d.ts +4 -9
  4. package/dist/bin/fireforge.js +42 -40
  5. package/dist/build-info.json +4 -4
  6. package/dist/src/cli.js +74 -8
  7. package/dist/src/commands/bootstrap.js +17 -20
  8. package/dist/src/commands/build.js +25 -32
  9. package/dist/src/commands/config.js +34 -41
  10. package/dist/src/commands/discard.js +8 -9
  11. package/dist/src/commands/doctor-check-core.d.ts +4 -18
  12. package/dist/src/commands/doctor-check-core.js +8 -35
  13. package/dist/src/commands/doctor-external-toolchains.js +2 -2
  14. package/dist/src/commands/doctor-furnace-config-sync.d.ts +18 -0
  15. package/dist/src/commands/{doctor-furnace-manifest-sync.js → doctor-furnace-config-sync.js} +27 -26
  16. package/dist/src/commands/doctor-furnace-jar.d.ts +7 -9
  17. package/dist/src/commands/doctor-furnace-jar.js +7 -9
  18. package/dist/src/commands/doctor-furnace.js +21 -24
  19. package/dist/src/commands/doctor-orphaned-harness.d.ts +16 -20
  20. package/dist/src/commands/doctor-orphaned-harness.js +18 -44
  21. package/dist/src/commands/doctor-post-rebase-audit.d.ts +2 -0
  22. package/dist/src/commands/{doctor/post-rebase-audit.js → doctor-post-rebase-audit.js} +3 -3
  23. package/dist/src/commands/doctor-working-tree.d.ts +10 -12
  24. package/dist/src/commands/doctor-working-tree.js +11 -18
  25. package/dist/src/commands/doctor.js +35 -53
  26. package/dist/src/commands/download.js +32 -48
  27. package/dist/src/commands/export-all.js +29 -33
  28. package/dist/src/commands/export-flow.js +6 -6
  29. package/dist/src/commands/export-placement-conflicts.js +10 -9
  30. package/dist/src/commands/export-placement-gate.js +5 -5
  31. package/dist/src/commands/export-shared.d.ts +30 -33
  32. package/dist/src/commands/export-shared.js +45 -43
  33. package/dist/src/commands/export.js +21 -27
  34. package/dist/src/commands/furnace/apply.js +14 -23
  35. package/dist/src/commands/furnace/chrome-doc-remove.js +14 -21
  36. package/dist/src/commands/furnace/chrome-doc-templates.d.ts +23 -23
  37. package/dist/src/commands/furnace/chrome-doc-templates.js +23 -23
  38. package/dist/src/commands/furnace/chrome-doc-tests.js +26 -29
  39. package/dist/src/commands/furnace/chrome-doc.d.ts +16 -17
  40. package/dist/src/commands/furnace/chrome-doc.js +31 -41
  41. package/dist/src/commands/furnace/create-browser-test.d.ts +4 -4
  42. package/dist/src/commands/furnace/create-browser-test.js +8 -8
  43. package/dist/src/commands/furnace/create-mochikit.d.ts +6 -7
  44. package/dist/src/commands/furnace/create-mochikit.js +8 -9
  45. package/dist/src/commands/furnace/create-readback.d.ts +12 -13
  46. package/dist/src/commands/furnace/create-readback.js +12 -13
  47. package/dist/src/commands/furnace/create-templates.d.ts +22 -28
  48. package/dist/src/commands/furnace/create-templates.js +35 -30
  49. package/dist/src/commands/furnace/create-xpcshell.js +2 -2
  50. package/dist/src/commands/furnace/create.js +33 -23
  51. package/dist/src/commands/furnace/deploy.js +16 -24
  52. package/dist/src/commands/furnace/diff.js +9 -9
  53. package/dist/src/commands/furnace/init.js +33 -36
  54. package/dist/src/commands/furnace/override.js +23 -25
  55. package/dist/src/commands/furnace/preview.js +47 -67
  56. package/dist/src/commands/furnace/refresh.js +12 -16
  57. package/dist/src/commands/furnace/remove-mutations.d.ts +3 -6
  58. package/dist/src/commands/furnace/remove-mutations.js +9 -16
  59. package/dist/src/commands/furnace/remove-state.js +1 -1
  60. package/dist/src/commands/furnace/remove.js +33 -38
  61. package/dist/src/commands/furnace/rename-xpcshell.d.ts +8 -11
  62. package/dist/src/commands/furnace/rename-xpcshell.js +8 -11
  63. package/dist/src/commands/furnace/rename.js +59 -69
  64. package/dist/src/commands/furnace/scan.js +19 -33
  65. package/dist/src/commands/furnace/status.js +12 -9
  66. package/dist/src/commands/furnace/sync.js +9 -16
  67. package/dist/src/commands/furnace/validate.js +20 -20
  68. package/dist/src/commands/import.js +42 -35
  69. package/dist/src/commands/lint-per-patch.js +15 -10
  70. package/dist/src/commands/lint-per-run-checkjs.d.ts +13 -13
  71. package/dist/src/commands/lint-per-run-checkjs.js +13 -13
  72. package/dist/src/commands/lint-report.js +6 -7
  73. package/dist/src/commands/lint.d.ts +15 -16
  74. package/dist/src/commands/lint.js +86 -102
  75. package/dist/src/commands/package.js +6 -11
  76. package/dist/src/commands/patch/compact.js +1 -1
  77. package/dist/src/commands/patch/delete.js +24 -33
  78. package/dist/src/commands/patch/index.d.ts +5 -6
  79. package/dist/src/commands/patch/index.js +10 -12
  80. package/dist/src/commands/patch/lint-ignore.js +14 -13
  81. package/dist/src/commands/patch/move-files-create.d.ts +6 -6
  82. package/dist/src/commands/patch/move-files-create.js +8 -8
  83. package/dist/src/commands/patch/move-files-into.d.ts +6 -6
  84. package/dist/src/commands/patch/move-files-into.js +8 -8
  85. package/dist/src/commands/patch/patch-context.d.ts +2 -3
  86. package/dist/src/commands/patch/patch-context.js +2 -3
  87. package/dist/src/commands/patch/rename.d.ts +10 -11
  88. package/dist/src/commands/patch/rename.js +11 -12
  89. package/dist/src/commands/patch/reorder.js +8 -9
  90. package/dist/src/commands/patch/split-plan.js +1 -1
  91. package/dist/src/commands/patch/split.d.ts +8 -10
  92. package/dist/src/commands/patch/split.js +9 -11
  93. package/dist/src/commands/patch/staged-dependency-validate.js +8 -8
  94. package/dist/src/commands/patch/staged-dependency.js +7 -3
  95. package/dist/src/commands/patch/tier.d.ts +9 -9
  96. package/dist/src/commands/patch/tier.js +18 -15
  97. package/dist/src/commands/re-export-adjacent.js +9 -8
  98. package/dist/src/commands/re-export-bulk-scan.d.ts +9 -9
  99. package/dist/src/commands/re-export-bulk-scan.js +22 -21
  100. package/dist/src/commands/re-export-drift.js +10 -10
  101. package/dist/src/commands/re-export-files.d.ts +6 -7
  102. package/dist/src/commands/re-export-files.js +34 -44
  103. package/dist/src/commands/re-export-lint.d.ts +10 -13
  104. package/dist/src/commands/re-export-lint.js +16 -14
  105. package/dist/src/commands/re-export-options.d.ts +6 -6
  106. package/dist/src/commands/re-export-options.js +6 -6
  107. package/dist/src/commands/re-export-register.d.ts +4 -10
  108. package/dist/src/commands/re-export-register.js +5 -11
  109. package/dist/src/commands/re-export-scan.js +1 -1
  110. package/dist/src/commands/re-export-single.d.ts +3 -3
  111. package/dist/src/commands/re-export-single.js +33 -25
  112. package/dist/src/commands/re-export.js +13 -21
  113. package/dist/src/commands/rebase/abort.js +3 -3
  114. package/dist/src/commands/rebase/confirm.js +2 -1
  115. package/dist/src/commands/rebase/continue.d.ts +1 -1
  116. package/dist/src/commands/rebase/continue.js +14 -9
  117. package/dist/src/commands/rebase/index.js +11 -11
  118. package/dist/src/commands/rebase/patch-loop.d.ts +7 -1
  119. package/dist/src/commands/rebase/patch-loop.js +60 -39
  120. package/dist/src/commands/rebase/summary.js +1 -1
  121. package/dist/src/commands/register.js +5 -7
  122. package/dist/src/commands/reset.js +2 -1
  123. package/dist/src/commands/resolve.d.ts +16 -13
  124. package/dist/src/commands/resolve.js +30 -33
  125. package/dist/src/commands/run.js +33 -35
  126. package/dist/src/commands/setup-support.js +15 -19
  127. package/dist/src/commands/setup.js +13 -9
  128. package/dist/src/commands/status-check.d.ts +6 -6
  129. package/dist/src/commands/status-json.d.ts +6 -6
  130. package/dist/src/commands/status-json.js +5 -0
  131. package/dist/src/commands/status-output.d.ts +5 -5
  132. package/dist/src/commands/status-output.js +6 -6
  133. package/dist/src/commands/status-ownership.d.ts +16 -14
  134. package/dist/src/commands/status-ownership.js +16 -14
  135. package/dist/src/commands/status.js +42 -34
  136. package/dist/src/commands/test-build-phase.js +26 -13
  137. package/dist/src/commands/test-diagnose.js +44 -44
  138. package/dist/src/commands/test-register.js +1 -0
  139. package/dist/src/commands/test-run.d.ts +14 -16
  140. package/dist/src/commands/test-run.js +21 -13
  141. package/dist/src/commands/test-stale-gate.d.ts +15 -16
  142. package/dist/src/commands/test-stale-gate.js +15 -16
  143. package/dist/src/commands/test-verdict.d.ts +20 -3
  144. package/dist/src/commands/test-verdict.js +30 -0
  145. package/dist/src/commands/test.js +83 -76
  146. package/dist/src/commands/token-coverage.js +3 -4
  147. package/dist/src/commands/token.js +16 -18
  148. package/dist/src/commands/tree.js +47 -31
  149. package/dist/src/commands/typecheck.d.ts +10 -12
  150. package/dist/src/commands/typecheck.js +24 -27
  151. package/dist/src/commands/verify.js +13 -15
  152. package/dist/src/commands/watch.js +21 -23
  153. package/dist/src/commands/wire.js +52 -62
  154. package/dist/src/core/ast-utils.d.ts +8 -7
  155. package/dist/src/core/ast-utils.js +8 -7
  156. package/dist/src/core/branding.d.ts +9 -14
  157. package/dist/src/core/branding.js +7 -11
  158. package/dist/src/core/browser-wire.d.ts +1 -1
  159. package/dist/src/core/browser-wire.js +14 -19
  160. package/dist/src/core/build-audit-platform.js +25 -33
  161. package/dist/src/core/build-audit-registration.js +17 -25
  162. package/dist/src/core/build-audit-resolve.d.ts +15 -17
  163. package/dist/src/core/build-audit-resolve.js +27 -33
  164. package/dist/src/core/build-audit-transforms.js +18 -19
  165. package/dist/src/core/build-audit.js +28 -42
  166. package/dist/src/core/build-baseline-types.d.ts +29 -35
  167. package/dist/src/core/build-baseline.d.ts +5 -4
  168. package/dist/src/core/build-baseline.js +14 -14
  169. package/dist/src/core/build-overwrite-guard.d.ts +7 -14
  170. package/dist/src/core/build-overwrite-guard.js +17 -27
  171. package/dist/src/core/build-prepare.d.ts +2 -2
  172. package/dist/src/core/build-prepare.js +8 -9
  173. package/dist/src/core/config-state.js +12 -4
  174. package/dist/src/core/config-validate.js +8 -5
  175. package/dist/src/core/config.d.ts +5 -8
  176. package/dist/src/core/config.js +7 -16
  177. package/dist/src/core/coverage-extend.d.ts +15 -13
  178. package/dist/src/core/coverage-extend.js +15 -13
  179. package/dist/src/core/destructive.d.ts +31 -9
  180. package/dist/src/core/destructive.js +29 -26
  181. package/dist/src/core/diff-hunks.js +10 -12
  182. package/dist/src/core/discard-baseline.d.ts +8 -8
  183. package/dist/src/core/discard-baseline.js +16 -15
  184. package/dist/src/core/display-state.d.ts +12 -14
  185. package/dist/src/core/display-state.js +12 -14
  186. package/dist/src/core/engine-changes.d.ts +2 -4
  187. package/dist/src/core/engine-changes.js +2 -4
  188. package/dist/src/core/engine-precondition.d.ts +28 -13
  189. package/dist/src/core/engine-precondition.js +25 -10
  190. package/dist/src/core/engine-session-lock.d.ts +47 -21
  191. package/dist/src/core/engine-session-lock.js +168 -33
  192. package/dist/src/core/export-moved-code-shape.d.ts +10 -10
  193. package/dist/src/core/export-moved-code-shape.js +10 -10
  194. package/dist/src/core/file-lock.d.ts +62 -5
  195. package/dist/src/core/file-lock.js +196 -59
  196. package/dist/src/core/firefox-cache.js +1 -3
  197. package/dist/src/core/firefox-extract.js +10 -14
  198. package/dist/src/core/firefox.d.ts +7 -5
  199. package/dist/src/core/firefox.js +4 -5
  200. package/dist/src/core/furnace-apply-dry-run.d.ts +2 -2
  201. package/dist/src/core/furnace-apply-dry-run.js +3 -2
  202. package/dist/src/core/furnace-apply-ftl.d.ts +7 -9
  203. package/dist/src/core/furnace-apply-ftl.js +12 -12
  204. package/dist/src/core/furnace-apply-helpers.d.ts +7 -7
  205. package/dist/src/core/furnace-apply-helpers.js +19 -16
  206. package/dist/src/core/furnace-apply-overwrite-warn.d.ts +8 -9
  207. package/dist/src/core/furnace-apply-overwrite-warn.js +8 -9
  208. package/dist/src/core/furnace-apply-undeploy-actions.d.ts +3 -4
  209. package/dist/src/core/furnace-apply-undeploy-actions.js +3 -4
  210. package/dist/src/core/furnace-apply.d.ts +5 -8
  211. package/dist/src/core/furnace-apply.js +19 -24
  212. package/dist/src/core/furnace-checksum-utils.d.ts +14 -0
  213. package/dist/src/core/furnace-checksum-utils.js +16 -0
  214. package/dist/src/core/furnace-config.d.ts +21 -30
  215. package/dist/src/core/furnace-config.js +32 -54
  216. package/dist/src/core/furnace-constants.d.ts +8 -0
  217. package/dist/src/core/furnace-constants.js +10 -2
  218. package/dist/src/core/furnace-css-fragments.d.ts +5 -5
  219. package/dist/src/core/furnace-css-fragments.js +5 -5
  220. package/dist/src/core/furnace-jsconfig.d.ts +11 -12
  221. package/dist/src/core/furnace-jsconfig.js +11 -12
  222. package/dist/src/core/furnace-marker.d.ts +7 -8
  223. package/dist/src/core/furnace-marker.js +7 -8
  224. package/dist/src/core/furnace-operation.d.ts +31 -0
  225. package/dist/src/core/furnace-operation.js +54 -17
  226. package/dist/src/core/furnace-precondition.d.ts +61 -0
  227. package/dist/src/core/furnace-precondition.js +67 -0
  228. package/dist/src/core/furnace-registration-remove.d.ts +5 -6
  229. package/dist/src/core/furnace-registration-remove.js +6 -7
  230. package/dist/src/core/furnace-registration-validate.d.ts +13 -0
  231. package/dist/src/core/furnace-registration-validate.js +20 -1
  232. package/dist/src/core/furnace-registration.d.ts +5 -6
  233. package/dist/src/core/furnace-registration.js +10 -12
  234. package/dist/src/core/furnace-rollback.js +7 -7
  235. package/dist/src/core/furnace-scanner.d.ts +1 -0
  236. package/dist/src/core/furnace-scanner.js +1 -2
  237. package/dist/src/core/furnace-stale-export.d.ts +10 -10
  238. package/dist/src/core/furnace-stale-export.js +10 -10
  239. package/dist/src/core/furnace-state-persist.d.ts +6 -8
  240. package/dist/src/core/furnace-state-persist.js +6 -8
  241. package/dist/src/core/furnace-validate-accessibility.d.ts +22 -0
  242. package/dist/src/core/furnace-validate-accessibility.js +310 -1
  243. package/dist/src/core/furnace-validate-compatibility.js +141 -1
  244. package/dist/src/core/furnace-validate-helpers.d.ts +5 -116
  245. package/dist/src/core/furnace-validate-helpers.js +0 -491
  246. package/dist/src/core/furnace-validate-registration.d.ts +7 -0
  247. package/dist/src/core/furnace-validate-registration.js +115 -41
  248. package/dist/src/core/furnace-validate.d.ts +16 -0
  249. package/dist/src/core/furnace-validate.js +188 -145
  250. package/dist/src/core/furnace-version-drift.d.ts +10 -11
  251. package/dist/src/core/furnace-version-drift.js +10 -11
  252. package/dist/src/core/git-base.d.ts +7 -9
  253. package/dist/src/core/git-base.js +7 -9
  254. package/dist/src/core/git-diff.d.ts +20 -9
  255. package/dist/src/core/git-diff.js +148 -63
  256. package/dist/src/core/git-file-ops.d.ts +19 -19
  257. package/dist/src/core/git-file-ops.js +19 -19
  258. package/dist/src/core/git-readonly-index.d.ts +53 -19
  259. package/dist/src/core/git-readonly-index.js +75 -31
  260. package/dist/src/core/git-status.d.ts +5 -6
  261. package/dist/src/core/git-status.js +5 -6
  262. package/dist/src/core/git.d.ts +9 -10
  263. package/dist/src/core/git.js +54 -70
  264. package/dist/src/core/license-headers.d.ts +17 -23
  265. package/dist/src/core/license-headers.js +17 -23
  266. package/dist/src/core/mach-build-artifacts.d.ts +9 -9
  267. package/dist/src/core/mach-build-artifacts.js +57 -19
  268. package/dist/src/core/mach-error-hints.js +42 -29
  269. package/dist/src/core/mach-known-noise-filter.d.ts +15 -16
  270. package/dist/src/core/mach-known-noise-filter.js +18 -20
  271. package/dist/src/core/mach-mozconfig.d.ts +14 -0
  272. package/dist/src/core/mach-mozconfig.js +30 -0
  273. package/dist/src/core/mach-resource-shim.d.ts +43 -58
  274. package/dist/src/core/mach-resource-shim.js +50 -67
  275. package/dist/src/core/mach.d.ts +37 -41
  276. package/dist/src/core/mach.js +50 -51
  277. package/dist/src/core/marionette-port.d.ts +36 -1
  278. package/dist/src/core/marionette-port.js +96 -31
  279. package/dist/src/core/marionette-preflight.d.ts +8 -12
  280. package/dist/src/core/marionette-preflight.js +86 -52
  281. package/dist/src/core/mochitest-server-port.d.ts +42 -0
  282. package/dist/src/core/mochitest-server-port.js +119 -0
  283. package/dist/src/core/module-resolution-preflight.d.ts +9 -11
  284. package/dist/src/core/module-resolution-preflight.js +9 -11
  285. package/dist/src/core/moz-manifest-helpers.d.ts +79 -0
  286. package/dist/src/core/moz-manifest-helpers.js +163 -0
  287. package/dist/src/core/{manifest-register.d.ts → moz-manifest-register.d.ts} +1 -1
  288. package/dist/src/core/{manifest-register.js → moz-manifest-register.js} +13 -28
  289. package/dist/src/core/{manifest-rules.d.ts → moz-manifest-rules.d.ts} +10 -1
  290. package/dist/src/core/{manifest-rules.js → moz-manifest-rules.js} +31 -24
  291. package/dist/src/core/{manifest-tokenizers.d.ts → moz-manifest-tokenizers.d.ts} +3 -5
  292. package/dist/src/core/{manifest-tokenizers.js → moz-manifest-tokenizers.js} +9 -12
  293. package/dist/src/core/ownership-table.d.ts +14 -16
  294. package/dist/src/core/ownership-table.js +14 -16
  295. package/dist/src/core/parser-fallback.d.ts +15 -1
  296. package/dist/src/core/parser-fallback.js +22 -3
  297. package/dist/src/core/patch-apply-fuzz.d.ts +10 -12
  298. package/dist/src/core/patch-apply-fuzz.js +15 -18
  299. package/dist/src/core/patch-apply.d.ts +13 -34
  300. package/dist/src/core/patch-apply.js +16 -76
  301. package/dist/src/core/patch-artifact-normalize.d.ts +13 -15
  302. package/dist/src/core/patch-artifact-normalize.js +13 -15
  303. package/dist/src/core/patch-export-metadata.d.ts +12 -2
  304. package/dist/src/core/patch-export-metadata.js +13 -4
  305. package/dist/src/core/patch-export-update.d.ts +13 -1
  306. package/dist/src/core/patch-export-update.js +25 -8
  307. package/dist/src/core/patch-export.d.ts +15 -8
  308. package/dist/src/core/patch-export.js +10 -11
  309. package/dist/src/core/patch-files.d.ts +5 -6
  310. package/dist/src/core/patch-files.js +5 -6
  311. package/dist/src/core/patch-identifier-suggest.d.ts +7 -12
  312. package/dist/src/core/patch-identifier-suggest.js +14 -19
  313. package/dist/src/core/patch-lint-binary.d.ts +51 -0
  314. package/dist/src/core/patch-lint-binary.js +39 -0
  315. package/dist/src/core/{lint-cache.d.ts → patch-lint-cache.d.ts} +5 -5
  316. package/dist/src/core/{lint-cache.js → patch-lint-cache.js} +21 -23
  317. package/dist/src/core/patch-lint-checkjs.d.ts +16 -16
  318. package/dist/src/core/patch-lint-checkjs.js +16 -16
  319. package/dist/src/core/patch-lint-chrome-jsdoc.d.ts +6 -9
  320. package/dist/src/core/patch-lint-chrome-jsdoc.js +10 -14
  321. package/dist/src/core/patch-lint-creators.d.ts +8 -8
  322. package/dist/src/core/patch-lint-creators.js +8 -8
  323. package/dist/src/core/patch-lint-cross.d.ts +17 -20
  324. package/dist/src/core/patch-lint-cross.js +16 -16
  325. package/dist/src/core/patch-lint-css.d.ts +3 -5
  326. package/dist/src/core/patch-lint-css.js +17 -22
  327. package/dist/src/core/patch-lint-diff-tag.d.ts +14 -16
  328. package/dist/src/core/patch-lint-diff-tag.js +14 -16
  329. package/dist/src/core/patch-lint-jsdoc.d.ts +7 -8
  330. package/dist/src/core/patch-lint-jsdoc.js +26 -19
  331. package/dist/src/core/patch-lint-mozbuild.js +20 -20
  332. package/dist/src/core/patch-lint-observer.d.ts +7 -7
  333. package/dist/src/core/patch-lint-observer.js +7 -7
  334. package/dist/src/core/patch-lint.d.ts +38 -29
  335. package/dist/src/core/patch-lint.js +89 -121
  336. package/dist/src/core/patch-lock.d.ts +1 -1
  337. package/dist/src/core/patch-lock.js +45 -9
  338. package/dist/src/core/patch-manifest-consistency.d.ts +2 -1
  339. package/dist/src/core/patch-manifest-consistency.js +25 -27
  340. package/dist/src/core/patch-manifest-io.js +14 -18
  341. package/dist/src/core/patch-manifest-resolve.d.ts +9 -12
  342. package/dist/src/core/patch-manifest-resolve.js +9 -12
  343. package/dist/src/core/patch-manifest-validate.d.ts +6 -1
  344. package/dist/src/core/patch-manifest-validate.js +25 -13
  345. package/dist/src/core/patch-parse.d.ts +24 -13
  346. package/dist/src/core/patch-parse.js +19 -14
  347. package/dist/src/core/patch-policy.d.ts +2 -2
  348. package/dist/src/core/patch-policy.js +2 -2
  349. package/dist/src/core/patch-registration-refs.d.ts +7 -8
  350. package/dist/src/core/patch-registration-refs.js +9 -9
  351. package/dist/src/core/process-cpu-time.d.ts +12 -0
  352. package/dist/src/core/process-cpu-time.js +52 -0
  353. package/dist/src/core/rebase-session.d.ts +38 -26
  354. package/dist/src/core/rebase-session.js +55 -28
  355. package/dist/src/core/register-browser-content.js +9 -74
  356. package/dist/src/core/{register-test-manifest.js → register-browser-test.js} +7 -42
  357. package/dist/src/core/register-module.js +10 -43
  358. package/dist/src/core/register-scaffold.d.ts +8 -8
  359. package/dist/src/core/register-scaffold.js +10 -10
  360. package/dist/src/core/register-shared-css.d.ts +9 -12
  361. package/dist/src/core/register-shared-css.js +17 -87
  362. package/dist/src/core/register-xpcshell-test.d.ts +6 -7
  363. package/dist/src/core/register-xpcshell-test.js +7 -8
  364. package/dist/src/core/shared-ftl.js +12 -4
  365. package/dist/src/core/state-file.d.ts +45 -0
  366. package/dist/src/core/state-file.js +34 -0
  367. package/dist/src/core/status-binary.d.ts +18 -11
  368. package/dist/src/core/status-binary.js +19 -12
  369. package/dist/src/core/status-classify.d.ts +30 -36
  370. package/dist/src/core/status-classify.js +21 -26
  371. package/dist/src/core/test-changed-prefs.d.ts +30 -0
  372. package/dist/src/core/test-changed-prefs.js +78 -0
  373. package/dist/src/core/test-harness-crash.d.ts +25 -63
  374. package/dist/src/core/test-harness-crash.js +121 -142
  375. package/dist/src/core/test-harness-signature.d.ts +18 -0
  376. package/dist/src/core/test-harness-signature.js +13 -0
  377. package/dist/src/core/test-path-scope.d.ts +12 -15
  378. package/dist/src/core/test-path-scope.js +15 -18
  379. package/dist/src/core/test-stale-check.d.ts +17 -17
  380. package/dist/src/core/test-stale-check.js +50 -43
  381. package/dist/src/core/test-stall-triage.d.ts +51 -0
  382. package/dist/src/core/test-stall-triage.js +126 -0
  383. package/dist/src/core/token-category.js +5 -7
  384. package/dist/src/core/token-coverage.js +9 -9
  385. package/dist/src/core/token-dark-mode.d.ts +9 -11
  386. package/dist/src/core/token-dark-mode.js +9 -11
  387. package/dist/src/core/token-docs.d.ts +2 -0
  388. package/dist/src/core/token-docs.js +2 -0
  389. package/dist/src/core/token-manager.d.ts +10 -2
  390. package/dist/src/core/token-manager.js +17 -8
  391. package/dist/src/core/token-scaffold.d.ts +7 -7
  392. package/dist/src/core/token-scaffold.js +7 -7
  393. package/dist/src/core/token-variant.d.ts +4 -4
  394. package/dist/src/core/token-variant.js +4 -4
  395. package/dist/src/core/toolchain-preflight.d.ts +20 -21
  396. package/dist/src/core/toolchain-preflight.js +28 -31
  397. package/dist/src/core/tree-guard.js +12 -2
  398. package/dist/src/core/tree-store.d.ts +41 -27
  399. package/dist/src/core/tree-store.js +63 -42
  400. package/dist/src/core/typecheck-shim.d.ts +23 -24
  401. package/dist/src/core/typecheck-shim.js +23 -24
  402. package/dist/src/core/typecheck.js +8 -8
  403. package/dist/src/core/wire-destroy.d.ts +3 -3
  404. package/dist/src/core/wire-destroy.js +7 -15
  405. package/dist/src/core/wire-dom-fragment.d.ts +9 -17
  406. package/dist/src/core/wire-dom-fragment.js +11 -44
  407. package/dist/src/core/wire-init.d.ts +2 -3
  408. package/dist/src/core/wire-init.js +8 -19
  409. package/dist/src/core/wire-subscript.d.ts +2 -3
  410. package/dist/src/core/wire-subscript.js +4 -13
  411. package/dist/src/core/wire-utils.d.ts +7 -8
  412. package/dist/src/core/wire-utils.js +7 -8
  413. package/dist/src/core/xpcshell-appdir.d.ts +38 -45
  414. package/dist/src/core/xpcshell-appdir.js +38 -45
  415. package/dist/src/errors/base.d.ts +37 -16
  416. package/dist/src/errors/base.js +37 -16
  417. package/dist/src/errors/build.d.ts +13 -1
  418. package/dist/src/errors/build.js +14 -2
  419. package/dist/src/errors/codes.d.ts +16 -0
  420. package/dist/src/errors/codes.js +16 -0
  421. package/dist/src/errors/furnace.d.ts +4 -4
  422. package/dist/src/errors/git.d.ts +6 -10
  423. package/dist/src/errors/git.js +6 -10
  424. package/dist/src/errors/patch.d.ts +7 -7
  425. package/dist/src/errors/patch.js +7 -7
  426. package/dist/src/errors/rebase.d.ts +4 -4
  427. package/dist/src/errors/rebase.js +4 -4
  428. package/dist/src/index.d.ts +7 -1
  429. package/dist/src/index.js +5 -0
  430. package/dist/src/types/commands/index.d.ts +2 -2
  431. package/dist/src/types/commands/options.d.ts +88 -70
  432. package/dist/src/types/commands/patches.d.ts +24 -34
  433. package/dist/src/types/commands/project.d.ts +5 -34
  434. package/dist/src/types/config.d.ts +25 -23
  435. package/dist/src/types/config.js +6 -1
  436. package/dist/src/types/furnace.d.ts +37 -13
  437. package/dist/src/types/furnace.js +19 -1
  438. package/dist/src/types/index.d.ts +3 -3
  439. package/dist/src/utils/build-info.d.ts +7 -8
  440. package/dist/src/utils/build-info.js +12 -11
  441. package/dist/src/utils/errors.d.ts +6 -8
  442. package/dist/src/utils/errors.js +6 -8
  443. package/dist/src/utils/logger.d.ts +27 -10
  444. package/dist/src/utils/logger.js +28 -16
  445. package/dist/src/utils/machine-output.d.ts +12 -0
  446. package/dist/src/utils/machine-output.js +33 -0
  447. package/dist/src/utils/options.d.ts +31 -14
  448. package/dist/src/utils/options.js +86 -30
  449. package/dist/src/utils/paths.d.ts +10 -8
  450. package/dist/src/utils/paths.js +10 -8
  451. package/dist/src/utils/platform.d.ts +0 -25
  452. package/dist/src/utils/platform.js +1 -42
  453. package/dist/src/utils/process-group.d.ts +9 -4
  454. package/dist/src/utils/process-group.js +19 -5
  455. package/dist/src/utils/process.d.ts +42 -7
  456. package/dist/src/utils/process.js +44 -17
  457. package/dist/src/utils/ps-duration.d.ts +31 -0
  458. package/dist/src/utils/ps-duration.js +70 -0
  459. package/dist/src/utils/regex.d.ts +9 -10
  460. package/dist/src/utils/regex.js +9 -10
  461. package/dist/src/utils/validation.d.ts +58 -28
  462. package/dist/src/utils/validation.js +60 -33
  463. package/package.json +2 -2
  464. package/dist/src/commands/doctor/post-rebase-audit.d.ts +0 -2
  465. package/dist/src/commands/doctor-furnace-manifest-sync.d.ts +0 -18
  466. package/dist/src/core/manifest-helpers.d.ts +0 -38
  467. package/dist/src/core/manifest-helpers.js +0 -120
  468. /package/dist/src/core/{lint-projection.d.ts → patch-lint-projection.d.ts} +0 -0
  469. /package/dist/src/core/{lint-projection.js → patch-lint-projection.js} +0 -0
  470. /package/dist/src/core/{register-test-manifest.d.ts → register-browser-test.d.ts} +0 -0
@@ -223,16 +223,16 @@ export async function reportForeignDrift(args) {
223
223
  return false;
224
224
  }
225
225
  /**
226
- * Splits the drifting files into "you probably wrote this" and "this
227
- * predates your last export". `--refuse-foreign-drift` calls every
228
- * absorbed line "foreign" — including the operator's OWN additions
229
- * from the same session — and "foreign" reads as "another session's",
230
- * which is precisely the case where proceeding would be wrong. Authorship
231
- * is unknowable, but RECENCY is not: a file whose mtime is newer than the
232
- * patch body this run is refreshing changed after the last export, which
233
- * on a single-operator slice is the operator's own edit. Returns the
234
- * subset of `files` that qualifies; an unstattable path is reported as
235
- * NOT recently edited, so the cautious wording is the fallback.
226
+ * Splits the drifting files into "you probably wrote this" and "this predates
227
+ * your last export". `--refuse-foreign-drift` calls every absorbed line
228
+ * "foreign" — including the operator's OWN additions from the same session —
229
+ * and "foreign" reads as "another session's", which is precisely the case
230
+ * where proceeding would be wrong. Authorship is unknowable, but RECENCY is
231
+ * not: a file whose mtime is newer than the patch body this run is refreshing
232
+ * changed after the last export, which on a single-operator slice is the
233
+ * operator's own edit. Returns the subset of `files` that qualifies; an
234
+ * unstattable path is reported as NOT recently edited, so the cautious
235
+ * wording is the fallback.
236
236
  */
237
237
  async function findFilesEditedSinceLastExport(engineDir, patchBodyPath, files) {
238
238
  const recent = new Set();
@@ -2,16 +2,15 @@ import { getProjectPaths } from '../core/config.js';
2
2
  import type { PatchMetadata, ReExportOptions } from '../types/commands/index.js';
3
3
  import type { FireForgeConfig } from '../types/config.js';
4
4
  /**
5
- * Handles `re-export --files` end-to-end: computes the projected diff,
6
- * runs the per-patch and cross-patch lint against a context in which the
7
- * target patch has been replaced with the projected state, gates on
5
+ * Handles `re-export --files` end-to-end: computes the projected diff, runs
6
+ * the per-patch and cross-patch lint against a context in which the target
7
+ * patch has been replaced with the projected state, gates on
8
8
  * confirmDestructive, and writes atomically.
9
9
  *
10
10
  * Lives outside reExportSinglePatch because the --files path has strictly
11
11
  * different semantics (authoritative file list, destructive shrink
12
- * confirmation, cross-patch projection lint) and shoehorning it through
13
- * the generic single-patch helper is what led to the earlier bug where
14
- * the projection lint ran against the current (unchanged) queue instead
15
- * of the projected state.
12
+ * confirmation, cross-patch projection lint). Shoehorning it through the
13
+ * generic single-patch helper is what makes the projection lint run against
14
+ * the current (unchanged) queue instead of the projected state.
16
15
  */
17
16
  export declare function reExportFilesInPlace(paths: ReturnType<typeof getProjectPaths>, selectedPatches: PatchMetadata[], options: ReExportOptions, config: FireForgeConfig): Promise<void>;
@@ -1,13 +1,13 @@
1
1
  // SPDX-License-Identifier: EUPL-1.2
2
2
  import { join } from 'node:path';
3
3
  import { getProjectPaths } from '../core/config.js';
4
- import { appendHistory, confirmDestructive } from '../core/destructive.js';
4
+ import { appendHistory, confirmDestructive, } from '../core/destructive.js';
5
5
  import { enforceFreshFurnaceSources } from '../core/furnace-stale-export.js';
6
6
  import { getDiffForFilesAgainstHead } from '../core/git-diff.js';
7
- import { computeProjectedLintRegressions } from '../core/lint-projection.js';
8
7
  import { extractAffectedFiles } from '../core/patch-apply.js';
9
8
  import { updatePatchAndMetadata } from '../core/patch-export.js';
10
9
  import { buildModifiedFileAdditionsFromDiff, buildPatchQueueContext, detectNewFilesInDiff, formatPatchLintIssue, lintPatchQueue, } from '../core/patch-lint.js';
10
+ import { computeProjectedLintRegressions } from '../core/patch-lint-projection.js';
11
11
  import { loadPatchesManifest } from '../core/patch-manifest.js';
12
12
  import { buildProjectedManifest, enforcePatchPolicy } from '../core/patch-policy.js';
13
13
  import { extractNewFileContentFromDiff } from '../core/patch-transform.js';
@@ -16,17 +16,13 @@ import { pathExists } from '../utils/fs.js';
16
16
  import { info, outro, success, warn } from '../utils/logger.js';
17
17
  import { runPatchLint } from './export-shared.js';
18
18
  /**
19
- * Computes the effective `tier` and `lintIgnore` carrying both the
20
- * patch's existing values and the CLI flag overrides. Pure helper —
21
- * extracted from {@link reExportFilesInPlace} both to share with the
22
- * standard re-export path conceptually and to keep the orchestrator
23
- * function under the per-file LOC budget.
19
+ * Computes the effective `tier` and `lintIgnore` carrying both the patch's
20
+ * existing values and the CLI flag overrides.
24
21
  *
25
- * Tier resolution: the CLI flag takes precedence; the patch's existing
26
- * tier is the fallback. Lint-ignore resolution: union of the patch's
27
- * existing list and the CLI flag values, de-duplicated; an empty
28
- * result returns `undefined` so the caller can drop the field rather
29
- * than write an empty array.
22
+ * Tier resolution: the CLI flag takes precedence; the patch's existing tier
23
+ * is the fallback. Lint-ignore resolution: union of the patch's existing list
24
+ * and the CLI flag values, de-duplicated; an empty result returns `undefined`
25
+ * so the caller can drop the field rather than write an empty array.
30
26
  */
31
27
  function resolveEffectiveTierAndLintIgnore(target, options) {
32
28
  const existingIgnoreSet = new Set(target.lintIgnore ?? []);
@@ -38,12 +34,10 @@ function resolveEffectiveTierAndLintIgnore(target, options) {
38
34
  }
39
35
  /**
40
36
  * Projects the cross-patch context (replace the target entry with its
41
- * shrunken self), runs the patch-queue lint against the projection,
42
- * and returns a conflict report only for regressions introduced *by*
43
- * this shrink. Pre-existing cross-patch errors are surfaced as a
44
- * non-blocking warning so the user does not walk away thinking the
45
- * queue is clean. Extracted from {@link reExportFilesInPlace} to keep
46
- * the orchestrator function under the per-file LOC budget.
37
+ * shrunken self), runs the patch-queue lint against the projection, and
38
+ * returns a conflict report only for regressions introduced *by* this
39
+ * shrink. Pre-existing cross-patch errors are surfaced as a non-blocking
40
+ * warning so the user does not walk away thinking the queue is clean.
47
41
  */
48
42
  async function runProjectedCrossPatchLint(patchesDir, targetFilename, projectedDiff) {
49
43
  const baseCtx = await buildPatchQueueContext(patchesDir);
@@ -78,9 +72,8 @@ async function runProjectedCrossPatchLint(patchesDir, targetFilename, projectedD
78
72
  }
79
73
  /**
80
74
  * Builds the `Partial<PatchMetadata>` payload for the `--files` write,
81
- * folding in the CLI flag overrides for `tier` and `lintIgnore` only
82
- * when the operator actually asked for them. Extracted to keep
83
- * {@link reExportFilesInPlace} under the per-file LOC budget.
75
+ * folding in the CLI flag overrides for `tier` and `lintIgnore` only when the
76
+ * operator actually asked for them.
84
77
  */
85
78
  function buildFilesModeMetadataUpdates(actualProjectedFiles, options, effectiveLintIgnore, flagIgnoreSet) {
86
79
  const updates = {
@@ -132,17 +125,16 @@ async function confirmFilesModeProjection(args) {
132
125
  });
133
126
  }
134
127
  /**
135
- * Handles `re-export --files` end-to-end: computes the projected diff,
136
- * runs the per-patch and cross-patch lint against a context in which the
137
- * target patch has been replaced with the projected state, gates on
128
+ * Handles `re-export --files` end-to-end: computes the projected diff, runs
129
+ * the per-patch and cross-patch lint against a context in which the target
130
+ * patch has been replaced with the projected state, gates on
138
131
  * confirmDestructive, and writes atomically.
139
132
  *
140
133
  * Lives outside reExportSinglePatch because the --files path has strictly
141
134
  * different semantics (authoritative file list, destructive shrink
142
- * confirmation, cross-patch projection lint) and shoehorning it through
143
- * the generic single-patch helper is what led to the earlier bug where
144
- * the projection lint ran against the current (unchanged) queue instead
145
- * of the projected state.
135
+ * confirmation, cross-patch projection lint). Shoehorning it through the
136
+ * generic single-patch helper is what makes the projection lint run against
137
+ * the current (unchanged) queue instead of the projected state.
146
138
  */
147
139
  export async function reExportFilesInPlace(paths, selectedPatches, options, config) {
148
140
  const target = selectedPatches[0];
@@ -154,8 +146,8 @@ export async function reExportFilesInPlace(paths, selectedPatches, options, conf
154
146
  throw new InvalidArgumentError('reExportFilesInPlace called with no --files.', '--files');
155
147
  }
156
148
  const requested = [...new Set(filesOption)].sort();
157
- // Stale-furnace-source gate (0.37.0 item 4): same refusal as the generic
158
- // re-export path — the projected diff would capture stale deployed copies.
149
+ // Stale-furnace-source gate: same refusal as the generic re-export path —
150
+ // the projected diff would capture stale deployed copies.
159
151
  await enforceFreshFurnaceSources(paths.root, requested, options.allowStaleFurnace === true, 're-export');
160
152
  const removed = target.filesAffected.filter((f) => !requested.includes(f));
161
153
  const added = requested.filter((f) => !target.filesAffected.includes(f));
@@ -193,16 +185,14 @@ export async function reExportFilesInPlace(paths, selectedPatches, options, conf
193
185
  'Keeping them in filesAffected would desync patches.json from the patch body. ' +
194
186
  'Remove those paths from --files or modify them before retrying.', '--files');
195
187
  }
196
- // Run the per-patch lint against the projected diff. This mirrors what
188
+ // Run the per-patch lint against the projected diff, mirroring what
197
189
  // runPatchLint does in the standard re-export path. The target patch's
198
190
  // `lintIgnore` threads through so a shrink of an advisory-noisy-but-
199
191
  // intentional patch (branding bundle, localised-resource pack) does not
200
192
  // have to choose between `--skip-lint` (blunt) and the full rebase path.
201
- // `target.tier` threads the explicit branding-threshold opt-in for
202
- // the branding patch that also touches a non-allowlisted sibling.
203
- // CLI flags `--tier` and `--lint-ignore` participate too, with
204
- // append/union semantics on the lint-ignore list (matching the
205
- // standard re-export path).
193
+ // `target.tier` threads the explicit branding-threshold opt-in. CLI flags
194
+ // `--tier` and `--lint-ignore` participate too, with append/union
195
+ // semantics on the lint-ignore list.
206
196
  const { effectiveTier, effectiveLintIgnore, flagIgnoreSet } = resolveEffectiveTierAndLintIgnore(target, options);
207
197
  const ignoreChecks = effectiveLintIgnore ? new Set(effectiveLintIgnore) : undefined;
208
198
  const patchQueueCtx = (await pathExists(paths.patches))
@@ -230,7 +220,7 @@ export async function reExportFilesInPlace(paths, selectedPatches, options, conf
230
220
  options,
231
221
  conflicts,
232
222
  });
233
- if (decision === 'cancelled') {
223
+ if (decision === 'declined') {
234
224
  outro('Re-export cancelled');
235
225
  return;
236
226
  }
@@ -239,13 +229,13 @@ export async function reExportFilesInPlace(paths, selectedPatches, options, conf
239
229
  outro('Dry run complete — no changes made');
240
230
  return;
241
231
  }
242
- // Execute the write. At this point the projected diff is guaranteed to
243
- // be non-empty and `actualProjectedFiles` is guaranteed to match the
244
- // paths the body really touches, so the manifest cannot drift from the
245
- // regenerated patch body. The history append runs inside the same patch
246
- // directory lock as the mutation (via the onCommitted hook) so two
247
- // concurrent re-exports cannot interleave records and a crash between
248
- // mutation and append cannot orphan the audit trail.
232
+ // Execute the write. At this point the projected diff is guaranteed
233
+ // non-empty and `actualProjectedFiles` is guaranteed to match the paths the
234
+ // body really touches, so the manifest cannot drift from the regenerated
235
+ // patch body. The history append runs inside the same patch directory lock
236
+ // as the mutation (via the onCommitted hook) so two concurrent re-exports
237
+ // cannot interleave records and a crash between mutation and append cannot
238
+ // orphan the audit trail.
249
239
  await updatePatchAndMetadata(paths.patches, target.filename, projectedDiff, filesUpdates, async () => {
250
240
  await appendHistory(paths.patches, {
251
241
  operation: 're-export-files',
@@ -1,30 +1,27 @@
1
1
  /**
2
2
  * Hoisted + cached lint context for `re-export`.
3
3
  *
4
- * The per-patch loop used to rebuild the whole patch-queue context AND a
5
- * fresh queue-wide checkJs TypeScript program for every patch — ~37 s of
6
- * fixed setup per patch (measured on a 290-patch consumer queue), so an
7
- * N-patch re-export cost N×37 s. This module:
4
+ * Rebuilding the whole patch-queue context AND a fresh queue-wide checkJs
5
+ * TypeScript program for every patch costs tens of seconds of fixed setup
6
+ * per patch, so an N-patch re-export pays it N times. This module:
8
7
  *
9
8
  * - builds the queue context and the {@link PerRunCheckJs} program
10
9
  * controller ONCE per invocation (`buildReExportLintContext`) and slices
11
- * per-patch findings out of it (the shape `move-files`/`split`
12
- * already use, plus the program-level hoist `lint --per-patch` has);
10
+ * per-patch findings out of it;
13
11
  * - reuses the existing per-patch lint RESULT cache
14
12
  * (`.fireforge/lint-cache/per-patch-v1.json`) across invocations —
15
- * re-export lints the identical input `lint --per-patch` does (the
16
- * fresh `git diff HEAD` of the owned files), and the key already
17
- * hashes engine HEAD, per-file content, patch body, config, shims, and
18
- * ownership, so a repeat single re-export is a warm hit (~4 s instead
19
- * of ~41 s). `--no-cache` opts out; run-level checkJs globals are
20
- * never cached and are emitted once per invocation;
13
+ * re-export lints the identical input `lint --per-patch` does (the fresh
14
+ * `git diff HEAD` of the owned files), and the key already hashes engine
15
+ * HEAD, per-file content, patch body, config, shims, and ownership, so a
16
+ * repeat single re-export is a warm hit. `--no-cache` opts out; run-level
17
+ * checkJs globals are never cached and are emitted once per invocation;
21
18
  * - keeps the in-memory queue context honest after each write
22
19
  * (`refreshQueueCtxEntry`), so later iterations of an `--all` run lint
23
20
  * against the just-refreshed body instead of the stale one.
24
21
  */
25
22
  import { getProjectPaths, loadConfig } from '../core/config.js';
26
- import { type PerPatchLintCacheFile } from '../core/lint-cache.js';
27
23
  import { type PatchQueueContext } from '../core/patch-lint.js';
24
+ import { type PerPatchLintCacheFile } from '../core/patch-lint-cache.js';
28
25
  import type { PatchLintIssue, PatchMetadata } from '../types/commands/index.js';
29
26
  import type { FireForgeConfig } from '../types/config.js';
30
27
  import { type PerRunCheckJs } from './lint-per-run-checkjs.js';
@@ -2,30 +2,27 @@
2
2
  /**
3
3
  * Hoisted + cached lint context for `re-export`.
4
4
  *
5
- * The per-patch loop used to rebuild the whole patch-queue context AND a
6
- * fresh queue-wide checkJs TypeScript program for every patch — ~37 s of
7
- * fixed setup per patch (measured on a 290-patch consumer queue), so an
8
- * N-patch re-export cost N×37 s. This module:
5
+ * Rebuilding the whole patch-queue context AND a fresh queue-wide checkJs
6
+ * TypeScript program for every patch costs tens of seconds of fixed setup
7
+ * per patch, so an N-patch re-export pays it N times. This module:
9
8
  *
10
9
  * - builds the queue context and the {@link PerRunCheckJs} program
11
10
  * controller ONCE per invocation (`buildReExportLintContext`) and slices
12
- * per-patch findings out of it (the shape `move-files`/`split`
13
- * already use, plus the program-level hoist `lint --per-patch` has);
11
+ * per-patch findings out of it;
14
12
  * - reuses the existing per-patch lint RESULT cache
15
13
  * (`.fireforge/lint-cache/per-patch-v1.json`) across invocations —
16
- * re-export lints the identical input `lint --per-patch` does (the
17
- * fresh `git diff HEAD` of the owned files), and the key already
18
- * hashes engine HEAD, per-file content, patch body, config, shims, and
19
- * ownership, so a repeat single re-export is a warm hit (~4 s instead
20
- * of ~41 s). `--no-cache` opts out; run-level checkJs globals are
21
- * never cached and are emitted once per invocation;
14
+ * re-export lints the identical input `lint --per-patch` does (the fresh
15
+ * `git diff HEAD` of the owned files), and the key already hashes engine
16
+ * HEAD, per-file content, patch body, config, shims, and ownership, so a
17
+ * repeat single re-export is a warm hit. `--no-cache` opts out; run-level
18
+ * checkJs globals are never cached and are emitted once per invocation;
22
19
  * - keeps the in-memory queue context honest after each write
23
20
  * (`refreshQueueCtxEntry`), so later iterations of an `--all` run lint
24
21
  * against the just-refreshed body instead of the stale one.
25
22
  */
26
23
  import { getProjectPaths, loadConfig } from '../core/config.js';
27
- import { buildPerPatchLintCacheKey, getCachedPerPatchLintIssues, getPerPatchLintCacheHeadSha, loadPerPatchLintCache, savePerPatchLintCache, setCachedPerPatchLintIssues, } from '../core/lint-cache.js';
28
24
  import { buildPatchQueueContext, countNonBinaryDiffLines, detectNewFilesInDiff, lintExportedPatch, resolvePatchSizeTier, } from '../core/patch-lint.js';
25
+ import { buildPerPatchLintCacheKey, getCachedPerPatchLintIssues, getPerPatchLintCacheHeadSha, loadPerPatchLintCache, savePerPatchLintCache, setCachedPerPatchLintIssues, } from '../core/patch-lint-cache.js';
29
26
  import { invalidateNewFileCreatorsCache } from '../core/patch-lint-cross.js';
30
27
  import { extractAddedLinesPerFile } from '../core/patch-lint-diff.js';
31
28
  import { resolvePatchOwnedSysMjs } from '../core/patch-lint-ownership.js';
@@ -138,7 +135,12 @@ export async function lintReExportedPatch(args) {
138
135
  else if (patchQueueCtx) {
139
136
  lintOptions.checkJsReportScope = resolvePatchOwnedSysMjs(detectNewFilesInDiff(diffContent));
140
137
  }
141
- const issues = await lintExportedPatch(paths.engine, existingFiles, diffContent, config, patchQueueCtx, args.ignoreChecks, args.patchTier, lintOptions);
138
+ const issues = await lintExportedPatch(paths.engine, existingFiles, diffContent, config, {
139
+ ...lintOptions,
140
+ ...(patchQueueCtx ? { patchQueueCtx } : {}),
141
+ ...(args.ignoreChecks ? { ignoreChecks: args.ignoreChecks } : {}),
142
+ ...(args.patchTier ? { patchTier: args.patchTier } : {}),
143
+ });
142
144
  reportPatchLintOutcome([...globalIssues, ...issues], args.skipLint);
143
145
  return {
144
146
  issues,
@@ -8,12 +8,12 @@ export interface NormalizedReExportArguments {
8
8
  }
9
9
  /**
10
10
  * Accepts the `export`-style space-separated path shape for
11
- * `re-export <patch> --files` (0.34.0 field report): commander's
12
- * `--files <paths>` consumes one comma-separated value, so
13
- * `re-export 006-x --files a/b.js c/d.js` used to park `c/d.js` in the
14
- * positional patches and fail with "--files operates on exactly one
15
- * target patch" — pointing at the wrong argument. When every positional
16
- * beyond the first looks like a file path, fold them into the file list.
11
+ * `re-export <patch> --files`. Commander's `--files <paths>` consumes one
12
+ * comma-separated value, so `re-export 006-x --files a/b.js c/d.js` parks
13
+ * `c/d.js` in the positional patches and fails with "--files operates on
14
+ * exactly one target patch" — pointing at the wrong argument. When every
15
+ * positional beyond the first looks like a file path, fold them into the
16
+ * file list.
17
17
  */
18
18
  export declare function normalizeReExportFilesPositionals(patches: readonly string[], options: ReExportOptions): NormalizedReExportArguments;
19
19
  /**
@@ -11,12 +11,12 @@ function looksLikeFilePath(value) {
11
11
  }
12
12
  /**
13
13
  * Accepts the `export`-style space-separated path shape for
14
- * `re-export <patch> --files` (0.34.0 field report): commander's
15
- * `--files <paths>` consumes one comma-separated value, so
16
- * `re-export 006-x --files a/b.js c/d.js` used to park `c/d.js` in the
17
- * positional patches and fail with "--files operates on exactly one
18
- * target patch" — pointing at the wrong argument. When every positional
19
- * beyond the first looks like a file path, fold them into the file list.
14
+ * `re-export <patch> --files`. Commander's `--files <paths>` consumes one
15
+ * comma-separated value, so `re-export 006-x --files a/b.js c/d.js` parks
16
+ * `c/d.js` in the positional patches and fails with "--files operates on
17
+ * exactly one target patch" — pointing at the wrong argument. When every
18
+ * positional beyond the first looks like a file path, fold them into the
19
+ * file list.
20
20
  */
21
21
  export function normalizeReExportFilesPositionals(patches, options) {
22
22
  if (options.files === undefined || patches.length <= 1) {
@@ -1,16 +1,10 @@
1
1
  /**
2
2
  * CLI registration for `fireforge re-export`.
3
3
  *
4
- * Split out of `re-export.ts` in 0.41.0. That file was the only one in `src/`
5
- * carrying a file-level `eslint-disable max-lines` — it measured 526 against
6
- * the 500 cap with the rule suppressed — and its own suppression comment named
7
- * this block as the obvious thing to move ("splitting register plumbing is
8
- * unrelated to this fix"). Moving it drops the file under the cap and removes
9
- * the suppression.
10
- *
11
- * §7 of the quality survey forbids folding `re-export-files.ts` back INTO the
12
- * orchestrator; this splits in the other direction, matching the existing
13
- * `re-export-scan.ts` / `re-export-options.ts` boundary.
4
+ * Split out of `re-export.ts`, which was otherwise over the per-file line
5
+ * cap. The split direction matches the existing `re-export-scan.ts` /
6
+ * `re-export-options.ts` boundary; folding `re-export-files.ts` back into
7
+ * the orchestrator would go the wrong way.
14
8
  */
15
9
  import { Command } from 'commander';
16
10
  import type { CommandContext } from '../types/cli.js';
@@ -2,16 +2,10 @@
2
2
  /**
3
3
  * CLI registration for `fireforge re-export`.
4
4
  *
5
- * Split out of `re-export.ts` in 0.41.0. That file was the only one in `src/`
6
- * carrying a file-level `eslint-disable max-lines` — it measured 526 against
7
- * the 500 cap with the rule suppressed — and its own suppression comment named
8
- * this block as the obvious thing to move ("splitting register plumbing is
9
- * unrelated to this fix"). Moving it drops the file under the cap and removes
10
- * the suppression.
11
- *
12
- * §7 of the quality survey forbids folding `re-export-files.ts` back INTO the
13
- * orchestrator; this splits in the other direction, matching the existing
14
- * `re-export-scan.ts` / `re-export-options.ts` boundary.
5
+ * Split out of `re-export.ts`, which was otherwise over the per-file line
6
+ * cap. The split direction matches the existing `re-export-scan.ts` /
7
+ * `re-export-options.ts` boundary; folding `re-export-files.ts` back into
8
+ * the orchestrator would go the wrong way.
15
9
  */
16
10
  import { Command, Option } from 'commander';
17
11
  import { withEngineSessionLock } from '../core/engine-session-lock.js';
@@ -34,7 +28,7 @@ export function registerReExport(program, { getProjectRoot, withErrorHandling })
34
28
  .filter((v) => v.length > 0))
35
29
  .option('--refuse-adjacent-unmanaged', 'Refuse a scan-less re-export (non-zero exit, patch not written) when unmanaged files exist adjacent to the patch ownership, instead of warning. Mutually exclusive with --scan and --files.')
36
30
  .option('--refuse-foreign-drift', "Refuse a scan-less re-export (non-zero exit, patch not written) when the refreshed body would absorb engine lines not present in the old patch body — protects multi-session checkouts from silently capturing another session's uncommitted edits. Mutually exclusive with --scan and --files.")
37
- .option('--expect <path>', "With --refuse-foreign-drift, name an engine-relative file whose drift is this session's intended edit: drift confined to --expect files proceeds, drift anywhere else still refuses. Repeatable.", ...stringListOption())
31
+ .option('--expect <path>', "With --refuse-foreign-drift, name an engine-relative file whose drift is this session's intended edit: drift confined to --expect files proceeds, drift anywhere else still refuses. Repeatable, and the whitelist applies across EVERY patch in this invocation, not per patch — so pass all the patches and all their --expect paths in one call rather than looping one patch at a time.", ...stringListOption())
38
32
  .option('--dry-run', 'Show what would change without writing')
39
33
  .option('--skip-lint', 'Skip patch lint checks (downgrade errors to warnings)')
40
34
  .option('--no-cache', 'Bypass per-patch lint result cache reads and writes for this re-export')
@@ -3,9 +3,9 @@ import { dirname, join } from 'node:path';
3
3
  import { confirm } from '@clack/prompts';
4
4
  import { getDiffForFilesAgainstHead } from '../core/git-diff.js';
5
5
  import { getModifiedFilesInDir, getUntrackedFilesInDir } from '../core/git-status.js';
6
- import { computeProjectedLintRegressions } from '../core/lint-projection.js';
7
6
  import { extractAffectedFiles } from '../core/patch-apply.js';
8
7
  import { buildModifiedFileAdditionsFromDiff, buildPatchQueueContext, detectNewFilesInDiff, lintPatchQueue, } from '../core/patch-lint.js';
8
+ import { computeProjectedLintRegressions } from '../core/patch-lint-projection.js';
9
9
  import { getClaimedFiles } from '../core/patch-manifest.js';
10
10
  import { extractNewFileContentFromDiff } from '../core/patch-transform.js';
11
11
  import { GeneralError, InvalidArgumentError } from '../errors/base.js';
@@ -1,8 +1,8 @@
1
1
  /**
2
2
  * Single-patch refresh core for `fireforge re-export`, split out of
3
- * `re-export.ts` (at the per-file line budget after the
4
- * hoisted-lint and foreign-drift wiring). The orchestrator loop calls
5
- * {@link reExportSinglePatchWithIndexLockRetry} per selected patch.
3
+ * `re-export.ts` to stay under the per-file line budget. The orchestrator
4
+ * loop calls {@link reExportSinglePatchWithIndexLockRetry} per selected
5
+ * patch.
6
6
  */
7
7
  import { getProjectPaths } from '../core/config.js';
8
8
  import type { PatchesManifest, PatchMetadata, ReExportOptions } from '../types/commands/index.js';
@@ -1,11 +1,12 @@
1
1
  // SPDX-License-Identifier: EUPL-1.2
2
2
  /**
3
3
  * Single-patch refresh core for `fireforge re-export`, split out of
4
- * `re-export.ts` (at the per-file line budget after the
5
- * hoisted-lint and foreign-drift wiring). The orchestrator loop calls
6
- * {@link reExportSinglePatchWithIndexLockRetry} per selected patch.
4
+ * `re-export.ts` to stay under the per-file line budget. The orchestrator
5
+ * loop calls {@link reExportSinglePatchWithIndexLockRetry} per selected
6
+ * patch.
7
7
  */
8
8
  import { getProjectPaths } from '../core/config.js';
9
+ import { stdioIsInteractive } from '../core/destructive.js';
9
10
  import { enforceFreshFurnaceSources } from '../core/furnace-stale-export.js';
10
11
  import { getDiffForFilesAgainstHead } from '../core/git-diff.js';
11
12
  import { updatePatchAndMetadata } from '../core/patch-export.js';
@@ -61,7 +62,7 @@ async function reExportSinglePatch(patch, paths, manifest, options, isDryRun, co
61
62
  added: scanResult.added,
62
63
  });
63
64
  if (options.scanFiles === undefined) {
64
- const isInteractive = process.stdin.isTTY && process.stdout.isTTY;
65
+ const isInteractive = stdioIsInteractive();
65
66
  const proceed = await confirmBroadScanAdditions({
66
67
  patchFilename: patch.filename,
67
68
  added: scanResult.added,
@@ -76,15 +77,14 @@ async function reExportSinglePatch(patch, paths, manifest, options, isDryRun, co
76
77
  currentFilesAffected = scanResult.updated;
77
78
  }
78
79
  else if (options.files === undefined) {
79
- // Finding #16: when neither `--scan` nor `--files` is set and some
80
- // of the manifest's claimed files no longer exist on disk, the
81
- // re-export silently writes a refreshed body whose filesAffected
82
- // still names the vanished paths. That is the documented contract,
83
- // but it is also a footgun — a later `verify` then fails on
84
- // manifest-consistency with no obvious trigger. Emit one advisory
85
- // warning up-front when we can detect the drift cheaply, so the
86
- // operator has a chance to re-run with `--scan` or `--files`
87
- // before the stale filesAffected lands in patches.json.
80
+ // When neither `--scan` nor `--files` is set and some of the manifest's
81
+ // claimed files no longer exist on disk, the re-export silently writes a
82
+ // refreshed body whose filesAffected still names the vanished paths.
83
+ // That is the documented contract, but it is also a footgun — a later
84
+ // `verify` then fails on manifest-consistency with no obvious trigger.
85
+ // Emit one advisory warning up-front when the drift is cheap to detect,
86
+ // so the operator can re-run with `--scan` or `--files` before the stale
87
+ // filesAffected lands in patches.json.
88
88
  const args = { patch, paths, manifest, currentFilesAffected, ctx: adjacentCtx };
89
89
  if (await reportAdjacentUnmanagedFiles(args))
90
90
  return false;
@@ -105,11 +105,11 @@ async function reExportSinglePatch(patch, paths, manifest, options, isDryRun, co
105
105
  for (const f of removed)
106
106
  info(` - ${f}`);
107
107
  }
108
- // Stale-furnace-source gate (0.37.0 item 4): re-export captures deployed
109
- // engine copies, so a component source edited after the last furnace
110
- // apply would land in the patch as its OLD deployed content. Refuse (or
111
- // warn under --allow-stale-furnace) before diffing. Runs in dry-run too
112
- // so the failure surfaces early.
108
+ // Stale-furnace-source gate: re-export captures deployed engine copies, so
109
+ // a component source edited after the last furnace apply would land in the
110
+ // patch as its OLD deployed content. Refuse (or warn under
111
+ // --allow-stale-furnace) before diffing. Runs in dry-run too so the failure
112
+ // surfaces early.
113
113
  await enforceFreshFurnaceSources(paths.root, currentFilesAffected, options.allowStaleFurnace === true, 're-export');
114
114
  const missingFiles = await findMissingFiles(paths.engine, currentFilesAffected);
115
115
  if (missingFiles.length === currentFilesAffected.length) {
@@ -207,7 +207,7 @@ async function reExportSinglePatch(patch, paths, manifest, options, isDryRun, co
207
207
  */
208
208
  async function commitRefreshedPatch(args) {
209
209
  const { patch, paths, manifest, options, config, lintCtx, diffContent, updates } = args;
210
- await updatePatchAndMetadata(paths.patches, patch.filename, diffContent, updates, undefined, {
210
+ const bodyChanged = await updatePatchAndMetadata(paths.patches, patch.filename, diffContent, updates, undefined, {
211
211
  config,
212
212
  command: 're-export',
213
213
  forceUnsafe: options.forceUnsafe === true,
@@ -226,17 +226,25 @@ async function commitRefreshedPatch(args) {
226
226
  };
227
227
  }
228
228
  }
229
- success(`Re-exported ${patch.filename}`);
229
+ // A bulk run refreshes every patch; saying "Re-exported" for one whose body
230
+ // did not move buries the patches that DID move. The run still counts this
231
+ // patch as successfully refreshed, so `--stamp` completeness is unaffected.
232
+ if (bodyChanged) {
233
+ success(`Re-exported ${patch.filename}`);
234
+ }
235
+ else {
236
+ info(`Unchanged ${patch.filename}`);
237
+ }
230
238
  }
231
239
  /**
232
240
  * Threads the patch's own `lintIgnore` list through so the per-patch
233
241
  * suppression honoured by export/export-all is also honoured here — a
234
242
  * re-export could otherwise not refresh an advisory-noisy but intentional
235
- * patch without the blunt `--skip-lint`. The paired `patch.tier` threads
236
- * the explicit branding-threshold opt-in the same way. The CLI flags
237
- * `--tier` and `--lint-ignore` participate with append/union semantics
238
- * (explicit removal lives on `fireforge patch lint-ignore`), computed
239
- * before the lint pass so the new intent takes effect on this invocation.
243
+ * patch without the blunt `--skip-lint`. The paired `patch.tier` threads the
244
+ * explicit branding-threshold opt-in the same way. The CLI flags `--tier`
245
+ * and `--lint-ignore` participate with append/union semantics (explicit
246
+ * removal lives on `fireforge patch lint-ignore`), computed before the lint
247
+ * pass so the new intent takes effect on this invocation.
240
248
  */
241
249
  function computeReExportUpdates(patch, options, currentFilesAffected) {
242
250
  const existingIgnoreSet = new Set(patch.lintIgnore ?? []);
@@ -1,14 +1,14 @@
1
1
  // SPDX-License-Identifier: EUPL-1.2
2
2
  import { multiselect } from '@clack/prompts';
3
3
  import { getProjectPaths, loadConfig } from '../core/config.js';
4
+ import { stdioIsInteractive } from '../core/destructive.js';
5
+ import { assertEngineGitReady } from '../core/engine-precondition.js';
4
6
  import { collectFurnaceManagedPrefixes } from '../core/furnace-config.js';
5
- import { isGitRepository } from '../core/git.js';
6
7
  import { formatPatchNotFoundError } from '../core/patch-identifier-suggest.js';
7
8
  import { loadPatchesManifest, resolvePatchIdentifier, stampPatchVersions, } from '../core/patch-manifest.js';
8
9
  import { GeneralError, InvalidArgumentError } from '../errors/base.js';
9
10
  import { elapsedSince } from '../utils/elapsed.js';
10
11
  import { toError } from '../utils/errors.js';
11
- import { pathExists } from '../utils/fs.js';
12
12
  import { cancel, info, intro, isCancel, outro, spinner, success, warn } from '../utils/logger.js';
13
13
  import { loadScanFilesAssignments, withDryRunPurityGuard, withDryRunReExportLock, } from './re-export-bulk-scan.js';
14
14
  import { reExportFilesInPlace } from './re-export-files.js';
@@ -25,7 +25,7 @@ async function resolveSelectedPatches(patches, options, manifest) {
25
25
  for (const identifier of patches) {
26
26
  const match = resolvePatchIdentifier(identifier, manifest.patches);
27
27
  if (!match) {
28
- // Suggest, never dump: a wrong guess used to print the
28
+ // Suggest, never dump: a wrong guess would otherwise print the
29
29
  // whole ~300-entry manifest, burying the error it was reporting.
30
30
  throw new InvalidArgumentError(formatPatchNotFoundError(identifier, manifest.patches), identifier);
31
31
  }
@@ -34,7 +34,7 @@ async function resolveSelectedPatches(patches, options, manifest) {
34
34
  return selectedPatches;
35
35
  }
36
36
  // No patches specified — prompt or error
37
- const isInteractive = process.stdin.isTTY && process.stdout.isTTY;
37
+ const isInteractive = stdioIsInteractive();
38
38
  if (!isInteractive) {
39
39
  throw new InvalidArgumentError('Specify patch identifiers or use --all in non-interactive mode.\n\n' +
40
40
  'Usage: fireforge re-export [patches...] or fireforge re-export --all', 'patches');
@@ -72,18 +72,11 @@ export async function reExportCommand(projectRoot, patches, options) {
72
72
  const isDryRun = options.dryRun === true;
73
73
  intro(isDryRun ? 'FireForge Re-export (dry run)' : 'FireForge Re-export');
74
74
  // Accept export-style space-separated paths after --files by folding
75
- // path-shaped extra positionals into the file list (0.34.0 field report).
75
+ // path-shaped extra positionals into the file list.
76
76
  ({ patches, options } = applyReExportFilesPositionalFolding(patches, options));
77
77
  validateReExportOptionCombinations(patches, options);
78
78
  const paths = getProjectPaths(projectRoot);
79
- // Check if engine exists
80
- if (!(await pathExists(paths.engine))) {
81
- throw new GeneralError('Firefox source not found. Run "fireforge download" first.');
82
- }
83
- // Check if it's a git repository
84
- if (!(await isGitRepository(paths.engine))) {
85
- throw new GeneralError('Engine directory is not a git repository. Run "fireforge download" to initialize.');
86
- }
79
+ await assertEngineGitReady(paths.engine);
87
80
  // Load the manifest
88
81
  const manifest = await loadPatchesManifest(paths.patches);
89
82
  if (!manifest || manifest.patches.length === 0) {
@@ -258,14 +251,13 @@ function throwRunLevelRefusals(adjacentCtx, driftCtx, progress) {
258
251
  }
259
252
  }
260
253
  /**
261
- * Prints the end-of-run summary and enforces the exit contract:
262
- * a partial run exits non-zero BY DEFAULT (adjudicated for 0.41.0, per the
263
- * follow-up 0.40.0's G7 recorded). "Re-exported 2 of 3" used to print and
264
- * exit 0, letting a partial refresh ride an `&&` chain as success. The
265
- * summary still prints first so the honest "N of M" accounting stays
266
- * visible; the throw then carries the failed/skipped breakdown. Dry-run
267
- * included: a preview reporting that the real run would partially fail
268
- * must not read as a passing preview in scripts.
254
+ * Prints the end-of-run summary and enforces the exit contract: a partial run
255
+ * exits non-zero by default. "Re-exported 2 of 3" printing with exit 0 lets a
256
+ * partial refresh ride an `&&` chain as success. The summary still prints
257
+ * first so the honest "N of M" accounting stays visible; the throw then
258
+ * carries the failed/skipped breakdown. Dry-run included: a preview
259
+ * reporting that the real run would partially fail must not read as a passing
260
+ * preview in scripts.
269
261
  */
270
262
  function reportReExportOutcome(args) {
271
263
  const { isDryRun, reExported, selectedCount, config, progress } = args;