@hominis/fireforge 0.49.2 → 0.51.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 (400) hide show
  1. package/CHANGELOG.md +87 -1
  2. package/README.md +1 -1
  3. package/dist/bin/fireforge.js +6 -0
  4. package/dist/build-info.json +4 -4
  5. package/dist/src/commands/build-prelock.d.ts +20 -0
  6. package/dist/src/commands/build-prelock.js +50 -0
  7. package/dist/src/commands/build.d.ts +3 -1
  8. package/dist/src/commands/build.js +13 -6
  9. package/dist/src/commands/check-report.d.ts +41 -0
  10. package/dist/src/commands/check-report.js +91 -0
  11. package/dist/src/commands/check-run.d.ts +33 -0
  12. package/dist/src/commands/check-run.js +112 -0
  13. package/dist/src/commands/check-steps.d.ts +75 -0
  14. package/dist/src/commands/check-steps.js +200 -0
  15. package/dist/src/commands/check.d.ts +32 -0
  16. package/dist/src/commands/check.js +160 -0
  17. package/dist/src/commands/config.js +5 -6
  18. package/dist/src/commands/declarations-report.d.ts +43 -0
  19. package/dist/src/commands/declarations-report.js +76 -0
  20. package/dist/src/commands/doctor-engine-eslint.js +6 -1
  21. package/dist/src/commands/doctor-source-pin.js +4 -1
  22. package/dist/src/commands/export-adopt-check.d.ts +38 -0
  23. package/dist/src/commands/export-adopt-check.js +98 -0
  24. package/dist/src/commands/export-flow.js +29 -14
  25. package/dist/src/commands/export-placement-gate.d.ts +6 -2
  26. package/dist/src/commands/export-placement-gate.js +8 -0
  27. package/dist/src/commands/export-shared.d.ts +2 -1
  28. package/dist/src/commands/export-staged-registration.d.ts +46 -0
  29. package/dist/src/commands/export-staged-registration.js +91 -0
  30. package/dist/src/commands/forward-import-remedy.d.ts +32 -0
  31. package/dist/src/commands/forward-import-remedy.js +63 -0
  32. package/dist/src/commands/furnace/apply.js +3 -3
  33. package/dist/src/commands/furnace/chrome-doc-remove.d.ts +2 -1
  34. package/dist/src/commands/furnace/chrome-doc-remove.js +2 -2
  35. package/dist/src/commands/furnace/chrome-doc.d.ts +2 -1
  36. package/dist/src/commands/furnace/chrome-doc.js +2 -2
  37. package/dist/src/commands/furnace/create.js +2 -2
  38. package/dist/src/commands/furnace/deploy-named.d.ts +48 -0
  39. package/dist/src/commands/furnace/deploy-named.js +107 -0
  40. package/dist/src/commands/furnace/deploy.d.ts +3 -2
  41. package/dist/src/commands/furnace/deploy.js +50 -86
  42. package/dist/src/commands/furnace/diff.js +26 -3
  43. package/dist/src/commands/furnace/index.js +66 -41
  44. package/dist/src/commands/furnace/init.js +13 -6
  45. package/dist/src/commands/furnace/override.js +4 -2
  46. package/dist/src/commands/furnace/preview.js +4 -3
  47. package/dist/src/commands/furnace/refresh.js +2 -2
  48. package/dist/src/commands/furnace/remove.js +4 -3
  49. package/dist/src/commands/furnace/rename-dry-run.d.ts +29 -0
  50. package/dist/src/commands/furnace/rename-dry-run.js +127 -0
  51. package/dist/src/commands/furnace/rename-helpers.d.ts +7 -0
  52. package/dist/src/commands/furnace/rename-helpers.js +15 -1
  53. package/dist/src/commands/furnace/rename-registrations.d.ts +41 -0
  54. package/dist/src/commands/furnace/rename-registrations.js +98 -0
  55. package/dist/src/commands/furnace/rename.d.ts +2 -1
  56. package/dist/src/commands/furnace/rename.js +28 -66
  57. package/dist/src/commands/furnace/scan.d.ts +9 -4
  58. package/dist/src/commands/furnace/scan.js +11 -9
  59. package/dist/src/commands/furnace/sync.js +3 -2
  60. package/dist/src/commands/furnace/validate-report.d.ts +45 -0
  61. package/dist/src/commands/furnace/validate-report.js +91 -0
  62. package/dist/src/commands/furnace/validate.d.ts +1 -1
  63. package/dist/src/commands/furnace/validate.js +151 -113
  64. package/dist/src/commands/furnace/validation-output.js +14 -3
  65. package/dist/src/commands/lint-per-patch.js +36 -61
  66. package/dist/src/commands/lint-per-run-checkjs.js +2 -2
  67. package/dist/src/commands/lint-report.d.ts +8 -4
  68. package/dist/src/commands/lint-report.js +20 -5
  69. package/dist/src/commands/lint.js +15 -34
  70. package/dist/src/commands/manifest.js +4 -0
  71. package/dist/src/commands/park.d.ts +22 -0
  72. package/dist/src/commands/park.js +232 -0
  73. package/dist/src/commands/patch/delete-gap-notice.js +3 -1
  74. package/dist/src/commands/patch/delete.d.ts +1 -1
  75. package/dist/src/commands/patch/delete.js +24 -104
  76. package/dist/src/commands/patch/index.d.ts +3 -3
  77. package/dist/src/commands/patch/index.js +10 -4
  78. package/dist/src/commands/patch/lint-ignore-from.d.ts +44 -0
  79. package/dist/src/commands/patch/lint-ignore-from.js +142 -0
  80. package/dist/src/commands/patch/lint-ignore.d.ts +5 -1
  81. package/dist/src/commands/patch/lint-ignore.js +78 -31
  82. package/dist/src/commands/patch/move-files-create.js +34 -18
  83. package/dist/src/commands/patch/move-files-into.js +15 -7
  84. package/dist/src/commands/patch/move-files.js +6 -2
  85. package/dist/src/commands/patch/removal-created-files.d.ts +48 -0
  86. package/dist/src/commands/patch/removal-created-files.js +83 -0
  87. package/dist/src/commands/patch/removal-dependents.d.ts +63 -0
  88. package/dist/src/commands/patch/removal-dependents.js +133 -0
  89. package/dist/src/commands/patch/rename.js +20 -1
  90. package/dist/src/commands/patch/reserve.d.ts +33 -0
  91. package/dist/src/commands/patch/reserve.js +152 -0
  92. package/dist/src/commands/patch/retire.d.ts +34 -0
  93. package/dist/src/commands/patch/retire.js +133 -0
  94. package/dist/src/commands/patch/split-plan.d.ts +17 -8
  95. package/dist/src/commands/patch/split-plan.js +60 -28
  96. package/dist/src/commands/patch/split-staged.d.ts +108 -0
  97. package/dist/src/commands/patch/split-staged.js +202 -0
  98. package/dist/src/commands/patch/split.d.ts +5 -0
  99. package/dist/src/commands/patch/split.js +62 -17
  100. package/dist/src/commands/patch/stage.d.ts +34 -0
  101. package/dist/src/commands/patch/stage.js +153 -0
  102. package/dist/src/commands/patch/staged-dependency-batch.d.ts +48 -0
  103. package/dist/src/commands/patch/staged-dependency-batch.js +176 -0
  104. package/dist/src/commands/patch/staged-dependency-entries.d.ts +36 -0
  105. package/dist/src/commands/patch/staged-dependency-entries.js +52 -0
  106. package/dist/src/commands/patch/staged-dependency-from.d.ts +14 -0
  107. package/dist/src/commands/patch/staged-dependency-from.js +108 -0
  108. package/dist/src/commands/patch/staged-dependency-remove.d.ts +31 -0
  109. package/dist/src/commands/patch/staged-dependency-remove.js +80 -0
  110. package/dist/src/commands/patch/staged-dependency.js +54 -139
  111. package/dist/src/commands/re-export-adjacent-registrations.d.ts +20 -0
  112. package/dist/src/commands/re-export-adjacent-registrations.js +75 -0
  113. package/dist/src/commands/re-export-adjacent.d.ts +50 -2
  114. package/dist/src/commands/re-export-adjacent.js +160 -40
  115. package/dist/src/commands/re-export-bulk-scan.d.ts +2 -1
  116. package/dist/src/commands/re-export-bulk-scan.js +22 -7
  117. package/dist/src/commands/re-export-drift.d.ts +36 -8
  118. package/dist/src/commands/re-export-drift.js +73 -49
  119. package/dist/src/commands/re-export-files.js +11 -8
  120. package/dist/src/commands/re-export-hunks.d.ts +35 -0
  121. package/dist/src/commands/re-export-hunks.js +220 -0
  122. package/dist/src/commands/re-export-lint.d.ts +2 -1
  123. package/dist/src/commands/re-export-lint.js +23 -10
  124. package/dist/src/commands/re-export-options.js +74 -6
  125. package/dist/src/commands/re-export-preflight.d.ts +23 -0
  126. package/dist/src/commands/re-export-preflight.js +160 -0
  127. package/dist/src/commands/re-export-purity-scope.d.ts +18 -0
  128. package/dist/src/commands/re-export-purity-scope.js +131 -0
  129. package/dist/src/commands/re-export-register.js +56 -17
  130. package/dist/src/commands/re-export-removed.d.ts +13 -2
  131. package/dist/src/commands/re-export-removed.js +57 -12
  132. package/dist/src/commands/re-export-scan-owner.d.ts +44 -0
  133. package/dist/src/commands/re-export-scan-owner.js +116 -0
  134. package/dist/src/commands/re-export-scan.d.ts +19 -9
  135. package/dist/src/commands/re-export-scan.js +60 -24
  136. package/dist/src/commands/re-export-single.js +122 -46
  137. package/dist/src/commands/re-export-stale-registrations.d.ts +18 -0
  138. package/dist/src/commands/re-export-stale-registrations.js +62 -0
  139. package/dist/src/commands/re-export-summary.d.ts +28 -0
  140. package/dist/src/commands/re-export-summary.js +36 -0
  141. package/dist/src/commands/re-export.js +71 -57
  142. package/dist/src/commands/rebase/index.js +17 -17
  143. package/dist/src/commands/run.js +16 -2
  144. package/dist/src/commands/status-check.d.ts +55 -16
  145. package/dist/src/commands/status-check.js +92 -37
  146. package/dist/src/commands/status-json.d.ts +22 -9
  147. package/dist/src/commands/status-json.js +47 -32
  148. package/dist/src/commands/status-output.js +3 -1
  149. package/dist/src/commands/status-scope.d.ts +37 -0
  150. package/dist/src/commands/status-scope.js +54 -0
  151. package/dist/src/commands/status.js +66 -23
  152. package/dist/src/commands/test-browser-preflight.js +19 -3
  153. package/dist/src/commands/test-build-furnace.d.ts +22 -0
  154. package/dist/src/commands/test-build-furnace.js +54 -0
  155. package/dist/src/commands/test-build-phase.js +64 -41
  156. package/dist/src/commands/test-checkjs.js +10 -2
  157. package/dist/src/commands/test-diagnose.js +7 -0
  158. package/dist/src/commands/test-dispatch.d.ts +39 -0
  159. package/dist/src/commands/test-dispatch.js +211 -0
  160. package/dist/src/commands/test-furnace-reach.d.ts +37 -0
  161. package/dist/src/commands/test-furnace-reach.js +132 -0
  162. package/dist/src/commands/test-modes.d.ts +16 -1
  163. package/dist/src/commands/test-modes.js +24 -1
  164. package/dist/src/commands/test-multi-verdict.d.ts +61 -0
  165. package/dist/src/commands/test-multi-verdict.js +111 -0
  166. package/dist/src/commands/test-orchestrate.d.ts +52 -0
  167. package/dist/src/commands/test-orchestrate.js +240 -0
  168. package/dist/src/commands/test-perf-scope.d.ts +50 -0
  169. package/dist/src/commands/test-perf-scope.js +138 -0
  170. package/dist/src/commands/test-prelock.d.ts +51 -0
  171. package/dist/src/commands/test-prelock.js +273 -0
  172. package/dist/src/commands/test-register.js +69 -10
  173. package/dist/src/commands/test-results.d.ts +62 -0
  174. package/dist/src/commands/test-results.js +62 -0
  175. package/dist/src/commands/test-run.d.ts +13 -55
  176. package/dist/src/commands/test-run.js +74 -99
  177. package/dist/src/commands/test-shards.d.ts +110 -0
  178. package/dist/src/commands/test-shards.js +255 -0
  179. package/dist/src/commands/test-stale-gate.d.ts +5 -1
  180. package/dist/src/commands/test-stale-gate.js +60 -28
  181. package/dist/src/commands/test-verdict.d.ts +11 -1
  182. package/dist/src/commands/test-verdict.js +28 -1
  183. package/dist/src/commands/test.d.ts +6 -1
  184. package/dist/src/commands/test.js +120 -124
  185. package/dist/src/commands/token-lint.d.ts +14 -0
  186. package/dist/src/commands/token-lint.js +151 -0
  187. package/dist/src/commands/token.js +10 -0
  188. package/dist/src/commands/verify-scope.d.ts +28 -0
  189. package/dist/src/commands/verify-scope.js +67 -0
  190. package/dist/src/commands/verify.d.ts +10 -2
  191. package/dist/src/commands/verify.js +67 -36
  192. package/dist/src/core/build-baseline-types.d.ts +46 -0
  193. package/dist/src/core/build-baseline-validate.js +19 -0
  194. package/dist/src/core/build-baseline.d.ts +5 -1
  195. package/dist/src/core/build-baseline.js +3 -1
  196. package/dist/src/core/build-overwrite-guard.d.ts +50 -0
  197. package/dist/src/core/build-overwrite-guard.js +84 -4
  198. package/dist/src/core/build-prepare.d.ts +13 -0
  199. package/dist/src/core/build-prepare.js +42 -10
  200. package/dist/src/core/build-run-record.d.ts +74 -0
  201. package/dist/src/core/build-run-record.js +136 -0
  202. package/dist/src/core/checkjs-support-heads.d.ts +41 -0
  203. package/dist/src/core/checkjs-support-heads.js +104 -0
  204. package/dist/src/core/config-paths.d.ts +2 -2
  205. package/dist/src/core/config-paths.js +10 -0
  206. package/dist/src/core/config-validate-check.d.ts +8 -0
  207. package/dist/src/core/config-validate-check.js +219 -0
  208. package/dist/src/core/config-validate-file-size.d.ts +9 -6
  209. package/dist/src/core/config-validate-file-size.js +91 -2
  210. package/dist/src/core/config-validate-history.d.ts +11 -0
  211. package/dist/src/core/config-validate-history.js +38 -0
  212. package/dist/src/core/config-validate-patch-policy.js +100 -0
  213. package/dist/src/core/config-validate-test-toolchains.js +21 -0
  214. package/dist/src/core/config-validate-token-scales.d.ts +9 -0
  215. package/dist/src/core/config-validate-token-scales.js +92 -0
  216. package/dist/src/core/config-validate.js +20 -5
  217. package/dist/src/core/config.d.ts +5 -0
  218. package/dist/src/core/config.js +16 -0
  219. package/dist/src/core/coverage-dispatch.d.ts +24 -0
  220. package/dist/src/core/coverage-dispatch.js +44 -0
  221. package/dist/src/core/coverage-extend.d.ts +70 -45
  222. package/dist/src/core/coverage-extend.js +199 -144
  223. package/dist/src/core/coverage-records.d.ts +108 -0
  224. package/dist/src/core/coverage-records.js +384 -0
  225. package/dist/src/core/destructive.d.ts +7 -4
  226. package/dist/src/core/destructive.js +10 -10
  227. package/dist/src/core/engine-session-lock.d.ts +16 -1
  228. package/dist/src/core/engine-session-lock.js +38 -10
  229. package/dist/src/core/export-moved-code-shape.d.ts +49 -11
  230. package/dist/src/core/export-moved-code-shape.js +135 -44
  231. package/dist/src/core/file-lock-queue.d.ts +67 -0
  232. package/dist/src/core/file-lock-queue.js +221 -0
  233. package/dist/src/core/file-lock-shared.d.ts +57 -0
  234. package/dist/src/core/file-lock-shared.js +117 -0
  235. package/dist/src/core/file-lock.d.ts +13 -25
  236. package/dist/src/core/file-lock.js +163 -140
  237. package/dist/src/core/furnace-apply-output.d.ts +10 -0
  238. package/dist/src/core/furnace-apply-output.js +31 -1
  239. package/dist/src/core/furnace-apply.js +22 -12
  240. package/dist/src/core/furnace-composed-source.d.ts +76 -0
  241. package/dist/src/core/furnace-composed-source.js +167 -0
  242. package/dist/src/core/furnace-config-validate-exceptions.d.ts +16 -0
  243. package/dist/src/core/furnace-config-validate-exceptions.js +102 -0
  244. package/dist/src/core/furnace-config-validate.js +14 -0
  245. package/dist/src/core/furnace-css-fragments.d.ts +10 -0
  246. package/dist/src/core/furnace-css-fragments.js +26 -0
  247. package/dist/src/core/furnace-operation.d.ts +3 -3
  248. package/dist/src/core/furnace-registration-jar-inplace.d.ts +12 -0
  249. package/dist/src/core/furnace-registration-jar-inplace.js +80 -0
  250. package/dist/src/core/furnace-registration-remove.d.ts +22 -1
  251. package/dist/src/core/furnace-registration-remove.js +53 -17
  252. package/dist/src/core/furnace-registration-rename.d.ts +26 -0
  253. package/dist/src/core/furnace-registration-rename.js +77 -0
  254. package/dist/src/core/furnace-registration.d.ts +14 -4
  255. package/dist/src/core/furnace-registration.js +44 -10
  256. package/dist/src/core/furnace-staleness.d.ts +7 -0
  257. package/dist/src/core/furnace-staleness.js +34 -24
  258. package/dist/src/core/furnace-validate-accessibility.d.ts +8 -4
  259. package/dist/src/core/furnace-validate-accessibility.js +71 -28
  260. package/dist/src/core/furnace-validate-exceptions.d.ts +48 -0
  261. package/dist/src/core/furnace-validate-exceptions.js +80 -0
  262. package/dist/src/core/furnace-validate-icon-button.d.ts +7 -0
  263. package/dist/src/core/furnace-validate-icon-button.js +78 -0
  264. package/dist/src/core/furnace-validate.js +1 -1
  265. package/dist/src/core/harness-port-fallback.d.ts +60 -0
  266. package/dist/src/core/harness-port-fallback.js +96 -0
  267. package/dist/src/core/history-log-file.d.ts +61 -0
  268. package/dist/src/core/history-log-file.js +164 -0
  269. package/dist/src/core/history-log.d.ts +2 -1
  270. package/dist/src/core/history-log.js +2 -1
  271. package/dist/src/core/json-preserving-edit.d.ts +22 -0
  272. package/dist/src/core/json-preserving-edit.js +199 -0
  273. package/dist/src/core/line-prefixer.d.ts +18 -0
  274. package/dist/src/core/line-prefixer.js +34 -0
  275. package/dist/src/core/mach.d.ts +7 -0
  276. package/dist/src/core/mach.js +32 -10
  277. package/dist/src/core/module-resolution-preflight.d.ts +19 -3
  278. package/dist/src/core/module-resolution-preflight.js +24 -6
  279. package/dist/src/core/negative-control-compiled.d.ts +27 -0
  280. package/dist/src/core/negative-control-compiled.js +73 -0
  281. package/dist/src/core/negative-control-diff.d.ts +51 -0
  282. package/dist/src/core/negative-control-diff.js +179 -0
  283. package/dist/src/core/negative-control.d.ts +150 -0
  284. package/dist/src/core/negative-control.js +399 -0
  285. package/dist/src/core/objdir-install-manifests.d.ts +73 -0
  286. package/dist/src/core/objdir-install-manifests.js +226 -0
  287. package/dist/src/core/park-store.d.ts +63 -0
  288. package/dist/src/core/park-store.js +216 -0
  289. package/dist/src/core/patch-export-update.d.ts +6 -0
  290. package/dist/src/core/patch-export-update.js +13 -3
  291. package/dist/src/core/patch-export.d.ts +3 -2
  292. package/dist/src/core/patch-export.js +22 -16
  293. package/dist/src/core/patch-files.js +26 -8
  294. package/dist/src/core/patch-lint-checkjs-any-import.d.ts +39 -0
  295. package/dist/src/core/patch-lint-checkjs-any-import.js +63 -0
  296. package/dist/src/core/patch-lint-checkjs-diagnostics.d.ts +17 -0
  297. package/dist/src/core/patch-lint-checkjs-diagnostics.js +32 -0
  298. package/dist/src/core/patch-lint-checkjs.d.ts +10 -1
  299. package/dist/src/core/patch-lint-checkjs.js +20 -13
  300. package/dist/src/core/patch-lint-code-lines.d.ts +59 -0
  301. package/dist/src/core/patch-lint-code-lines.js +105 -0
  302. package/dist/src/core/patch-lint-cross.d.ts +3 -1
  303. package/dist/src/core/patch-lint-cross.js +17 -4
  304. package/dist/src/core/patch-lint-css.d.ts +8 -2
  305. package/dist/src/core/patch-lint-css.js +24 -14
  306. package/dist/src/core/patch-lint-file-size.d.ts +12 -5
  307. package/dist/src/core/patch-lint-file-size.js +22 -11
  308. package/dist/src/core/patch-lint-forward-registration-extended.d.ts +23 -0
  309. package/dist/src/core/patch-lint-forward-registration-extended.js +36 -11
  310. package/dist/src/core/patch-lint-forward-registration.js +10 -0
  311. package/dist/src/core/patch-lint-ignore.d.ts +196 -0
  312. package/dist/src/core/patch-lint-ignore.js +429 -0
  313. package/dist/src/core/patch-lint-ownership.d.ts +10 -0
  314. package/dist/src/core/patch-lint-ownership.js +26 -0
  315. package/dist/src/core/patch-lint-size-thresholds.d.ts +52 -0
  316. package/dist/src/core/patch-lint-size-thresholds.js +110 -0
  317. package/dist/src/core/patch-lint-size.d.ts +117 -0
  318. package/dist/src/core/patch-lint-size.js +331 -0
  319. package/dist/src/core/patch-lint-staged-registration.d.ts +18 -1
  320. package/dist/src/core/patch-lint-staged-registration.js +20 -0
  321. package/dist/src/core/patch-lint-token-scale.d.ts +57 -0
  322. package/dist/src/core/patch-lint-token-scale.js +286 -0
  323. package/dist/src/core/patch-lint.d.ts +11 -83
  324. package/dist/src/core/patch-lint.js +66 -288
  325. package/dist/src/core/patch-lock.js +7 -6
  326. package/dist/src/core/patch-manifest-consistency.js +7 -6
  327. package/dist/src/core/patch-manifest-io.d.ts +6 -3
  328. package/dist/src/core/patch-manifest-io.js +27 -9
  329. package/dist/src/core/patch-manifest-key-order.d.ts +24 -0
  330. package/dist/src/core/patch-manifest-key-order.js +61 -0
  331. package/dist/src/core/patch-manifest-stage.d.ts +46 -0
  332. package/dist/src/core/patch-manifest-stage.js +96 -0
  333. package/dist/src/core/patch-manifest-validate.js +61 -3
  334. package/dist/src/core/patch-order-legal.d.ts +26 -0
  335. package/dist/src/core/patch-order-legal.js +88 -0
  336. package/dist/src/core/patch-policy-content.d.ts +40 -0
  337. package/dist/src/core/patch-policy-content.js +216 -0
  338. package/dist/src/core/patch-policy.d.ts +22 -5
  339. package/dist/src/core/patch-policy.js +26 -12
  340. package/dist/src/core/patch-retired.d.ts +57 -0
  341. package/dist/src/core/patch-retired.js +92 -0
  342. package/dist/src/core/patch-subset.d.ts +16 -0
  343. package/dist/src/core/patch-subset.js +66 -0
  344. package/dist/src/core/preflight-wait.d.ts +20 -0
  345. package/dist/src/core/preflight-wait.js +38 -0
  346. package/dist/src/core/rebase-from-version.d.ts +46 -0
  347. package/dist/src/core/rebase-from-version.js +71 -0
  348. package/dist/src/core/run-log.d.ts +26 -0
  349. package/dist/src/core/run-log.js +106 -4
  350. package/dist/src/core/run-profile.d.ts +7 -0
  351. package/dist/src/core/run-profile.js +7 -1
  352. package/dist/src/core/smoke-patterns.d.ts +5 -0
  353. package/dist/src/core/smoke-patterns.js +13 -0
  354. package/dist/src/core/test-harness-crash.d.ts +19 -1
  355. package/dist/src/core/test-harness-crash.js +8 -9
  356. package/dist/src/core/test-harness-signature.d.ts +33 -0
  357. package/dist/src/core/test-harness-signature.js +23 -1
  358. package/dist/src/core/test-raw-log.d.ts +66 -0
  359. package/dist/src/core/test-raw-log.js +122 -0
  360. package/dist/src/core/test-run-completeness.d.ts +90 -0
  361. package/dist/src/core/test-run-completeness.js +184 -0
  362. package/dist/src/core/test-stale-check.d.ts +27 -1
  363. package/dist/src/core/test-stale-check.js +39 -49
  364. package/dist/src/core/test-stale-exempt.d.ts +40 -0
  365. package/dist/src/core/test-stale-exempt.js +70 -0
  366. package/dist/src/core/test-xpcshell-retry.d.ts +2 -0
  367. package/dist/src/core/test-xpcshell-retry.js +2 -1
  368. package/dist/src/core/token-lint.d.ts +53 -0
  369. package/dist/src/core/token-lint.js +131 -0
  370. package/dist/src/core/token-sibling-sheets.d.ts +46 -0
  371. package/dist/src/core/token-sibling-sheets.js +119 -0
  372. package/dist/src/core/tree-guard.js +5 -0
  373. package/dist/src/core/typecheck-shim.d.ts +6 -2
  374. package/dist/src/core/typecheck-shim.js +205 -4
  375. package/dist/src/core/typecheck.js +3 -1
  376. package/dist/src/index.d.ts +14 -3
  377. package/dist/src/index.js +6 -1
  378. package/dist/src/types/commands/index.d.ts +2 -2
  379. package/dist/src/types/commands/options.d.ts +212 -24
  380. package/dist/src/types/commands/patches.d.ts +118 -1
  381. package/dist/src/types/config.d.ts +264 -0
  382. package/dist/src/types/config.js +9 -0
  383. package/dist/src/types/furnace.d.ts +63 -1
  384. package/dist/src/types/furnace.js +7 -0
  385. package/dist/src/types/index.d.ts +1 -1
  386. package/dist/src/utils/options.d.ts +36 -7
  387. package/dist/src/utils/options.js +94 -8
  388. package/dist/src/utils/path-glob.d.ts +15 -0
  389. package/dist/src/utils/path-glob.js +47 -0
  390. package/dist/src/utils/regex.d.ts +15 -3
  391. package/dist/src/utils/regex.js +37 -16
  392. package/docs/configuration.md +369 -11
  393. package/docs/exit-codes.md +18 -1
  394. package/docs/furnace.md +139 -3
  395. package/docs/lifecycle-invariants.md +65 -30
  396. package/docs/machine-output.md +120 -12
  397. package/docs/patch-workflow.md +458 -22
  398. package/docs/run-logs.md +20 -1
  399. package/docs/testing.md +346 -21
  400. package/package.json +3 -3
