@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
@@ -2,9 +2,10 @@
2
2
  import { basename, join } from 'node:path';
3
3
  import { GeneralError, InvalidArgumentError } from '../errors/base.js';
4
4
  import { pathExists, readText } from '../utils/fs.js';
5
+ import { warn } from '../utils/logger.js';
5
6
  import { escapeRegex } from '../utils/regex.js';
6
7
  import { getProjectPaths, loadConfig } from './config.js';
7
- import { registerBrowserContent, registerFireForgeModule, registerSharedCSS, registerTestManifest, registerToolkitWidget, } from './manifest-register.js';
8
+ import { registerBrowserContent, registerFireForgeModule, registerSharedCSS, registerTestManifest, registerToolkitWidget, } from './moz-manifest-register.js';
8
9
  import { isXpcshellTestRegistered, registerXpcshellTest } from './register-xpcshell-test.js';
9
10
  /**
10
11
  * Returns manifest registration rules for the supported engine file
@@ -21,64 +22,65 @@ export function getRules(binaryName, createManifest = false) {
21
22
  isRegistered: (engineDir, fileName) => isSharedCSSRegistered(engineDir, fileName),
22
23
  register: (engineDir, after, dryRun, fileName) => registerSharedCSS(engineDir, fileName, after, dryRun),
23
24
  extractArgs: (m) => [m[1] ?? ''],
25
+ supportsAfter: true,
24
26
  },
25
27
  {
26
28
  // `.inc.xhtml` fragments under browser/base/content/ are deliberately
27
29
  // excluded: they are consumed via `#include` from a registered chrome
28
- // document (typically browser.xhtml) and do not get their own
29
- // packaged chrome URI. Before this carve-out, `status` flagged every
30
- // wired fragment as "potentially unregistered" and `register --dry-run`
31
- // proposed a bogus jar.mn entry. The lookahead blocks the match so
32
- // `getUnregistrableAdvice` gets a chance to emit the correct
33
- // guidance for the `.inc.xhtml` case.
30
+ // document (typically browser.xhtml) and do not get their own packaged
31
+ // chrome URI. Without the carve-out, `status` flags every wired
32
+ // fragment as "potentially unregistered" and `register --dry-run`
33
+ // proposes a bogus jar.mn entry. The lookahead blocks the match so
34
+ // `getUnregistrableAdvice` can emit the correct guidance instead.
34
35
  //
35
36
  // Test implementation files under `browser/base/content/test/` are
36
37
  // also excluded: they belong in the nearest `browser.toml` manifest,
37
- // not in jar.mn. 2026-04-23 eval 2: `status --unmanaged` proposed
38
- // `fireforge register browser/base/content/test/<dir>/browser_*.js`
39
- // which would have clutter-registered a test file as browser
40
- // chrome content. The negative lookahead routes those paths to
41
- // `getUnregistrableAdvice`, which returns the correct
42
- // browser.toml-centric guidance.
38
+ // not in jar.mn. The negative lookahead routes those paths to
39
+ // `getUnregistrableAdvice`, which returns browser.toml-centric
40
+ // guidance rather than proposing a jar.mn entry for a test file.
43
41
  pattern: /^browser\/base\/content\/(?!.+\.inc\.xhtml$)(?!test\/)(.+\.(?:js|mjs|xhtml|css))$/,
44
42
  isRegistered: (engineDir, fileName) => isBrowserContentRegistered(engineDir, fileName),
45
43
  register: (engineDir, after, dryRun, fileName) => registerBrowserContent(engineDir, fileName, after, undefined, dryRun),
46
44
  extractArgs: (m) => [m[1] ?? ''],
45
+ supportsAfter: true,
47
46
  },
48
47
  {
49
48
  // Fork-owned browser.toml manifests at ARBITRARY depth under
50
- // browser/base/content/test/ (0.34.0 field report: only one level
51
- // was supported, rejecting nested browser-chrome manifests).
49
+ // browser/base/content/test/ — a one-level pattern rejects nested
50
+ // browser-chrome manifests.
52
51
  pattern: /^browser\/base\/content\/test\/((?:[^/]+\/)*[^/]+)\/browser\.toml$/,
53
52
  isRegistered: (_engineDir, testDir) => isTestManifestRegistered(_engineDir, testDir),
54
53
  register: (_engineDir, _after, dryRun, testDir) => registerTestManifest(_engineDir, testDir, dryRun),
55
54
  extractArgs: (m) => [m[1] ?? ''],
55
+ supportsAfter: false,
56
56
  },
57
57
  {
58
58
  pattern: new RegExp(`^browser/modules/${escapeRegex(binaryName)}/(.+\\.sys\\.mjs)$`),
59
59
  isRegistered: (_engineDir, fileName) => isFireForgeModuleRegistered(_engineDir, fileName, moduleDir),
60
60
  register: (_engineDir, _after, dryRun, fileName) => registerFireForgeModule(_engineDir, fileName, moduleDir, dryRun, createManifest),
61
61
  extractArgs: (m) => [m[1] ?? ''],
62
+ supportsAfter: false,
62
63
  },
63
64
  {
64
65
  pattern: /^toolkit\/content\/widgets\/([^/]+)\/(.+\.(?:mjs|css))$/,
65
66
  isRegistered: (_engineDir, tagName, fileName) => isToolkitWidgetRegistered(_engineDir, tagName, fileName),
66
67
  register: (_engineDir, _after, dryRun, tagName, fileName) => registerToolkitWidget(_engineDir, tagName, fileName, dryRun),
67
68
  extractArgs: (m) => [m[1] ?? '', m[2] ?? ''],
69
+ supportsAfter: false,
68
70
  },
69
71
  {
70
- // xpcshell test files (0.34.0 field report: rejected as "Unknown
71
- // file pattern"). Any `test_*.js` outside browser/base/content/test/
72
- // (which stays browser-chrome territory with its browser.toml
73
- // guidance) registers into the directory's xpcshell.toml; with
74
- // --create-manifest a missing manifest is scaffolded and wired via
75
- // XPCSHELL_TESTS_MANIFESTS.
72
+ // xpcshell test files. Any `test_*.js` outside
73
+ // browser/base/content/test/ (which stays browser-chrome territory
74
+ // with its browser.toml guidance) registers into the directory's
75
+ // xpcshell.toml; with --create-manifest a missing manifest is
76
+ // scaffolded and wired via XPCSHELL_TESTS_MANIFESTS.
76
77
  pattern: /^(?!browser\/base\/content\/test\/)(.+)\/(test_[^/]+\.js)$/,
77
78
  isRegistered: (engineDir, dirRel, fileName) => isXpcshellTestRegistered(engineDir, dirRel, fileName),
78
79
  register: (engineDir, _after, dryRun, dirRel, fileName) => registerXpcshellTest(engineDir, dirRel, fileName, dryRun, createManifest),
79
80
  // Both groups are guaranteed by the pattern; slice avoids dead
80
81
  // fallback branches.
81
82
  extractArgs: (m) => m.slice(1, 3),
83
+ supportsAfter: false,
82
84
  },
83
85
  ];
84
86
  }
@@ -166,9 +168,8 @@ function getUnregistrableAdvice(filePath) {
166
168
  // scaffold intentionally does NOT auto-register — wiring
167
169
  // `XPCSHELL_TESTS_MANIFESTS` requires a deliberate choice about which
168
170
  // moz.build should own the entry. `register` surfaces that same guidance
169
- // instead of falling through to browser.toml-centric advice, which was
170
- // the eval finding (operator saw "register browser.toml" hint for a
171
- // path that was xpcshell-shaped and contained no browser.toml).
171
+ // instead of falling through to browser.toml-centric advice for a path
172
+ // that is xpcshell-shaped and contains no browser.toml.
172
173
  if (filePath.endsWith('/xpcshell.toml')) {
173
174
  return (`xpcshell.toml manifests are not auto-registered by "fireforge register". ` +
174
175
  `Add "XPCSHELL_TESTS_MANIFESTS += ['${basename(filePath)}']" to the ` +
@@ -241,6 +242,12 @@ export async function registerFile(root, filePath, dryRun = false, after, option
241
242
  const match = normalizedPath.match(rule.pattern);
242
243
  if (match) {
243
244
  const args = rule.extractArgs(match);
245
+ if (after !== undefined && !rule.supportsAfter) {
246
+ // Say so rather than inserting alphabetically and letting the
247
+ // operator believe their placement was honoured.
248
+ warn(`--after is not supported for ${normalizedPath}: this manifest is ` +
249
+ 'kept in sorted order, so the entry was inserted alphabetically.');
250
+ }
244
251
  return rule.register(engineDir, after, dryRun, ...args);
245
252
  }
246
253
  }
@@ -27,11 +27,9 @@ export declare function tokenizeJarMn(lines: string[]): JarMnToken[];
27
27
  * Tokenizes a moz.build Python list block, returning the tokens and their
28
28
  * line range within the file.
29
29
  *
30
- * Supports both multi-line lists (the common shape) and single-line
31
- * empty lists of the form `EXTRA_JS_MODULES += []` — the eval-2 finding
32
- * case where a freshly-scaffolded module directory's `moz.build`
33
- * started with an empty list and the tokenizer returned `null`,
34
- * leaving `register` unable to add the first entry.
30
+ * Supports both multi-line lists (the common shape) and single-line empty
31
+ * lists of the form `EXTRA_JS_MODULES += []`, which a freshly-scaffolded
32
+ * module directory's `moz.build` can start with.
35
33
  */
