@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
@@ -20,6 +20,19 @@ which is worth knowing when you revert that file. Running
20
20
  uncommitted pin, and the tree is then building a different version than the
21
21
  config claims.
22
22
 
23
+ `fireforge source set`, `fireforge config <key> <value>` and `furnace init`
24
+ edit `fireforge.json` in place (since 0.50.0). Only the values that change
25
+ are rewritten. Indentation, key order, and objects or arrays kept on one
26
+ line stay as they are, so a pin move is a diff of the `firefox` block alone.
27
+ New keys follow the layout of the object they land in. Before 0.50.0 every
28
+ write re-serialized the whole file and expanded every compact section.
29
+
30
+ `fireforge doctor`'s "Source pin matches engine" check compares the pin with
31
+ the engine's committed `browser/config/version.txt`. That file never carries
32
+ the `esr` suffix, so a trailing `esr` is dropped from the pin for this
33
+ comparison (a `153.4.0esr` pin matches `153.4.0`). The comparison with the
34
+ version the last download recorded keeps the full pin.
35
+
23
36
  ### Archive integrity: `firefox.sha256` and `firefox.allowUnverifiedDownload`
24
37
 
25
38
  Every fresh download is checked against Mozilla's published `SHA256SUMS` for
@@ -76,6 +89,12 @@ been bootstrapped.
76
89
 
77
90
  Per-patch lint type-checks plain Firefox JS against a built-in
78
91
  Firefox-globals shim that tracks upstream WebIDL additions per release.
92
+ Most globals in it are `any`. `Cu` is typed as `CuShim`, the members of
93
+ `nsIXPCComponents_Utils` (`js/xpconnect/idl/xpccomponents.idl`) with loose
94
+ parameter and result types, so a call to a member `Cu` does not have (such
95
+ as `Cu.now()`, which is `ChromeUtils.now()`) fails `typecheck` and per-patch
96
+ lint instead of throwing at runtime (since 0.50.0). The same shim backs
97
+ `fireforge typecheck`.
79
98
 
80
99
  - `patchLint.checkJsExtraShim` adds members to the structured shim globals
81
100
  via TypeScript interface merging, for example
@@ -113,7 +132,11 @@ Firefox-globals shim that tracks upstream WebIDL additions per release.
113
132
  alone: a `%` or `@AB_CD@` substitution, `**`, `!`, a path that leaves the
114
133
  tree, or a chrome URL no queue jar.mn line packages. Each finding prints
115
134
  the same paste-and-run `patch staged-dependency --add --kind registration`
116
- command as the `support-files` arm. The setting is opt-in because a queue
135
+ command as the `support-files` arm, ending in a `--reason '<why …>'`
136
+ placeholder to fill in. Each finding also carries the declaration as
137
+ structured `stagedDeclarations`, so a `lint --per-patch --report` file
138
+ can be applied with one `patch staged-dependency <patch> --add --from
139
+ <report>` per patch instead of one call per edge. The setting is opt-in because a queue
117
140
  that predates it can carry many such edges, and a new error would red a
118
141
  `--max-warnings 0` gate on install. The same census is on the public API as
119
142
  `findForwardRegistrations(patchesDir, { scope })`, which defaults to
@@ -138,7 +161,126 @@ Firefox-globals shim that tracks upstream WebIDL additions per release.
138
161
  `notice <= warning <= error`, which is validated at config load. Under
139
162
  the recommended gate posture `--max-warnings 0`, the `warning` band
140
163
  is a hard failure rather than a soft limit, which is what these thresholds
