@hominis/fireforge 0.52.0 → 0.54.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 (248) hide show
  1. package/CHANGELOG.md +45 -0
  2. package/dist/build-info.json +4 -4
  3. package/dist/src/commands/bootstrap.js +2 -3
  4. package/dist/src/commands/build-prelock.d.ts +3 -3
  5. package/dist/src/commands/build-prelock.js +3 -3
  6. package/dist/src/commands/build.js +4 -0
  7. package/dist/src/commands/declarations-report.d.ts +9 -3
  8. package/dist/src/commands/declarations-report.js +18 -11
  9. package/dist/src/commands/discard.js +3 -3
  10. package/dist/src/commands/doctor-furnace-config-sync.js +4 -4
  11. package/dist/src/commands/doctor-furnace.js +5 -5
  12. package/dist/src/commands/export-adopt-check.d.ts +5 -6
  13. package/dist/src/commands/export-adopt-check.js +5 -6
  14. package/dist/src/commands/export-flow.js +6 -9
  15. package/dist/src/commands/export-staged-registration.d.ts +4 -4
  16. package/dist/src/commands/export-staged-registration.js +4 -4
  17. package/dist/src/commands/forward-import-remedy.d.ts +2 -3
  18. package/dist/src/commands/forward-import-remedy.js +2 -3
  19. package/dist/src/commands/furnace/create-dry-run.d.ts +2 -2
  20. package/dist/src/commands/furnace/deploy-fragment-includers.d.ts +2 -2
  21. package/dist/src/commands/furnace/deploy-fragment-includers.js +2 -2
  22. package/dist/src/commands/furnace/index.js +2 -2
  23. package/dist/src/commands/lint.js +4 -4
  24. package/dist/src/commands/patch/compact.js +1 -1
  25. package/dist/src/commands/patch/lint-ignore-from.d.ts +3 -4
  26. package/dist/src/commands/patch/lint-ignore-from.js +3 -4
  27. package/dist/src/commands/patch/move-files-adopt.d.ts +33 -0
  28. package/dist/src/commands/patch/move-files-adopt.js +65 -0
  29. package/dist/src/commands/patch/move-files-create.js +41 -20
  30. package/dist/src/commands/patch/move-files-into.d.ts +18 -0
  31. package/dist/src/commands/patch/move-files-into.js +125 -60
  32. package/dist/src/commands/patch/move-files-retire.d.ts +39 -0
  33. package/dist/src/commands/patch/move-files-retire.js +91 -0
  34. package/dist/src/commands/patch/move-files.d.ts +3 -0
  35. package/dist/src/commands/patch/move-files.js +42 -12
  36. package/dist/src/commands/patch/move-size-tier.d.ts +27 -0
  37. package/dist/src/commands/patch/move-size-tier.js +66 -0
  38. package/dist/src/commands/patch/rename.js +1 -1
  39. package/dist/src/commands/patch/reorder-projection.d.ts +17 -0
  40. package/dist/src/commands/patch/reorder-projection.js +49 -0
  41. package/dist/src/commands/patch/reorder-shift.d.ts +30 -0
  42. package/dist/src/commands/patch/reorder-shift.js +307 -0
  43. package/dist/src/commands/patch/reorder.d.ts +9 -15
  44. package/dist/src/commands/patch/reorder.js +52 -50
  45. package/dist/src/commands/patch/split-plan.d.ts +31 -3
  46. package/dist/src/commands/patch/split-plan.js +36 -12
  47. package/dist/src/commands/patch/split-staged.d.ts +2 -2
  48. package/dist/src/commands/patch/split-staged.js +2 -2
  49. package/dist/src/commands/patch/split.js +18 -5
  50. package/dist/src/commands/patch/staged-dependency-entries.d.ts +9 -1
  51. package/dist/src/commands/patch/staged-dependency-entries.js +32 -4
  52. package/dist/src/commands/patch/staged-dependency-from.js +15 -9
  53. package/dist/src/commands/patch/staged-dependency-remove.d.ts +26 -4
  54. package/dist/src/commands/patch/staged-dependency-remove.js +60 -23
  55. package/dist/src/commands/patch/staged-dependency.js +35 -24
  56. package/dist/src/commands/patch/tier.js +2 -2
  57. package/dist/src/commands/patch-rename-map.d.ts +14 -3
  58. package/dist/src/commands/patch-rename-map.js +21 -3
  59. package/dist/src/commands/re-export-adjacent.d.ts +4 -5
  60. package/dist/src/commands/re-export-lint.d.ts +4 -3
  61. package/dist/src/commands/re-export-lint.js +4 -3
  62. package/dist/src/commands/re-export-options.js +8 -2
  63. package/dist/src/commands/re-export-preflight.js +1 -2
  64. package/dist/src/commands/re-export-purity-scope.d.ts +1 -1
  65. package/dist/src/commands/re-export-purity-scope.js +13 -7
  66. package/dist/src/commands/re-export-retired-declarations.d.ts +22 -0
  67. package/dist/src/commands/re-export-retired-declarations.js +113 -0
  68. package/dist/src/commands/re-export-single.js +2 -2
  69. package/dist/src/commands/re-export-stale-registrations.d.ts +27 -6
  70. package/dist/src/commands/re-export-stale-registrations.js +65 -21
  71. package/dist/src/commands/re-export.js +4 -0
  72. package/dist/src/commands/rebase/continue.js +3 -3
  73. package/dist/src/commands/register.js +5 -4
  74. package/dist/src/commands/run.js +11 -4
  75. package/dist/src/commands/status.js +1 -1
  76. package/dist/src/commands/test-build-furnace.d.ts +1 -2
  77. package/dist/src/commands/test-build-furnace.js +1 -2
  78. package/dist/src/commands/test-build-phase.d.ts +8 -0
  79. package/dist/src/commands/test-build-phase.js +42 -7
  80. package/dist/src/commands/test-control-restore.d.ts +40 -0
  81. package/dist/src/commands/test-control-restore.js +86 -0
  82. package/dist/src/commands/test-dispatch.js +68 -7
  83. package/dist/src/commands/test-multi-verdict.js +1 -0
  84. package/dist/src/commands/test-orchestrate.d.ts +6 -0
  85. package/dist/src/commands/test-orchestrate.js +32 -1
  86. package/dist/src/commands/test-perf-scope.d.ts +1 -1
  87. package/dist/src/commands/test-perf-scope.js +1 -1
  88. package/dist/src/commands/test-prelock.d.ts +18 -8
  89. package/dist/src/commands/test-prelock.js +42 -14
  90. package/dist/src/commands/test-register.js +4 -3
  91. package/dist/src/commands/test-results.d.ts +10 -1
  92. package/dist/src/commands/test-results.js +20 -3
  93. package/dist/src/commands/test-run.d.ts +6 -0
  94. package/dist/src/commands/test-run.js +23 -4
  95. package/dist/src/commands/test-shards.d.ts +7 -3
  96. package/dist/src/commands/test-shards.js +24 -7
  97. package/dist/src/commands/test-stale-gate.d.ts +6 -1
  98. package/dist/src/commands/test-stale-gate.js +40 -2
  99. package/dist/src/commands/test-verdict.d.ts +5 -3
  100. package/dist/src/commands/test.js +14 -2
  101. package/dist/src/commands/token.js +2 -2
  102. package/dist/src/commands/verify.js +1 -1
  103. package/dist/src/commands/watch.js +1 -1
  104. package/dist/src/commands/wire.js +1 -1
  105. package/dist/src/core/build-audit-resolve.d.ts +4 -5
  106. package/dist/src/core/build-audit-resolve.js +4 -5
  107. package/dist/src/core/build-audit-skip.d.ts +2 -2
  108. package/dist/src/core/build-audit.d.ts +3 -4
  109. package/dist/src/core/build-baseline-types.d.ts +24 -3
  110. package/dist/src/core/build-baseline-validate.d.ts +30 -1
  111. package/dist/src/core/build-baseline-validate.js +127 -35
  112. package/dist/src/core/build-baseline.d.ts +8 -2
  113. package/dist/src/core/build-baseline.js +25 -16
  114. package/dist/src/core/build-jar-escalation.d.ts +4 -4
  115. package/dist/src/core/build-jar-escalation.js +4 -4
  116. package/dist/src/core/build-prepare.js +4 -4
  117. package/dist/src/core/config-validate.js +4 -4
  118. package/dist/src/core/coverage-extend.d.ts +5 -3
  119. package/dist/src/core/coverage-extend.js +8 -3
  120. package/dist/src/core/coverage-records.d.ts +4 -5
  121. package/dist/src/core/coverage-records.js +4 -5
  122. package/dist/src/core/destructive.d.ts +2 -2
  123. package/dist/src/core/destructive.js +2 -2
  124. package/dist/src/core/discard-baseline.d.ts +2 -2
  125. package/dist/src/core/discard-baseline.js +3 -3
  126. package/dist/src/core/engine-session-lock.d.ts +1 -1
  127. package/dist/src/core/engine-session-lock.js +1 -1
  128. package/dist/src/core/file-lock-owner.d.ts +5 -5
  129. package/dist/src/core/file-lock-owner.js +5 -5
  130. package/dist/src/core/file-lock-queue.js +6 -8
  131. package/dist/src/core/file-lock-shared.d.ts +4 -4
  132. package/dist/src/core/file-lock-shared.js +4 -4
  133. package/dist/src/core/file-lock.js +7 -10
  134. package/dist/src/core/firefox.js +2 -2
  135. package/dist/src/core/furnace-apply-overwrite-warn.d.ts +1 -1
  136. package/dist/src/core/furnace-apply-overwrite-warn.js +1 -1
  137. package/dist/src/core/furnace-apply.js +3 -3
  138. package/dist/src/core/furnace-operation.js +5 -5
  139. package/dist/src/core/furnace-registration-jar-inplace.js +5 -6
  140. package/dist/src/core/furnace-registration-rename.d.ts +5 -5
  141. package/dist/src/core/furnace-registration-rename.js +5 -5
  142. package/dist/src/core/furnace-registration-validate.d.ts +2 -1
  143. package/dist/src/core/furnace-registration-validate.js +2 -1
  144. package/dist/src/core/furnace-registration.js +2 -2
  145. package/dist/src/core/git-base.js +4 -3
  146. package/dist/src/core/git-diff.js +1 -1
  147. package/dist/src/core/git.js +1 -1
  148. package/dist/src/core/harness-orphans.d.ts +6 -6
  149. package/dist/src/core/harness-orphans.js +6 -6
  150. package/dist/src/core/harness-port-reservation.d.ts +60 -0
  151. package/dist/src/core/harness-port-reservation.js +122 -0
  152. package/dist/src/core/history-log-file.d.ts +9 -9
  153. package/dist/src/core/history-log-file.js +15 -15
  154. package/dist/src/core/history-log.d.ts +3 -3
  155. package/dist/src/core/history-log.js +3 -3
  156. package/dist/src/core/launchable-build.d.ts +39 -0
  157. package/dist/src/core/launchable-build.js +85 -0
  158. package/dist/src/core/marionette-port.js +1 -3
  159. package/dist/src/core/moz-manifest-rules.js +3 -2
  160. package/dist/src/core/negative-control-compiled.d.ts +13 -3
  161. package/dist/src/core/negative-control-compiled.js +27 -5
  162. package/dist/src/core/negative-control-diff.js +31 -6
  163. package/dist/src/core/parser-fallback.d.ts +5 -5
  164. package/dist/src/core/parser-fallback.js +5 -5
  165. package/dist/src/core/patch-identifier-suggest.d.ts +6 -0
  166. package/dist/src/core/patch-identifier-suggest.js +11 -4
  167. package/dist/src/core/patch-lint-checkjs.d.ts +1 -1
  168. package/dist/src/core/patch-lint-checkjs.js +1 -1
  169. package/dist/src/core/patch-lint-css.js +2 -2
  170. package/dist/src/core/patch-lint-file-size.d.ts +5 -7
  171. package/dist/src/core/patch-lint-file-size.js +5 -7
  172. package/dist/src/core/patch-lint-ignore.d.ts +3 -3
  173. package/dist/src/core/patch-lint-ignore.js +3 -3
  174. package/dist/src/core/patch-lint-prettier.d.ts +4 -6
  175. package/dist/src/core/patch-lint-prettier.js +4 -6
  176. package/dist/src/core/patch-lint-projection.d.ts +1 -1
  177. package/dist/src/core/patch-lint-projection.js +1 -1
  178. package/dist/src/core/patch-lint-queue-types.d.ts +2 -2
  179. package/dist/src/core/patch-lint-queue-types.js +2 -2
  180. package/dist/src/core/patch-manifest-consistency.d.ts +2 -2
  181. package/dist/src/core/patch-manifest-consistency.js +2 -2
  182. package/dist/src/core/patch-manifest-io.d.ts +5 -1
  183. package/dist/src/core/patch-manifest-io.js +12 -10
  184. package/dist/src/core/patch-manifest-key-order.d.ts +3 -4
  185. package/dist/src/core/patch-manifest-key-order.js +3 -4
  186. package/dist/src/core/patch-parse.d.ts +3 -3
  187. package/dist/src/core/patch-parse.js +3 -3
  188. package/dist/src/core/patch-policy.d.ts +1 -1
  189. package/dist/src/core/patch-policy.js +1 -1
  190. package/dist/src/core/patch-source-metadata.d.ts +1 -1
  191. package/dist/src/core/patch-source-metadata.js +1 -1
  192. package/dist/src/core/patch-subset.d.ts +5 -3
  193. package/dist/src/core/patch-subset.js +8 -7
  194. package/dist/src/core/patch-transform.d.ts +2 -2
  195. package/dist/src/core/patch-transform.js +2 -2
  196. package/dist/src/core/rebase-session.js +4 -6
  197. package/dist/src/core/register-xpcshell-test.d.ts +28 -7
  198. package/dist/src/core/register-xpcshell-test.js +76 -27
  199. package/dist/src/core/run-log.d.ts +8 -8
  200. package/dist/src/core/run-log.js +8 -8
  201. package/dist/src/core/status-classify.d.ts +1 -2
  202. package/dist/src/core/status-classify.js +1 -2
  203. package/dist/src/core/test-harness-crash.d.ts +5 -3
  204. package/dist/src/core/test-harness-crash.js +13 -14
  205. package/dist/src/core/test-harness-infra.d.ts +32 -0
  206. package/dist/src/core/test-harness-infra.js +69 -0
  207. package/dist/src/core/test-harness-signature.d.ts +6 -0
  208. package/dist/src/core/test-stale-check.d.ts +38 -0
  209. package/dist/src/core/test-stale-check.js +82 -1
  210. package/dist/src/core/test-stall-triage.js +5 -7
  211. package/dist/src/core/token-category.js +2 -2
  212. package/dist/src/core/token-inventory.js +3 -3
  213. package/dist/src/core/token-manager.d.ts +2 -2
  214. package/dist/src/core/token-manager.js +5 -7
  215. package/dist/src/core/token-variant.d.ts +6 -6
  216. package/dist/src/core/token-variant.js +7 -7
  217. package/dist/src/core/typecheck-shim.js +1 -1
  218. package/dist/src/core/wire-destroy.d.ts +1 -1
  219. package/dist/src/core/wire-destroy.js +1 -1
  220. package/dist/src/core/wire-dom-fragment.js +1 -1
  221. package/dist/src/core/wire-init.d.ts +1 -1
  222. package/dist/src/core/wire-init.js +1 -1
  223. package/dist/src/core/wire-subscript.d.ts +1 -1
  224. package/dist/src/core/wire-subscript.js +1 -1
  225. package/dist/src/core/wire-utils.d.ts +2 -2
  226. package/dist/src/core/wire-utils.js +3 -3
  227. package/dist/src/errors/base.d.ts +1 -1
  228. package/dist/src/errors/base.js +1 -1
  229. package/dist/src/errors/rebase.d.ts +1 -1
  230. package/dist/src/errors/rebase.js +1 -1
  231. package/dist/src/types/commands/options.d.ts +38 -3
  232. package/dist/src/types/config.d.ts +5 -7
  233. package/dist/src/utils/options.js +2 -2
  234. package/dist/src/utils/process.js +2 -2
  235. package/dist/src/utils/regex.d.ts +2 -2
  236. package/dist/src/utils/regex.js +3 -3
  237. package/dist/src/utils/sleep.d.ts +5 -6
  238. package/dist/src/utils/sleep.js +5 -6
  239. package/dist/src/utils/validation.js +2 -2
  240. package/docs/configuration.md +28 -23
  241. package/docs/exit-codes.md +8 -11
  242. package/docs/furnace.md +3 -3
  243. package/docs/lifecycle-invariants.md +36 -45
  244. package/docs/machine-output.md +41 -24
  245. package/docs/patch-workflow.md +140 -29
  246. package/docs/run-logs.md +8 -9
  247. package/docs/testing.md +114 -48
  248. package/package.json +1 -1