package/docs/testing.md CHANGED
@@ -19,6 +19,149 @@ FireForge announces this with a notice, since isolated instances do not
19
19
  exercise cross-argument state. `--no-shard` restores one combined
20
20
  invocation.
21
21
 
22
+ ## Several runs under one lock hold
23
+
24
+ Every `fireforge test` holds the engine-session lock for its whole run. Three
25
+ request shapes run more than one mach invocation inside that one hold, so a
26
+ peer cannot take the lock, build, or replace the packaging record between
27
+ them:
28
+
29
+ - **Mixed harnesses.** xpcshell and browser/mochitest paths in one request
30
+ run as two consecutive mach invocations, the xpcshell half first. With
31
+ `--build`, one pre-test build packages both halves (its coverage claim is
32
+ the union), and the second half runs build-less against it. Before 0.50.0
33
+ a mixed request was refused, and the documented split lost its coverage
34
+ claim to peers' scoped builds between the steps.
35
+ - **`--repeat <n>`** runs the same selection n times. A `--build` builds
36
+ once, and `--doctor` probes once. Every run is reported, so a flaky suite's
37
+ rate is visible from one invocation.
38
+ - **`--negative-control <diff>`**, below.
39
+
40
+ Each sub-run prints the verdict it would have printed alone as a
41
+ `FIREFORGE-RUN:` line (its own status, reason and counts, plus
42
+ `run=<i>/<n>` and, for a mixed request, `harness=xpcshell|mochitest`). The
43
+ invocation still ends with exactly one `FIREFORGE-VERDICT:` line:
44
+ `PASS runs=<n>/<n>`, or `FAIL reason=<most structural failing run>
45
+ [note=…] runs=<passed>/<planned>`. Runs continue after a red or a crash; a
46
+ preflight refusal or an inconclusive run stops the invocation, since the
47
+ runs after it would not be comparable. `--mach-arg` and every other option
48
+ apply to each sub-run. `--repeat` and `--negative-control` need explicit
49
+ paths and cannot be combined with `--build-only`, `--canary` or `--auto`.
50
+
51
+ ## Negative controls
52
+
53
+ A negative control proves a test can fail: neuter the code under test, run
54
+ the test, and expect red. Done by hand on a shared engine it is dangerous.
55
+ The objdir's chrome and widget files are symlinks into `engine/`, so the
56
+ browser reads the sources when it loads them, after the build step. A
57
+ mutation is therefore live for every build and suite that touches the file
58
+ while it is in place: a peer's `test --build` can build and test the
59
+ neuter, a `--build` run re-deploys `components/` over an engine-side
60
+ control, and a neuter restored at `Build complete` (or after the first
61
+ `TEST_START`) is already gone for the later shards of the same run.
62
+
63
+ `fireforge test --negative-control <diff> <paths…>` makes the control part
64
+ of the run:
65
+
66
+ 1. The diff is read (resolved against the project root), parsed, and every
67
+ hunk is checked against the current file before anything else, so a
68
+ stale control is refused (`note=negative-control`) before the build. A
69
+ `components/` target is checked after the build instead, because the
70
+ build redeploys it.
71
+ 2. With `--build`, the pre-test build (including the Furnace deploy)
72
+ runs first and packages the clean sources.
73
+ 3. After every gate has passed and right before the harness spawns, the
74
+ control is applied. It stays in place until the run, every shard of it,
75
+ has finished.
76
+ 4. The files are restored byte-exact. Then the next repetition (if any)
77
+ re-applies it, and only after the last restore is the lock released.
78
+
79
+ The diff is `git diff` output (a `diff --git` header per file). Paths may be
80
+ project-relative (`engine/…`, `components/…`) or engine-relative, so both
81
+ `git diff` at the project root and `git -C engine diff` work. A
82
+ `components/custom/<name>/<file>.mjs|.css` or
83
+ `components/overrides/<name>/<file>` path is applied to the engine copy
84
+ Furnace deployed it to, since that is what the run reads; the component
85
+ source itself is never touched. Only modifications of existing text files
86
+ are accepted: a created, deleted, renamed or binary file, or a symlinked
87
+ target, is refused. Hunks must match exactly; the only tolerance is a line
88
+ offset, as in `git apply`, never fuzz.
89
+
90
+ The verdict says how the control came out with `control=`:
91
+
92
+ - `caught`: every repetition went red with `reason=test-failures`, which is
93
+ what a control is for. The invocation exits 0.
94
+ - `missed`: a repetition stayed green with the mutation in place, so the
95
+ selected tests do not detect it. Exit 5, like a red suite.
96
+ - `inconclusive`: a run crashed, found no tests, was refused, or did not
97
+ run. The exit code is that failure's.
98
+
99
+ The status word keeps describing what the harness saw, so a caught control
100
+ reads `FIREFORGE-VERDICT: FAIL reason=test-failures … control=caught` and
101
+ exits 0. Key a control's success on `control=caught`, not on `PASS`.
102
+
103
+ A one-run control keeps its own counts on the verdict line; a repeated or
104
+ mixed one aggregates them as above. The mutation targets what the objdir
105
+ symlinks. A file the build preprocesses or copies (rather than links) is
106
+ read from the objdir, not from `engine/`, so a control on it stays green
107
+ and reports `missed`: that result is the signal to target the file the
108
+ browser actually loads.
109
+
110
+ A control on compiled source (C/C++, Rust, IDL, WebIDL, IPDL or YAML that no
111
+ install manifest ships) can only reach the binary through a build. Without
112
+ `--build` it is refused before the lock. With `--build` it is applied before
113
+ the pre-test build, so the binary under test carries it, stays applied for
114
+ every `--repeat` run, and is restored with a fresh mtime so the next build
115
+ recompiles the original. The verdict adds `control-build=compiled`. A
116
+ build-less control whose packaging is not current is refused before the
117
+ lock with the advice to add `--build`, instead of ending `inconclusive`
118
+ after a full queue.
119
+
120
+ Besides `git diff` output, a control may be a plain unified diff
121
+ (`diff -u`, no `diff --git` lines; the path comes from `---`/`+++`) or a
122
+ `git diff --no-index <engine file> <edited copy>`: when the new side names a
123
+ copy outside `engine/` and `components/`, the control targets the old side.
124
+
125
+ ### The restore safety model
126
+
127
+ - **Only under the lock.** Apply, run and restore all happen inside the
128
+ engine-session lock hold of the `fireforge test` invocation, and the
129
+ control is applied after the pre-test build. No peer build or test
130
+ observes it, and the build cannot overwrite it or trip `stale-build`
131
+ over it.
132
+ - **Journal first.** Before the first mutated byte is written, the
133
+ original bytes of every target go to `.fireforge/negative-control/`
134
+ with a journal of each file's original and mutated SHA-256, mode and
135
+ timestamps. Every write (originals, journal, mutation, restore) is an
136
+ atomic temp-file-and-rename. A failure while writing the mutation puts
137
+ back whatever was written before the run can start.
138
+ - **Byte-exact restore, verified.** Restore writes the original bytes back,
139
+ re-applies the original mode and timestamps (so make-based tooling sees
140
+ no change either), and reads the file back to prove the bytes match. The
141
+ stale-build gate hashes content, so a repeated control's next run is not
142
+ refused.
143
+ - **Never clobber.** A file is only restored while it still holds exactly
144
+ the bytes the control wrote. A file someone edited while the control ran
145
+ (an agent working outside the lock, say) keeps that edit. Its original
146
+ stays in the journal directory, and the run ends
147
+ `FAIL reason=inconclusive note=negative-control-restore` with the paths
148
+ named. Reconcile by hand, then delete the directory.
149
+ - **Every exit path.** Pass, red, crash and a refusal after the apply all
150
+ restore in the run's own control flow. SIGINT and SIGTERM restore in the
151
+ signal pipeline after the harness has shut down and before the held
152
+ locks are released. A restore already in flight is awaited, not
153
+ repeated.
154
+ - **Even after SIGKILL.** A SIGKILLed FireForge cannot restore, but the
155
+ journal survives it. Every later `fireforge test` checks for it first,
156
+ under the lock, before any gate or build: a file still holding the
157
+ control's bytes is restored, with a notice; any other state refuses with
158
+ `note=negative-control-pending` rather than guess.
159
+
160
+ The shorthand `--mutate <file> <old> <new>` that was proposed alongside this
161
+ was not added. Commander options take one value, so a three-value option
162
+ would have to swallow the positional test paths. A one-hunk diff expresses
163
+ the same edit and can be reviewed before it runs.
164
+
22
165
  ## Pathless runs must choose a mode