36
34
  export declare function tokenizeMozBuildList(lines: string[], listPattern: RegExp): {
37
35
  tokens: MozBuildToken[];
@@ -45,11 +45,9 @@ export function tokenizeJarMn(lines) {
45
45
  * Tokenizes a moz.build Python list block, returning the tokens and their
46
46
  * line range within the file.
47
47
  *
48
- * Supports both multi-line lists (the common shape) and single-line
49
- * empty lists of the form `EXTRA_JS_MODULES += []` — the eval-2 finding
50
- * case where a freshly-scaffolded module directory's `moz.build`
51
- * started with an empty list and the tokenizer returned `null`,
52
- * leaving `register` unable to add the first entry.
48
+ * Supports both multi-line lists (the common shape) and single-line empty
49
+ * lists of the form `EXTRA_JS_MODULES += []`, which a freshly-scaffolded
50
+ * module directory's `moz.build` can start with.
53
51
  */
54
52
  export function tokenizeMozBuildList(lines, listPattern) {
55
53
  const tokens = [];
@@ -60,16 +58,15 @@ export function tokenizeMozBuildList(lines, listPattern) {
60
58
  if (startLine === -1) {
61
59
  if (listPattern.test(raw)) {
62
60
  // Single-line empty-list handling: a fresh scaffold sometimes
63
- // writes `EXTRA_JS_MODULES += []` on one line. The pre-fix
64
- // tokenizer returned `null` because it never saw a line
65
- // starting with `]`, which stranded `register` with a "Could
66
- // not find module list section" error against the documented
67
- // browser/modules/<fork>/ scaffold (eval 2).
61
+ // writes `EXTRA_JS_MODULES += []` on one line, which a tokenizer
62
+ // looking for a line starting with `]` never closes — leaving
63
+ // `register` with a "Could not find module list section" error
64
+ // against the documented browser/modules/<fork>/ scaffold.
68
65
  //
69
66
  // The in-place split rewrites the single-line form into the
70
67
  // canonical multi-line shape so the caller's
71
- // `lines.splice(insertIndex, 0, entry)` lands inside the list
72
- // body. The tokens are emitted to mirror the new structure.
68
+ // `lines.splice(insertIndex, 0, entry)` lands inside the list body.
69
+ // The tokens are emitted to mirror the new structure.
73
70
  const singleLineMatch = /^([^[]*\[)\s*\]\s*$/.exec(raw);
74
71
  if (singleLineMatch) {
75
72
  const openPart = singleLineMatch[1] ?? '';
@@ -16,30 +16,28 @@ interface StatusFile {
16
16
  file: string;
17
17
  }
18
18
  /**
19
- * Builds the flat ownership table from the manifest, worktree status, and
20
- * the duplicate-new-file-creation map produced by cross-patch lint.
19
+ * Builds the flat ownership table from the manifest, worktree status, and the
20
+ * duplicate-new-file-creation map produced by cross-patch lint.
21
21
  *
22
22
  * Populated from three sources:
23
23
  *
24
- * 1. Every path in every patch's `filesAffected` — so managed paths
25
- * show up even when they are not currently modified on disk.
24
+ * 1. Every path in every patch's `filesAffected` — so managed paths show up
25
+ * even when they are not currently modified on disk.
26
26
  * 2. Any worktree status entries not claimed by any patch (flagged as
27
27
  * `unmanaged`).
28
- * 3. Paths created by more than one patch in `new file mode`,
29
- * surfaced as ownership conflicts with
30
- * `conflictReason = 'duplicate-create'`. This is the alignment
31
- * fix between `status --ownership` and `fireforge verify`: a
32
- * queue that `verify` rejects for duplicate `/dev/null → b/foo.js`
33
- * creations was previously reported as clean here because the
34
- * check only walked `filesAffected`, not the patch bodies.
28
+ * 3. Paths created by more than one patch in `new file mode`, surfaced as
29
+ * ownership conflicts with `conflictReason = 'duplicate-create'`. This
30
+ * is what keeps `status --ownership` aligned with `fireforge verify`:
31
+ * walking only `filesAffected` reports a queue clean that `verify`
32
+ * rejects for duplicate `/dev/null → b/foo.js` creations.
35
33
  *
36
- * A path claimed by more than one patch (either via `filesAffected` or
37
- * as a duplicate creation) is flagged as `conflict` with the origin
38
- * recorded in `conflictReason` so the output can disambiguate.
34
+ * A path claimed by more than one patch (either via `filesAffected` or as a
35
+ * duplicate creation) is flagged as `conflict` with the origin recorded in
36
+ * `conflictReason` so the output can disambiguate.
39
37
  *
40
38
  * @param manifestPatches - Manifest rows, each with its `filesAffected`
41
- * @param worktreeFiles - Raw worktree status entries; untracked and
42
- * modified both acceptable
39
+ * @param worktreeFiles - Raw worktree status entries; untracked and modified
40
+ * both acceptable
43
41
  * @param newFileCreatorsByPath - Map produced by
44
42
  * {@link import('../core/patch-lint.js').collectNewFileCreatorsByPath};
45
43
  * paths with a `.length > 1` owner list become duplicate-create conflicts
@@ -1,30 +1,28 @@
1
1
  import { info } from '../utils/logger.js';
2
2
  import { buildPatchClaims } from './status-classify.js';
3
3
  /**
4
- * Builds the flat ownership table from the manifest, worktree status, and
5
- * the duplicate-new-file-creation map produced by cross-patch lint.
4
+ * Builds the flat ownership table from the manifest, worktree status, and the
5
+ * duplicate-new-file-creation map produced by cross-patch lint.
6
6
  *
7
7
  * Populated from three sources:
8
8
  *
9
- * 1. Every path in every patch's `filesAffected` — so managed paths
10
- * show up even when they are not currently modified on disk.
9
+ * 1. Every path in every patch's `filesAffected` — so managed paths show up
10
+ * even when they are not currently modified on disk.
11
11
  * 2. Any worktree status entries not claimed by any patch (flagged as
12
12
  * `unmanaged`).
13
- * 3. Paths created by more than one patch in `new file mode`,
14
- * surfaced as ownership conflicts with
15
- * `conflictReason = 'duplicate-create'`. This is the alignment
16
- * fix between `status --ownership` and `fireforge verify`: a
17
- * queue that `verify` rejects for duplicate `/dev/null → b/foo.js`
18
- * creations was previously reported as clean here because the
19
- * check only walked `filesAffected`, not the patch bodies.
13
+ * 3. Paths created by more than one patch in `new file mode`, surfaced as
14
+ * ownership conflicts with `conflictReason = 'duplicate-create'`. This
15
+ * is what keeps `status --ownership` aligned with `fireforge verify`:
16
+ * walking only `filesAffected` reports a queue clean that `verify`
17
+ * rejects for duplicate `/dev/null → b/foo.js` creations.
20
18
  *
21
- * A path claimed by more than one patch (either via `filesAffected` or
22
- * as a duplicate creation) is flagged as `conflict` with the origin
23
- * recorded in `conflictReason` so the output can disambiguate.
19
+ * A path claimed by more than one patch (either via `filesAffected` or as a
20
+ * duplicate creation) is flagged as `conflict` with the origin recorded in
21
+ * `conflictReason` so the output can disambiguate.
24
22
  *
25
23
  * @param manifestPatches - Manifest rows, each with its `filesAffected`
26
- * @param worktreeFiles - Raw worktree status entries; untracked and
27
- * modified both acceptable
24
+ * @param worktreeFiles - Raw worktree status entries; untracked and modified
25
+ * both acceptable
28
26
  * @param newFileCreatorsByPath - Map produced by
29
27
  * {@link import('../core/patch-lint.js').collectNewFileCreatorsByPath};
30
28
  * paths with a `.length > 1` owner list become duplicate-create conflicts
@@ -3,13 +3,27 @@ export interface ParserFallbackEvent {
3
3
  reason: string;
4
4
  }
5
5
  /** Returns recorded parser fallback events without clearing the event buffer. */
6
- export declare function peekParserFallbackEvents(): ParserFallbackEvent[];
7
6
  /** Returns and clears the recorded parser fallback events. */
8
7
  export declare function consumeParserFallbackEvents(): ParserFallbackEvent[];
9
8
  /**
10
9
  * Result of a parser-with-fallback invocation, carrying both the computed
11
10
  * value and metadata about which code path produced it.
12
11
  */
12
+ /**
13
+ * The `rethrowIf` predicate every AST-primary caller wants.
14
+ *
15
+ * Rethrows internal-invariant `GeneralError`s ("Unexpected empty …array"):
16
+ * those are programming bugs, and retrying the legacy scanner cannot fix a
17
+ * broken invariant — it just buries the stack. Everything else still falls
18
+ * back, which is load-bearing: the AST path raises a raw acorn SyntaxError
19
+ * on chrome sources acorn cannot parse (preprocessor directives), and
20
+ * BuildError when the file's shape is unexpected. Both are exactly what the
21
+ * legacy scanner is here to handle.
22
+ *
23
+ * @param error - The error the primary parser threw
24
+ * @returns True when the error must propagate instead of falling back
25
+ */
26
+ export declare function isInternalInvariantFailure(error: unknown): boolean;
13
27
  export interface ParserResult<T> {
14
28
  /** The computed value (from either the primary or fallback path). */
15
29
  value: T;
@@ -1,17 +1,36 @@
1
1
  // SPDX-License-Identifier: EUPL-1.2
2
+ import { GeneralError } from '../errors/base.js';
2
3
  import { toError } from '../utils/errors.js';
3
4
  import { warn } from '../utils/logger.js';
4
5
  const parserFallbackEvents = [];
5
6
  /** Returns recorded parser fallback events without clearing the event buffer. */
6
- export function peekParserFallbackEvents() {
7
- return [...parserFallbackEvents];
8
- }
9
7
  /** Returns and clears the recorded parser fallback events. */
10
8
  export function consumeParserFallbackEvents() {
11
9
  const events = [...parserFallbackEvents];
12
10
  parserFallbackEvents.length = 0;
13
11
  return events;
14
12
  }
13
+ /**
14
+ * Result of a parser-with-fallback invocation, carrying both the computed
15
+ * value and metadata about which code path produced it.
16
+ */
17
+ /**
18
+ * The `rethrowIf` predicate every AST-primary caller wants.
19
+ *
20
+ * Rethrows internal-invariant `GeneralError`s ("Unexpected empty …array"):
21
+ * those are programming bugs, and retrying the legacy scanner cannot fix a
22
+ * broken invariant — it just buries the stack. Everything else still falls
23
+ * back, which is load-bearing: the AST path raises a raw acorn SyntaxError
24
+ * on chrome sources acorn cannot parse (preprocessor directives), and
25
+ * BuildError when the file's shape is unexpected. Both are exactly what the
26
+ * legacy scanner is here to handle.
27
+ *
28
+ * @param error - The error the primary parser threw
29
+ * @returns True when the error must propagate instead of falling back
30
+ */
31
+ export function isInternalInvariantFailure(error) {
32
+ return error instanceof GeneralError;
33
+ }
15
34
  /**
16
35
  * Wraps a primary (AST/tokenizer) parser with a legacy (regex/line-based)
17
36
  * fallback. If the primary throws, a warning is logged and the fallback is
@@ -2,21 +2,19 @@
2
2
  * Fuzz-like patch application with escalating context reduction.
3
3
  *
4
4
  * Tries an exact `git apply` first, then retries with git's real
5
- * drift-tolerance knob: `-C<n>` (reduced context matching). `git apply`
6
- * has NO `--fuzz` option — that flag belongs to GNU `patch(1)`. The
7
- * original implementation passed `--fuzz=N`, which git rejects with a
8
- * usage error (exit 129) that the escalation loop swallowed, so every
9
- * "fuzzy" attempt silently failed and patches that would have applied
10
- * with context drift were reported as hard conflicts (2026-07-05 review,
11
- * finding H1; verified against git 2.50). If all context-reduction levels
12
- * fail, falls through to `git apply --reject` so the user gets `.rej`
13
- * files for manual resolution.
5
+ * drift-tolerance knob: `-C<n>` (reduced context matching). `git apply` has
6
+ * NO `--fuzz` option — that flag belongs to GNU `patch(1)`, and passing it
7
+ * makes git exit 129 with a usage error that an escalation loop will happily
8
+ * swallow, so every "fuzzy" attempt silently fails and patches that would
9
+ * have applied with context drift are reported as hard conflicts. If all
10
+ * context-reduction levels fail, falls through to `git apply --reject` so
11
+ * the user gets `.rej` files for manual resolution.
14
12
  *
15
13
  * Semantics note: GNU fuzz *fuzzily matches* context; `-C<n>` *ignores*
16
14
  * outer context lines instead. Step k maps to `-C(3-k)` (git's default
17
- * context width is 3), so the final step `-C0` matches on line positions
18
- * and -/+ content alone — the rough analogue of GNU `--fuzz=3` on a
19
- * 3-context patch.
15
+ * context width is 3), so the final step `-C0` matches on line positions and
16
+ * -/+ content alone — the rough analogue of GNU `--fuzz=3` on a 3-context
17
+ * patch.
20
18
  */
21
19
  export interface FuzzyApplyResult {
22
20
  /** Whether the patch was applied successfully. */
@@ -3,21 +3,19 @@
3
3
  * Fuzz-like patch application with escalating context reduction.
4
4
  *
5
5
  * Tries an exact `git apply` first, then retries with git's real
6
- * drift-tolerance knob: `-C<n>` (reduced context matching). `git apply`
7
- * has NO `--fuzz` option — that flag belongs to GNU `patch(1)`. The
8
- * original implementation passed `--fuzz=N`, which git rejects with a
9
- * usage error (exit 129) that the escalation loop swallowed, so every
10
- * "fuzzy" attempt silently failed and patches that would have applied
11
- * with context drift were reported as hard conflicts (2026-07-05 review,
12
- * finding H1; verified against git 2.50). If all context-reduction levels
13
- * fail, falls through to `git apply --reject` so the user gets `.rej`
14
- * files for manual resolution.
6
+ * drift-tolerance knob: `-C<n>` (reduced context matching). `git apply` has
7
+ * NO `--fuzz` option — that flag belongs to GNU `patch(1)`, and passing it
8
+ * makes git exit 129 with a usage error that an escalation loop will happily
9
+ * swallow, so every "fuzzy" attempt silently fails and patches that would
10
+ * have applied with context drift are reported as hard conflicts. If all
11
+ * context-reduction levels fail, falls through to `git apply --reject` so
12
+ * the user gets `.rej` files for manual resolution.
15
13
  *
16
14
  * Semantics note: GNU fuzz *fuzzily matches* context; `-C<n>` *ignores*
17
15
  * outer context lines instead. Step k maps to `-C(3-k)` (git's default
18
- * context width is 3), so the final step `-C0` matches on line positions
19
- * and -/+ content alone — the rough analogue of GNU `--fuzz=3` on a
20
- * 3-context patch.
16
+ * context width is 3), so the final step `-C0` matches on line positions and
17
+ * -/+ content alone — the rough analogue of GNU `--fuzz=3` on a 3-context
18
+ * patch.
21
19
  */
22
20
  import { InvalidArgumentError } from '../errors/base.js';
23
21
  import { verbose } from '../utils/logger.js';
@@ -84,16 +82,15 @@ export async function applyPatchWithFuzz(patchPath, engineDir, maxFuzz = 3) {
84
82
  /**
85
83
  * Extracts `.rej` file paths from `git apply --reject` stderr.
86
84
  *
87
- * Git's actual output shape (verified against git 2.50):
85
+ * Git's output shape:
88
86
  *
89
87
  * Applying patch f.txt with 1 reject...
90
88
  * Rejected hunk #1.
91
89
  *
92
- * The reject file is `<file>.rej` next to the target. The previous regex
93
- * (`Rejected hunk.*to (.+\.rej)`) targeted GNU `patch(1)`'s "saving
94
- * rejects to file X.rej" phrasing, which git never prints — so
95
- * `rejectFiles` was always empty and the conflict-summary ".rej files
96
- * created" hint never fired.
90
+ * The reject file is `<file>.rej` next to the target. Matching GNU
91
+ * `patch(1)`'s "saving rejects to file X.rej" phrasing instead — which git
92
+ * never prints — leaves `rejectFiles` always empty and the
93
+ * conflict-summary ".rej files created" hint never fires.
97
94
  */
98
95
  function extractRejectFiles(stderr) {
99
96
  const rejectFiles = [];
@@ -2,30 +2,12 @@
2
2
  * Patch orchestration — coordinates patch discovery, application, and validation.
3
3
  * Pure parsing, content transformation, and lock management are in separate modules.
4
4
  */
5
- import type { ImportSummary, PatchInfo, PatchMetadata, PatchResult } from '../types/commands/index.js';
5
+ import type { ImportSummary, PatchInfo, PatchMetadata } from '../types/commands/index.js';
6
6
  export { PatchError } from '../errors/patch.js';
7
7
  export { countPatches, discoverPatches, getAllTargetFilesFromPatch, getTargetFileFromPatch, isNewFilePatch, } from './patch-files.js';
8
8
  export { withPatchDirectoryLock } from './patch-lock.js';
9
9
  export { extractAffectedFiles, extractOrder, isNewFileInPatch } from './patch-parse.js';
10
10
  export { applyPatchToContent, extractNewFileContent } from './patch-transform.js';
11
- /**
12
- * Applies all patches in order. Rolls back all successfully applied
13
- * patches when one fails so the engine directory stays clean.
14
- * @param patchesDir - Path to the patches directory
15
- * @param engineDir - Path to the engine directory
16
- * @returns Results for each patch
17
- */
18
- export declare function applyPatches(patchesDir: string, engineDir: string): Promise<PatchResult[]>;
19
- /**
20
- * Validates that all patches can be applied.
21
- * @param patchesDir - Path to the patches directory
22
- * @param engineDir - Path to the engine directory
23
- * @returns Validation results
24
- */
25
- export declare function validatePatches(patchesDir: string, engineDir: string): Promise<{
26
- valid: boolean;
27
- errors: string[];
28
- }>;
29
11
  /**
30
12
  * Options for {@link applyPatchesWithContinue}.
31
13
  */
@@ -49,17 +31,14 @@ export interface ApplyPatchesOptions {
49
31
  * 1. **Exact filename** — `005-foo.patch`. Matches only that filename.
50
32
  * 2. **Filename without extension** — `005-foo`. Matches `005-foo.patch`.
51
33
  * 3. **Bare numeric ordinal** — `5` or `005`. Matches the patch whose
52
- * order prefix parses to the same integer (so `5` and `005` both
53
- * match `005-foo.patch`, and `05` matches too because parseInt
54
- * normalizes leading zeros).
34
+ * order prefix parses to the same integer (so `5` and `005` both match
35
+ * `005-foo.patch`, and `05` matches too because parseInt normalizes
36
+ * leading zeros).
55
37
  *
56
- * A purely-numeric identifier is treated **only** as an ordinal: it does
57
- * not also match a filename that happens to literally equal the digits.
58
- * That would require a patch literally named `5` or `005` — which would
59
- * collide with the filename prefix anyway — and we prefer the explicit
60
- * ordinal interpretation. The earlier form's `patchFilename === needle`
61
- * short-circuit was kept behind the numeric gate so the match stays
62
- * single-meaning per identifier.
38
+ * A purely-numeric identifier is treated **only** as an ordinal: it does not
39
+ * also match a filename that happens to literally equal the digits. That
40
+ * would require a patch literally named `5` or `005`, which would collide
41
+ * with the filename prefix anyway.
63
42
  */
64
43
  export declare function matchesUntilFilename(patchFilename: string, needle: string): boolean;
65
44
  /**
@@ -88,10 +67,10 @@ export interface PatchedContentContext {
88
67
  }
89
68
  /**
90
69
  * Builds a batched patched-content context that loads the manifest and
91
- * discovers patch files ONCE for many lookups, and memoizes each patch
92
- * body read across the batch. The old per-call helper re-ran
93
- * `loadPatchesManifest` + `discoverPatches` and re-read every affecting
94
- * patch body for every file — O(dirtyFiles × patches) redundant IO when
95
- * classifying a broad engine edit session during `status` or `import`.
70
+ * discovers patch files ONCE for many lookups, and memoizes each patch body
71
+ * read across the batch. A per-call helper re-runs `loadPatchesManifest` +
72
+ * `discoverPatches` and re-reads every affecting patch body for every file —
73
+ * O(dirtyFiles × patches) redundant IO when classifying a broad engine edit
74
+ * session during `status` or `import`.
96
75
  */
97
76
  export declare function createPatchedContentContext(patchesDir: string, engineDir: string): Promise<PatchedContentContext>;
@@ -10,7 +10,6 @@ import { toError } from '../utils/errors.js';
10
10
  import { pathExists, readText, writeText } from '../utils/fs.js';
11
11
  import { verbose } from '../utils/logger.js';
12
12
  import { isContainedRelativePath } from '../utils/paths.js';
13
- import { exec } from '../utils/process.js';
14
13
  import { applyPatchIdempotent, reversePatch } from './git.js';
15
14
  import { getFileContentFromHead } from './git-file-ops.js';
16
15
  import { discoverPatches } from './patch-files.js';
@@ -25,13 +24,14 @@ export { extractAffectedFiles, extractOrder, isNewFileInPatch } from './patch-pa
25
24
  export { applyPatchToContent, extractNewFileContent } from './patch-transform.js';
26
25
  /**
27
26
  * Applies a single patch.
27
+ *
28
28
  * @param patch - Patch info
29
29
  * @param engineDir - Path to the engine directory
30
30
  * @param protectedFiles - Files touched by patches already applied in the
31
31
  * current run; the idempotent-recovery reset must not wipe them (see
32
- * applyPatchIdempotent). Overlapping queues (`--allow-overlap`) share
33
- * files between patches, and a later patch's recovery used to reset the
34
- * shared file to HEAD — silently discarding the earlier patch's changes.
32
+ * applyPatchIdempotent). Overlapping queues (`--allow-overlap`) share files
33
+ * between patches, and resetting a shared file to HEAD during a later
34
+ * patch's recovery silently discards the earlier patch's changes.
35
35
  * @returns Patch result
36
36
  */
37
37
  async function applySinglePatch(patch, engineDir, protectedFiles) {
@@ -148,63 +148,6 @@ async function rollbackPatches(results, engineDir) {
148
148
  }
149
149
  }
150
150
  }
151
- /**
152
- * Applies all patches in order. Rolls back all successfully applied
153
- * patches when one fails so the engine directory stays clean.
154
- * @param patchesDir - Path to the patches directory
155
- * @param engineDir - Path to the engine directory
156
- * @returns Results for each patch
157
- */
158
- export async function applyPatches(patchesDir, engineDir) {
159
- const patches = await discoverPatches(patchesDir);
160
- const results = [];
161
- const appliedFiles = new Set();
162
- for (const patch of patches) {
163
- const result = await applySinglePatch(patch, engineDir, appliedFiles);
164
- results.push(result);
165
- if (result.success) {
166
- for (const file of extractAffectedFiles(await readText(patch.path))) {
167
- appliedFiles.add(file);
168
- }
169
- }
170
- // Stop on first failure and roll back all previously applied patches
171
- if (!result.success) {
172
- const succeeded = results.filter((r) => r.success);
173
- if (succeeded.length > 0) {
174
- verbose(`Rolling back ${succeeded.length} previously applied patch(es)…`);
175
- await rollbackPatches(succeeded, engineDir);
176
- }
177
- break;
178
- }
179
- }
180
- return results;
181
- }
182
- /**
183
- * Validates that all patches can be applied.
184
- * @param patchesDir - Path to the patches directory
185
- * @param engineDir - Path to the engine directory
186
- * @returns Validation results
187
- */
188
- export async function validatePatches(patchesDir, engineDir) {
189
- const patches = await discoverPatches(patchesDir);
190
- const errors = [];
191
- for (const patch of patches) {
192
- try {
193
- const patchContent = await readText(patch.path);
194
- await validatePatchTargets(patch, extractAffectedFiles(patchContent), engineDir);
195
- }
196
- catch (error) {
197
- errors.push(`${patch.filename}: ${toError(error).message}`);
198
- continue;
199
- }
200
- const result = await exec('git', ['apply', '--check', '--', patch.path], { cwd: engineDir });
201
- if (result.exitCode !== 0) {
202
- const message = result.stderr.trim() || 'git apply --check failed';
203
- errors.push(`${patch.filename}: ${message}`);
204
- }
205
- }
206
- return { valid: errors.length === 0, errors };
207
- }
208
151
  async function validatePatchTargets(patch, affectedFiles, engineDir) {
209
152
  // realpath the engine root once so containment is checked against the
210
153
  // physical tree (the root itself may sit behind a symlink, e.g. /tmp on
@@ -272,17 +215,14 @@ async function resolvePatchWriteDestination(targetPath) {
272
215
  * 1. **Exact filename** — `005-foo.patch`. Matches only that filename.
273
216
  * 2. **Filename without extension** — `005-foo`. Matches `005-foo.patch`.
274
217
  * 3. **Bare numeric ordinal** — `5` or `005`. Matches the patch whose
275
- * order prefix parses to the same integer (so `5` and `005` both
276
- * match `005-foo.patch`, and `05` matches too because parseInt
277
- * normalizes leading zeros).
218
+ * order prefix parses to the same integer (so `5` and `005` both match
219
+ * `005-foo.patch`, and `05` matches too because parseInt normalizes
220
+ * leading zeros).
278
221
  *
279
- * A purely-numeric identifier is treated **only** as an ordinal: it does
280
- * not also match a filename that happens to literally equal the digits.
281
- * That would require a patch literally named `5` or `005` — which would
282
- * collide with the filename prefix anyway — and we prefer the explicit
283
- * ordinal interpretation. The earlier form's `patchFilename === needle`
284
- * short-circuit was kept behind the numeric gate so the match stays
285
- * single-meaning per identifier.
222
+ * A purely-numeric identifier is treated **only** as an ordinal: it does not
223
+ * also match a filename that happens to literally equal the digits. That
224
+ * would require a patch literally named `5` or `005`, which would collide
225
+ * with the filename prefix anyway.
286
226
  */
287
227
  export function matchesUntilFilename(patchFilename, needle) {
288
228
  const isNumeric = /^\d+$/.test(needle);
@@ -395,11 +335,11 @@ export async function applyPatchesWithContinue(patchesDir, engineDir, optionsOrC
395
335
  }
396
336
  /**
397
337
  * Builds a batched patched-content context that loads the manifest and
398
- * discovers patch files ONCE for many lookups, and memoizes each patch
399
- * body read across the batch. The old per-call helper re-ran
400
- * `loadPatchesManifest` + `discoverPatches` and re-read every affecting
401
- * patch body for every file — O(dirtyFiles × patches) redundant IO when
402
- * classifying a broad engine edit session during `status` or `import`.
338
+ * discovers patch files ONCE for many lookups, and memoizes each patch body
339
+ * read across the batch. A per-call helper re-runs `loadPatchesManifest` +
340
+ * `discoverPatches` and re-reads every affecting patch body for every file —
341
+ * O(dirtyFiles × patches) redundant IO when classifying a broad engine edit
342
+ * session during `status` or `import`.
403
343
  */
404
344
  export async function createPatchedContentContext(patchesDir, engineDir) {
405
345
  const manifest = await loadPatchesManifest(patchesDir);