package/docs/testing.md CHANGED
@@ -29,9 +29,7 @@ them:
29
29
  - **Mixed harnesses.** xpcshell and browser/mochitest paths in one request
30
30
  run as two consecutive mach invocations, the xpcshell half first. With
31
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.
32
+ the union), and the second half runs build-less against it.
35
33
  - **`--repeat <n>`** runs the same selection n times. A `--build` builds
36
34
  once, and `--doctor` probes once. Every run is reported, so a flaky suite's
37
35
  rate is visible from one invocation.
@@ -85,7 +83,10 @@ Furnace deployed it to, since that is what the run reads; the component
85
83
  source itself is never touched. Only modifications of existing text files
86
84
  are accepted: a created, deleted, renamed or binary file, or a symlinked
87
85
  target, is refused. Hunks must match exactly; the only tolerance is a line
88
- offset, as in `git apply`, never fuzz.
86
+ offset, as in `git apply`, never fuzz. A file named by more than one
87
+ section (a generator that writes one section per edit) is applied as one
88
+ section with every hunk in file order; sections whose hunks overlap are
89
+ refused, with the advice to write one section for the file.
89
90
 
90
91
  The verdict says how the control came out with `control=`:
91
92
 
@@ -108,15 +109,30 @@ and reports `missed`: that result is the signal to target the file the
108
109
  browser actually loads.