23
166
 
24
167
  - `--auto` forwards mach's own auto-selection.
@@ -32,22 +175,94 @@ invocation.
32
175
  When packageable engine files changed since the last successful FireForge
33
176
  build, `test` fails before launching stale artifacts. Use `--build` to
34
177
  refresh, or `--allow-stale-build` only for intentional out-of-band rebuilds.
178
+ The refusal prints the one-line repackaging command for the requested paths
179
+ (`fireforge test --build-only <paths>`), so a build-less sitting can
180
+ repackage without dispatching anything.
181
+
182
+ Two kinds of edit do not count as stale, because the packaged runtime
183
+ already serves them. FireForge reads the objdir's install manifests
184
+ (`obj-*/_build_manifests/install/*`, `obj-*/faster/install_*`) to decide:
185
+
186
+ - a file whose every objdir copy is a symlink resolving to the edited source
187
+ (the usual dev-build shape on macOS and Linux for chrome scripts and test
188
+ files);
189
+ - a test file the build does not package: one installed only by `mach test`
190
+ itself at dispatch (`_test_files`), or a test-tree file no manifest installs.
191
+
192
+ A copy, a preprocessed file, a symlink that does not resolve to the source,
193
+ or an unreadable objdir keeps the edit stale. Exempted edits are named on
194
+ the run (and in the refusal, when other edits are stale). On a
195
+ `--perf-samples` run the refusal also says which stale files are staging
196
+ inputs of the sampled test and which lie elsewhere, so a sample whose fixture
197
+ is unaffected can proceed knowingly under `--allow-stale-build`.
198
+
199
+ ### Packaging coverage
35
200
 
