@hominis/fireforge 0.52.0 → 0.53.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 (243) hide show
  1. package/CHANGELOG.md +26 -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.js +13 -9
  54. package/dist/src/commands/patch/tier.js +2 -2
  55. package/dist/src/commands/patch-rename-map.d.ts +14 -3
  56. package/dist/src/commands/patch-rename-map.js +21 -3
  57. package/dist/src/commands/re-export-adjacent.d.ts +4 -5
  58. package/dist/src/commands/re-export-lint.d.ts +4 -3
  59. package/dist/src/commands/re-export-lint.js +4 -3
  60. package/dist/src/commands/re-export-preflight.js +1 -2
  61. package/dist/src/commands/re-export-purity-scope.d.ts +1 -1
  62. package/dist/src/commands/re-export-purity-scope.js +13 -7
  63. package/dist/src/commands/re-export-retired-declarations.d.ts +22 -0
  64. package/dist/src/commands/re-export-retired-declarations.js +113 -0
  65. package/dist/src/commands/re-export-single.js +2 -2
  66. package/dist/src/commands/re-export-stale-registrations.d.ts +27 -6
  67. package/dist/src/commands/re-export-stale-registrations.js +65 -21
  68. package/dist/src/commands/re-export.js +4 -0
  69. package/dist/src/commands/rebase/continue.js +3 -3
  70. package/dist/src/commands/register.js +5 -4
  71. package/dist/src/commands/status.js +1 -1
  72. package/dist/src/commands/test-build-furnace.d.ts +1 -2
  73. package/dist/src/commands/test-build-furnace.js +1 -2
  74. package/dist/src/commands/test-build-phase.d.ts +8 -0
  75. package/dist/src/commands/test-build-phase.js +42 -7
  76. package/dist/src/commands/test-control-restore.d.ts +40 -0
  77. package/dist/src/commands/test-control-restore.js +86 -0
  78. package/dist/src/commands/test-dispatch.js +68 -7
  79. package/dist/src/commands/test-multi-verdict.js +1 -0
  80. package/dist/src/commands/test-orchestrate.d.ts +6 -0
  81. package/dist/src/commands/test-orchestrate.js +28 -0
  82. package/dist/src/commands/test-perf-scope.d.ts +1 -1
  83. package/dist/src/commands/test-perf-scope.js +1 -1
  84. package/dist/src/commands/test-prelock.d.ts +7 -8
  85. package/dist/src/commands/test-prelock.js +15 -12
  86. package/dist/src/commands/test-register.js +2 -2
  87. package/dist/src/commands/test-results.d.ts +10 -1
  88. package/dist/src/commands/test-results.js +20 -3
  89. package/dist/src/commands/test-run.d.ts +6 -0
  90. package/dist/src/commands/test-run.js +23 -4
  91. package/dist/src/commands/test-shards.d.ts +7 -3
  92. package/dist/src/commands/test-shards.js +24 -7
  93. package/dist/src/commands/test-stale-gate.d.ts +6 -1
  94. package/dist/src/commands/test-stale-gate.js +40 -2
  95. package/dist/src/commands/test-verdict.d.ts +5 -3
  96. package/dist/src/commands/test.js +10 -0
  97. package/dist/src/commands/token.js +2 -2
  98. package/dist/src/commands/verify.js +1 -1
  99. package/dist/src/commands/watch.js +1 -1
  100. package/dist/src/commands/wire.js +1 -1
  101. package/dist/src/core/build-audit-resolve.d.ts +4 -5
  102. package/dist/src/core/build-audit-resolve.js +4 -5
  103. package/dist/src/core/build-audit-skip.d.ts +2 -2
  104. package/dist/src/core/build-audit.d.ts +3 -4
  105. package/dist/src/core/build-baseline-types.d.ts +24 -3
  106. package/dist/src/core/build-baseline-validate.d.ts +30 -1
  107. package/dist/src/core/build-baseline-validate.js +127 -35
  108. package/dist/src/core/build-baseline.d.ts +8 -2
  109. package/dist/src/core/build-baseline.js +25 -16
  110. package/dist/src/core/build-jar-escalation.d.ts +4 -4
  111. package/dist/src/core/build-jar-escalation.js +4 -4
  112. package/dist/src/core/build-prepare.js +4 -4
  113. package/dist/src/core/config-validate.js +4 -4
  114. package/dist/src/core/coverage-extend.d.ts +5 -3
  115. package/dist/src/core/coverage-extend.js +8 -3
  116. package/dist/src/core/coverage-records.d.ts +4 -5
  117. package/dist/src/core/coverage-records.js +4 -5
  118. package/dist/src/core/destructive.d.ts +2 -2
  119. package/dist/src/core/destructive.js +2 -2
  120. package/dist/src/core/discard-baseline.d.ts +2 -2
  121. package/dist/src/core/discard-baseline.js +3 -3
  122. package/dist/src/core/engine-session-lock.d.ts +1 -1
  123. package/dist/src/core/engine-session-lock.js +1 -1
  124. package/dist/src/core/file-lock-owner.d.ts +5 -5
  125. package/dist/src/core/file-lock-owner.js +5 -5
  126. package/dist/src/core/file-lock-queue.js +6 -8
  127. package/dist/src/core/file-lock-shared.d.ts +4 -4
  128. package/dist/src/core/file-lock-shared.js +4 -4
  129. package/dist/src/core/file-lock.js +7 -10
  130. package/dist/src/core/firefox.js +2 -2
  131. package/dist/src/core/furnace-apply-overwrite-warn.d.ts +1 -1
  132. package/dist/src/core/furnace-apply-overwrite-warn.js +1 -1
  133. package/dist/src/core/furnace-apply.js +3 -3
  134. package/dist/src/core/furnace-operation.js +5 -5
  135. package/dist/src/core/furnace-registration-jar-inplace.js +5 -6
  136. package/dist/src/core/furnace-registration-rename.d.ts +5 -5
  137. package/dist/src/core/furnace-registration-rename.js +5 -5
  138. package/dist/src/core/furnace-registration-validate.d.ts +2 -1
  139. package/dist/src/core/furnace-registration-validate.js +2 -1
  140. package/dist/src/core/furnace-registration.js +2 -2
  141. package/dist/src/core/git-base.js +4 -3
  142. package/dist/src/core/git-diff.js +1 -1
  143. package/dist/src/core/git.js +1 -1
  144. package/dist/src/core/harness-orphans.d.ts +6 -6
  145. package/dist/src/core/harness-orphans.js +6 -6
  146. package/dist/src/core/harness-port-reservation.d.ts +60 -0
  147. package/dist/src/core/harness-port-reservation.js +122 -0
  148. package/dist/src/core/history-log-file.d.ts +9 -9
  149. package/dist/src/core/history-log-file.js +15 -15
  150. package/dist/src/core/history-log.d.ts +3 -3
  151. package/dist/src/core/history-log.js +3 -3
  152. package/dist/src/core/launchable-build.d.ts +39 -0
  153. package/dist/src/core/launchable-build.js +85 -0
  154. package/dist/src/core/marionette-port.js +1 -3
  155. package/dist/src/core/moz-manifest-rules.js +3 -2
  156. package/dist/src/core/negative-control-compiled.d.ts +13 -3
  157. package/dist/src/core/negative-control-compiled.js +27 -5
  158. package/dist/src/core/parser-fallback.d.ts +5 -5
  159. package/dist/src/core/parser-fallback.js +5 -5
  160. package/dist/src/core/patch-identifier-suggest.d.ts +6 -0
  161. package/dist/src/core/patch-identifier-suggest.js +11 -4
  162. package/dist/src/core/patch-lint-checkjs.d.ts +1 -1
  163. package/dist/src/core/patch-lint-checkjs.js +1 -1
  164. package/dist/src/core/patch-lint-css.js +2 -2
  165. package/dist/src/core/patch-lint-file-size.d.ts +5 -7
  166. package/dist/src/core/patch-lint-file-size.js +5 -7
  167. package/dist/src/core/patch-lint-ignore.d.ts +3 -3
  168. package/dist/src/core/patch-lint-ignore.js +3 -3
  169. package/dist/src/core/patch-lint-prettier.d.ts +4 -6
  170. package/dist/src/core/patch-lint-prettier.js +4 -6
  171. package/dist/src/core/patch-lint-projection.d.ts +1 -1
  172. package/dist/src/core/patch-lint-projection.js +1 -1
  173. package/dist/src/core/patch-lint-queue-types.d.ts +2 -2
  174. package/dist/src/core/patch-lint-queue-types.js +2 -2
  175. package/dist/src/core/patch-manifest-consistency.d.ts +2 -2
  176. package/dist/src/core/patch-manifest-consistency.js +2 -2
  177. package/dist/src/core/patch-manifest-io.d.ts +5 -1
  178. package/dist/src/core/patch-manifest-io.js +12 -10
  179. package/dist/src/core/patch-manifest-key-order.d.ts +3 -4
  180. package/dist/src/core/patch-manifest-key-order.js +3 -4
  181. package/dist/src/core/patch-parse.d.ts +3 -3
  182. package/dist/src/core/patch-parse.js +3 -3
  183. package/dist/src/core/patch-policy.d.ts +1 -1
  184. package/dist/src/core/patch-policy.js +1 -1
  185. package/dist/src/core/patch-source-metadata.d.ts +1 -1
  186. package/dist/src/core/patch-source-metadata.js +1 -1
  187. package/dist/src/core/patch-subset.d.ts +5 -3
  188. package/dist/src/core/patch-subset.js +8 -7
  189. package/dist/src/core/patch-transform.d.ts +2 -2
  190. package/dist/src/core/patch-transform.js +2 -2
  191. package/dist/src/core/rebase-session.js +4 -6
  192. package/dist/src/core/register-xpcshell-test.d.ts +28 -7
  193. package/dist/src/core/register-xpcshell-test.js +76 -27
  194. package/dist/src/core/run-log.d.ts +8 -8
  195. package/dist/src/core/run-log.js +8 -8
  196. package/dist/src/core/status-classify.d.ts +1 -2
  197. package/dist/src/core/status-classify.js +1 -2
  198. package/dist/src/core/test-harness-crash.d.ts +5 -3
  199. package/dist/src/core/test-harness-crash.js +13 -14
  200. package/dist/src/core/test-harness-infra.d.ts +32 -0
  201. package/dist/src/core/test-harness-infra.js +69 -0
  202. package/dist/src/core/test-harness-signature.d.ts +6 -0
  203. package/dist/src/core/test-stale-check.d.ts +38 -0
  204. package/dist/src/core/test-stale-check.js +82 -1
  205. package/dist/src/core/test-stall-triage.js +5 -7
  206. package/dist/src/core/token-category.js +2 -2
  207. package/dist/src/core/token-inventory.js +3 -3
  208. package/dist/src/core/token-manager.d.ts +2 -2
  209. package/dist/src/core/token-manager.js +5 -7
  210. package/dist/src/core/token-variant.d.ts +6 -6
  211. package/dist/src/core/token-variant.js +7 -7
  212. package/dist/src/core/typecheck-shim.js +1 -1
  213. package/dist/src/core/wire-destroy.d.ts +1 -1
  214. package/dist/src/core/wire-destroy.js +1 -1
  215. package/dist/src/core/wire-dom-fragment.js +1 -1
  216. package/dist/src/core/wire-init.d.ts +1 -1
  217. package/dist/src/core/wire-init.js +1 -1
  218. package/dist/src/core/wire-subscript.d.ts +1 -1
  219. package/dist/src/core/wire-subscript.js +1 -1
  220. package/dist/src/core/wire-utils.d.ts +2 -2
  221. package/dist/src/core/wire-utils.js +3 -3
  222. package/dist/src/errors/base.d.ts +1 -1
  223. package/dist/src/errors/base.js +1 -1
  224. package/dist/src/errors/rebase.d.ts +1 -1
  225. package/dist/src/errors/rebase.js +1 -1
  226. package/dist/src/types/commands/options.d.ts +26 -3
  227. package/dist/src/types/config.d.ts +5 -7
  228. package/dist/src/utils/options.js +2 -2
  229. package/dist/src/utils/process.js +2 -2
  230. package/dist/src/utils/regex.d.ts +2 -2
  231. package/dist/src/utils/regex.js +3 -3
  232. package/dist/src/utils/sleep.d.ts +5 -6
  233. package/dist/src/utils/sleep.js +5 -6
  234. package/dist/src/utils/validation.js +2 -2
  235. package/docs/configuration.md +21 -23
  236. package/docs/exit-codes.md +8 -11
  237. package/docs/furnace.md +3 -3
  238. package/docs/lifecycle-invariants.md +36 -45
  239. package/docs/machine-output.md +41 -24
  240. package/docs/patch-workflow.md +129 -24
  241. package/docs/run-logs.md +8 -9
  242. package/docs/testing.md +105 -46
  243. 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.