109
110
 
110
111
  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
+ install manifest ships) can only reach the binary through a build. A
113
+ header (`.h`, `.hh`, `.hpp`, `.ipdlh`) counts as compiled even when an
114
+ `EXPORTS` install manifest copies it into `dist/include`: that copy only feeds
115
+ other compiles. Without
112
116
  `--build` it is refused before the lock. With `--build` it is applied before
113
117
  the pre-test build, so the binary under test carries it, stays applied for
114
118
  every `--repeat` run, and is restored with a fresh mtime so the next build
115
- recompiles the original. Since 0.52.0 that pre-test build is a full
119
+ recompiles the original. That pre-test build is a full
116
120
  `mach build`, with a notice naming the control's files: the default
117
- `mach build faster` compiles nothing, so before, the control still tested
118
- the previous binary and reported `missed`. The verdict adds
119
- `control-build=compiled`. A
121
+ `mach build faster` compiles nothing, so the control would still test
122
+ the previous binary and report `missed`. The verdict adds
123
+ `control-build=compiled`.
124
+
125
+ FireForge also rebuilds after such a control. Restoring the
126
+ source byte-exact does not unbuild the binary, which would keep the mutation
127
+ until the next full build, so every later run would test the control. After the last
128
+ run's restore, still under the same lock hold, it runs one more full
129
+ `mach build` and records a fresh baseline. The verdict adds
130
+ `control-restore-build=done` (or `=failed`). The baseline the control's build
131
+ writes carries a `controlBuild` stamp (diff file, targets, time applied) that
132
+ only a full build clears: if the run is killed before the restore build, or
133
+ that build fails, the next `fireforge test` refuses with `note=control-built`
134
+ until `fireforge build` succeeds, and a `test --build` escalates to a full
135
+ build. `fireforge build --ui` compiles nothing and keeps the stamp. A
120
136
  build-less control whose packaging is not current is refused before the