141
- exist to let you move.
164
+ exist to let you move. A notice is the design target: advisory, and it
165
+ never fails `--max-warnings 0`. Only the error band suggests splitting.
166
+
167
+ - `patchLint.fileSizeMetric` (`'raw'` or `'code'`, default `'raw'`) picks
168
+ what `file-too-large` counts. `'raw'` counts every line, the way `wc -l`
169
+ does. `'code'` blanks comments with acorn's tokenizer (module first, then
170
+ script, since chrome subscripts are scripts) and counts the lines left
171
+ non-blank, so JSDoc and blank lines stop counting. A file acorn cannot
172
+ tokenize is counted in raw lines, the upper bound, and a
173
+ `file-size-unparsed` notice names it. Every message says which unit it
174
+ counted ("lines" or "code lines"). The counter is on the public API as
175
+ `countCodeLines(content)`, next to `resolveFileSizeThresholds` and
176
+ `isTestFile`.
177
+
178
+ - `patchLint.patchSizeThresholds` tunes `large-patch-lines` and
179
+ `large-patch-files` per tier (`general`, `test`, `branding`), each with a
180
+ `lines` and a `files` triple:
181
+
182
+ ```json
183
+ {
184
+ "patchLint": {
185
+ "patchSizeThresholds": {
186
+ "general": {
187
+ "lines": { "notice": 1000, "warning": 2000, "error": 4000 },
188
+ "files": { "notice": 8, "warning": 12, "error": 24 }
189
+ },
190
+ "branding": { "files": { "error": 90 } }
191
+ }
192
+ }
193
+ }
194
+ ```
195
+
196
+ Every field is optional and merges over the defaults, and each merged
197
+ triple has to satisfy `notice <= warning <= error`. The line defaults are
198
+ general `800/1500/3000`, test `1500/3000/6000` and branding
199
+ `8000/18000/30000`. Files warn above 5 (general, test) or 60 (branding).
200
+ The files triple has no notice or error band unless you set one: an unset
201
+ `files.notice` follows `files.warning`, and an unset `files.error` never
202
+ fires. The `branding` tier applies to a patch whose files all sit under
203
+ `browser/branding/` (plus `browser/moz.configure` and
204
+ `browser/confvars.sh`), or one marked `"tier": "branding"` in
205
+ `patches.json` (`re-export --tier branding`). A patch whose files are all
206
+ tests takes the `test` tier, and wins over branding.
207
+ `getPatchSizeThresholds(tier, config)` returns the configured values.
208
+
209
+ - `patchLint.patchSizeMetric` (`'diff'` or `'addedCode'`, default `'diff'`)
210
+ picks what `large-patch-lines` counts. `'diff'` counts every non-binary
211
+ line of the unified diff, headers and context included. `'addedCode'`
212
+ counts only added lines that are neither blank nor comment, judged on
213
+ each file's post-image in `engine/` (a hunk can start inside a block
214
+ comment). Comments are recognised per file kind: JS through acorn, CSS
215
+ block comments, `<!-- -->` in markup, and whole-line `#` comments in
216
+ manifests, `moz.build`, Fluent and similar. In CSS it also skips lines
217
+ inside a Furnace `@fireforge-include` … `@fireforge-end-include`
218
+ expansion: they are a copy of a shared fragment. Under `'addedCode'`, a
219
+ general-tier patch that carries tests counts per class: lines in test
220
+ files against the test tier's `lines`, everything else against the
221
+ general tier's, each with its own finding.
222
+
223
+ - `patchLint.patchSizeRegistrationFiles` lists globs whose files count
224
+ toward neither `large-patch-lines` nor `large-patch-files`, for example
225
+ `["jar.mn", "moz.build", "components.conf", "*.toml", "jsconfig*.json"]`.
226
+ A glob without a `/` matches the basename, one with a `/` the
227
+ engine-relative path; `*` stays within a path segment and `**` crosses
228
+ segments. Default: none.
229
+
230
+ - `patchLint.tokenScales` (default unset) puts property families on a token
231
+ scale. In every CSS file a patch creates, a declaration of a governed
232
+ property must resolve to the scale (`token-scale`, an error):
233
+
234
+ ```json
235
+ {
236
+ "patchLint": {
237
+ "tokenScales": [
238
+ {
239
+ "properties": ["gap", "row-gap", "column-gap", "padding*", "margin*"],
240
+ "prefix": "--mybrowser-space-",
241
+ "allowLiterals": ["0", "auto", "*%", "1px"],
242
+ "allow": ["--mybrowser-page-padding"]
243
+ },
244
+ { "properties": ["z-index"], "prefix": "--mybrowser-z-" }
245
+ ]
246
+ }
247
+ }
248
+ ```
249
+
250
+ `properties` takes exact names or a `*`-suffixed prefix. Each value atom
251
+ must be a `var()` of a `prefix` token or of an `allow` name (exact, or
252
+ `*`-suffixed such as `--moz-*`), a literal matching `allowLiterals` (`*`
253
+ is a wildcard), or a CSS-wide keyword (`inherit`, `initial`, `unset`,
254
+ `revert`, `revert-layer`). A `var()` fallback is held to the same scale,
255
+ so `var(--mybrowser-gap, 7px)` fails on `7px`. `calc()`, `min()`, `max()`
256
+ and `clamp()` are transparent. Files the patch modifies rather than
257
+ creates are not checked, and a line carrying
258
+ `fireforge-ignore: token-scale` is skipped. Declarations inside
259
+ descriptor at-rules (`@font-face`, `@counter-style`, `@property`,
260
+ `@font-feature-values`, `@font-palette-values`, `@page` and its margin
261
+ boxes) are descriptors, not properties, and are not judged.
262
+
263
+ Since 0.51.0 a scale also takes:
264
+
265
+ - `prefix` as a list (`["--mybrowser-space-", "--mybrowser-gap-"]`) for a
266
+ scale whose steps are spelled more than one way.
267
+ - `allowInCalc`: literals legal only inside a math function, such as the
268
+ unitless multiplier in `calc(var(--mybrowser-space-2) * 2)`, without
269
+ also passing a bare `2`. Same wildcard syntax as `allowLiterals`.
270
+ - `offsetCap`: the px a declaration may subtract from the scale's tokens
271
+ inside a math function (`calc(var(--mybrowser-space-4) - 1px)`), summed
272
+ over the declaration. A px value anywhere else still fails.
273
+ - `exclude`: engine-relative globs of files the scale does not govern,
274
+ such as a vendored minified sheet, so its patch needs no patch-wide
275
+ waiver.
276
+ - `minFiles`: the fewest patch-created stylesheets (outside `exclude`)
277
+ that must declare one of the scale's properties. Under it the queue
278
+ fails `token-scale-vacuous` (an error on `fireforge.json` in
279
+ `lint --per-patch`), so a scale that matches nothing, or a scan set a
280
+ move emptied, cannot pass by judging nothing. A `--patches` run does
281
+ not judge the floor.
282
+
283
+ An unknown key in a scale is refused.
142
284
 
