@hominis/fireforge 0.51.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.
- package/CHANGELOG.md +46 -0
- package/dist/build-info.json +4 -4
- package/dist/src/commands/bootstrap.js +2 -3
- package/dist/src/commands/build-prelock.d.ts +3 -3
- package/dist/src/commands/build-prelock.js +3 -3
- package/dist/src/commands/build.js +4 -0
- package/dist/src/commands/declarations-report.d.ts +9 -3
- package/dist/src/commands/declarations-report.js +18 -11
- package/dist/src/commands/discard.js +3 -3
- package/dist/src/commands/doctor-furnace-config-sync.js +4 -4
- package/dist/src/commands/doctor-furnace.js +5 -5
- package/dist/src/commands/export-adopt-check.d.ts +5 -6
- package/dist/src/commands/export-adopt-check.js +5 -6
- package/dist/src/commands/export-flow.js +6 -9
- package/dist/src/commands/export-staged-registration.d.ts +4 -4
- package/dist/src/commands/export-staged-registration.js +4 -4
- package/dist/src/commands/forward-import-remedy.d.ts +2 -3
- package/dist/src/commands/forward-import-remedy.js +2 -3
- package/dist/src/commands/furnace/create-dry-run.d.ts +2 -2
- package/dist/src/commands/furnace/deploy-fragment-includers.d.ts +2 -2
- package/dist/src/commands/furnace/deploy-fragment-includers.js +2 -2
- package/dist/src/commands/furnace/index.js +2 -2
- package/dist/src/commands/lint.js +4 -4
- package/dist/src/commands/patch/compact.js +1 -1
- package/dist/src/commands/patch/lint-ignore-from.d.ts +3 -4
- package/dist/src/commands/patch/lint-ignore-from.js +3 -4
- package/dist/src/commands/patch/move-files-adopt.d.ts +33 -0
- package/dist/src/commands/patch/move-files-adopt.js +65 -0
- package/dist/src/commands/patch/move-files-create.js +41 -20
- package/dist/src/commands/patch/move-files-into.d.ts +18 -0
- package/dist/src/commands/patch/move-files-into.js +125 -60
- package/dist/src/commands/patch/move-files-retire.d.ts +39 -0
- package/dist/src/commands/patch/move-files-retire.js +91 -0
- package/dist/src/commands/patch/move-files.d.ts +3 -0
- package/dist/src/commands/patch/move-files.js +42 -12
- package/dist/src/commands/patch/move-size-tier.d.ts +27 -0
- package/dist/src/commands/patch/move-size-tier.js +66 -0
- package/dist/src/commands/patch/rename.js +1 -1
- package/dist/src/commands/patch/reorder-projection.d.ts +17 -0
- package/dist/src/commands/patch/reorder-projection.js +49 -0
- package/dist/src/commands/patch/reorder-shift.d.ts +30 -0
- package/dist/src/commands/patch/reorder-shift.js +307 -0
- package/dist/src/commands/patch/reorder.d.ts +9 -15
- package/dist/src/commands/patch/reorder.js +52 -50
- package/dist/src/commands/patch/split-plan.d.ts +31 -3
- package/dist/src/commands/patch/split-plan.js +36 -12
- package/dist/src/commands/patch/split-staged.d.ts +2 -2
- package/dist/src/commands/patch/split-staged.js +2 -2
- package/dist/src/commands/patch/split.js +18 -5
- package/dist/src/commands/patch/staged-dependency-entries.d.ts +9 -1
- package/dist/src/commands/patch/staged-dependency-entries.js +32 -4
- package/dist/src/commands/patch/staged-dependency-from.js +15 -9
- package/dist/src/commands/patch/staged-dependency.js +13 -9
- package/dist/src/commands/patch/tier.js +2 -2
- package/dist/src/commands/patch-rename-map.d.ts +14 -3
- package/dist/src/commands/patch-rename-map.js +21 -3
- package/dist/src/commands/re-export-adjacent.d.ts +4 -5
- package/dist/src/commands/re-export-lint.d.ts +4 -3
- package/dist/src/commands/re-export-lint.js +4 -3
- package/dist/src/commands/re-export-preflight.js +1 -2
- package/dist/src/commands/re-export-purity-scope.d.ts +1 -1
- package/dist/src/commands/re-export-purity-scope.js +13 -7
- package/dist/src/commands/re-export-retired-declarations.d.ts +22 -0
- package/dist/src/commands/re-export-retired-declarations.js +113 -0
- package/dist/src/commands/re-export-single.js +2 -2
- package/dist/src/commands/re-export-stale-registrations.d.ts +27 -6
- package/dist/src/commands/re-export-stale-registrations.js +65 -21
- package/dist/src/commands/re-export.js +4 -0
- package/dist/src/commands/rebase/continue.js +3 -3
- package/dist/src/commands/register.js +5 -4
- package/dist/src/commands/status-output.js +5 -1
- package/dist/src/commands/status.js +1 -1
- package/dist/src/commands/test-build-furnace.d.ts +1 -2
- package/dist/src/commands/test-build-furnace.js +1 -2
- package/dist/src/commands/test-build-phase.d.ts +10 -0
- package/dist/src/commands/test-build-phase.js +51 -16
- package/dist/src/commands/test-control-restore.d.ts +40 -0
- package/dist/src/commands/test-control-restore.js +86 -0
- package/dist/src/commands/test-dispatch.js +83 -13
- package/dist/src/commands/test-multi-verdict.js +1 -0
- package/dist/src/commands/test-orchestrate.d.ts +11 -0
- package/dist/src/commands/test-orchestrate.js +33 -2
- package/dist/src/commands/test-perf-scope.d.ts +1 -1
- package/dist/src/commands/test-perf-scope.js +1 -1
- package/dist/src/commands/test-prelock.d.ts +7 -8
- package/dist/src/commands/test-prelock.js +15 -12
- package/dist/src/commands/test-register.js +2 -2
- package/dist/src/commands/test-results.d.ts +10 -1
- package/dist/src/commands/test-results.js +20 -3
- package/dist/src/commands/test-run.d.ts +6 -0
- package/dist/src/commands/test-run.js +23 -4
- package/dist/src/commands/test-shards.d.ts +7 -3
- package/dist/src/commands/test-shards.js +24 -7
- package/dist/src/commands/test-stale-gate.d.ts +6 -1
- package/dist/src/commands/test-stale-gate.js +47 -2
- package/dist/src/commands/test-verdict.d.ts +5 -3
- package/dist/src/commands/test.js +14 -1
- package/dist/src/commands/token.js +2 -2
- package/dist/src/commands/verify.js +1 -1
- package/dist/src/commands/watch.js +1 -1
- package/dist/src/commands/wire.js +1 -1
- package/dist/src/core/build-audit-resolve.d.ts +4 -5
- package/dist/src/core/build-audit-resolve.js +4 -5
- package/dist/src/core/build-audit-skip.d.ts +2 -2
- package/dist/src/core/build-audit.d.ts +3 -4
- package/dist/src/core/build-baseline-types.d.ts +37 -3
- package/dist/src/core/build-baseline-validate.d.ts +30 -1
- package/dist/src/core/build-baseline-validate.js +134 -33
- package/dist/src/core/build-baseline.d.ts +8 -2
- package/dist/src/core/build-baseline.js +32 -16
- package/dist/src/core/build-jar-escalation.d.ts +4 -4
- package/dist/src/core/build-jar-escalation.js +4 -4
- package/dist/src/core/build-prepare.js +4 -4
- package/dist/src/core/config-validate.js +4 -4
- package/dist/src/core/coverage-extend.d.ts +5 -3
- package/dist/src/core/coverage-extend.js +8 -3
- package/dist/src/core/coverage-records.d.ts +4 -5
- package/dist/src/core/coverage-records.js +4 -5
- package/dist/src/core/destructive.d.ts +2 -2
- package/dist/src/core/destructive.js +2 -2
- package/dist/src/core/discard-baseline.d.ts +2 -2
- package/dist/src/core/discard-baseline.js +3 -3
- package/dist/src/core/engine-session-lock.d.ts +1 -1
- package/dist/src/core/engine-session-lock.js +1 -1
- package/dist/src/core/file-lock-owner.d.ts +5 -5
- package/dist/src/core/file-lock-owner.js +5 -5
- package/dist/src/core/file-lock-queue.js +6 -8
- package/dist/src/core/file-lock-shared.d.ts +4 -4
- package/dist/src/core/file-lock-shared.js +4 -4
- package/dist/src/core/file-lock.js +7 -10
- package/dist/src/core/firefox.js +2 -2
- package/dist/src/core/furnace-apply-overwrite-warn.d.ts +1 -1
- package/dist/src/core/furnace-apply-overwrite-warn.js +1 -1
- package/dist/src/core/furnace-apply.js +3 -3
- package/dist/src/core/furnace-config-validate-exceptions.d.ts +4 -3
- package/dist/src/core/furnace-config-validate-exceptions.js +26 -6
- package/dist/src/core/furnace-operation.js +5 -5
- package/dist/src/core/furnace-registration-jar-inplace.js +5 -6
- package/dist/src/core/furnace-registration-rename.d.ts +5 -5
- package/dist/src/core/furnace-registration-rename.js +5 -5
- package/dist/src/core/furnace-registration-validate.d.ts +2 -1
- package/dist/src/core/furnace-registration-validate.js +2 -1
- package/dist/src/core/furnace-registration.js +2 -2
- package/dist/src/core/furnace-validate-accessibility.d.ts +1 -1
- package/dist/src/core/furnace-validate-accessibility.js +22 -11
- package/dist/src/core/furnace-validate-exceptions.d.ts +2 -1
- package/dist/src/core/furnace-validate-exceptions.js +31 -13
- package/dist/src/core/git-base.js +4 -3
- package/dist/src/core/git-diff.js +1 -1
- package/dist/src/core/git.js +1 -1
- package/dist/src/core/harness-orphans.d.ts +6 -6
- package/dist/src/core/harness-orphans.js +6 -6
- package/dist/src/core/harness-port-reservation.d.ts +60 -0
- package/dist/src/core/harness-port-reservation.js +122 -0
- package/dist/src/core/history-log-file.d.ts +9 -9
- package/dist/src/core/history-log-file.js +15 -15
- package/dist/src/core/history-log.d.ts +3 -3
- package/dist/src/core/history-log.js +3 -3
- package/dist/src/core/launchable-build.d.ts +39 -0
- package/dist/src/core/launchable-build.js +85 -0
- package/dist/src/core/marionette-port.js +1 -3
- package/dist/src/core/moz-manifest-rules.js +3 -2
- package/dist/src/core/negative-control-compiled.d.ts +22 -3
- package/dist/src/core/negative-control-compiled.js +41 -5
- package/dist/src/core/parser-fallback.d.ts +5 -5
- package/dist/src/core/parser-fallback.js +5 -5
- package/dist/src/core/patch-identifier-suggest.d.ts +6 -0
- package/dist/src/core/patch-identifier-suggest.js +11 -4
- package/dist/src/core/patch-lint-checkjs.d.ts +1 -1
- package/dist/src/core/patch-lint-checkjs.js +1 -1
- package/dist/src/core/patch-lint-css.js +2 -2
- package/dist/src/core/patch-lint-file-size.d.ts +5 -7
- package/dist/src/core/patch-lint-file-size.js +5 -7
- package/dist/src/core/patch-lint-ignore.d.ts +3 -3
- package/dist/src/core/patch-lint-ignore.js +3 -3
- package/dist/src/core/patch-lint-prettier.d.ts +4 -6
- package/dist/src/core/patch-lint-prettier.js +4 -6
- package/dist/src/core/patch-lint-projection.d.ts +1 -1
- package/dist/src/core/patch-lint-projection.js +1 -1
- package/dist/src/core/patch-lint-queue-types.d.ts +2 -2
- package/dist/src/core/patch-lint-queue-types.js +2 -2
- package/dist/src/core/patch-manifest-consistency.d.ts +2 -2
- package/dist/src/core/patch-manifest-consistency.js +2 -2
- package/dist/src/core/patch-manifest-io.d.ts +5 -1
- package/dist/src/core/patch-manifest-io.js +12 -10
- package/dist/src/core/patch-manifest-key-order.d.ts +3 -4
- package/dist/src/core/patch-manifest-key-order.js +3 -4
- package/dist/src/core/patch-parse.d.ts +3 -3
- package/dist/src/core/patch-parse.js +3 -3
- package/dist/src/core/patch-policy.d.ts +1 -1
- package/dist/src/core/patch-policy.js +1 -1
- package/dist/src/core/patch-source-metadata.d.ts +1 -1
- package/dist/src/core/patch-source-metadata.js +1 -1
- package/dist/src/core/patch-subset.d.ts +5 -3
- package/dist/src/core/patch-subset.js +8 -7
- package/dist/src/core/patch-transform.d.ts +2 -2
- package/dist/src/core/patch-transform.js +2 -2
- package/dist/src/core/rebase-session.js +4 -6
- package/dist/src/core/register-xpcshell-test.d.ts +28 -7
- package/dist/src/core/register-xpcshell-test.js +76 -27
- package/dist/src/core/run-log.d.ts +8 -8
- package/dist/src/core/run-log.js +8 -8
- package/dist/src/core/status-classify.d.ts +1 -2
- package/dist/src/core/status-classify.js +1 -2
- package/dist/src/core/test-harness-crash.d.ts +5 -3
- package/dist/src/core/test-harness-crash.js +13 -14
- package/dist/src/core/test-harness-infra.d.ts +32 -0
- package/dist/src/core/test-harness-infra.js +69 -0
- package/dist/src/core/test-harness-signature.d.ts +6 -0
- package/dist/src/core/test-run-completeness.d.ts +12 -5
- package/dist/src/core/test-run-completeness.js +15 -8
- package/dist/src/core/test-stale-check.d.ts +48 -1
- package/dist/src/core/test-stale-check.js +97 -2
- package/dist/src/core/test-stall-triage.js +5 -7
- package/dist/src/core/token-category.js +2 -2
- package/dist/src/core/token-inventory.js +3 -3
- package/dist/src/core/token-manager.d.ts +2 -2
- package/dist/src/core/token-manager.js +5 -7
- package/dist/src/core/token-variant.d.ts +6 -6
- package/dist/src/core/token-variant.js +7 -7
- package/dist/src/core/typecheck-shim.d.ts +2 -1
- package/dist/src/core/typecheck-shim.js +29 -5
- package/dist/src/core/wire-destroy.d.ts +1 -1
- package/dist/src/core/wire-destroy.js +1 -1
- package/dist/src/core/wire-dom-fragment.js +1 -1
- package/dist/src/core/wire-init.d.ts +1 -1
- package/dist/src/core/wire-init.js +1 -1
- package/dist/src/core/wire-subscript.d.ts +1 -1
- package/dist/src/core/wire-subscript.js +1 -1
- package/dist/src/core/wire-utils.d.ts +2 -2
- package/dist/src/core/wire-utils.js +3 -3
- package/dist/src/errors/base.d.ts +1 -1
- package/dist/src/errors/base.js +1 -1
- package/dist/src/errors/rebase.d.ts +1 -1
- package/dist/src/errors/rebase.js +1 -1
- package/dist/src/types/commands/options.d.ts +26 -3
- package/dist/src/types/config.d.ts +5 -7
- package/dist/src/types/furnace.d.ts +9 -0
- package/dist/src/utils/options.js +2 -2
- package/dist/src/utils/process.js +2 -2
- package/dist/src/utils/regex.d.ts +2 -2
- package/dist/src/utils/regex.js +3 -3
- package/dist/src/utils/sleep.d.ts +5 -6
- package/dist/src/utils/sleep.js +5 -6
- package/dist/src/utils/validation.js +2 -2
- package/docs/configuration.md +40 -26
- package/docs/exit-codes.md +8 -11
- package/docs/furnace.md +21 -3
- package/docs/lifecycle-invariants.md +36 -45
- package/docs/machine-output.md +43 -22
- package/docs/patch-workflow.md +129 -24
- package/docs/run-logs.md +8 -9
- package/docs/testing.md +118 -44
- package/package.json +1 -1
package/docs/configuration.md
CHANGED
|
@@ -21,11 +21,10 @@ uncommitted pin, and the tree is then building a different version than the
|
|
|
21
21
|
config claims.
|
|
22
22
|
|
|
23
23
|
`fireforge source set`, `fireforge config <key> <value>` and `furnace init`
|
|
24
|
-
edit `fireforge.json` in place
|
|
24
|
+
edit `fireforge.json` in place. Only the values that change
|
|
25
25
|
are rewritten. Indentation, key order, and objects or arrays kept on one
|
|
26
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.
|
|
28
|
-
write re-serialized the whole file and expanded every compact section.
|
|
27
|
+
New keys follow the layout of the object they land in.
|
|
29
28
|
|
|
30
29
|
`fireforge doctor`'s "Source pin matches engine" check compares the pin with
|
|
31
30
|
the engine's committed `browser/config/version.txt`. That file never carries
|
|
@@ -93,7 +92,7 @@ Most globals in it are `any`. `Cu` is typed as `CuShim`, the members of
|
|
|
93
92
|
`nsIXPCComponents_Utils` (`js/xpconnect/idl/xpccomponents.idl`) with loose
|
|
94
93
|
parameter and result types, so a call to a member `Cu` does not have (such
|
|
95
94
|
as `Cu.now()`, which is `ChromeUtils.now()`) fails `typecheck` and per-patch
|
|
96
|
-
lint instead of throwing at runtime
|
|
95
|
+
lint instead of throwing at runtime. The same shim backs
|
|
97
96
|
`fireforge typecheck`.
|
|
98
97
|
|
|
99
98
|
- `patchLint.checkJsExtraShim` adds members to the structured shim globals
|
|
@@ -137,7 +136,7 @@ lint instead of throwing at runtime (since 0.50.0). The same shim backs
|
|
|
137
136
|
structured `stagedDeclarations`, so a `lint --per-patch --report` file
|
|
138
137
|
can be applied with one `patch staged-dependency <patch> --add --from
|
|
139
138
|
<report>` per patch instead of one call per edge. The setting is opt-in because a queue
|
|
140
|
-
that
|
|
139
|
+
that was never checked for these carriers can carry many such edges, and a new error would red a
|
|
141
140
|
`--max-warnings 0` gate on install. The same census is on the public API as
|
|
142
141
|
`findForwardRegistrations(patchesDir, { scope })`, which defaults to
|
|
143
142
|
`'extended'`, for a consumer that keeps its own ratchet over these edges.
|
|
@@ -168,7 +167,7 @@ lint instead of throwing at runtime (since 0.50.0). The same shim backs
|
|
|
168
167
|
what `file-too-large` counts. `'raw'` counts every line, the way `wc -l`
|
|
169
168
|
does. `'code'` blanks comments with acorn's tokenizer (module first, then
|
|
170
169
|
script, since chrome subscripts are scripts) and counts the lines left
|
|
171
|
-
non-blank, so JSDoc and blank lines
|
|
170
|
+
non-blank, so JSDoc and blank lines do not count. A file acorn cannot
|
|
172
171
|
tokenize is counted in raw lines, the upper bound, and a
|
|
173
172
|
`file-size-unparsed` notice names it. Every message says which unit it
|
|
174
173
|
counted ("lines" or "code lines"). The counter is on the public API as
|
|
@@ -260,7 +259,7 @@ lint instead of throwing at runtime (since 0.50.0). The same shim backs
|
|
|
260
259
|
`@font-feature-values`, `@font-palette-values`, `@page` and its margin
|
|
261
260
|
boxes) are descriptors, not properties, and are not judged.
|
|
262
261
|
|
|
263
|
-
|
|
262
|
+
A scale also takes:
|
|
264
263
|
|
|
265
264
|
- `prefix` as a list (`["--mybrowser-space-", "--mybrowser-gap-"]`) for a
|
|
266
265
|
scale whose steps are spelled more than one way.
|
|
@@ -297,21 +296,37 @@ FireForge version. Diagnostics always use a fresh project
|
|
|
297
296
|
program: prior incremental diagnostic state is never restored. Cached and
|
|
298
297
|
`--no-cache` runs therefore check the same complete file set. `--no-cache`
|
|
299
298
|
also disables build-info writes. A jsconfig's own `incremental` and
|
|
300
|
-
`tsBuildInfoFile`
|
|
299
|
+
`tsBuildInfoFile` are ignored.
|
|
301
300
|
|
|
302
|
-
`typecheck.litTypes: true` (
|
|
301
|
+
`typecheck.litTypes: true` (default off) types Lit in the
|
|
303
302
|
shim: `LitElement` and the helpers of
|
|
304
303
|
`chrome://global/content/vendor/lit.all.mjs`, and `MozLitElement` of
|
|
305
304
|
`chrome://global/content/lit-utils.mjs`. The element classes carry closed
|
|
306
305
|
member lists, as `Cu` does, so a misspelt member of a widget host is an
|
|
307
306
|
error rather than `any`. Template helpers and directives stay loose. It is
|
|
308
307
|
off by default because a reactive property declared only in
|
|
309
|
-
`static properties` or `static queries` then needs a
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
308
|
+
`static properties` or `static queries` then needs a declaration to be
|
|
309
|
+
known. The shim declares the global type
|
|
310
|
+
`MozLitElementWith<Extra>`: a widget casts its base to it, and its
|
|
311
|
+
instances carry `Extra` beside MozLitElement's members. A query getter
|
|
312
|
+
cannot be declared any other way: a class field redefines the getter
|
|
313
|
+
MozLitElement installs and throws, and a constructor declaration reads it
|
|
314
|
+
before `renderRoot` exists.
|
|
315
|
+
|
|
316
|
+
```js
|
|
317
|
+
const Base = /** @type {MozLitElementWith<{ input: HTMLInputElement }>} */ (MozLitElement);
|
|
318
|
+
export class MozSearch extends Base {
|
|
319
|
+
static queries = { input: 'input' };
|
|
320
|
+
}
|
|
321
|
+
```
|
|
322
|
+
|
|
323
|
+
Without `litTypes` (and under per-patch checkJs, which does not type Lit)
|
|
324
|
+
`MozLitElementWith<Extra>` is `any`, as the base is, so the same source
|
|
325
|
+
checks in both. A project shim can add members by merging
|
|
326
|
+
`interface LitElementShimMembers`; a jsconfig `paths` entry that maps these
|
|
327
|
+
URLs to real sources takes precedence.
|
|
313
328
|
|
|
314
|
-
Per-patch checkJs gives each test script its own program.
|
|
329
|
+
Per-patch checkJs gives each test script its own program. A
|
|
315
330
|
test's `resource:///` and `chrome://` imports (including a
|
|
316
331
|
`typeof import("…")` cast) resolve to the modules the queue creates up to
|
|
317
332
|
the test's own patch, so a test of an earlier patch's module is checked
|
|
@@ -425,11 +440,11 @@ carries `invocationId` (shared by every record one command writes), `pid`,
|
|
|
425
440
|
`ppid`, and `sessionId` when the environment sets `FIREFORGE_SESSION_ID`, so
|
|
426
441
|
a session sharing the checkout can select its own lines.
|
|
427
442
|
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
443
|
+
If a log exists at `patches/.fireforge-history.jsonl`, inside the tracked
|
|
444
|
+
queue, the next append moves it to `history.path`; when both files exist, its
|
|
445
|
+
records are appended to the `history.path` file rather than either being
|
|
446
|
+
overwritten. Setting `history.path` to `patches/.fireforge-history.jsonl`
|
|
447
|
+
keeps the log at that location.
|
|
433
448
|
|
|
434
449
|
## `buildAudit`
|
|
435
450
|
|
|
@@ -595,7 +610,7 @@ The dark and variant blocks mirror it and appear in `token show`.
|
|
|
595
610
|
- `token-undeclared`: a `var(--<prefix>…)` in the tokens CSS, or in any CSS
|
|
596
611
|
file a patch in the queue touches, names a token no block of the tokens
|
|
597
612
|
CSS declares. A property declared in the same file, and the `furnace.json`
|
|
598
|
-
`tokenAllowlist` and `runtimeVariables` names, are exempt.
|
|
613
|
+
`tokenAllowlist` and `runtimeVariables` names, are exempt. A
|
|
599
614
|
reference with a fallback (`var(--x, 0)`) is optional and not reported,
|
|
600
615
|
and a token a sibling sheet declares counts as declared. Sheets are
|
|
601
616
|
siblings when one queue document links both (`<link rel="stylesheet">`,
|
|
@@ -617,7 +632,7 @@ non-CI launches print a warning saying so. Exit codes 12 and 13 separate a
|
|
|
617
632
|
console regression from a launch failure. See
|
|
618
633
|
[`exit-codes.md`](exit-codes.md).
|
|
619
634
|
|
|
620
|
-
A smoke run starts on a fresh temporary profile by default
|
|
635
|
+
A smoke run starts on a fresh temporary profile by default.
|
|
621
636
|
The step exists to prove what the build does on a clean start. The
|
|
622
637
|
developer's `obj-*/tmp/profile-default` carries whatever the last session
|
|
623
638
|
left (a pre-reset database, a restored hand-made applet), and those reds
|
|
@@ -633,7 +648,7 @@ owning process is gone.
|
|
|
633
648
|
|
|
634
649
|
- `--profile <path>` launches with a named profile directory and leaves it
|
|
635
650
|
in place. Under `--smoke-exit` it replaces the fresh default. Firefox also
|
|
636
|
-
gets `-purgecaches
|
|
651
|
+
gets `-purgecaches`, which discards the profile's startup
|
|
637
652
|
cache of compiled chrome scripts. That cache is keyed on the build id, and
|
|
638
653
|
a `build --ui` does not change it, so without the purge a kept profile runs
|
|
639
654
|
the chrome scripts an earlier build cached. `--no-purge-caches` keeps the
|
|
@@ -643,12 +658,11 @@ owning process is gone.
|
|
|
643
658
|
profile.
|
|
644
659
|
|
|
645
660
|
A smoke run whose browser exits with a clean status before the window
|
|
646
|
-
elapses, without printing any console output, fails with exit 13
|
|
647
|
-
|
|
661
|
+
elapses, without printing any console output, fails with exit 13.
|
|
662
|
+
Lines from mach's own log (the timestamped command echo) do not
|
|
648
663
|
count as output. A launch that exits silently never reached a window: a
|
|
649
664
|
stale `.parentlock`, or a profile whose run of SIGTERM-ended smoke runs
|
|
650
|
-
counts as a startup-crash streak (`toolkit.startup.recent_crashes`).
|
|
651
|
-
0.50.0 such a run passed as a clean exit.
|
|
665
|
+
counts as a startup-crash streak (`toolkit.startup.recent_crashes`).
|
|
652
666
|
|
|
653
667
|
A plain `run` without either flag keeps mach's `profile-default`. `mach run`'s
|
|
654
668
|
desktop parser has no `--profile` option (its `--profile/-P` belongs to the
|
package/docs/exit-codes.md
CHANGED
|
@@ -29,8 +29,7 @@ which error class produces each one.
|
|
|
29
29
|
|
|
30
30
|
Usage errors that commander detects itself (an unknown command, an unknown
|
|
31
31
|
or malformed option, a missing required argument) never reach a command
|
|
32
|
-
action.
|
|
33
|
-
and printed no refusal envelope under `--json`. `createProgram` now installs
|
|
32
|
+
action. `createProgram` installs
|
|
34
33
|
commander's `exitOverride()`, and the entry point maps the resulting
|
|
35
34
|
`CommanderError` to `INVALID_ARGUMENT` (8) with the standard envelope on
|
|
36
35
|
stdout. `--help` and `--version` take the same path and still exit 0, and so
|
|
@@ -46,10 +45,10 @@ action.
|
|
|
46
45
|
change something, and a retry may then help. `INTERNAL_ERROR` means nothing
|
|
47
46
|
they could change would have helped. Escalate it, do not retry.
|
|
48
47
|
|
|
49
|
-
**Red, never ran, or thrown away.** These are three different facts,
|
|
50
|
-
|
|
48
|
+
**Red, never ran, or thrown away.** These are three different facts, each
|
|
49
|
+
with its own code.
|
|
51
50
|
|
|
52
|
-
- `BUILD_ERROR` (5) is a suite that failed.
|
|
51
|
+
- `BUILD_ERROR` (5) is a suite that failed. It is thrown as
|
|
53
52
|
`TestFailureError`, which keeps the code but carries test remedies rather
|
|
54
53
|
than build ones (`--json` reports it as `test-failure`).
|
|
55
54
|
- `LOCK_TIMEOUT` (15) is a run that never started, because another FireForge
|
|
@@ -59,18 +58,16 @@ before 0.44.0 two of them shared exit 1.
|
|
|
59
58
|
`engine/` moved underneath it. The code may be perfectly green, so
|
|
60
59
|
reporting it as red is wrong.
|
|
61
60
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
them. The `FIREFORGE-VERDICT:` line's `reason=` key carries the same
|
|
61
|
+
Separate codes keep a summary line from showing opposite facts as the same
|
|
62
|
+
kind of failure, such as `FAIL - exit 1` beside `FAIL - exit 5`. The `FIREFORGE-VERDICT:` line's `reason=` key carries the same
|
|
65
63
|
distinction for humans.
|
|
66
64
|
|
|
67
65
|
`LockContentionError` backs every lock in FireForge (engine session, patch
|
|
68
66
|
directory, build, furnace), so all four exit 15. That is intentional: the
|
|
69
67
|
fact is the same whichever lock was contended.
|
|
70
68
|
|
|
71
|
-
**Interrupted or declined.**
|
|
72
|
-
|
|
73
|
-
not tell them apart. They are now distinct: an interrupt raises
|
|
69
|
+
**Interrupted or declined.** A Ctrl+C and a deliberate "no" at a
|
|
70
|
+
confirmation are distinct, so a script can tell them apart: an interrupt raises
|
|
74
71
|
`CancellationError` and exits 130, and a declined confirmation returns
|
|
75
72
|
normally and exits 0, because the run did what it was asked and the answer
|
|
76
73
|
was no.
|
package/docs/furnace.md
CHANGED
|
@@ -115,7 +115,7 @@ warning asking for the entry to be deleted. A run over one component judges
|
|
|
115
115
|
only that component's entries. `deploy` honours the same entries when it
|
|
116
116
|
validates, but leaves the staleness report to `validate`.
|
|
117
117
|
|
|
118
|
-
An entry never suppresses an error
|
|
118
|
+
An entry never suppresses an error: an error blocks apply,
|
|
119
119
|
and a review record cannot make a broken component deployable. The error
|
|
120
120
|
stays counted, and the entry is reported as a
|
|
121
121
|
`validation-exception-on-error` error until the finding is fixed and the
|
|
@@ -136,12 +136,30 @@ entries cover all of them:
|
|
|
136
136
|
}
|
|
137
137
|
```
|
|
138
138
|
|
|
139
|
+
An optional `file` narrows an entry the same way to findings
|
|
140
|
+
in one module of the component, by file name. `hardcoded-text` names the
|
|
141
|
+
modules it found text in, so a vendored bundle whose bytes are pinned (and
|
|
142
|
+
so cannot carry a `furnace-ignore` comment) can be accepted while the
|
|
143
|
+
authored modules beside it keep the check. An entry names a `tag` or a
|
|
144
|
+
`file`, not both:
|
|
145
|
+
|
|
146
|
+
```json
|
|
147
|
+
{
|
|
148
|
+
"component": "moz-editor",
|
|
149
|
+
"check": "hardcoded-text",
|
|
150
|
+
"file": "moz-editor-codemirror.mjs",
|
|
151
|
+
"reason": "The vendored bundle's width probe is never rendered."
|
|
152
|
+
}
|
|
153
|
+
```
|
|
154
|
+
|
|
139
155
|
Accessibility checks judge the composed component: the host
|
|
140
156
|
`<tag>.mjs` and its companion modules (`<tag>-*.mjs`, tests and stories
|
|
141
157
|
left out) read as one source. Moving a template between the component's
|
|
142
|
-
modules therefore
|
|
158
|
+
modules therefore does not change its findings: a keyboard handler in a
|
|
143
159
|
companion covers an `@click` in the host, and an `@click` in a companion
|
|
144
|
-
is judged too.
|
|
160
|
+
is judged too. `hardcoded-text` judges each module on its own, so a
|
|
161
|
+
`// furnace-ignore: hardcoded-text` comment covers the file it is in, not
|
|
162
|
+
its siblings. Toolkit's `panel-item` counts as natively
|
|
145
163
|
keyboard-activated, beside `button`, form controls and the `moz-*` buttons.
|
|
146
164
|
|
|
147
165
|
`minComponents` sets the fewest components a full `furnace validate` must
|
|
@@ -25,7 +25,7 @@ command, read the decision table at the bottom first.
|
|
|
25
25
|
exception: it writes nothing, runs its git plumbing on a private index
|
|
26
26
|
(so even the `--intent-to-add` staging an untracked binary needs never
|
|
27
27
|
reaches the shared `.git/index`), and serializes only against other dry
|
|
28
|
-
runs, so a preview
|
|
28
|
+
runs, so a preview does not queue behind a peer's build or test run.
|
|
29
29
|
|
|
30
30
|
3. **A furnace mutation that does not finish restores the engine or says
|
|
31
31
|
so.** Both a signal (SIGINT or SIGTERM) and a thrown error trigger a
|
|
@@ -33,14 +33,11 @@ command, read the decision table at the bottom first.
|
|
|
33
33
|
`pendingRepair` marker blocks all further furnace mutations until
|
|
34
34
|
`fireforge doctor --repair-furnace` reconciles.
|
|
35
35
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
it rolls back on collected `result.errors` and `stepErrors`, but a throw
|
|
42
|
-
from its pre-loop or post-loop work escaped both. The wrapper now runs
|
|
43
|
-
cleanups, restores the journal, and rethrows the original error. A
|
|
36
|
+
On a thrown error `runFurnaceMutation` runs cleanups, restores the
|
|
37
|
+
journal, and rethrows the original error, so a throw outside a body's own
|
|
38
|
+
catch does not leave the checkout torn with no marker. `applyAllComponents`
|
|
39
|
+
rolls back on collected `result.errors` and `stepErrors`, but a throw from
|
|
40
|
+
its pre-loop or post-loop work escapes both and relies on the wrapper. A
|
|
44
41
|
rollback failure becomes a marker plus a warning, never a replacement
|
|
45
42
|
error.
|
|
46
43
|
|
|
@@ -70,17 +67,15 @@ command, read the decision table at the bottom first.
|
|
|
70
67
|
refusal on structural conflicts (`--force-unsafe` to override), and a
|
|
71
68
|
JSONL history entry appended only after the mutation succeeded. This
|
|
72
69
|
covers metadata mutations too: `patch tier` and `patch lint-ignore` route
|
|
73
|
-
through `confirmDestructive`.
|
|
74
|
-
prompting, so the flag only showed up in the history record. Enforced by
|
|
70
|
+
through `confirmDestructive`. Enforced by
|
|
75
71
|
`patch-tier-and-lint-ignore.integration.test.ts`.
|
|
76
72
|
|
|
77
73
|
The history log is write-only: FireForge appends to it and no command
|
|
78
74
|
reads it back, so nothing depends on its contents or location. It lives
|
|
79
75
|
at `.fireforge/history.jsonl` (or `fireforge.json#history.path`), outside
|
|
80
|
-
the tracked patch queue.
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
overwriting either. Each record carries `invocationId` (one per FireForge
|
|
76
|
+
the tracked patch queue. If `patches/.fireforge-history.jsonl` exists,
|
|
77
|
+
the next append moves it there, and appends its records when both exist
|
|
78
|
+
rather than overwriting either. Each record carries `invocationId` (one per FireForge
|
|
84
79
|
process), `pid`, `ppid`, and `sessionId` when `FIREFORGE_SESSION_ID` is
|
|
85
80
|
set, so a session sharing the checkout can select its own lines.
|
|
86
81
|
Enforced by `history-log-file.test.ts`.
|
|
@@ -117,14 +112,14 @@ command, read the decision table at the bottom first.
|
|
|
117
112
|
and `tree remove` refuses while a live PID holds a tree lock and checks
|
|
118
113
|
that its `rm -rf` target is contained in the tree path.
|
|
119
114
|
|
|
120
|
-
In-tree `test`
|
|
115
|
+
In-tree `test` is the one conditional carve-out, and it is
|
|
121
116
|
marker-gated. mach objdirs embed absolute `topsrcdir` and `topobjdir`
|
|
122
117
|
paths, so `tree create --with-objdir` rewrites the cloned objdir's
|
|
123
118
|
`mozinfo.json` to the tree using the same safe-relocation rewriter that
|
|
124
119
|
`build --rewrite-mozinfo` uses, scrubs the cloned `_virtualenvs` (they
|
|
125
120
|
carry primary shebangs, and mach rebuilds them in-tree), and runs
|
|
126
121
|
`mach configure` inside the tree so the configure-generated root files are
|
|
127
|
-
regenerated against the tree's paths rather than keeping the primary's.
|
|
122
|
+
regenerated against the tree's paths rather than keeping the primary's.
|
|
128
123
|
Before configure, relocation rewrites old-source symlinks, `.pp`/`.d`,
|
|
129
124
|
FasterMake and Cargo fingerprint metadata, and removes copied
|
|
130
125
|
`config.statusd/*/config.track` inventories. Those inventories contain
|
|
@@ -151,14 +146,14 @@ command, read the decision table at the bottom first.
|
|
|
151
146
|
**Both halves of that enforcement fail closed on an unreadable state,
|
|
152
147
|
because "we cannot tell" is not "there is nothing there."** A marker that
|
|
153
148
|
exists but does not parse reports `corrupt`, not `absent`, and refuses the
|
|
154
|
-
command. Reading it as absent
|
|
155
|
-
set on the strength of a file that failed to parse. A lock directory whose
|
|
149
|
+
command. Reading it as absent would grant a snapshot the full mutating
|
|
150
|
+
command set on the strength of a file that failed to parse. A lock directory whose
|
|
156
151
|
owner cannot be identified reports `unknown`, not free, and refuses
|
|
157
|
-
removal.
|
|
152
|
+
removal. `withFileLock` treats its owner-record write as
|
|
158
153
|
fatal (`writeLockOwner` in `file-lock-owner.ts` removes the just-created
|
|
159
154
|
directory and throws a `GeneralError` if the record cannot be written or
|
|
160
|
-
does not read back as written), so an owner-less lock is only
|
|
161
|
-
|
|
155
|
+
does not read back as written), so an owner-less lock is left only by a
|
|
156
|
+
crash inside that write or by a holder that never wrote a record. It is refused,
|
|
162
157
|
for the same reason. The one exception is a lock directory that vanished
|
|
163
158
|
between the probe and the owner read: that is a clean release, and reads
|
|
164
159
|
as free.
|
|
@@ -168,7 +163,7 @@ command, read the decision table at the bottom first.
|
|
|
168
163
|
refusal spares the read-only commands that are unconditionally allowed
|
|
169
164
|
(`status`, `lint`, `typecheck`, `verify`): their verdict never consults
|
|
170
165
|
marker fields, so an unreadable marker cannot change their answer, and
|
|
171
|
-
blocking them
|
|
166
|
+
blocking them would leave the operator unable to diagnose the very tree that
|
|
172
167
|
needs inspecting. `conditional` verdicts can write, and stay refused.
|
|
173
168
|
Enforced by `tree-guard.test.ts` (verdict drift gate and corrupt-marker
|
|
174
169
|
refusal), `tree-store.integration.test.ts` (marker tri-state,
|
|
@@ -208,7 +203,7 @@ command, read the decision table at the bottom first.
|
|
|
208
203
|
`GIT_INDEX_FILE` from the repository's own index so that every refresh
|
|
209
204
|
lands there and is discarded. `typecheck` additionally ignores a
|
|
210
205
|
jsconfig's own `incremental` and `tsBuildInfoFile`, so no sidecar is
|
|
211
|
-
written under `engine/`. Its incremental build info
|
|
206
|
+
written under `engine/`. Its incremental build info lives in the
|
|
212
207
|
project's `.fireforge/typecheck/`, outside the engine. The scope fails open, meaning an unresolvable git dir
|
|
213
208
|
simply does not install it, and it is not reentrant. This exists so that
|
|
214
209
|
invariant 8 stays evidential: a concurrent `fireforge test` must not be
|
|
@@ -221,16 +216,14 @@ command, read the decision table at the bottom first.
|
|
|
221
216
|
in `<lock>.waiters/` named `<startedAtMs>-<pid>-<uuid>` and deregisters in
|
|
222
217
|
a `finally` that covers both outcomes: acquired the lock, or timed out.
|
|
223
218
|
A newcomer that finds live tickets takes one before trying the lock at
|
|
224
|
-
all.
|
|
219
|
+
all. The tickets decide the grant: only the waiter with no
|
|
225
220
|
live ticket ahead of it (arrival time, then ticket name) attempts the
|
|
226
|
-
lock, so "You are next" is a promise.
|
|
227
|
-
and a waiter whose poll had backed off lost each free moment to later
|
|
228
|
-
arrivals. Because a ticket now blocks the queue, a dead one must not: a
|
|
221
|
+
lock, so "You are next" is a promise. Because a ticket blocks the queue, a dead one must not: a
|
|
229
222
|
ticket whose PID is gone (or reused, where the start tick can tell) is
|
|
230
223
|
skipped and removed, and one its owner has not refreshed for 30 s (every
|
|
231
224
|
waiter rewrites its ticket every 5 s) is skipped, which covers a stopped
|
|
232
225
|
waiter and PID reuse elsewhere. A registry that cannot be written falls
|
|
233
|
-
back to
|
|
226
|
+
back to unordered contention rather than failing an acquisition.
|
|
234
227
|
This applies to every `withFileLock` lock: the engine-session, patch,
|
|
235
228
|
furnace and build locks among them. `fireforge status --lock` and the
|
|
236
229
|
`--wait-lock` progress lines read it, and the lines name the ordering
|
|
@@ -258,7 +251,7 @@ command, read the decision table at the bottom first.
|
|
|
258
251
|
Enforced by `patch-manifest-repair.test.ts` (real temp queues) and the
|
|
259
252
|
repair cases in `doctor.test.ts`.
|
|
260
253
|
|
|
261
|
-
## Lock release
|
|
254
|
+
## Lock release
|
|
262
255
|
|
|
263
256
|
`releaseLockIfOwned(lockPath)` in `src/core/file-lock.ts` is the
|
|
264
257
|
ownership-checked removal for callers that hold no acquisition token.
|
|
@@ -266,13 +259,12 @@ Currently that is the signal-time furnace sweeper
|
|
|
266
259
|
(`forceReleaseFurnaceLocksForActiveOperations`). It verifies the PID before
|
|
267
260
|
removing, which is the half of `releaseLock`'s guard a sweeper can still
|
|
268
261
|
perform: the sweeper knows which lock paths its own operations opened, but
|
|
269
|
-
not the per-acquisition UUID they minted.
|
|
262
|
+
not the per-acquisition UUID they minted. A bare `rm` could
|
|
270
263
|
delete a lock that a different process had acquired in the window between our
|
|
271
264
|
operation dying and the sweep running.
|
|
272
265
|
|
|
273
266
|
`completeJournalRollback` in `src/core/furnace-operation.ts` owns the
|
|
274
|
-
mutation-body rollback sequence that eight furnace commands
|
|
275
|
-
duplicated verbatim. The ordering is the invariant: `markRolledBack()` runs
|
|
267
|
+
mutation-body rollback sequence that eight furnace commands share. The ordering is the invariant: `markRolledBack()` runs
|
|
276
268
|
before the restore, so a restore that itself fails does not leave the
|
|
277
269
|
lifecycle wrapper replaying the same journal on the way out, and the original
|
|
278
270
|
error is rethrown unless the rollback is what failed.
|
|
@@ -297,7 +289,7 @@ seconds while waiting, so a holder dying mid-wait cannot strand waiters until
|
|
|
297
289
|
The owner-record write is fatal. A failed or unverifiable write releases the
|
|
298
290
|
just-created lock and throws a `GeneralError` instead of running the
|
|
299
291
|
operation. Without that, a lock with no readable owner is reaped by the age
|
|
300
|
-
heuristic after 5 minutes, which for a multi-hour build
|
|
292
|
+
heuristic after 5 minutes, which for a multi-hour build would mean a second holder
|
|
301
293
|
inside the critical section. Covered by `file-lock.test.ts`, "owner record
|
|
302
294
|
write at acquisition": write failure, corrupt read-back, recorded acquisition
|
|
303
295
|
time.
|
|
@@ -312,8 +304,7 @@ other layer.
|
|
|
312
304
|
Wait ergonomics are opt-in: `pollMaxMs` (the poll interval doubles from
|
|
313
305
|
`pollMs` up to the cap) and `waitProgressMs` with `onWaitProgress` (a periodic
|
|
314
306
|
progress callback carrying the holder's PID, liveness, and owner-metadata
|
|
315
|
-
lines from the pid file). All three are inert when unset
|
|
316
|
-
keep byte-identical behavior. Within one poll iteration a due progress probe
|
|
307
|
+
lines from the pid file). All three are inert when unset. Within one poll iteration a due progress probe
|
|
317
308
|
runs before the deadline check, so a wait that times out has always reported
|
|
318
309
|
the holder at least once when its budget exceeds `waitProgressMs`, however
|
|
319
310
|
slow the host (`file-lock.test.ts`, "budget shorter than one iteration").
|
|
@@ -321,8 +312,8 @@ slow the host (`file-lock.test.ts`, "budget shorter than one iteration").
|
|
|
321
312
|
### `src/core/file-lock-owner.ts`
|
|
322
313
|
|
|
323
314
|
The owner record (the `pid` file) itself: its format (PID, token,
|
|
324
|
-
`acquired-at-ms=` and `start-tick=` lines, plus free-form metadata
|
|
325
|
-
|
|
315
|
+
`acquired-at-ms=` and `start-tick=` lines, plus free-form metadata; a record
|
|
316
|
+
without the mechanical lines parses too), the write-and-verify
|
|
326
317
|
contract described above (a read-back that errors is retried before it counts
|
|
327
318
|
as a failed write, while a missing or mismatching record fails immediately),
|
|
328
319
|
and PID-reuse liveness.
|
|
@@ -333,13 +324,13 @@ re-verification, status snapshot and timeout message uses. Beyond
|
|
|
333
324
|
tick (`/proc/self/stat` field 22), and the probe reads the candidate's tick
|
|
334
325
|
from `/proc/<pid>/stat`. A different tick means a different process, so the
|
|
335
326
|
lock is stale. A crashed build's PID handed to a long-lived daemon therefore
|
|
336
|
-
|
|
327
|
+
does not keep the dead lock honoured until the waiter's timeout. It uses
|
|
337
328
|
ticks rather than wall-clock times because `btime` moves with clock steps, and
|
|
338
329
|
a wall-clock comparison would reap a live holder after NTP steps the clock
|
|
339
330
|
forward. macOS and Windows have no cheap start-time source (a `ps` spawn per
|
|
340
331
|
poll is not worth it) and keep the PID-only answer, and so do records without
|
|
341
|
-
a start tick. Enforced by `file-lock-owner.test.ts`:
|
|
342
|
-
|
|
332
|
+
a start tick. Enforced by `file-lock-owner.test.ts`: parsing of records without the
|
|
333
|
+
mechanical lines, forged mechanical lines dropped, transient read-back error retried
|
|
343
334
|
versus persistent error versus mismatch, fake-procfs tick parsing, reused-PID
|
|
344
335
|
versus genuine-holder verdicts, stepped-clock immunity, and on Linux a
|
|
345
336
|
real-procfs `withFileLock` reap of a live-PID stale record.
|
|
@@ -360,9 +351,9 @@ log or the engine-session lock shows one in the window (`re-export-purity-scope.
|
|
|
360
351
|
|
|
361
352
|
Contention fails fast after about a second by default, with the fixed message
|
|
362
353
|
"Another FireForge engine-mutating command is already running. Wait for it to
|
|
363
|
-
finish, then retry `<command>`."
|
|
364
|
-
|
|
365
|
-
`--wait-lock [seconds]` (bare flag means 60, valid 1 to
|
|
354
|
+
finish, then retry `<command>`." The same message also closes the bounded
|
|
355
|
+
wait. Each of those commands accepts
|
|
356
|
+
`--wait-lock [seconds]` (bare flag means 60, valid 1 to 86400) for a bounded
|
|
366
357
|
operator wait instead: polling backs off exponentially from 100 ms to 2 s, and
|
|
367
358
|
roughly every 5 s a progress line identifies the holder from the lock's
|
|
368
359
|
owner-metadata lines, in the form `Waiting for the FireForge engine lock held
|
|
@@ -432,7 +423,7 @@ hold it.
|
|
|
432
423
|
The destructive-operation contract: `confirmDestructive` (summary, prompt,
|
|
433
424
|
`--yes`, `--dry-run`, conflict refusal, `--force-unsafe`) and the
|
|
434
425
|
append-only history log (`src/core/history-log-file.ts` resolves its path,
|
|
435
|
-
|
|
426
|
+
moves a `patches/.fireforge-history.jsonl` it finds to that path, and stamps each
|
|
436
427
|
record's invocation and session).
|
|
437
428
|
|
|
438
429
|
### `src/core/tree-store.ts`
|
package/docs/machine-output.md
CHANGED
|
@@ -2,12 +2,9 @@
|
|
|
2
2
|
|
|
3
3
|
# Machine-readable output contract (internal)
|
|
4
4
|
|
|
5
|
-
The `--json` surface is a contract with scripted consumers.
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
`FIREFORGE-VERDICT:` line, and `lint --per-patch --report` wrote a versioned
|
|
9
|
-
file that nothing ever reads back. This file states what a `--json` command
|
|
10
|
-
has to do, so the next one added does not invent a fifth shape.
|
|
5
|
+
The `--json` surface is a contract with scripted consumers. This file states
|
|
6
|
+
what a `--json` command has to do, so the next one added does not invent a
|
|
7
|
+
shape of its own.
|
|
11
8
|
|
|
12
9
|
## The rules
|
|
13
10
|
|
|
@@ -56,11 +53,11 @@ if (options.json === true) {
|
|
|
56
53
|
| Surface | Shape | Notes |
|
|
57
54
|
| ---------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
58
55
|
| `status --json` | `{ schemaVersion: 1, … }` | Error envelope on three engine preconditions |
|
|
59
|
-
| `status --json` under `--check` | adds `check: { enabled, failOn, allow?, failOnUnknown?, failed, offenders }` |
|
|
56
|
+
| `status --json` under `--check` | adds `check: { enabled, failOn, allow?, failOnUnknown?, failed, offenders }` | On the full payload too, not only `--summary`. `allow` and `failOnUnknown` appear only when set. An offender failing only through `--fail-on-unknown` carries `unnamed: true`. `--patches` adds `scope: { patches }` |
|
|
60
57
|
| `furnace validate --json` | `{ schemaVersion: 1, passed, summary, maxWarnings?, components, issues, excepted, staleExceptions }` | `issues` counts after `validationExceptions`, stale-exception warnings included. `excepted` carries each suppressed finding with its `reason` |
|
|
61
58
|
| `check --json` | `{ schemaVersion: 1, verdict, reason?, summary, steps }` | One entry per step: `name`, `kind`, `command`, `status` (`pass`/`fail`/`skipped`), `exitCode`, `durationMs`, `detail`, and on failure `outputTail` (`timedOut` when killed at its budget). No verdict line under `--json` |
|
|
62
59
|
| `check` verdict line | `FIREFORGE-VERDICT: PASS\|FAIL [reason=step-failures\|lock-timeout\|skipped-steps failed=<steps>] steps=<n> skipped=<n> [skipped-steps=<steps>]` | Not JSON. The last stdout line, after the step table, sealed like `test`'s. Its `reason=` set is its own, not `test`'s |
|
|
63
|
-
| `tree list --json` | `{ schemaVersion: 1, trees }` | Error envelope
|
|
60
|
+
| `tree list --json` | `{ schemaVersion: 1, trees }` | Error envelope on failure |
|
|
64
61
|
| `token list --json` | `{ schemaVersion: 1, tokensCssPath, categories }` | Categories in file order, each with its tokens (`name`, `line`, `value`) |
|
|
65
62
|
| `token show --json` | `{ schemaVersion: 1, name, category, declarations }` | One entry per declaring block, with its selector trail and line |
|
|
66
63
|
| `token lint --json` | `{ schemaVersion: 1, tokensCssPath, tokenPrefix, filesScanned, findings }` | Each finding has `check`, `file`, `line`, `token`, `message`. The document is written even when findings exist; the exit is then non-zero, as with `status --check --json` |
|
|
@@ -80,7 +77,7 @@ it. Follow the rules above rather than inventing a shape.
|
|
|
80
77
|
|
|
81
78
|
The run logs behind `log=` are specified in [`run-logs.md`](run-logs.md).
|
|
82
79
|
|
|
83
|
-
Additive keys
|
|
80
|
+
Additive keys outside `test`:
|
|
84
81
|
|
|
85
82
|
- `check --json`: a skipped step carries `skipKind`, `config` when
|
|
86
83
|
`check.skip` names it and `unavailable` when the project has nothing for
|
|
@@ -92,6 +89,8 @@ Additive keys since 0.51.0 outside `test`:
|
|
|
92
89
|
`@click`). An exception that matched an error adds a
|
|
93
90
|
`validation-exception-on-error` error, and a full run under
|
|
94
91
|
`furnace.json#minComponents` a `component-floor` error on `furnace.json`.
|
|
92
|
+
- `furnace validate --json`: a `hardcoded-text` finding
|
|
93
|
+
carries `files`, the component's module file names it was found in.
|
|
95
94
|
|
|
96
95
|
## Versioning
|
|
97
96
|
|
|
@@ -108,6 +107,7 @@ moved.
|
|
|
108
107
|
| Reason | Meaning |
|
|
109
108
|
| ------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
110
109
|
| `crash` | The harness or the browser died, so there is no trustworthy suite result. |
|
|
110
|
+
| `server-startup` | A mochitest server never came up (`could not start server on port`, `Timed out while waiting for server startup`) before any test ran. An infrastructure failure, retried like `crash` within `--harness-retries`; this reason is what is left once the budget is spent. |
|
|
111
111
|
| `harness-arguments` | Profile or other harness argument setup failed before any tests could run; a rebuild is not the repair. |
|
|
112
112
|
| `no-tests` | The run dispatched but nothing ran. |
|
|
113
113
|
| `test-failures` | The suite ran and reported unexpected results. |
|
|
@@ -124,15 +124,19 @@ developer browser holding the objdir. An unattended reader whose pipe kept
|
|
|
124
124
|
only the verdict line could not tell those apart, so a preflight refusal that
|
|
125
125
|
can classify itself also emits `note=<class>`.
|
|
126
126
|
|
|
127
|
-
`note=` is additive, like `log=`, `signal=` and `shards=`. `reason=`
|
|
128
|
-
|
|
127
|
+
`note=` is additive, like `log=`, `signal=` and `shards=`. `reason=` always
|
|
128
|
+
comes from the closed set above, so a consumer that
|
|
129
129
|
tokenises `key=value` pairs is unaffected, and a gate that names no class
|
|
130
130
|
emits no `note=` at all. The classes are not a closed set and may grow, so
|
|
131
131
|
consumers should treat an unrecognised one as opaque. Current values:
|
|
132
132
|
`browser-busy`, `stale-browser`, `stale-browser-kill-failed`, `marionette-port-busy`, `mochitest-port-busy`,
|
|
133
133
|
`coverage-replaced`, `stale-build`, `stale-components`, `no-launchable-binary`, `negative-control` (the
|
|
134
134
|
control diff was refused), `negative-control-pending` (an interrupted run's
|
|
135
|
-
control could not be undone safely). `
|
|
135
|
+
control could not be undone safely). Also `stale-compiled`
|
|
136
|
+
(compiled sources changed after the binary under test was linked) and
|
|
137
|
+
`control-built` (the binary still carries a compiled negative control whose
|
|
138
|
+
restore build never ran or failed). An `invalid-build-baseline` refusal
|
|
139
|
+
names the first failing field and its value. `note=negative-control-restore` rides a
|
|
136
140
|
`reason=inconclusive` line whose control could not be restored byte-exact.
|
|
137
141
|
|
|
138
142
|
### Multi-run invocations: `FIREFORGE-RUN:`, `runs=` and `control=`
|
|
@@ -151,7 +155,7 @@ A `FIREFORGE-RUN:` line is never a verdict: the invocation still ends with
|
|
|
151
155
|
exactly one `FIREFORGE-VERDICT:` line. With more than one planned run it
|
|
152
156
|
carries `runs=<passed>/<planned>` and no count keys; a failed aggregate takes
|
|
153
157
|
the most structural reason among its runs (`inconclusive`, `preflight`,
|
|
154
|
-
`crash`, `harness-arguments`, `no-tests`, `test-failures`) and that run's
|
|
158
|
+
`crash`, `server-startup`, `harness-arguments`, `no-tests`, `test-failures`) and that run's
|
|
155
159
|
`note=`. A run that never started (the invocation stopped at a refusal)
|
|
156
160
|
counts toward `<planned>` but not `<passed>`.
|
|
157
161
|
|
|
@@ -183,7 +187,7 @@ A sharded run prints one `FIREFORGE-SHARD:` line per finished shard, before
|
|
|
183
187
|
the verdict line:
|
|
184
188
|
|
|
185
189
|
```
|
|
186
|
-
FIREFORGE-SHARD: PASS|FAIL [reason=…] [checks=<n>] [unexpected=<n>] shard=<i>/<n> path=<label> [failed-files=<path>,…]
|
|
190
|
+
FIREFORGE-SHARD: PASS|FAIL [reason=…] [checks=<n>] [unexpected=<n>] shard=<i>/<n> path=<label> [failed-files=<path>,…] [ports=http:<n>,ssl:<n>,ws:<n>]
|
|
187
191
|
```
|
|
188
192
|
|
|
189
193
|
`path=` is the shard's path argument (whitespace replaced by `_`), or a
|
|
@@ -193,13 +197,31 @@ aggregate verdict appends `failed-shards=<label>,…` after `shards=` when any
|
|
|
193
197
|
shard did not pass; under `--shard-size` `shards=` counts files and
|
|
194
198
|
`failed-shards=` names files. Both are absent on a green run.
|
|
195
199
|
|
|
200
|
+
`ports=` names the mochitest HTTP server, ssltunnel and
|
|
201
|
+
WebSocket ports the shard's harness reported (its "falling back to port"
|
|
202
|
+
lines), in that order and only those it reported; it is absent when the
|
|
203
|
+
harness reported none (an xpcshell shard, or a harness that died before its
|
|
204
|
+
servers). A shard whose server never started says `reason=server-startup`,
|
|
205
|
+
and the aggregate verdict does too when every crashed shard failed that way.
|
|
206
|
+
|
|
196
207
|
### Additive keys of parallel and per-file runs
|
|
197
208
|
|
|
198
209
|
`jobs=<n>` marks a `--jobs` run, `lock=shared` a run that held the engine
|
|
199
|
-
session lock shared, and `results=<path>` names the `--results` document.
|
|
210
|
+
session lock shared, and `results=<path>` names the `--results` document.
|
|
211
|
+
A `--jobs` run whose caller set `MOZ_UPLOAD_DIR` appends
|
|
212
|
+
`upload-dirs=<dir>,…`, the per-instance upload directories
|
|
213
|
+
(`<MOZ_UPLOAD_DIR>/job-<i>`, one per instance that ran), and a `--results`
|
|
214
|
+
record whose `test` is `automation.py` (a harness-level result) carries
|
|
215
|
+
`shardFiles`, plus `file` when its shard has exactly one file. A
|
|
200
216
|
run whose engine changed mid-run only in files the running browser cannot
|
|
201
217
|
see keeps its verdict and appends `drift-tolerated=<n>`. A negative control
|
|
202
|
-
on compiled source appends `control-build=compiled
|
|
218
|
+
on compiled source appends `control-build=compiled`, and
|
|
219
|
+
`control-restore-build=done|failed` for the full build that recompiles the
|
|
220
|
+
restored source after the last run. Every run that reaches
|
|
221
|
+
dispatch appends `build-id=<BuildID>`, read from the launchable build's
|
|
222
|
+
`application.ini` (absent when that file has no `BuildID`). A raw log
|
|
223
|
+
that starts none of a dispatch's requested files counts as
|
|
224
|
+
`started=0/<m> ... started-source=raw`.
|
|
203
225
|
|
|
204
226
|
### The additive `shuffle=` key
|
|
205
227
|
|
|
@@ -219,9 +241,8 @@ preflight, survivors of an earlier run in this objdir under `--reap-orphans`
|
|
|
219
241
|
or `test.reapOrphans: "reap"`; at teardown, helpers this run's harness
|
|
220
242
|
launched (httpd, websocket server, ssltunnel, process bridge, the browser,
|
|
221
243
|
`moz-http2`) that were still alive after mach exited. Summed across the census, every
|
|
222
|
-
retry attempt and every shard. Absent when nothing was reaped, so a green
|
|
223
|
-
a
|
|
224
|
-
distinguishable from it. A run ended by SIGTERM or by the parent-exit
|
|
244
|
+
retry attempt and every shard. Absent when nothing was reaped, so a green after a reap is
|
|
245
|
+
distinguishable from a green on a quiet machine. A run ended by SIGTERM or by the parent-exit
|
|
225
246
|
watchdog writes its verdict before the teardown reap runs, so that line never
|
|
226
247
|
carries the key; the reap is reported on stderr instead.
|
|
227
248
|
|
|
@@ -239,10 +260,10 @@ and measured CPU. These diagnostics annotate a test failure without changing
|
|
|
239
260
|
its classifier reason.
|
|
240
261
|
|
|
241
262
|
Perf runs append `power-source=ac|battery|unknown`. On macOS the source is
|
|
242
|
-
read from `pmset -g ps`, so charging on AC
|
|
263
|
+
read from `pmset -g ps`, so charging on AC reads `ac`. A known source
|
|
243
264
|
transition appends `power-changed=true` and refuses the run as
|
|
244
|
-
`reason=inconclusive`. The producer's sample JSON
|
|
245
|
-
|
|
265
|
+
`reason=inconclusive`. The producer's sample JSON carries an additional
|
|
266
|
+
`fireforgeHost: { start, end, powerSourceChanged }` object, where each host
|
|
246
267
|
state includes `load`, `power` and an optional `topProcess` with CPU and
|
|
247
268
|
command. Consumers should tolerate this additive object. Unknown power
|
|
248
269
|
state is visible but never treated as a proven transition.
|