121
137
  lock with the advice to add `--build`, instead of ending `inconclusive`
122
138
  after a full queue.
@@ -155,15 +171,18 @@ copy outside `engine/` and `components/`, the control targets the old side.
155
171
  signal pipeline after the harness has shut down and before the held
156
172
  locks are released. A restore already in flight is awaited, not
157
173
  repeated.
174
+ - **The binary too.** A compiled control's binary is rebuilt
175
+ after the restore, under the same hold, and a binary still carrying a
176
+ control is refused (`note=control-built`) rather than tested. See above.
158
177
  - **Even after SIGKILL.** A SIGKILLed FireForge cannot restore, but the
159
178
  journal survives it. Every later `fireforge test` checks for it first,
160
179
  under the lock, before any gate or build: a file still holding the
161
180
  control's bytes is restored, with a notice; any other state refuses with
162
181
  `note=negative-control-pending` rather than guess.
163
182
 
164
- The shorthand `--mutate <file> <old> <new>` that was proposed alongside this
165
- was not added. Commander options take one value, so a three-value option
166
- would have to swallow the positional test paths. A one-hunk diff expresses
183
+ There is no `--mutate <file> <old> <new>` shorthand. Commander options take
184
+ one value, so a three-value option would have to swallow the positional test
185
+ paths. A one-hunk diff expresses
167
186
  the same edit and can be reviewed before it runs.