@@ -108,15 +106,30 @@ and reports `missed`: that result is the signal to target the file the
108
106
  browser actually loads.
109
107
 
110
108
  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
109
+ install manifest ships) can only reach the binary through a build. A
110
+ header (`.h`, `.hh`, `.hpp`, `.ipdlh`) counts as compiled even when an
111
+ `EXPORTS` install manifest copies it into `dist/include`: that copy only feeds
112
+ other compiles. Without
112
113
  `--build` it is refused before the lock. With `--build` it is applied before
113
114
  the pre-test build, so the binary under test carries it, stays applied for
114
115
  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
116
+ recompiles the original. That pre-test build is a full
116
117
  `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
118
+ `mach build faster` compiles nothing, so the control would still test
119
+ the previous binary and report `missed`. The verdict adds
120
+ `control-build=compiled`.
121
+
122
+ FireForge also rebuilds after such a control. Restoring the
123
+ source byte-exact does not unbuild the binary, which would keep the mutation
124
+ until the next full build, so every later run would test the control. After the last
125
+ run's restore, still under the same lock hold, it runs one more full
126
+ `mach build` and records a fresh baseline. The verdict adds
127
+ `control-restore-build=done` (or `=failed`). The baseline the control's build
128
+ writes carries a `controlBuild` stamp (diff file, targets, time applied) that
129
+ only a full build clears: if the run is killed before the restore build, or
130
+ that build fails, the next `fireforge test` refuses with `note=control-built`
131
+ until `fireforge build` succeeds, and a `test --build` escalates to a full
132
+ build. `fireforge build --ui` compiles nothing and keeps the stamp. A
120
133
  build-less control whose packaging is not current is refused before the
121
134
  lock with the advice to add `--build`, instead of ending `inconclusive`
122
135
  after a full queue.
@@ -155,15 +168,18 @@ copy outside `engine/` and `components/`, the control targets the old side.
155
168
  signal pipeline after the harness has shut down and before the held
156
169
  locks are released. A restore already in flight is awaited, not
157
170
  repeated.
171
+ - **The binary too.** A compiled control's binary is rebuilt
172
+ after the restore, under the same hold, and a binary still carrying a
173
+ control is refused (`note=control-built`) rather than tested. See above.
158
174
  - **Even after SIGKILL.** A SIGKILLed FireForge cannot restore, but the
159
175
  journal survives it. Every later `fireforge test` checks for it first,
160
176
  under the lock, before any gate or build: a file still holding the
161
177
  control's bytes is restored, with a notice; any other state refuses with
162
178
  `note=negative-control-pending` rather than guess.
163
179
 
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
180
+ There is no `--mutate <file> <old> <new>` shorthand. Commander options take
181
+ one value, so a three-value option would have to swallow the positional test
182
+ paths. A one-hunk diff expresses
167
183
  the same edit and can be reviewed before it runs.
168
184
 
169
185
  ## Pathless runs must choose a mode
@@ -200,10 +216,30 @@ the run (and in the refusal, when other edits are stale). On a
200
216
  inputs of the sampled test and which lie elsewhere, so a sample whose fixture
201
217
  is unaffected can proceed knowingly under `--allow-stale-build`.
202
218
 
219
+ ### Compiled sources newer than the binary
220
+
221
+ The packaging check above judges packaged files only. Every run
222
+ also compares the compiled sources changed since the last build (C/C++,
223
+ Rust, IDL, WebIDL, IPDL, and YAML such as `StaticPrefList.yaml`) with the
224
+ time the binary under test was last linked: the newer of the launchable
225
+ binary and the `libxul` beside it. Sources under `test`, `tests`, `gtest`,
226
+ `testing` or `taskcluster` directories never reach that binary and are not
227
+ counted. A newer source means the run would test the binary from before the
228
+ edit, where a red reads as a failed fix. Without `--build` the run refuses
229
+ with `note=stale-compiled`, naming the files and the link time, and suggests
230
+ `fireforge build` or `test --build`; `--allow-stale-build` turns the refusal
231
+ into a warning. With `--build` the pre-test build escalates to a full
232
+ `mach build` with a notice, since `mach build faster` compiles nothing.
233
+
234
+ Every run that reaches dispatch also stamps the binary's `BuildID` (from the
235
+ `application.ini` beside it, the `moz:buildID` the browser reports) on its
236
+ verdict line as `build-id=`, so a result can be matched to the build it ran
237
+ against.
238
+
203
239
  ### Packaging coverage
204
240
 
205
241
  `--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