143
285
  ## `typecheck`
144
286
 
@@ -157,6 +299,26 @@ program: prior incremental diagnostic state is never restored. Cached and
157
299
  also disables build-info writes. A jsconfig's own `incremental` and
158
300
  `tsBuildInfoFile` remain ignored.
159
301
 
302
+ `typecheck.litTypes: true` (since 0.51.0, default off) types Lit in the
303
+ shim: `LitElement` and the helpers of
304
+ `chrome://global/content/vendor/lit.all.mjs`, and `MozLitElement` of
305
+ `chrome://global/content/lit-utils.mjs`. The element classes carry closed
306
+ member lists, as `Cu` does, so a misspelt member of a widget host is an
307
+ error rather than `any`. Template helpers and directives stay loose. It is
308
+ off by default because a reactive property declared only in
309
+ `static properties` or `static queries` then needs a constructor
310
+ assignment or a JSDoc declaration to be known. A project shim can add
311
+ members by merging `interface LitElementShimMembers`; a jsconfig `paths`
312
+ entry that maps these URLs to real sources takes precedence.
313
+
314
+ Per-patch checkJs gives each test script its own program. Since 0.51.0 a
315
+ test's `resource:///` and `chrome://` imports (including a
316
+ `typeof import("…")` cast) resolve to the modules the queue creates up to
317
+ the test's own patch, so a test of an earlier patch's module is checked
318
+ against its real types. A module a later patch creates, an upstream module
319
+ and a basename two patches create still type as `any`, and an implicit-any
320
+ finding on such an import names it.
321
+
160
322
  Both project and per-patch checkJs provide Gecko DOM constructor
161
323
  `isInstance(value)` predicates with instance narrowing, plus
162
324
  `MouseEvent.MOZ_SOURCE_PEN`. These declarations retain normal DOM member
@@ -167,6 +329,61 @@ checking; they do not turn constructors or instances into `any`.
167
329
  `patchPolicy.ranges` makes `patch compact` range-aware, so closing ordinal
168
330
  gaps does not move a patch out of the band its category owns.
169
331
 