168
187
 
169
188
  ## Pathless runs must choose a mode
@@ -200,10 +219,30 @@ the run (and in the refusal, when other edits are stale). On a
200
219
  inputs of the sampled test and which lie elsewhere, so a sample whose fixture
201
220
  is unaffected can proceed knowingly under `--allow-stale-build`.
202
221
 
222
+ ### Compiled sources newer than the binary
223
+
224
+ The packaging check above judges packaged files only. Every run
225
+ also compares the compiled sources changed since the last build (C/C++,
226
+ Rust, IDL, WebIDL, IPDL, and YAML such as `StaticPrefList.yaml`) with the
227
+ time the binary under test was last linked: the newer of the launchable
228
+ binary and the `libxul` beside it. Sources under `test`, `tests`, `gtest`,
229
+ `testing` or `taskcluster` directories never reach that binary and are not
230
+ counted. A newer source means the run would test the binary from before the
231
+ edit, where a red reads as a failed fix. Without `--build` the run refuses
232
+ with `note=stale-compiled`, naming the files and the link time, and suggests
233
+ `fireforge build` or `test --build`; `--allow-stale-build` turns the refusal
234
+ into a warning. With `--build` the pre-test build escalates to a full
235
+ `mach build` with a notice, since `mach build faster` compiles nothing.
236
+
237
+ Every run that reaches dispatch also stamps the binary's `BuildID` (from the
238
+ `application.ini` beside it, the `moz:buildID` the browser reports) on its
239
+ verdict line as `build-id=`, so a result can be matched to the build it ran
240
+ against.
241
+
203
242
  ### Packaging coverage