242
+ can run without `--build`. A plain mixed `test --build` does both in one
207
243
  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
244
  scoped build records its own staging inputs: its manifest directory (the
209
245
  nearest directory at or above it with a test manifest) plus whatever a
@@ -214,7 +250,7 @@ moved elsewhere in the engine, including a peer's edits and an engine HEAD
214
250
  move that touches none of them. A path whose inputs changed is dropped and
215
251
  named, with the inputs that changed. Changed inputs this build restages are
216
252
  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
253
+ too: a manifest that gained an entry for the new file does not drop the
218
254
  claims of its sibling files. A build-less run's packaging gates also run
219
255
  before the lock is requested, so a `coverage-replaced` or `stale-build`
220
256
  refusal arrives before the run queues.
@@ -223,20 +259,23 @@ A scoped build after a full build keeps the claim full while nothing outside
223
259
  its scope moved. Otherwise it carries the full build's anchor forward, and a
224
260
  later build-less run over any path stays covered while that path's own
225
261
  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
262
+ that did change, and who wrote the coverage record: its
227
263
  invocation, when, and the writing process's pid (marked `still running`
228
264
  while it is), `FIREFORGE_SESSION_ID` and invocation id, the id its history
229
265
  records carry. `status --test-coverage` shows the pid and session too. A