36
201
  `--build-only` packages mixed-harness paths once, and then each harness half
37
- can run without `--build`. Scoped builds retain prior coverage automatically
38
- when engine HEAD, `engine/mozconfig` and recorded staging inputs outside the
39
- rebuilt scope are unchanged. Changed files explicitly included in this
40
- build are allowed. The fingerprints include test scripts and support files,
41
- not only packageable chrome sources. A failed anchor narrows the claim and
42
- prints the dropped paths; `--extend-coverage` instead refuses. Baselines
43
- without complete staging-input fingerprints require a new build before they
44
- can retain prior coverage.
45
- New dirty inputs outside the rebuilt scope invalidate retention conservatively,
46
- including shared fixtures outside test directories.
202
+ can run without `--build`. A plain mixed `test --build` now does both in one
203
+ invocation (see [Several runs under one lock hold](#several-runs-under-one-lock-hold)). Coverage is kept per staged path. Each path of a
204
+ scoped build records its own staging inputs: its manifest directory (the
205
+ nearest directory at or above it with a test manifest) plus whatever a
206
+ manifest there names outside it (`support-files`, `head`, `!/` shared
207
+ fixtures), with their content at that build. A later scoped build keeps every
208
+ earlier path whose own inputs and `engine/mozconfig` are unchanged, whatever
209
+ moved elsewhere in the engine, including a peer's edits and an engine HEAD
210
+ move that touches none of them. A path whose inputs changed is dropped and
211
+ named, with the inputs that changed. Changed inputs this build restages are
212
+ allowed, and a scoped build of one file restages that file's test manifest
213
+ too: a manifest that gained an entry for the new file no longer drops the
214
+ claims of its sibling files. A build-less run's packaging gates also run
215
+ before the lock is requested, so a `coverage-replaced` or `stale-build`
216
+ refusal arrives before the run queues.
217
+
218
+ A scoped build after a full build keeps the claim full while nothing outside
219
+ its scope moved. Otherwise it carries the full build's anchor forward, and a
220
+ later build-less run over any path stays covered while that path's own
221
+ staging inputs are unchanged since the full build. A refusal names the inputs
222
+ that did change.
223
+
224
+ `--extend-coverage` remains accepted. Retention is now the default, so the
225
+ flag only turns a drop into a refusal before the build. Before 0.50.0 a
226
+ scoped build without the flag replaced the claim whenever anything outside
227
+ its scope had changed, and the flag refused unless engine HEAD, the
228
+ mozconfig and every staging input recorded by the previous build were
229
+ unchanged. Baselines without complete staging-input fingerprints (older than
230
+ 0.49.0) cannot prove anything unchanged and are dropped once.
231
+
232
+ ### Furnace components in a pre-test build
233
+
234
+ `test --build` and `--build-only` run `furnace apply` first, like
235
+ `fireforge build`, and that apply deploys every component whose
236
+ `components/` source changed since its last deploy, another session's
237
+ undeployed edits included. The run names those components in a notice and
238
+ on the verdict line (`furnace-applied=<names>`). `--no-furnace-apply`
239
+ packages `engine/` as it stands, for example for a before-capture, names the
240
+ components with undeployed edits it left out, and stamps
241
+ `furnace-apply=skipped`.
242
+
243
+ On a shared engine a peer's default `test --build` deploys every session's
244
+ undeployed component edits. `--furnace-apply reached` (or
245
+ `test.furnaceApply: "reached"`) deploys only the components a requested test
246
+ reaches: the test path, the test file, a `head*.js` beside it, or any test
247
+ file under a requested directory names the component. The rest are named in
248
+ a notice and stamped `furnace-skipped=<names>`. A path-less build reaches
249
+ every component. `--furnace-apply none` is `--no-furnace-apply`; `all` is the
250
+ default.
47
251
 
48
252
  When `patchLint.checkJs` and `patchLint.checkJsTestFiles` are enabled, named
49
253
  pre-test builds check the selected test scripts before deployment or mach.
50
- This includes new scripts not yet owned by an exported patch.
254
+ This includes new scripts not yet owned by an exported patch. The check runs
255
+ before the engine lock is requested, so a type error refuses at once instead
256
+ of after a place in the lock queue. An unowned `head*.js` in a named test's
257
+ directory joins the check when that test loads it with `loadSubScript` or a
258
+ manifest beside it lists it in `support-files`, so a suite moved onto a new
259
+ support head can be proven before the head is exported. A notice names each
260
+ such head and the `re-export --scan --scan-file` command that adopts it.
261
+
262
+ `--restart-between-tests` forwards mochitest's flag of the same name, which
263
+ restarts the browser between test files (the run shape a manifest's
264
+ `standalone` key asks for). It is refused for an xpcshell or generic
265
+ dispatch, like `--shuffle`.
51
266
 
52
267
  ### Shared browsers, ports and host state
53
268
 
@@ -60,9 +275,40 @@ launchd-parented app remains unattributed and is not automatically killed.
60
275
  `test --wait-browser [seconds]` waits for this objdir's browser to exit;
61
276
  `test --wait-port [seconds]` waits for mochitest and Marionette listeners.
62
277
  `build --wait-browser [seconds]` queues a full or UI build behind the browser.
63
- Bare flags wait 60 seconds; explicit values accept 1–3600 seconds. They are
64
- independent of the FireForge lock budget. On expiry the normal preflight
65
- refusal and its remedy are preserved.
278
+ Bare flags wait 60 seconds; explicit values accept 1–86400 seconds. They are
279
+ independent of the FireForge lock budget, and they are spent BEFORE the
280
+ engine session lock is requested, so a run waiting out a browser or a port
281
+ does not hold every peer's build, test and re-export behind it. The run then
282
+ joins the lock queue and re-checks once under the lock; the normal preflight
283
+ refusal and its remedy apply if the resource is busy again (or still busy)
284
+ there. With `--kill-stale-marionette` a reapable stale browser counts as
285
+ clear before the lock, and the port waits stay under the lock, where the
286
+ stale listener can be reaped.
287
+
288
+ A path-shaped argument right after `--wait-lock`, `--wait-browser`,
289
+ `--wait-port` or `--shuffle` (it has a `/`, a file extension, or is `.`) is
290
+ a test path, not the flag's value, and the flag takes its default:
291
+ `fireforge test --wait-lock browser_x.js` waits 60 seconds and runs
292
+ `browser_x.js`. A bare word (`--wait-lock soon`) is still a usage error.
293
+
294
+ `--wait-port` makes sibling checkouts take turns. `--auto-ports` (or
295
+ `test.mochitestPorts: "auto"` in `fireforge.json`) lets them run browser
296
+ suites at the same time. Desktop `mach mochitest` has no `--http-port` or
297
+ `--ssl-port` option; those exist only for Android and iOS. Recent engines
298
+ do something better instead: `testing/mochitest/runtests.py` bind-probes
299
+ the HTTP server, ssltunnel and WebSocket ports before starting its servers,
300
+ and the Marionette port before launching the browser, moves each busy one to
301
+ a free port, and routes `mochi.test:8888` to wherever the server landed.
302
+ FireForge's own refusal used to fire before that fallback could. In auto
303
+ mode the mochitest-server and Marionette gates step aside, with a notice
304
+ naming the holder, when the holder is not this checkout's own (a sibling
305
+ checkout's live suite or an unrelated listener). This checkout's own
306
+ leftovers are refused exactly as before, and `--kill-stale-marionette`
307
+ still applies to them. Auto mode takes effect only when the engine's
308
+ `runtests.py` carries the fallback; otherwise a notice says so and the
309
+ default refusal stays. It never applies to `--doctor`'s Marionette probe,
310
+ which launches its own browser on that port. The default (`"fixed"`) is
311
+ unchanged.
66
312
 
67
313
  Every suite samples host load and the highest CPU process before and after
68
314
  dispatch. Load at least 4 or a process at least 90% CPU produces a warning;
@@ -215,9 +461,27 @@ group sweep.
215
461
  Every test run ends with one machine-readable line:
216
462
 
217
463
  ```
218
- FIREFORGE-VERDICT: PASS|FAIL reason=… [note=<class>] [shuffle=<seed>] [orphans-reaped=<n>] [log=<path>]
464
+ FIREFORGE-VERDICT: PASS|FAIL reason=… [note=<class>] [started=<n>/<m> first-unstarted=<path> started-source=<src>] [shards=<p>/<t> [failed-shards=<labels>]] [runs=<p>/<n>] [control=<outcome>] [shuffle=<seed>] [orphans-reaped=<n>] [furnace-applied=<names>|furnace-apply=skipped] [furnace-skipped=<names>] [jobs=<n>] [lock=shared] [results=<path>] [log=<path>]
219
465
  ```
220
466
 
467
+ The start count reads every line the harness printed, not the last 2 MB of
468
+ captured output: a suite printing more than that (a large browser directory,
469
+ or any run under `--full-output`) used to report files that ran and passed
470
+ as never started. `started-source=` names the evidence. A sharded run also
471
+ prints a `FIREFORGE-SHARD:` line per shard and names the shards that did not
472
+ pass as `failed-shards=`; see [`machine-output.md`](machine-output.md).
473
+
474
+ A run is never `PASS` when its summary reports unexpected results, when the
475
+ harness printed "Application shut down (without crashing) in the middle of a
476
+ test", or when a requested test file never produced a start (or skip)
477
+ marker, even if mach exited 0. A browser that quits cleanly mid-suite does
478
+ exactly that: the counts then cover only the files that ran. Such a run is
479
+ `FAIL reason=test-failures`, and a short start count adds
480
+ `started=<n>/<m> first-unstarted=<path>`: how many requested files started,
481
+ and the first, in dispatch order, that never did. The file count is only
482
+ taken when the output's start lines name the requested files; an xpcshell
483
+ dispatch that proves execution with a result summary alone is not counted.
484
+
221
485
  Automation should branch on this line rather than on the raw process code,
222
486
  and has to treat a missing verdict as a failure. The closed set of `reason=`
223
487
  values and the stdout rules around the line are in
@@ -240,9 +504,9 @@ disables this argument permutation. FireForge also forwards native mach
240
504
  `--shuffle` within each invocation, whose file order remains unseeded and is
241
505
  not replayed by the FireForge seed. `FIREFORGE_SHUFFLE_SEED=<seed>` is available
242
506
  to custom harness `head.js` code for in-file task ordering, and `shuffle=<seed>`
243
- is recorded on the verdict. The option is mochitest-only. Write
244
- `--shuffle=<seed>` or place it after the paths because a bare
245
- `--shuffle <path>` consumes the path as its optional seed.
507
+ is recorded on the verdict. The option is mochitest-only. A path-shaped
508
+ argument right after a bare `--shuffle` is a test path, not a seed (see
509
+ "Shared browsers, ports and host state" above).
246
510
 
247
511
  Exit code 14 (`INCONCLUSIVE`) is not red: it means `engine/` moved while the
248
512
  harness ran and the result was thrown away. Exit 15 (`LOCK_TIMEOUT`) means
@@ -299,14 +563,75 @@ The two phases handle it differently, on purpose:
299
563
 
300
564
  A test run holds the engine-session lock and snapshots the engine git
301
565
  generation before and after the harness run, failing the verdict as invalid
302
- if the tree changed mid-run. To verify beside a busy primary checkout
566
+ if the tree changed mid-run in a way the running browser can see: a file the
567
+ objdir links to its source, a file staged at dispatch, or a test file or
568
+ staging input of the run. A peer's edit to anything else (a compiled source,
569
+ a copied file, an unrelated test) leaves the verdict standing with a warning
570
+ and `drift-tolerated=<n>`; the next run's stale-build gate judges whether it
571
+ needs a rebuild.
572
+
573
+ `--shared-lock` (or `test.lockMode: "shared"`) holds the lock shared for a
574
+ build-less run that applies no negative control and uses auto ports, so
575
+ several such runs on one objdir overlap. Anything that writes (a build, a
576
+ re-export, a `test --build`) still holds the lock alone: it waits for shared
577
+ holders to finish, and new shared holders queue behind it.
578
+ `status --lock` counts shared holders. Orphan reaping only touches helpers
579
+ whose parent died, so overlapping runs do not reap each other's live
580
+ helpers.
581
+
582
+ `--jobs <n>` runs a request's shards on n harness instances inside one lock
583
+ hold. Each instance has its own profile and its own Marionette port, and
584
+ auto ports (required) move each instance's mochitest server ports; output
585
+ lines carry a `[job <i>]` prefix in the terminal and the run log. With
586
+ `--no-shard`, or a single directory argument, the files are split in order
587
+ into n contiguous chunks. Parallel browsers raise host load, so measure
588
+ before relying on it.
589
+
590
+ `--shard-size <n>` dispatches n files per mach invocation (mochitest restarts
591
+ the browser between files), paying the harness start once per chunk instead
592
+ of once per file, and judges each file from mozlog's structured log:
593
+ `shards=` then counts files and `failed-shards=` names failed files.
594
+
595
+ `--results <path>` writes one JSON record per test file and `--repeat` run
596
+ (status, expected status, duration, unexpected subtests, the shard, and the
597
+ run-log line where the dispatch began) from mozlog's structured log, which
598
+ each dispatch then writes with `--log-raw`, and names it on the verdict as
599
+ `results=<path>`. A `--log-raw <file>` already forwarded with `--mach-arg` is
600
+ read instead. The checks that need no lock run before it is
601
+ requested: the launchable binary, the named-file checkJs pass, and the
602
+ `--wait-browser`/`--wait-port` budgets. The run log is open from the start,
603
+ so a `reason=lock-timeout` line carries `log=` too.
604
+ A `--perf-samples` run fails only when HEAD
605
+ moved or a changed path is packaged by the running build (an install-manifest
606
+ source or a test file); an edit no manifest installs, such as a compiled
607
+ source, leaves the sample standing with a warning. To verify beside a busy primary checkout
303
608
  instead, use a [verification tree](verification-trees.md).
304
609
 
305
610
  ## Dev-build gotcha
306
611
 
307
612
  In dev builds, files under `obj-*/dist/bin` may be symlinks back into the
308
- source tree (prefs especially), so edit source prefs directly and keep a
309
- backup before bisection experiments.
613
+ source tree (prefs, chrome JS and CSS, deployed widgets), so edit source
614
+ prefs directly and keep a backup before bisection experiments. The same
615
+ symlinks mean a running suite reads `engine/` when its browser loads a file,
616
+ after any `--build` step: `Build complete` is not a snapshot. An edit to
617
+ `engine/`, yours or a peer session's, made before the `FIREFORGE-VERDICT`
618
+ line can reach the running suite, so keep a temporary edit, such as a
619
+ hand-made neuter, in place until the verdict line, or use
620
+ `--negative-control` for deliberate mutations. `fireforge test --help` says
621
+ so too.
622
+
623
+ ## Missing launchable binary
624
+
625
+ `test` checks for the launchable binary before it requests the engine lock,
626
+ and names the cause when the bundle is incomplete. Every protected mach
627
+ build (`build`, `build --ui`, `test --build`) records itself in
628
+ `.fireforge/build-run.json` while it runs. A successful build removes the
629
+ record, a failed one keeps it with its exit code, and a build whose process
630
+ died part-way leaves it marked running with a PID that no longer exists. The
631
+ refusal (`note=no-launchable-binary`) then says, in any session, that the
632
+ last build was interrupted or failed, by which command and when. A missing
633
+ binary while a build is still running is not refused early: the run queues
634
+ behind that build, which relinks the bundle before it releases the lock.
310
635
 
311
636
  ## Repository release gate
312
637
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hominis/fireforge",
3
- "version": "0.49.2",
3
+ "version": "0.51.0",
4
4
  "description": "FireForge — a build tool for customizing Firefox",
5
5
  "type": "module",
6
6
  "main": "./dist/src/index.js",
@@ -76,9 +76,9 @@
76
76
  "eslint-plugin-simple-import-sort": "^14.0.0",
77
77
  "fast-check": "^4.6.0",
78
78
  "husky": "^9.1.7",
79
- "knip": "6.39.0",
79
+ "knip": "6.41.0",
80
80
  "lint-staged": "^17.0.4",
81
- "prettier": "3.9.9",
81
+ "prettier": "3.9.10",
82
82
  "tsx": "^4.7.0",
83
83
  "typescript": "~6.0.0",
84
84
  "typescript-eslint": "^8.0.0",