332
+ With `patchPolicy.allowGaps: false`, orders are contiguous within a range:
333
+ a new patch must fill an existing gap or take the number right after the
334
+ range's last patch. A patch that has to leave the queue without opening a
335
+ gap is removed with `patch retire`, which keeps its order as a retired slot.
336
+ An order a peer has claimed but not exported yet is held with `patch
337
+ reserve`, so a later order can be exported without a gap in between (see
338
+ [`patch-workflow.md`](patch-workflow.md#queue-maintenance)).
339
+
340
+ ### Registration-only rules
341
+
342
+ Four opt-in rules read the patch bodies rather than `patches.json` alone.
343
+ `verify` and `lint --per-patch` report them (as `patch-policy/<code>` in
344
+ lint), at the severity `mutationMode` implies. Mutating commands do not
345
+ evaluate them, because those commands check a projected manifest before
346
+ any body exists.
347
+
348
+ ```json
349
+ {
350
+ "patchPolicy": {
351
+ "ranges": [{ "from": 100, "to": 899, "category": "ui" }],
352
+ "addOnlyMarker": "hominis",
353
+ "upstreamAllowlist": [
354
+ "browser/moz.configure",
355
+ { "path": "**/jar.mn", "addOnly": true },
356
+ { "path": "**/moz.build", "addOnly": true }
357
+ ],
358
+ "scopeRules": [
359
+ { "filenamePattern": "-tests\\.patch$", "files": ["**/test/**", "**/tests/**", "**/*.toml"] }
360
+ ],
361
+ "verifyDocumentPaths": true
362
+ }
363
+ }
364
+ ```
365
+
366
+ - `upstreamAllowlist` names, as path globs, the upstream files a
367
+ non-reserved patch may modify (`upstream-allowlist`). A file is upstream
368
+ when no patch in the queue creates it, so fork-owned files never need an
369
+ entry. A patch in a `reservedRanges` band is exempt: its allowlist entry's
370
+ `files` already governs it. Globs are anchored engine-relative paths: `*`
371
+ stays within a segment, `**` spans segments, so `*.toml` matches only a
372
+ top-level file and `**/*.toml` matches one anywhere.
373
+ - An object entry with `addOnly: true` puts matching files in
374
+ registration-only mode (`add-only`): the patch may only add lines, every
375
+ non-blank added line must contain the marker (the entry's `marker`, else
376
+ `addOnlyMarker`, matched case-insensitively), and deleting the file or
377
+ changing it as binary is refused. When several entries match a file, any
378
+ add-only one makes it add-only.
379
+ - `scopeRules` limits a class of patch to the files its globs name
380
+ (`scope`). A rule selects patches by `category`, `filenamePattern` (a
381
+ regular expression over the patch filename), or both. The example keeps a
382
+ `-tests` patch to test directories and test manifests.
383
+ - `verifyDocumentPaths: true` requires each reserved allowlist entry's `adr`
384
+ and `documentation` path to exist under the project root
385
+ (`reserved-document-missing`).
386
+
170
387
  ## `test`
171
388
 
172
389
  `test.canaryPath` and `test.canaryTimeoutSeconds` supply the defaults for
@@ -178,6 +395,42 @@ objdir. `"reap"` terminates it and stamps `orphans-reaped=<n>` on the verdict
178
395
  line; `--reap-orphans` does the same for one invocation. The objdir anchor
179
396
  rule is the same under both. See [`testing.md`](testing.md).
180
397
 
398
+ `test.mochitestPorts` is `"fixed"` (default) or `"auto"`. `"auto"` lets a
399
+ browser run proceed while the mochitest server or Marionette port is held by
400
+ something that is not this checkout's own, relying on the engine
401
+ harness's own busy-port fallback, so sibling checkouts can run browser suites
402
+ at once. `--auto-ports` does the same for one invocation. See
403
+ [`testing.md`](testing.md#shared-browsers-ports-and-host-state).
404
+
405
+ `test.lockMode` is `"exclusive"` (default) or `"shared"`. `"shared"` lets a
406
+ build-less run that applies no negative control and uses auto ports hold the
407
+ engine-session lock shared, so peers' build-less runs on the same objdir
408
+ overlap while builds, re-exports and every other writer still hold it alone.
409
+ `--shared-lock` does the same for one invocation. See
410
+ [`testing.md`](testing.md#concurrency).
411
+
412
+ `test.furnaceApply` is `"all"` (default), `"reached"` or `"none"`: which
413
+ components a `test --build` deploys before building. `--furnace-apply` does
414
+ the same for one invocation. See
415
+ [`testing.md`](testing.md#furnace-components-in-a-pre-test-build).
416
+
417
+ ## `history`
418
+
419
+ `history.path` is where FireForge appends its patch history log, relative to
420
+ the project root (default `.fireforge/history.jsonl`). The log records
421
+ structural patch operations (staged dependencies, splits, renames, export
422
+ orders, re-exports that change a patch's file list) as one JSON object per
423
+ line. FireForge never reads it back; it is an audit trail only. Each record
424
+ carries `invocationId` (shared by every record one command writes), `pid`,
425
+ `ppid`, and `sessionId` when the environment sets `FIREFORGE_SESSION_ID`, so
426
+ a session sharing the checkout can select its own lines.
427
+
428
+ Before 0.50.0 the log was `patches/.fireforge-history.jsonl`, inside the
429
+ tracked queue. The first append after upgrading moves it to `history.path`;
430
+ when both files exist, the old records are appended to the new file rather
431
+ than either being overwritten. Setting `history.path` to
432
+ `patches/.fireforge-history.jsonl` keeps the old location.
433
+
181
434
  ## `buildAudit`
182
435
 
183
436
  The post-build packaging audit is warn-only. Most of what it would otherwise
@@ -224,6 +477,63 @@ The `Packaged:` summary line names each non-zero skip class with its count,
224
477
  so a run that dismissed four unselected-branding files reads differently from
225
478
  one that dismissed four unregistered sources.
226
479
 
480
+ ## `check`
481
+
482
+ `fireforge check` is the composed static gate. It runs six built-in steps,
483
+ `status`, `verify`, `lint`, `typecheck`, `furnace-validate` and
484
+ `token-coverage`, and then the project's own commands. Every field of the
485
+ `check` block is optional:
486
+
487
+ ```json
488
+ {
489
+ "check": {
490
+ "skip": ["token-coverage"],
491
+ "status": {
492
+ "failOn": ["unmanaged", "patch-owned-drift", "conflict", "ownership-conflict"],
493
+ "allow": ["patch-backed", "branding", "furnace", "binary-unsupported"],
494
+ "failOnUnknown": true
495
+ },
496
+ "maxWarnings": { "lint": 0, "furnace": 0 },
497
+ "extraSteps": [
498
+ { "name": "policy-audit", "command": "npm run audit:policy", "timeout": 600 },
499
+ { "name": "invariants", "command": "node check-invariants.mjs", "cwd": "tools" }
500
+ ]
501
+ }
502
+ }
503
+ ```
504
+
505
+ - `skip` lists the built-in steps this project never runs. `typecheck` is
506
+ also skipped when there is no `typecheck` block, and `furnace-validate`
507
+ when there is no `furnace.json`.
508
+ - `status` is the status step's `--check` policy: `--fail-on`, `--allow` and
509
+ `--fail-on-unknown` (see [`patch-workflow.md`](patch-workflow.md#ci-enforcement)).
510
+ An invalid policy is refused as a config error before any step runs.
511
+ - `maxWarnings` passes `--max-warnings` to `lint --per-patch` and
512
+ `furnace validate`.
513
+ - `extraSteps[]` adds project commands. `name` is lowercase letters, digits
514
+ and dashes and must not repeat a built-in name. `command` runs with
515
+ `/bin/sh -c` (`cmd.exe /c` on Windows) from the project root, or from the
516
+ project-relative `cwd`. `timeout` is in seconds: past it the step's whole
517
+ process tree is killed and the step fails. A step passes when it exits 0.
518
+ `after` lists steps, built-in or extra, that must finish before it starts
519
+ (whatever their outcome); a name that is not a step, or an ordering cycle,
520
+ is refused.
521
+ - `timeout` bounds every built-in step, in seconds, and `timeouts` sets it
522
+ per step (`{ "typecheck": 600 }`). A step past its budget is killed and
523
+ fails. Unset, built-in steps are unbounded.
524
+ - `failOnSkipped: true` fails the check (`reason=skipped-steps`) when a
525
+ built-in step is skipped because the project has nothing for it to run
526
+ (no `typecheck` block, no `furnace.json`). A step named in `skip` is a
527
+ decision and never fails it.
528
+ - `lintReport` is a project-relative path the lint step writes its
529
+ `lint --per-patch --report` JSON to. Every extra step receives the
530
+ absolute path as `FIREFORGE_CHECK_LINT_REPORT`, so an audit that runs
531
+ `after: ["lint"]` can read the run's lint report instead of linting the
532
+ queue a second time.
533
+
534
+ The verdict line names the skipped steps with an additive
535
+ `skipped-steps=<a,b>` key beside `skipped=<n>`.
536
+
227
537
  ## Design tokens
228
538
 
229
539
  Tokens are managed with `fireforge token add`. `fireforge token list` and
@@ -273,6 +583,31 @@ hand-parsing a `= Category =` banner out of the file.
273
583
  Only the base `:root` block owns a token, so `token list` reports it once.
274
584
  The dark and variant blocks mirror it and appear in `token show`.
275
585
 
586
+ ### Checking the token file
587
+
588
+ `fireforge token lint [--json]` exits non-zero on either of two findings:
589
+
590
+ - `token-lockstep`: a themed override block (the dark `@media` mirror, a
591
+ `:root[variant]` block) declares a token with the project's token prefix
592
+ that the base `:root` does not declare. Every other theme would resolve
593
+ it to nothing. Overrides of non-prefixed properties (a `--moz-*` platform
594
+ variable) are left alone.
595
+ - `token-undeclared`: a `var(--<prefix>…)` in the tokens CSS, or in any CSS
596
+ file a patch in the queue touches, names a token no block of the tokens
597
+ CSS declares. A property declared in the same file, and the `furnace.json`
598
+ `tokenAllowlist` and `runtimeVariables` names, are exempt. Since 0.51.0 a
599
+ reference with a fallback (`var(--x, 0)`) is optional and not reported,
600
+ and a token a sibling sheet declares counts as declared. Sheets are
601
+ siblings when one queue document links both (`<link rel="stylesheet">`,
602
+ `<html:link>` or `<?xml-stylesheet?>`, in markup or a Lit template; a
603
+ `chrome://` URL resolves through the queue's jar.mn lines, a relative
604
+ one beside the document), when one `@import`s the other, or when
605
+ `furnace.json` `tokenSiblingSheets` pairs them:
606
+ `{ "browser/themes/**/panel*.css": ["browser/base/content/host.css"] }`
607
+ (a partner is a path or a glob over the queue's sheets).
608
+
609
+ The prefix is `furnace.json` `tokenPrefix`, else `--<binaryName>-`.
610
+
276
611
  ## Smoke runs
277
612
 
278
613
  For unattended smoke checks, `fireforge run --smoke-exit <s> --headless`
@@ -297,10 +632,24 @@ up after itself, so the next `run` removes any temporary profile whose
297
632
  owning process is gone.
298
633
 
299
634
  - `--profile <path>` launches with a named profile directory and leaves it
300
- in place. Under `--smoke-exit` it replaces the fresh default.
635
+ in place. Under `--smoke-exit` it replaces the fresh default. Firefox also
636
+ gets `-purgecaches` (since 0.50.0), which discards the profile's startup
637
+ cache of compiled chrome scripts. That cache is keyed on the build id, and
638
+ a `build --ui` does not change it, so without the purge a kept profile runs
639
+ the chrome scripts an earlier build cached. `--no-purge-caches` keeps the
640
+ cache. mach's `profile-default` has its `startupCache/` removed before
641
+ every run, and a temporary profile starts without one.
301
642
  - `--temp-profile` gives a plain `run` the same fresh, removed-afterwards
302
643
  profile.
303
644
 
645
+ A smoke run whose browser exits with a clean status before the window
646
+ elapses, without printing any console output, fails with exit 13 (since
647
+ 0.50.0). Lines from mach's own log (the timestamped command echo) do not
648
+ count as output. A launch that exits silently never reached a window: a
649
+ stale `.parentlock`, or a profile whose run of SIGTERM-ended smoke runs
650
+ counts as a startup-crash streak (`toolkit.startup.recent_crashes`). Before
651
+ 0.50.0 such a run passed as a clean exit.
652
+
304
653
  A plain `run` without either flag keeps mach's `profile-default`. `mach run`'s
305
654
  desktop parser has no `--profile` option (its `--profile/-P` belongs to the
306
655
  Android parser), so the profile is always passed as a program parameter.
@@ -321,21 +670,28 @@ Every FireForge command that mutates the engine takes the engine-session
321
670
  lock, and some take a second subsystem lock as well. Contention fails fast
322
671
  after about a second by default.
323
672
 
324
- `--wait-lock [seconds]` (bare flag means 60, valid range 1 to 3600) replaces
673
+ `--wait-lock [seconds]` (bare flag means 60, valid range 1 to 86400, a day) replaces
325
674
  that with a bounded wait, and the budget covers every lock the command takes.
326
675
  For `furnace apply`, `deploy` and `sync` that means the furnace lock as well
327
- as the engine-session lock. While waiting, a progress line roughly every 5
328
- seconds identifies the holder by PID, command and start time.
676
+ as the engine-session lock. The furnace leaves that take only the furnace lock
677
+ (`create`, `remove`, `rename`, `refresh`, `scan`, `override`, `preview`, and
678
+ `chrome-doc create`/`remove`) apply the flag to that lock. While waiting, a
679
+ progress line roughly every 5 seconds identifies the holder by PID, command
680
+ and start time.
329
681
 
330
682
  Commands that take no lock accept `--wait-lock` and ignore it, so a scripted
331
683
  sequence can append the flag everywhere without a usage error killing the
332
684
  run.
333
685
 
334
686
  `FIREFORGE_WAIT_LOCK=<seconds>` applies the same budget to every command in a
335
- session, using the same bounds as the flag. It is the only way to give a
336
- budget to the furnace mutators that declare no flag (`create`, `remove`,
337
- `rename`, `refresh`, `scan`, `override`, `chrome-doc`, and the rest). An
338
- explicit `--wait-lock` always wins.
687
+ session, using the same bounds as the flag. It is the fallback whenever the
688
+ flag is absent, including for the furnace lock a build's pre-build apply and
689
+ `doctor --repair-furnace` take. An explicit `--wait-lock` always wins.
690
+
691
+ Waiters are granted a lock in arrival order: the progress line's "You are
692
+ next" or "N ahead of you" is the order the lock will actually be handed out.
693
+ A waiter that crashed, was killed, or is stopped drops out of the queue
694
+ instead of blocking it.
339
695
 
340
696
  `fireforge status --lock` reports the current holder and queue depth.
341
697
 
@@ -343,7 +699,9 @@ explicit `--wait-lock` always wins.
343
699
 
344
700
  | Variable | Effect |
345
701
  | ------------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------- |
346
- | `FIREFORGE_WAIT_LOCK` | Session-wide lock wait budget in seconds (1 to 3600). See above. |
702
+ | `FIREFORGE_WAIT_LOCK` | Session-wide lock wait budget in seconds (1 to 86400). See above. |
703
+ | `FIREFORGE_SESSION_ID` | Recorded as `sessionId` on every patch history log record this process writes. See `history` above. |
704
+ | `FIREFORGE_LOG_KEEP` | Also write every `test`/`build` run log here, outside retention (a directory collects one file per run). See `run-logs.md`. |
347
705
  | `FIREFORGE_MAX_UNTRACKED_FILES` | Per-directory cap when expanding collapsed untracked directories in `status` (default 5000). A non-positive value warns and is ignored. |
348
706
  | `FIREFORGE_GIT_ADD_TIMEOUT_MS` | Timeout for the monolithic `git add -A` baseline pass (default 10 min). For slow or loaded filesystems. |
349
707
  | `FIREFORGE_GIT_ADD_CHUNK_TIMEOUT_MS` | Timeout for the chunked `git add -- <dir>` fallback (default 30 min). Paired with the above. |
@@ -22,7 +22,7 @@ which error class produces each one.
22
22
  | 10 | `RESOLUTION_ERROR` | Conflict resolution failed. | `ResolutionError` |
23
23
  | 11 | `INTERNAL_ERROR` | A FireForge invariant did not hold. This is a bug in FireForge, not something the operator can fix. | `InternalInvariantError` |
24
24
  | 12 | `SMOKE_EXIT_FAILURE` | `run --smoke-exit` saw console errors that were not allowed in the smoke window, or an allowlisted shape fired past its `# max-hits` ceiling. | `SmokeRunError` |
25
- | 13 | `SMOKE_LAUNCH_FAILURE` | `run --smoke-exit` saw the browser exit uncleanly before the window elapsed. | `SmokeRunError` |
25
+ | 13 | `SMOKE_LAUNCH_FAILURE` | `run --smoke-exit` saw the browser exit uncleanly before the window elapsed, or exit cleanly before it without any console output. | `SmokeRunError` |
26
26
  | 14 | `INCONCLUSIVE` | A test run's verdict was thrown away because `engine/` moved while the harness ran. This is not red. Re-run it. | `InconclusiveVerdictError` |
27
27
  | 15 | `LOCK_TIMEOUT` | A lock wait expired, so the run never started. Re-queue it with a larger `--wait-lock`. | `LockContentionError` |
28
28
  | 130 | `USER_CANCELLED` | The operator interrupted a prompt (Esc or Ctrl+C). 128 + SIGINT. | `CancellationError` |
@@ -75,6 +75,23 @@ not tell them apart. They are now distinct: an interrupt raises
75
75
  normally and exits 0, because the run did what it was asked and the answer
76
76
  was no.
77
77
 
78
+ ## `fireforge check`
79
+
80
+ The composed gate maps its verdict onto the existing codes rather than
81
+ adding one:
82
+
83
+ | Exit | When |
84
+ | ---: | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
85
+ | 0 | Every step passed or was skipped. |
86
+ | 1 | At least one step failed (`reason=step-failures`). Each step's own exit code is in the `--json` document's `steps[].exitCode`. Also a `--patches` name that matches no patch, before any step runs. |
87
+ | 15 | Every failed step exited 15 (`reason=lock-timeout`): nothing was judged red, the steps never got their locks. Re-queue it. |
88
+ | 2 | `fireforge.json` is invalid, including a `check.status` policy `status` would refuse. Raised before any step runs. |
89
+ | 8 | An unknown `--only`/`--skip` step, or a bad `--jobs`. Raised before any step runs. |
90
+
91
+ `furnace validate` exits 9 (`FURNACE_ERROR`) both for errors and for
92
+ warnings past `--max-warnings`, so a gate that wants the distinction reads
93
+ `summary.errors` from its `--json` document.
94
+
78
95
  ## Adding a code
79
96
 
80
97
  New codes go in `src/errors/codes.ts` with a comment saying what a consumer
package/docs/furnace.md CHANGED
@@ -29,7 +29,46 @@ comment:
29
29
  ```
30
30
 
31
31
  `deploy` expands the fragment into the deployed copy only, so editing the
32
- fragment shows up as component drift until the next deploy.
32
+ fragment shows up as component drift until the next deploy. `furnace diff`
33
+ compares the deployed copy against this composed form (and says so in the
34
+ `+++` header), so a freshly deployed includer shows no difference.
35
+
36
+ ## Deploying and applying
37
+
38
+ `furnace deploy` takes any number of names and deploys them under one lock
39
+ hold (`fireforge furnace deploy moz-a moz-b moz-c`), so a batch of widgets
40
+ waits for the engine lock once rather than once per widget. Each name is its
41
+ own atomic unit: it is applied and its state persisted before the next starts.
42
+ An unknown name refuses the whole invocation before anything is written, and
43
+ a stock name is warned about and skipped. With no name, everything deploys.
44
+
45
+ Deploy registers every `.mjs` and `.css` file in a custom component directory
46
+ in `toolkit/content/jar.mn`, including extra modules beside the main one. Add
47
+ the file to the directory and deploy instead of writing the jar line by hand.
48
+ A line that already registers the file anywhere in the jar (same target, or
49
+ same `(widgets/<tag>/<file>)` source) is kept and never duplicated, so mach
50
+ does not fail with "Item already in manifest". Removing a file from the
51
+ directory drops only its line, and `furnace rename` rewrites the widget's
52
+ lines where they stand, so the rest of the block keeps its order and the
53
+ owning patch carries no reorder hunks.
54
+
55
+ The apply and deploy summaries name why each component was skipped, for
56
+ example `Applied 0, skipped 1 (1 already current)`. "Already current" means
57
+ the source is unchanged since the last recorded apply and the engine copy
58
+ still matches it. The apply state is shared by every session on the checkout,
59
+ so that apply may have been another session's, such as a peer's
60
+ `test --build`.
61
+
62
+ ## Renaming
63
+
64
+ `furnace rename <old> <new>` moves the component and rewrites its
65
+ registrations in place. The `customElements.js` entry keeps its position,
66
+ layout and `// <MARKER>:` comments (the marker is `markerComment` from
67
+ `fireforge.json`, else the upper-cased `binaryName`); an entry is only added
68
+ fresh, with the marker, when none existed. The old entry never survives the
69
+ rename. The locale `jar.mn` line is re-pointed only when the old component had
70
+ one, so a `sharedFtl` component never gains a per-component `.ftl` line.
71
+ `--dry-run` prints every file move and engine edit without writing.
33
72
 
34
73
  ## Typed cross-module imports
35
74
 
@@ -42,6 +81,91 @@ An entry counts as Furnace-managed if it is contained in the components
42
81
  workspace. A hand-written entry is therefore preserved, and a managed entry
43
82
  whose helper was deleted is pruned.
44
83
 
84
+ ## Validation as a gate
85
+
86
+ `furnace validate` prints its findings for people. A gate reads
87
+ `furnace validate --json` instead: one document with the verdict
88
+ (`passed`), the counts, per-component counts and every finding, specified in
89
+ [`machine-output.md`](machine-output.md). Errors fail the run.
90
+ `--max-warnings <n>` also fails it when more than `n` warnings remain, so
91
+ `--max-warnings 0` keeps a component tree warning-clean.
92
+
93
+ A finding that was reviewed and accepted is recorded in `furnace.json`
94
+ rather than in a gate script:
95
+
96
+ ```json
97
+ {
98
+ "validationExceptions": [
99
+ {
100
+ "component": "moz-dock-button",
101
+ "check": "no-keyboard-handler",
102
+ "reason": "Activation goes through the inner moz-button."
103
+ }
104
+ ]
105
+ }
106
+ ```
107
+
108
+ An entry suppresses every finding of `check` (the name `validate` prints in
109
+ brackets) on `component`. Each field is required and the reason must be
110
+ non-empty, because the entry is the review record. Suppressed findings are
111
+ still listed, with their reason, under `excepted` in the JSON document and
112
+ counted in the summary. An entry that matches nothing is stale: the finding
113
+ it records is gone, so `validate` reports a `stale-validation-exception`
114
+ warning asking for the entry to be deleted. A run over one component judges
115
+ only that component's entries. `deploy` honours the same entries when it
116
+ validates, but leaves the staleness report to `validate`.
117
+
118
+ An entry never suppresses an error (since 0.51.0): an error blocks apply,
119
+ and a review record cannot make a broken component deployable. The error
120
+ stays counted, and the entry is reported as a
121
+ `validation-exception-on-error` error until the finding is fixed and the
122
+ entry deleted.
123
+
124
+ An optional `tag` narrows an entry to findings about one element tag, so a
125
+ reviewed `<panel-list>` menu does not mute `no-keyboard-handler` for the
126
+ rest of the component. A finding that names several tags (`no-keyboard-handler`
127
+ names every synthetic element with an `@click`) is suppressed only when
128
+ entries cover all of them:
129
+
130
+ ```json
131
+ {
132
+ "component": "moz-vault",
133
+ "check": "no-keyboard-handler",
134
+ "tag": "li",
135
+ "reason": "Rows are reached through the list's roving focus."
136
+ }
137
+ ```
138
+
139
+ Accessibility checks judge the composed component: the host
140
+ `<tag>.mjs` and its companion modules (`<tag>-*.mjs`, tests and stories
141
+ left out) read as one source. Moving a template between the component's
142
+ modules therefore no longer changes its findings: a keyboard handler in a
143
+ companion covers an `@click` in the host, and an `@click` in a companion
144
+ is judged too. Toolkit's `panel-item` counts as natively
145
+ keyboard-activated, beside `button`, form controls and the `moz-*` buttons.
146
+
147
+ `minComponents` sets the fewest components a full `furnace validate` must
148
+ judge. A run under it, an empty tree included, fails with a
149
+ `component-floor` error on `furnace.json`, so a moved or emptied
150
+ components tree cannot pass by validating nothing. A run naming one
151
+ component is not held to it.
152
+
153
+ ```json
154
+ { "minComponents": 40 }
155
+ ```
156
+
157
+ `optInChecks` turns on checks that are off by default:
158
+
159
+ ```json
160
+ { "optInChecks": ["icon-button-label"] }
161
+ ```
162
+
163
+ `icon-button-label` warns about an icon-only `<moz-button>` in a component's
164
+ Lit templates (one with an `iconsrc` or an `icon` type, and no `label` or
165
+ text content) that has neither `data-l10n-id` nor `aria-label`, so a screen
166
+ reader would announce it only as "button". A button built with
167
+ `document.createElement` is not seen.
168
+
45
169
  ## Safety
46
170
 
47
171
  Every furnace mutation runs through `runFurnaceMutation`, which gives it a
@@ -53,6 +177,18 @@ commands take which locks, is in
53
177
  [`lifecycle-invariants.md`](lifecycle-invariants.md).
54
178
 
55
179
  `apply`, `deploy` and `sync` accept `--wait-lock [seconds]`, and that budget
56
- covers both locks they take. The twelve mutators without the flag pick up a
57
- session budget from `FIREFORGE_WAIT_LOCK`. See
180
+ covers both locks they take. The leaves that take only the furnace lock
181
+ (`create`, `remove`, `rename`, `refresh`, `scan`, `override`, `preview` and
182
+ the `chrome-doc` pair) apply the flag to that lock. Without the flag, the
183
+ session budget from `FIREFORGE_WAIT_LOCK` applies. See
58
184
  [`configuration.md`](configuration.md#lock-waits).
185
+
186
+ `build` and `test` rewrite deployed component files from their sources before
187
+ building, and `--refuse-unexported-drift` refuses when that would destroy
188
+ engine content no patch records. A deployed file that is a Furnace deployment
189
+ of its own source is classified `deployed-unexported` and allowed: it equals
190
+ the composed current source, differs from it only inside generated fragment
191
+ expansions, or is exactly what the last recorded apply deployed. Those files
192
+ are listed in an informational note, since their patches still owe a
193
+ re-export. Only content that matches no patch body, no baseline and none of
194
+ these source forms is refused.