230
266
  peer whose run a scoped build or a test-file edit refused can tell whose
231
267
  build to wait for.
232
268
 
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.
269
+ Retention is the default, so `--extend-coverage` only turns a drop into a
270
+ refusal before the build. A baseline without complete staging-input
271
+ fingerprints cannot prove anything unchanged, so its claims are dropped once.
272
+
273
+ A scoped build records its request paths normalized (no trailing `/`, no
274
+ `./`), as the baseline validator requires. An invalid baseline's refusal
275
+ names the first failing field and its value, and when that field is part of
276
+ the coverage claim it offers rerunning with `--build` as well as
277
+ `fireforge build`. Dirty paths are fingerprinted unquoted, so a non-ASCII
278
+ file name does not make the baseline invalid.
240
279
 
241
280
  ### Furnace components in a pre-test build
242
281
 
@@ -308,22 +347,21 @@ do something better instead: `testing/mochitest/runtests.py` bind-probes
308
347
  the HTTP server, ssltunnel and WebSocket ports before starting its servers,
309
348
  and the Marionette port before launching the browser, moves each busy one to
310
349
  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
350
+ In the default mode FireForge's own refusal fires before that fallback can.
351
+ In auto mode the mochitest-server and Marionette gates step aside, with a notice
313
352
  naming the holder, when the holder is not this checkout's own (a sibling