204
243
 
205
244
  `--build-only` packages mixed-harness paths once, and then each harness half
206
- can run without `--build`. A plain mixed `test --build` now does both in one
245
+ can run without `--build`. A plain mixed `test --build` does both in one
207
246
  invocation (see [Several runs under one lock hold](#several-runs-under-one-lock-hold)). Coverage is kept per staged path. Each path of a
208
247
  scoped build records its own staging inputs: its manifest directory (the
209
248
  nearest directory at or above it with a test manifest) plus whatever a
@@ -214,7 +253,7 @@ moved elsewhere in the engine, including a peer's edits and an engine HEAD
214
253
  move that touches none of them. A path whose inputs changed is dropped and
215
254
  named, with the inputs that changed. Changed inputs this build restages are
216
255
  allowed, and a scoped build of one file restages that file's test manifest
217
- too: a manifest that gained an entry for the new file no longer drops the
256
+ too: a manifest that gained an entry for the new file does not drop the
218
257
  claims of its sibling files. A build-less run's packaging gates also run
219
258
  before the lock is requested, so a `coverage-replaced` or `stale-build`
220
259
  refusal arrives before the run queues.
@@ -223,20 +262,23 @@ A scoped build after a full build keeps the claim full while nothing outside
223
262
  its scope moved. Otherwise it carries the full build's anchor forward, and a
224
263
  later build-less run over any path stays covered while that path's own
225
264
  staging inputs are unchanged since the full build. A refusal names the inputs
226
- that did change, and since 0.52.0 who wrote the coverage record: its
265
+ that did change, and who wrote the coverage record: its
227
266
  invocation, when, and the writing process's pid (marked `still running`
228
267
  while it is), `FIREFORGE_SESSION_ID` and invocation id, the id its history
229
268
  records carry. `status --test-coverage` shows the pid and session too. A
230
269
  peer whose run a scoped build or a test-file edit refused can tell whose
231
270
  build to wait for.
232
271
 
233
- `--extend-coverage` remains accepted. Retention is now the default, so the
234
- flag only turns a drop into a refusal before the build. Before 0.50.0 a
235
- scoped build without the flag replaced the claim whenever anything outside
236
- its scope had changed, and the flag refused unless engine HEAD, the
237
- mozconfig and every staging input recorded by the previous build were
238
- unchanged. Baselines without complete staging-input fingerprints (older than
239
- 0.49.0) cannot prove anything unchanged and are dropped once.
272
+ Retention is the default, so `--extend-coverage` only turns a drop into a
273
+ refusal before the build. A baseline without complete staging-input
274
+ fingerprints cannot prove anything unchanged, so its claims are dropped once.
275
+
276
+ A scoped build records its request paths normalized (no trailing `/`, no
277
+ `./`), as the baseline validator requires. An invalid baseline's refusal
278
+ names the first failing field and its value, and when that field is part of
279
+ the coverage claim it offers rerunning with `--build` as well as
280
+ `fireforge build`. Dirty paths are fingerprinted unquoted, so a non-ASCII
281
+ file name does not make the baseline invalid.
240
282
 
241
283
  ### Furnace components in a pre-test build
242
284
 
@@ -290,7 +332,11 @@ engine session lock is requested, so a run waiting out a browser or a port
290
332
  does not hold every peer's build, test and re-export behind it. The run then
291
333
  joins the lock queue and re-checks once under the lock; the normal preflight
292
334
  refusal and its remedy apply if the resource is busy again (or still busy)
293
- there. With `--kill-stale-marionette` a reapable stale browser counts as
335
+ there. A check that follows work the run already did under the lock waits
336
+ the budgets out again instead: the browser and port checks after a
337
+ `--build` run's pre-test build, and those of every later run of a `--repeat`
338
+ or `--negative-control` sequence, so a peer's browser that started during
339
+ the build does not throw the build away. With `--kill-stale-marionette` a reapable stale browser counts as
294
340
  clear before the lock, and the port waits stay under the lock, where the
295
341
  stale listener can be reaped.
296
342
 
@@ -308,22 +354,21 @@ do something better instead: `testing/mochitest/runtests.py` bind-probes
308
354
  the HTTP server, ssltunnel and WebSocket ports before starting its servers,
309
355
  and the Marionette port before launching the browser, moves each busy one to
310
356
  a free port, and routes `mochi.test:8888` to wherever the server landed.
311
- FireForge's own refusal used to fire before that fallback could. In auto
312
- mode the mochitest-server and Marionette gates step aside, with a notice
357
+ In the default mode FireForge's own refusal fires before that fallback can.
358
+ In auto mode the mochitest-server and Marionette gates step aside, with a notice
313
359
  naming the holder, when the holder is not this checkout's own (a sibling
314
360
  checkout's live suite or an unrelated listener). This checkout's own
315
- leftovers are refused exactly as before, and `--kill-stale-marionette`
361
+ leftovers are refused exactly as in the default mode, and `--kill-stale-marionette`
316
362
  still applies to them. Auto mode takes effect only when the engine's
317
363
  `runtests.py` carries the fallback; otherwise a notice says so and the
318
364
  default refusal stays. It never applies to `--doctor`'s Marionette probe,
319
- which launches its own browser on that port. The default (`"fixed"`) is
320
- unchanged.
365
+ which launches its own browser on that port. The default is `"fixed"`.
321
366
 
322
367
  Every suite samples host load and the highest CPU process before and after
323
368
  dispatch. Load at least 4 or a process at least 90% CPU produces a warning;
324
369
  verdicts include `host-load` and, when needed, `host-cpu-warning=true`.
325
370
  Perf runs include `power-source=ac|battery|unknown`; on macOS this comes from
326
- `pmset -g ps`, including charging on AC. Sample JSON gains a `fireforgeHost`
371
+ `pmset -g ps`, including charging on AC. Sample JSON carries a `fireforgeHost`
327
372
  object with start/end states and `powerSourceChanged`. A known power-source
328
373
  transition produces `FAIL reason=inconclusive power-changed=true`.
329
374
  Unknown power state is reported without inventing a transition.
@@ -358,7 +403,7 @@ Furnace-applied components:
358
403
  (untracked in the engine repo, so no install manifest exists for it yet),
359
404
  or when its jar declaration carries a bracketed base-directory prefix,
360
405
  which redirects the install destination away from the default chrome root.
361
- An entry added to an existing `dist/bin` manifest no longer escalates. Any
406
+ An entry added to an existing `dist/bin` manifest does not escalate. Any
362
407
  probe failure (an unreadable manifest, no git) escalates, and the notice
363
408
  names the manifest and the reason.
364
409
 
@@ -370,16 +415,13 @@ carried forward from the previous full build, so a registration made between
370
415
  a `build --ui` and the next `test --build` still triggers the full build
371
416
  once.
372
417
 
373
- The 0.44.0 changelog left an open question here: whether a full build is
374
- really required for an entry added to an existing `dist/bin` `jar.mn`. It was
375
- settled downstream by exactly the experiment that entry asked for. In two
376
- clean runs, a jar-only registration of a new content file was installed by a
377
- plain `fireforge build --ui` (`faster/install_dist_bin_browser` named the
378
- destination, and the file reached `dist/bin` and the `.app` bundle) and then
379
- fetched over `chrome://` by a plain `fireforge test`. That case no longer
380
- escalates. The two halves the experiment did not cover, a new `jar.mn` file
381
- and a non-default install destination, still escalate, for the reason the
382
- original entry gives: relaxing a stale-artifact guard without evidence trades
418
+ An entry added to an existing `dist/bin` `jar.mn` needs no full build: a
419
+ jar-only registration of a new content file is installed by a plain
420
+ `fireforge build --ui` (`faster/install_dist_bin_browser` names the
421
+ destination, and the file reaches `dist/bin` and the `.app` bundle) and is
422
+ then fetched over `chrome://` by a plain `fireforge test`. A new `jar.mn`
423
+ file and a non-default install destination have no such evidence and
424
+ escalate: relaxing a stale-artifact guard without evidence trades
383
425
  a slow build for a silently wrong test.
384
426
 
385
427
  ## Resilience
@@ -474,9 +516,9 @@ FIREFORGE-VERDICT: PASS|FAIL reason=… [note=<class>] [started=<n>/<m> first-un
474
516
  ```
475
517
 
476
518
  The start count reads every line the harness printed, not the last 2 MB of
477
- captured output: a suite printing more than that (a large browser directory,
478
- or any run under `--full-output`) used to report files that ran and passed
479
- as never started. `started-source=` names the evidence. A sharded run also
519
+ captured output, so a suite printing more than that (a large browser
520
+ directory, or any run under `--full-output`) does not report files that ran
521
+ and passed as never started. `started-source=` names the evidence. A sharded run also
480
522
  prints a `FIREFORGE-SHARD:` line per shard and names the shards that did not
481
523
  pass as `failed-shards=`; see [`machine-output.md`](machine-output.md).
482
524
 
@@ -591,17 +633,39 @@ helpers.
591
633
  `--jobs <n>` runs a request's shards on n harness instances inside one lock
592
634
  hold. Each instance has its own profile and its own Marionette port, and
593
635
  auto ports (required) move each instance's mochitest server ports; output
594
- lines carry a `[job <i>]` prefix in the terminal and the run log. Since
595
- 0.52.0 each instance also writes its own mochitest test list
636
+ lines carry a `[job <i>]` prefix in the terminal and the run log. Each
637
+ instance also writes its own mochitest test list
596
638
  (`--testrun-manifest-file`): on the harness's shared default
597
- `_tests/testing/mochitest/tests.json`, the second instance ran the first
598
- shard's file and passed, or found none. A `--jobs` run always reads each
639
+ `_tests/testing/mochitest/tests.json`, the second instance would run the
640
+ first shard's file and pass, or find none. A `--jobs` run always reads each
599
641
  dispatch's mozlog raw log, and a dispatch whose raw log starts none of its
600
642
  requested files fails with `started=0/<m>` instead of passing on another
601
643
  shard's results. With `--no-shard`, or a single directory argument, the
602
644
  files are split in order into n contiguous chunks. Parallel browsers raise
603
645
  host load, so measure before relying on it.
604
646
 
647
+ When the caller sets `MOZ_UPLOAD_DIR`, each `--jobs` instance gets its own
648
+ `<MOZ_UPLOAD_DIR>/job-<i>` (created up front) instead of the shared
649
+ directory, where instances would replace each other's fixed-name artifacts
650
+ such as the `modifiedPrefs.json` pref census. The verdict names them as
651
+ `upload-dirs=<dir>,<dir>,...` so a caller can merge per-instance artifacts.
652
+ Without `MOZ_UPLOAD_DIR` nothing changes.
653
+
654
+ A browser `--jobs` run on more than one instance also holds
655
+ placeholder listeners on `127.0.0.1` on the mochitest HTTP, ssltunnel and
656
+ WebSocket ports (8888, 4443, 9988) for the whole parallel hold, after the
657
+ server-port preflight. Desktop mochitest has no flags for these ports, and
658
+ its busy-port probe passes for instances that start together, which then
659
+ race for 8888 and die with `could not start server on port 8888`. With the
660
+ ports held, every instance's probe fails and each falls back to its own
661
+ port; a port that is already busy is left alone. Each `FIREFORGE-SHARD:`
662
+ line carries the ports its instance took as `ports=http:<n>,ssl:<n>,ws:<n>`.
663
+ A harness whose server still fails to start (`could not start server on
664
+ port` or `Timed out while waiting for server startup`, before any test) is
665
+ an infrastructure failure, not `no-tests`: it is retried within the
666
+ `--harness-retries` budget like a harness crash, and reported as
667
+ `reason=server-startup` once the budget is spent.
668
+
605
669
  `--shard-size <n>` dispatches n files per mach invocation (mochitest restarts
606
670
  the browser between files), paying the harness start once per chunk instead
607
671
  of once per file, and judges each file from mozlog's structured log:
@@ -612,7 +676,9 @@ of once per file, and judges each file from mozlog's structured log:
612
676
  run-log line where the dispatch began) from mozlog's structured log, which
613
677
  each dispatch then writes with `--log-raw`, and names it on the verdict as
614
678
  `results=<path>`. A `--log-raw <file>` already forwarded with `--mach-arg` is
615
- read instead. The checks that need no lock run before it is
679
+ read instead. A harness-level record (`test` is `automation.py`,
680
+ such as a hung browser's no-output TIMEOUT) also carries `shardFiles`, the
681
+ shard's dispatched files, and `file` when the shard has exactly one. The checks that need no lock run before it is
616
682
  requested: the launchable binary, the named-file checkJs pass, and the
617
683
  `--wait-browser`/`--wait-port` budgets. The run log is open from the start,
618
684
  so a `reason=lock-timeout` line carries `log=` too.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hominis/fireforge",
3
- "version": "0.52.0",
3
+ "version": "0.54.0",
4
4
  "description": "FireForge — a build tool for customizing Firefox",
5
5
  "type": "module",
6
6
  "main": "./dist/src/index.js",