314
353
  checkout's live suite or an unrelated listener). This checkout's own
315
- leftovers are refused exactly as before, and `--kill-stale-marionette`
354
+ leftovers are refused exactly as in the default mode, and `--kill-stale-marionette`
316
355
  still applies to them. Auto mode takes effect only when the engine's
317
356
  `runtests.py` carries the fallback; otherwise a notice says so and the
318
357
  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.
358
+ which launches its own browser on that port. The default is `"fixed"`.
321
359
 
322
360
  Every suite samples host load and the highest CPU process before and after
323
361
  dispatch. Load at least 4 or a process at least 90% CPU produces a warning;
324
362
  verdicts include `host-load` and, when needed, `host-cpu-warning=true`.
325
363
  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`
364
+ `pmset -g ps`, including charging on AC. Sample JSON carries a `fireforgeHost`
327
365
  object with start/end states and `powerSourceChanged`. A known power-source
328
366
  transition produces `FAIL reason=inconclusive power-changed=true`.
329
367
  Unknown power state is reported without inventing a transition.
@@ -358,7 +396,7 @@ Furnace-applied components:
358
396
  (untracked in the engine repo, so no install manifest exists for it yet),
359
397
  or when its jar declaration carries a bracketed base-directory prefix,
360
398
  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
399
+ An entry added to an existing `dist/bin` manifest does not escalate. Any
362
400
  probe failure (an unreadable manifest, no git) escalates, and the notice
363
401
  names the manifest and the reason.
364
402
 
@@ -370,16 +408,13 @@ carried forward from the previous full build, so a registration made between
370
408
  a `build --ui` and the next `test --build` still triggers the full build
371
409
  once.
372
410
 
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
411
+ An entry added to an existing `dist/bin` `jar.mn` needs no full build: a
412
+ jar-only registration of a new content file is installed by a plain
413
+ `fireforge build --ui` (`faster/install_dist_bin_browser` names the
414
+ destination, and the file reaches `dist/bin` and the `.app` bundle) and is
415
+ then fetched over `chrome://` by a plain `fireforge test`. A new `jar.mn`
416
+ file and a non-default install destination have no such evidence and
417
+ escalate: relaxing a stale-artifact guard without evidence trades
383
418
  a slow build for a silently wrong test.
384
419
 
385
420
  ## Resilience
@@ -474,9 +509,9 @@ FIREFORGE-VERDICT: PASS|FAIL reason=… [note=<class>] [started=<n>/<m> first-un
474
509
  ```
475
510
 
476
511
  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
512
+ captured output, so a suite printing more than that (a large browser
513
+ directory, or any run under `--full-output`) does not report files that ran
514
+ and passed as never started. `started-source=` names the evidence. A sharded run also
480
515
  prints a `FIREFORGE-SHARD:` line per shard and names the shards that did not
481
516
  pass as `failed-shards=`; see [`machine-output.md`](machine-output.md).
482
517
 
@@ -591,17 +626,39 @@ helpers.
591
626
  `--jobs <n>` runs a request's shards on n harness instances inside one lock
592
627
  hold. Each instance has its own profile and its own Marionette port, and
593
628
  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
629
+ lines carry a `[job <i>]` prefix in the terminal and the run log. Each
630
+ instance also writes its own mochitest test list
596
631
  (`--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
632
+ `_tests/testing/mochitest/tests.json`, the second instance would run the
633
+ first shard's file and pass, or find none. A `--jobs` run always reads each
599
634
  dispatch's mozlog raw log, and a dispatch whose raw log starts none of its
600
635
  requested files fails with `started=0/<m>` instead of passing on another
601
636
  shard's results. With `--no-shard`, or a single directory argument, the
602
637
  files are split in order into n contiguous chunks. Parallel browsers raise
603
638
  host load, so measure before relying on it.
604
639
 
640
+ When the caller sets `MOZ_UPLOAD_DIR`, each `--jobs` instance gets its own
641
+ `<MOZ_UPLOAD_DIR>/job-<i>` (created up front) instead of the shared
642
+ directory, where instances would replace each other's fixed-name artifacts
643
+ such as the `modifiedPrefs.json` pref census. The verdict names them as
644
+ `upload-dirs=<dir>,<dir>,...` so a caller can merge per-instance artifacts.
645
+ Without `MOZ_UPLOAD_DIR` nothing changes.
646
+
647
+ A browser `--jobs` run on more than one instance also holds
648
+ placeholder listeners on `127.0.0.1` on the mochitest HTTP, ssltunnel and
649
+ WebSocket ports (8888, 4443, 9988) for the whole parallel hold, after the
650
+ server-port preflight. Desktop mochitest has no flags for these ports, and
651
+ its busy-port probe passes for instances that start together, which then
652
+ race for 8888 and die with `could not start server on port 8888`. With the
653
+ ports held, every instance's probe fails and each falls back to its own
654
+ port; a port that is already busy is left alone. Each `FIREFORGE-SHARD:`
655
+ line carries the ports its instance took as `ports=http:<n>,ssl:<n>,ws:<n>`.
656
+ A harness whose server still fails to start (`could not start server on
657
+ port` or `Timed out while waiting for server startup`, before any test) is
658
+ an infrastructure failure, not `no-tests`: it is retried within the
659
+ `--harness-retries` budget like a harness crash, and reported as
660
+ `reason=server-startup` once the budget is spent.
661
+
605
662
  `--shard-size <n>` dispatches n files per mach invocation (mochitest restarts
606
663
  the browser between files), paying the harness start once per chunk instead
607
664
  of once per file, and judges each file from mozlog's structured log:
@@ -612,7 +669,9 @@ of once per file, and judges each file from mozlog's structured log:
612
669
  run-log line where the dispatch began) from mozlog's structured log, which
613
670
  each dispatch then writes with `--log-raw`, and names it on the verdict as
614
671
  `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
672
+ read instead. A harness-level record (`test` is `automation.py`,
673
+ such as a hung browser's no-output TIMEOUT) also carries `shardFiles`, the
674
+ shard's dispatched files, and `file` when the shard has exactly one. The checks that need no lock run before it is
616
675
  requested: the launchable binary, the named-file checkJs pass, and the
617
676
  `--wait-browser`/`--wait-port` budgets. The run log is open from the start,
618
677
  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.53.0",
4
4
  "description": "FireForge — a build tool for customizing Firefox",
5
5
  "type": "module",
6
6
  "main": "./dist/src/index.js",