@hominis/fireforge 0.45.0 → 0.46.1
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 +409 -446
- package/dist/bin/fireforge.d.ts +1 -1
- package/dist/bin/fireforge.js +21 -15
- package/dist/build-info.json +4 -4
- package/dist/src/cli-usage-error.d.ts +46 -0
- package/dist/src/cli-usage-error.js +81 -0
- package/dist/src/cli.d.ts +7 -2
- package/dist/src/cli.js +47 -47
- package/dist/src/commands/bootstrap-checks.js +2 -1
- package/dist/src/commands/bootstrap.js +3 -4
- package/dist/src/commands/build.js +27 -17
- package/dist/src/commands/config.js +9 -9
- package/dist/src/commands/destructive-decision.d.ts +19 -0
- package/dist/src/commands/destructive-decision.js +31 -0
- package/dist/src/commands/discard.js +5 -5
- package/dist/src/commands/doctor-check-core.d.ts +4 -10
- package/dist/src/commands/doctor-check-core.js +0 -8
- package/dist/src/commands/doctor-external-toolchains.js +2 -2
- package/dist/src/commands/doctor-furnace-config-sync.d.ts +2 -2
- package/dist/src/commands/doctor-furnace-config-sync.js +20 -20
- package/dist/src/commands/doctor-furnace-jar.d.ts +1 -1
- package/dist/src/commands/doctor-furnace-jar.js +1 -1
- package/dist/src/commands/doctor-furnace.js +22 -22
- package/dist/src/commands/doctor-orphaned-harness.d.ts +10 -17
- package/dist/src/commands/doctor-orphaned-harness.js +14 -23
- package/dist/src/commands/doctor-patch-manifest.d.ts +2 -1
- package/dist/src/commands/doctor-patch-manifest.js +7 -6
- package/dist/src/commands/doctor-post-rebase-audit.js +3 -3
- package/dist/src/commands/doctor-source-pin.d.ts +12 -12
- package/dist/src/commands/doctor-source-pin.js +14 -14
- package/dist/src/commands/doctor-working-tree.d.ts +3 -3
- package/dist/src/commands/doctor-working-tree.js +3 -3
- package/dist/src/commands/doctor.d.ts +3 -1
- package/dist/src/commands/doctor.js +15 -16
- package/dist/src/commands/download.js +50 -37
- package/dist/src/commands/export-all.js +29 -12
- package/dist/src/commands/export-flow.d.ts +5 -5
- package/dist/src/commands/export-flow.js +29 -59
- package/dist/src/commands/export-placement-conflicts.d.ts +3 -3
- package/dist/src/commands/export-placement-conflicts.js +12 -12
- package/dist/src/commands/export-placement-gate.d.ts +2 -2
- package/dist/src/commands/export-placement-gate.js +7 -13
- package/dist/src/commands/export-placement-policy.d.ts +1 -1
- package/dist/src/commands/export-placement-policy.js +4 -6
- package/dist/src/commands/export-shared.d.ts +51 -32
- package/dist/src/commands/export-shared.js +17 -32
- package/dist/src/commands/export.js +14 -5
- package/dist/src/commands/furnace/apply.js +16 -16
- package/dist/src/commands/furnace/authoring-config.d.ts +13 -0
- package/dist/src/commands/furnace/authoring-config.js +19 -0
- package/dist/src/commands/furnace/chrome-doc-remove.d.ts +1 -1
- package/dist/src/commands/furnace/chrome-doc-remove.js +2 -2
- package/dist/src/commands/furnace/chrome-doc-templates.d.ts +14 -14
- package/dist/src/commands/furnace/chrome-doc-templates.js +17 -17
- package/dist/src/commands/furnace/chrome-doc-tests.d.ts +2 -2
- package/dist/src/commands/furnace/chrome-doc-tests.js +4 -4
- package/dist/src/commands/furnace/chrome-doc.d.ts +8 -8
- package/dist/src/commands/furnace/chrome-doc.js +18 -18
- package/dist/src/commands/furnace/create-browser-test.d.ts +1 -1
- package/dist/src/commands/furnace/create-browser-test.js +7 -12
- package/dist/src/commands/furnace/create-dry-run.d.ts +4 -4
- package/dist/src/commands/furnace/create-dry-run.js +6 -9
- package/dist/src/commands/furnace/create-features.d.ts +2 -2
- package/dist/src/commands/furnace/create-features.js +2 -2
- package/dist/src/commands/furnace/create-mochikit.d.ts +4 -4
- package/dist/src/commands/furnace/create-mochikit.js +7 -7
- package/dist/src/commands/furnace/create-templates.d.ts +31 -15
- package/dist/src/commands/furnace/create-templates.js +20 -19
- package/dist/src/commands/furnace/create-xpcshell.d.ts +5 -5
- package/dist/src/commands/furnace/create-xpcshell.js +8 -8
- package/dist/src/commands/furnace/create.d.ts +1 -1
- package/dist/src/commands/furnace/create.js +35 -29
- package/dist/src/commands/furnace/deploy.js +15 -6
- package/dist/src/commands/furnace/diff.js +7 -7
- package/dist/src/commands/furnace/index.js +1 -1
- package/dist/src/commands/furnace/init.js +17 -16
- package/dist/src/commands/furnace/list.js +2 -2
- package/dist/src/commands/furnace/override.d.ts +1 -1
- package/dist/src/commands/furnace/override.js +43 -34
- package/dist/src/commands/furnace/preview.js +17 -17
- package/dist/src/commands/furnace/refresh.js +15 -7
- package/dist/src/commands/furnace/remove-mutations.d.ts +9 -10
- package/dist/src/commands/furnace/remove-mutations.js +19 -19
- package/dist/src/commands/furnace/remove-state.d.ts +1 -1
- package/dist/src/commands/furnace/remove-state.js +1 -1
- package/dist/src/commands/furnace/remove.js +4 -8
- package/dist/src/commands/furnace/rename-browser-test.js +10 -15
- package/dist/src/commands/furnace/rename-xpcshell.d.ts +2 -2
- package/dist/src/commands/furnace/rename-xpcshell.js +3 -3
- package/dist/src/commands/furnace/rename.js +36 -36
- package/dist/src/commands/furnace/scan.js +3 -3
- package/dist/src/commands/furnace/status.js +19 -16
- package/dist/src/commands/furnace/sync.js +6 -6
- package/dist/src/commands/furnace/test-file-name.d.ts +28 -0
- package/dist/src/commands/furnace/test-file-name.js +39 -0
- package/dist/src/commands/furnace/validate.js +11 -12
- package/dist/src/commands/furnace/validation-output.d.ts +21 -9
- package/dist/src/commands/furnace/validation-output.js +3 -8
- package/dist/src/commands/import.js +22 -29
- package/dist/src/commands/lint-per-patch.d.ts +2 -2
- package/dist/src/commands/lint-per-patch.js +27 -12
- package/dist/src/commands/lint-per-run-checkjs.d.ts +14 -15
- package/dist/src/commands/lint-per-run-checkjs.js +14 -15
- package/dist/src/commands/lint-report.d.ts +3 -3
- package/dist/src/commands/lint-report.js +4 -4
- package/dist/src/commands/lint.d.ts +5 -4
- package/dist/src/commands/lint.js +36 -36
- package/dist/src/commands/manifest.d.ts +4 -4
- package/dist/src/commands/manifest.js +1 -1
- package/dist/src/commands/package.js +4 -6
- package/dist/src/commands/patch/compact.d.ts +2 -2
- package/dist/src/commands/patch/compact.js +19 -20
- package/dist/src/commands/patch/delete.d.ts +1 -1
- package/dist/src/commands/patch/delete.js +23 -33
- package/dist/src/commands/patch/entry-projection.d.ts +13 -0
- package/dist/src/commands/patch/entry-projection.js +24 -0
- package/dist/src/commands/patch/lint-ignore.d.ts +3 -12
- package/dist/src/commands/patch/lint-ignore.js +33 -44
- package/dist/src/commands/patch/move-files-create.d.ts +2 -2
- package/dist/src/commands/patch/move-files-create.js +29 -15
- package/dist/src/commands/patch/move-files-into.d.ts +2 -2
- package/dist/src/commands/patch/move-files-into.js +41 -37
- package/dist/src/commands/patch/move-files.js +5 -14
- package/dist/src/commands/patch/patch-context.d.ts +1 -1
- package/dist/src/commands/patch/rename.d.ts +4 -4
- package/dist/src/commands/patch/rename.js +35 -49
- package/dist/src/commands/patch/reorder.js +35 -48
- package/dist/src/commands/patch/split-plan.d.ts +7 -8
- package/dist/src/commands/patch/split-plan.js +10 -13
- package/dist/src/commands/patch/split.d.ts +2 -2
- package/dist/src/commands/patch/split.js +50 -48
- package/dist/src/commands/patch/staged-dependency-validate.d.ts +1 -1
- package/dist/src/commands/patch/staged-dependency-validate.js +3 -3
- package/dist/src/commands/patch/staged-dependency.d.ts +1 -1
- package/dist/src/commands/patch/staged-dependency.js +22 -28
- package/dist/src/commands/patch/tier.d.ts +2 -2
- package/dist/src/commands/patch/tier.js +20 -30
- package/dist/src/commands/patch-rename-map.d.ts +19 -0
- package/dist/src/commands/patch-rename-map.js +36 -0
- package/dist/src/commands/pending-resolution.d.ts +15 -0
- package/dist/src/commands/pending-resolution.js +25 -0
- package/dist/src/commands/re-export-adjacent.d.ts +25 -3
- package/dist/src/commands/re-export-adjacent.js +40 -24
- package/dist/src/commands/re-export-bulk-scan.d.ts +3 -3
- package/dist/src/commands/re-export-bulk-scan.js +23 -27
- package/dist/src/commands/re-export-drift.d.ts +10 -10
- package/dist/src/commands/re-export-drift.js +33 -33
- package/dist/src/commands/re-export-files.d.ts +2 -3
- package/dist/src/commands/re-export-files.js +52 -44
- package/dist/src/commands/re-export-lint.d.ts +29 -30
- package/dist/src/commands/re-export-lint.js +36 -29
- package/dist/src/commands/re-export-options.d.ts +1 -1
- package/dist/src/commands/re-export-options.js +1 -1
- package/dist/src/commands/re-export-register.d.ts +1 -1
- package/dist/src/commands/re-export-register.js +1 -1
- package/dist/src/commands/re-export-scan.d.ts +1 -1
- package/dist/src/commands/re-export-scan.js +12 -9
- package/dist/src/commands/re-export-single.d.ts +23 -4
- package/dist/src/commands/re-export-single.js +39 -31
- package/dist/src/commands/re-export.js +35 -17
- package/dist/src/commands/rebase/abort.js +9 -14
- package/dist/src/commands/rebase/continue.js +20 -19
- package/dist/src/commands/rebase/index.d.ts +1 -1
- package/dist/src/commands/rebase/index.js +5 -5
- package/dist/src/commands/rebase/patch-loop.d.ts +2 -2
- package/dist/src/commands/rebase/patch-loop.js +20 -24
- package/dist/src/commands/register.js +5 -5
- package/dist/src/commands/reset.js +1 -1
- package/dist/src/commands/resolve.d.ts +2 -2
- package/dist/src/commands/resolve.js +21 -13
- package/dist/src/commands/run.d.ts +0 -13
- package/dist/src/commands/run.js +38 -51
- package/dist/src/commands/setup-support.d.ts +16 -4
- package/dist/src/commands/setup-support.js +20 -20
- package/dist/src/commands/setup.js +4 -10
- package/dist/src/commands/source.js +9 -2
- package/dist/src/commands/status-check.d.ts +3 -3
- package/dist/src/commands/status-check.js +6 -6
- package/dist/src/commands/status-json.d.ts +14 -13
- package/dist/src/commands/status-json.js +9 -8
- package/dist/src/commands/status-output.d.ts +3 -3
- package/dist/src/commands/status-output.js +5 -5
- package/dist/src/commands/status-ownership.d.ts +3 -3
- package/dist/src/commands/status-ownership.js +3 -3
- package/dist/src/commands/status.js +25 -26
- package/dist/src/commands/test-build-phase.d.ts +3 -3
- package/dist/src/commands/test-build-phase.js +48 -24
- package/dist/src/commands/test-diagnose.d.ts +1 -1
- package/dist/src/commands/test-diagnose.js +20 -20
- package/dist/src/commands/test-modes.d.ts +4 -4
- package/dist/src/commands/test-modes.js +4 -5
- package/dist/src/commands/test-register.js +5 -3
- package/dist/src/commands/test-run.d.ts +11 -11
- package/dist/src/commands/test-run.js +40 -33
- package/dist/src/commands/test-stale-gate.d.ts +12 -12
- package/dist/src/commands/test-stale-gate.js +17 -17
- package/dist/src/commands/test-verdict.d.ts +19 -5
- package/dist/src/commands/test-verdict.js +26 -11
- package/dist/src/commands/test.d.ts +3 -3
- package/dist/src/commands/test.js +73 -36
- package/dist/src/commands/token-coverage.js +3 -3
- package/dist/src/commands/token-list.d.ts +26 -0
- package/dist/src/commands/token-list.js +153 -0
- package/dist/src/commands/token.js +26 -10
- package/dist/src/commands/tree.js +26 -21
- package/dist/src/commands/typecheck.d.ts +6 -6
- package/dist/src/commands/typecheck.js +16 -16
- package/dist/src/commands/verify.d.ts +3 -3
- package/dist/src/commands/verify.js +10 -10
- package/dist/src/commands/watch.js +11 -11
- package/dist/src/commands/wire.js +17 -16
- package/dist/src/core/ast-utils.d.ts +7 -7
- package/dist/src/core/ast-utils.js +8 -8
- package/dist/src/core/branding.d.ts +5 -12
- package/dist/src/core/branding.js +6 -5
- package/dist/src/core/browser-wire.d.ts +1 -1
- package/dist/src/core/browser-wire.js +10 -7
- package/dist/src/core/build-audit-platform.d.ts +32 -3
- package/dist/src/core/build-audit-platform.js +153 -13
- package/dist/src/core/build-audit-registration.d.ts +5 -5
- package/dist/src/core/build-audit-registration.js +10 -9
- package/dist/src/core/build-audit-resolve.d.ts +5 -5
- package/dist/src/core/build-audit-resolve.js +6 -6
- package/dist/src/core/build-audit-skip.d.ts +57 -0
- package/dist/src/core/build-audit-skip.js +112 -0
- package/dist/src/core/build-audit-transforms.d.ts +2 -2
- package/dist/src/core/build-audit-transforms.js +3 -3
- package/dist/src/core/build-audit.d.ts +21 -8
- package/dist/src/core/build-audit.js +142 -40
- package/dist/src/core/build-baseline-types.d.ts +19 -18
- package/dist/src/core/build-baseline-types.js +1 -1
- package/dist/src/core/build-baseline.d.ts +48 -31
- package/dist/src/core/build-baseline.js +20 -43
- package/dist/src/core/build-jar-escalation.d.ts +8 -8
- package/dist/src/core/build-jar-escalation.js +18 -17
- package/dist/src/core/build-overwrite-guard.d.ts +4 -4
- package/dist/src/core/build-overwrite-guard.js +14 -14
- package/dist/src/core/build-prepare.d.ts +4 -12
- package/dist/src/core/build-prepare.js +22 -26
- package/dist/src/core/config-mutate.js +4 -4
- package/dist/src/core/config-paths.d.ts +2 -6
- package/dist/src/core/config-paths.js +4 -2
- package/dist/src/core/config-state.d.ts +0 -6
- package/dist/src/core/config-state.js +3 -21
- package/dist/src/core/config-validate-build-audit.d.ts +8 -0
- package/dist/src/core/config-validate-build-audit.js +80 -0
- package/dist/src/core/config-validate-file-size.d.ts +1 -1
- package/dist/src/core/config-validate-file-size.js +3 -3
- package/dist/src/core/config-validate-patch-policy.d.ts +2 -2
- package/dist/src/core/config-validate-patch-policy.js +3 -3
- package/dist/src/core/config-validate-test-toolchains.d.ts +2 -2
- package/dist/src/core/config-validate-test-toolchains.js +4 -5
- package/dist/src/core/config-validate.js +22 -12
- package/dist/src/core/config.d.ts +12 -12
- package/dist/src/core/config.js +21 -25
- package/dist/src/core/coverage-extend.d.ts +16 -16
- package/dist/src/core/coverage-extend.js +20 -20
- package/dist/src/core/destructive.d.ts +14 -14
- package/dist/src/core/destructive.js +9 -9
- package/dist/src/core/diff-hunks.d.ts +2 -2
- package/dist/src/core/diff-hunks.js +7 -7
- package/dist/src/core/discard-baseline.d.ts +10 -10
- package/dist/src/core/discard-baseline.js +22 -23
- package/dist/src/core/display-state.d.ts +11 -11
- package/dist/src/core/display-state.js +12 -12
- package/dist/src/core/engine-changes.d.ts +2 -2
- package/dist/src/core/engine-changes.js +2 -2
- package/dist/src/core/engine-precondition.d.ts +5 -13
- package/dist/src/core/engine-precondition.js +5 -10
- package/dist/src/core/engine-session-lock.d.ts +18 -18
- package/dist/src/core/engine-session-lock.js +50 -54
- package/dist/src/core/export-moved-code-shape.d.ts +7 -7
- package/dist/src/core/export-moved-code-shape.js +10 -10
- package/dist/src/core/file-lock-owner.d.ts +103 -0
- package/dist/src/core/file-lock-owner.js +259 -0
- package/dist/src/core/file-lock.d.ts +14 -19
- package/dist/src/core/file-lock.js +90 -128
- package/dist/src/core/firefox-cache.d.ts +13 -1
- package/dist/src/core/firefox-cache.js +61 -36
- package/dist/src/core/firefox-download.d.ts +15 -0
- package/dist/src/core/firefox-download.js +38 -22
- package/dist/src/core/firefox-extract.d.ts +8 -7
- package/dist/src/core/firefox-extract.js +45 -27
- package/dist/src/core/firefox.d.ts +34 -36
- package/dist/src/core/firefox.js +13 -44
- package/dist/src/core/furnace-apply-dry-run.d.ts +1 -6
- package/dist/src/core/furnace-apply-dry-run.js +2 -8
- package/dist/src/core/furnace-apply-ftl.d.ts +5 -5
- package/dist/src/core/furnace-apply-ftl.js +8 -8
- package/dist/src/core/furnace-apply-helpers.d.ts +9 -20
- package/dist/src/core/furnace-apply-helpers.js +28 -39
- package/dist/src/core/furnace-apply-output.js +1 -1
- package/dist/src/core/furnace-apply-overwrite-warn.d.ts +9 -9
- package/dist/src/core/furnace-apply-overwrite-warn.js +13 -11
- package/dist/src/core/furnace-apply-undeploy-actions.d.ts +1 -1
- package/dist/src/core/furnace-apply-undeploy-actions.js +1 -1
- package/dist/src/core/furnace-apply.d.ts +4 -4
- package/dist/src/core/furnace-apply.js +50 -29
- package/dist/src/core/furnace-checksum-utils.d.ts +5 -5
- package/dist/src/core/furnace-checksum-utils.js +5 -5
- package/dist/src/core/furnace-config-custom.d.ts +1 -1
- package/dist/src/core/furnace-config-custom.js +2 -2
- package/dist/src/core/furnace-config-order.js +1 -1
- package/dist/src/core/furnace-config-tokens.d.ts +3 -3
- package/dist/src/core/furnace-config-tokens.js +3 -3
- package/dist/src/core/furnace-config-validate.js +2 -2
- package/dist/src/core/furnace-config.d.ts +5 -5
- package/dist/src/core/furnace-config.js +40 -53
- package/dist/src/core/furnace-constants.d.ts +6 -6
- package/dist/src/core/furnace-constants.js +9 -8
- package/dist/src/core/furnace-css-fragments.d.ts +6 -6
- package/dist/src/core/furnace-css-fragments.js +11 -11
- package/dist/src/core/furnace-dir-entry.d.ts +20 -0
- package/dist/src/core/furnace-dir-entry.js +21 -0
- package/dist/src/core/furnace-jsconfig.d.ts +7 -7
- package/dist/src/core/furnace-jsconfig.js +22 -20
- package/dist/src/core/furnace-operation.d.ts +22 -19
- package/dist/src/core/furnace-operation.js +38 -34
- package/dist/src/core/furnace-precondition.d.ts +10 -10
- package/dist/src/core/furnace-precondition.js +8 -8
- package/dist/src/core/furnace-refresh.d.ts +18 -6
- package/dist/src/core/furnace-refresh.js +5 -8
- package/dist/src/core/furnace-registration-ast.d.ts +2 -3
- package/dist/src/core/furnace-registration-ast.js +9 -12
- package/dist/src/core/furnace-registration-remove.d.ts +4 -4
- package/dist/src/core/furnace-registration-remove.js +6 -6
- package/dist/src/core/furnace-registration-validate.d.ts +2 -2
- package/dist/src/core/furnace-registration-validate.js +2 -2
- package/dist/src/core/furnace-registration.d.ts +7 -6
- package/dist/src/core/furnace-registration.js +29 -36
- package/dist/src/core/furnace-rollback.d.ts +1 -1
- package/dist/src/core/furnace-rollback.js +5 -5
- package/dist/src/core/furnace-scanner.js +3 -6
- package/dist/src/core/furnace-stale-export.d.ts +17 -16
- package/dist/src/core/furnace-stale-export.js +16 -15
- package/dist/src/core/furnace-staleness.d.ts +2 -2
- package/dist/src/core/furnace-staleness.js +2 -2
- package/dist/src/core/furnace-state-persist.d.ts +12 -12
- package/dist/src/core/furnace-state-persist.js +10 -10
- package/dist/src/core/furnace-step-errors.d.ts +6 -6
- package/dist/src/core/furnace-step-errors.js +6 -6
- package/dist/src/core/furnace-validate-accessibility.js +14 -14
- package/dist/src/core/furnace-validate-compatibility.js +9 -9
- package/dist/src/core/furnace-validate-registration.d.ts +2 -2
- package/dist/src/core/furnace-validate-registration.js +18 -20
- package/dist/src/core/furnace-validate-structure.d.ts +1 -1
- package/dist/src/core/furnace-validate-structure.js +4 -4
- package/dist/src/core/furnace-validate.js +9 -9
- package/dist/src/core/furnace-version-drift.d.ts +5 -5
- package/dist/src/core/furnace-version-drift.js +5 -5
- package/dist/src/core/git-base.d.ts +6 -4
- package/dist/src/core/git-base.js +29 -7
- package/dist/src/core/git-diff-new-file.d.ts +40 -0
- package/dist/src/core/git-diff-new-file.js +119 -0
- package/dist/src/core/git-diff.d.ts +13 -13
- package/dist/src/core/git-diff.js +121 -189
- package/dist/src/core/git-file-ops.d.ts +6 -13
- package/dist/src/core/git-file-ops.js +11 -35
- package/dist/src/core/git-readonly-index.d.ts +12 -14
- package/dist/src/core/git-readonly-index.js +12 -16
- package/dist/src/core/git-status.d.ts +9 -2
- package/dist/src/core/git-status.js +23 -11
- package/dist/src/core/git.d.ts +3 -9
- package/dist/src/core/git.js +28 -57
- package/dist/src/core/harness-orphans.d.ts +17 -17
- package/dist/src/core/harness-orphans.js +28 -27
- package/dist/src/core/history-log.d.ts +19 -0
- package/dist/src/core/history-log.js +29 -0
- package/dist/src/core/license-headers.d.ts +19 -18
- package/dist/src/core/license-headers.js +29 -28
- package/dist/src/core/mach-build-artifacts.d.ts +21 -21
- package/dist/src/core/mach-build-artifacts.js +23 -23
- package/dist/src/core/mach-error-hints.d.ts +5 -10
- package/dist/src/core/mach-error-hints.js +14 -14
- package/dist/src/core/mach-known-noise-filter.d.ts +42 -38
- package/dist/src/core/mach-known-noise-filter.js +57 -56
- package/dist/src/core/mach-mozconfig.d.ts +6 -6
- package/dist/src/core/mach-mozconfig.js +17 -16
- package/dist/src/core/mach-python.d.ts +3 -0
- package/dist/src/core/mach-python.js +13 -7
- package/dist/src/core/mach-resource-shim.d.ts +24 -12
- package/dist/src/core/mach-resource-shim.js +124 -21
- package/dist/src/core/mach.d.ts +59 -73
- package/dist/src/core/mach.js +47 -115
- package/dist/src/core/marionette-port.d.ts +15 -30
- package/dist/src/core/marionette-port.js +46 -89
- package/dist/src/core/marionette-preflight.d.ts +6 -6
- package/dist/src/core/marionette-preflight.js +32 -50
- package/dist/src/core/markdown-table.d.ts +9 -9
- package/dist/src/core/markdown-table.js +14 -14
- package/dist/src/core/mochitest-server-port.d.ts +8 -8
- package/dist/src/core/mochitest-server-port.js +17 -17
- package/dist/src/core/module-resolution-preflight.d.ts +8 -8
- package/dist/src/core/module-resolution-preflight.js +11 -11
- package/dist/src/core/moz-manifest-helpers.d.ts +7 -7
- package/dist/src/core/moz-manifest-helpers.js +7 -7
- package/dist/src/core/moz-manifest-register.d.ts +1 -1
- package/dist/src/core/moz-manifest-register.js +2 -2
- package/dist/src/core/moz-manifest-rules.js +46 -42
- package/dist/src/core/moz-manifest-tokenizers.js +1 -1
- package/dist/src/core/ownership-table.d.ts +5 -5
- package/dist/src/core/ownership-table.js +7 -7
- package/dist/src/core/parser-fallback.d.ts +3 -3
- package/dist/src/core/parser-fallback.js +3 -3
- package/dist/src/core/patch-apply-fuzz.d.ts +5 -5
- package/dist/src/core/patch-apply-fuzz.js +13 -13
- package/dist/src/core/patch-apply.d.ts +13 -14
- package/dist/src/core/patch-apply.js +36 -42
- package/dist/src/core/patch-export-coverage.d.ts +0 -9
- package/dist/src/core/patch-export-coverage.js +1 -30
- package/dist/src/core/patch-export-update.d.ts +21 -4
- package/dist/src/core/patch-export-update.js +7 -6
- package/dist/src/core/patch-export.d.ts +20 -30
- package/dist/src/core/patch-export.js +55 -77
- package/dist/src/core/patch-files.d.ts +0 -4
- package/dist/src/core/patch-files.js +0 -11
- package/dist/src/core/patch-identifier-suggest.d.ts +1 -1
- package/dist/src/core/patch-identifier-suggest.js +4 -4
- package/dist/src/core/patch-lint-binary.d.ts +12 -18
- package/dist/src/core/patch-lint-cache.d.ts +18 -2
- package/dist/src/core/patch-lint-cache.js +16 -19
- package/dist/src/core/patch-lint-checkjs.d.ts +55 -38
- package/dist/src/core/patch-lint-checkjs.js +78 -64
- package/dist/src/core/patch-lint-chrome-jsdoc.d.ts +8 -9
- package/dist/src/core/patch-lint-chrome-jsdoc.js +10 -11
- package/dist/src/core/patch-lint-creators.d.ts +5 -9
- package/dist/src/core/patch-lint-creators.js +3 -3
- package/dist/src/core/patch-lint-cross.d.ts +27 -19
- package/dist/src/core/patch-lint-cross.js +67 -110
- package/dist/src/core/patch-lint-css.d.ts +1 -1
- package/dist/src/core/patch-lint-css.js +15 -11
- package/dist/src/core/patch-lint-diff-tag.d.ts +5 -5
- package/dist/src/core/patch-lint-diff-tag.js +5 -5
- package/dist/src/core/patch-lint-diff.d.ts +4 -4
- package/dist/src/core/patch-lint-diff.js +4 -4
- package/dist/src/core/patch-lint-file-size.d.ts +3 -3
- package/dist/src/core/patch-lint-file-size.js +6 -6
- package/dist/src/core/patch-lint-forward-registration.d.ts +58 -0
- package/dist/src/core/patch-lint-forward-registration.js +210 -0
- package/dist/src/core/patch-lint-jsdoc.d.ts +2 -2
- package/dist/src/core/patch-lint-jsdoc.js +46 -46
- package/dist/src/core/patch-lint-module-registration.d.ts +3 -9
- package/dist/src/core/patch-lint-module-registration.js +1 -1
- package/dist/src/core/patch-lint-mozbuild.d.ts +1 -1
- package/dist/src/core/patch-lint-mozbuild.js +10 -10
- package/dist/src/core/patch-lint-observer.d.ts +3 -3
- package/dist/src/core/patch-lint-observer.js +7 -7
- package/dist/src/core/patch-lint-ownership.d.ts +6 -6
- package/dist/src/core/patch-lint-ownership.js +6 -6
- package/dist/src/core/patch-lint-prettier.d.ts +6 -6
- package/dist/src/core/patch-lint-prettier.js +7 -7
- package/dist/src/core/patch-lint-queue-types.d.ts +60 -0
- package/dist/src/core/patch-lint-queue-types.js +12 -0
- package/dist/src/core/patch-lint-staged-registration.d.ts +61 -0
- package/dist/src/core/patch-lint-staged-registration.js +90 -0
- package/dist/src/core/patch-lint-unmanaged-companion.d.ts +23 -23
- package/dist/src/core/patch-lint-unmanaged-companion.js +26 -26
- package/dist/src/core/patch-lint.d.ts +41 -35
- package/dist/src/core/patch-lint.js +52 -49
- package/dist/src/core/patch-lock.d.ts +1 -1
- package/dist/src/core/patch-lock.js +11 -11
- package/dist/src/core/patch-manifest-consistency.d.ts +7 -7
- package/dist/src/core/patch-manifest-consistency.js +16 -17
- package/dist/src/core/patch-manifest-files-affected.d.ts +1 -1
- package/dist/src/core/patch-manifest-files-affected.js +3 -3
- package/dist/src/core/patch-manifest-io.d.ts +14 -14
- package/dist/src/core/patch-manifest-io.js +35 -34
- package/dist/src/core/patch-manifest-query.d.ts +1 -1
- package/dist/src/core/patch-manifest-query.js +4 -4
- package/dist/src/core/patch-manifest-resolve.d.ts +5 -5
- package/dist/src/core/patch-manifest-resolve.js +7 -7
- package/dist/src/core/patch-manifest-validate.js +3 -3
- package/dist/src/core/patch-manifest.d.ts +2 -2
- package/dist/src/core/patch-manifest.js +2 -2
- package/dist/src/core/patch-parse.d.ts +32 -21
- package/dist/src/core/patch-parse.js +40 -15
- package/dist/src/core/patch-policy.js +15 -27
- package/dist/src/core/patch-registration-refs.d.ts +4 -4
- package/dist/src/core/patch-registration-refs.js +7 -7
- package/dist/src/core/patch-source-metadata.d.ts +1 -3
- package/dist/src/core/patch-source-metadata.js +0 -4
- package/dist/src/core/patch-transform.d.ts +8 -16
- package/dist/src/core/patch-transform.js +13 -23
- package/dist/src/core/process-cpu-time.d.ts +1 -1
- package/dist/src/core/process-cpu-time.js +6 -6
- package/dist/src/core/rebase-session.d.ts +9 -15
- package/dist/src/core/rebase-session.js +13 -25
- package/dist/src/core/register-browser-content.js +3 -2
- package/dist/src/core/register-browser-test.js +2 -1
- package/dist/src/core/register-module.js +2 -1
- package/dist/src/core/register-result.d.ts +1 -1
- package/dist/src/core/register-result.js +1 -1
- package/dist/src/core/register-scaffold.d.ts +2 -2
- package/dist/src/core/register-scaffold.js +8 -7
- package/dist/src/core/register-shared-css.d.ts +3 -3
- package/dist/src/core/register-shared-css.js +6 -5
- package/dist/src/core/register-xpcshell-test.d.ts +2 -2
- package/dist/src/core/register-xpcshell-test.js +2 -2
- package/dist/src/core/run-log-redact.d.ts +38 -0
- package/dist/src/core/run-log-redact.js +69 -0
- package/dist/src/core/run-log.d.ts +21 -10
- package/dist/src/core/run-log.js +76 -27
- package/dist/src/core/shared-ftl.d.ts +2 -2
- package/dist/src/core/shared-ftl.js +6 -6
- package/dist/src/core/signal-critical.d.ts +2 -2
- package/dist/src/core/signal-critical.js +4 -6
- package/dist/src/core/smoke-patterns.d.ts +5 -6
- package/dist/src/core/smoke-patterns.js +15 -20
- package/dist/src/core/state-file.d.ts +15 -4
- package/dist/src/core/state-file.js +14 -1
- package/dist/src/core/status-binary.d.ts +8 -8
- package/dist/src/core/status-binary.js +12 -12
- package/dist/src/core/status-classify.d.ts +17 -17
- package/dist/src/core/status-classify.js +13 -12
- package/dist/src/core/test-changed-prefs.d.ts +12 -12
- package/dist/src/core/test-changed-prefs.js +40 -25
- package/dist/src/core/test-harness-crash.d.ts +39 -39
- package/dist/src/core/test-harness-crash.js +69 -69
- package/dist/src/core/test-harness-output.d.ts +7 -7
- package/dist/src/core/test-harness-output.js +7 -7
- package/dist/src/core/test-harness-verdict-notes.d.ts +13 -14
- package/dist/src/core/test-harness-verdict-notes.js +4 -4
- package/dist/src/core/test-path-scope.d.ts +8 -8
- package/dist/src/core/test-path-scope.js +11 -11
- package/dist/src/core/test-stale-check.d.ts +22 -23
- package/dist/src/core/test-stale-check.js +31 -30
- package/dist/src/core/test-stale-symlink.d.ts +1 -1
- package/dist/src/core/test-stale-symlink.js +1 -1
- package/dist/src/core/test-stall-triage.d.ts +9 -9
- package/dist/src/core/test-stall-triage.js +22 -22
- package/dist/src/core/test-xpcshell-retry.d.ts +26 -7
- package/dist/src/core/test-xpcshell-retry.js +14 -11
- package/dist/src/core/token-category.d.ts +35 -2
- package/dist/src/core/token-category.js +67 -58
- package/dist/src/core/token-coverage.js +4 -5
- package/dist/src/core/token-dark-mode.d.ts +9 -9
- package/dist/src/core/token-dark-mode.js +13 -25
- package/dist/src/core/token-docs.d.ts +1 -1
- package/dist/src/core/token-inventory.d.ts +56 -0
- package/dist/src/core/token-inventory.js +109 -0
- package/dist/src/core/token-manager.d.ts +4 -4
- package/dist/src/core/token-manager.js +22 -22
- package/dist/src/core/token-scaffold.d.ts +4 -4
- package/dist/src/core/token-scaffold.js +4 -4
- package/dist/src/core/token-variant.d.ts +14 -14
- package/dist/src/core/token-variant.js +52 -53
- package/dist/src/core/toolchain-preflight.d.ts +15 -15
- package/dist/src/core/toolchain-preflight.js +23 -23
- package/dist/src/core/tree-cow.d.ts +3 -5
- package/dist/src/core/tree-cow.js +8 -8
- package/dist/src/core/tree-guard.d.ts +3 -3
- package/dist/src/core/tree-guard.js +23 -23
- package/dist/src/core/tree-store.d.ts +15 -15
- package/dist/src/core/tree-store.js +39 -38
- package/dist/src/core/typecheck-shim.d.ts +16 -15
- package/dist/src/core/typecheck-shim.js +26 -25
- package/dist/src/core/typecheck.d.ts +12 -12
- package/dist/src/core/typecheck.js +33 -33
- package/dist/src/core/wire-destroy.d.ts +2 -2
- package/dist/src/core/wire-destroy.js +5 -5
- package/dist/src/core/wire-dom-fragment.d.ts +3 -3
- package/dist/src/core/wire-dom-fragment.js +12 -23
- package/dist/src/core/wire-init.d.ts +2 -2
- package/dist/src/core/wire-init.js +7 -7
- package/dist/src/core/wire-subscript.d.ts +1 -1
- package/dist/src/core/wire-subscript.js +3 -3
- package/dist/src/core/wire-utils.d.ts +9 -9
- package/dist/src/core/wire-utils.js +16 -28
- package/dist/src/core/xpcshell-appdir.d.ts +20 -20
- package/dist/src/core/xpcshell-appdir.js +28 -30
- package/dist/src/core/xpcshell-profile-dir.d.ts +3 -3
- package/dist/src/core/xpcshell-profile-dir.js +7 -7
- package/dist/src/errors/base.d.ts +69 -16
- package/dist/src/errors/base.js +95 -26
- package/dist/src/errors/build.d.ts +6 -6
- package/dist/src/errors/build.js +26 -34
- package/dist/src/errors/codes.d.ts +10 -10
- package/dist/src/errors/codes.js +10 -10
- package/dist/src/errors/config.d.ts +0 -14
- package/dist/src/errors/config.js +13 -34
- package/dist/src/errors/download.d.ts +13 -0
- package/dist/src/errors/download.js +53 -24
- package/dist/src/errors/furnace.d.ts +2 -2
- package/dist/src/errors/furnace.js +8 -9
- package/dist/src/errors/git.d.ts +9 -9
- package/dist/src/errors/git.js +21 -31
- package/dist/src/errors/patch.d.ts +3 -3
- package/dist/src/errors/patch.js +11 -13
- package/dist/src/errors/rebase.d.ts +1 -1
- package/dist/src/errors/rebase.js +8 -8
- package/dist/src/errors/run.d.ts +1 -1
- package/dist/src/errors/run.js +1 -1
- package/dist/src/index.d.ts +4 -4
- package/dist/src/index.js +4 -4
- package/dist/src/types/commands/options.d.ts +155 -200
- package/dist/src/types/commands/patches.d.ts +19 -19
- package/dist/src/types/commands/project.d.ts +3 -3
- package/dist/src/types/config.d.ts +52 -19
- package/dist/src/types/furnace.d.ts +17 -17
- package/dist/src/types/index.d.ts +0 -1
- package/dist/src/types/json.d.ts +3 -3
- package/dist/src/types/json.js +2 -2
- package/dist/src/types/typecheck.d.ts +3 -3
- package/dist/src/utils/assert.d.ts +4 -16
- package/dist/src/utils/assert.js +7 -24
- package/dist/src/utils/build-info.d.ts +6 -6
- package/dist/src/utils/build-info.js +6 -6
- package/dist/src/utils/child-env.d.ts +7 -6
- package/dist/src/utils/child-env.js +5 -5
- package/dist/src/utils/concurrency.d.ts +2 -2
- package/dist/src/utils/concurrency.js +2 -2
- package/dist/src/utils/elapsed.js +10 -1
- package/dist/src/utils/errors.d.ts +8 -8
- package/dist/src/utils/errors.js +8 -8
- package/dist/src/utils/fs.d.ts +1 -1
- package/dist/src/utils/fs.js +15 -20
- package/dist/src/utils/hash.d.ts +12 -0
- package/dist/src/utils/hash.js +16 -0
- package/dist/src/utils/line-dispatch.d.ts +15 -0
- package/dist/src/utils/line-dispatch.js +48 -0
- package/dist/src/utils/logger.d.ts +4 -4
- package/dist/src/utils/logger.js +11 -11
- package/dist/src/utils/machine-output.js +2 -2
- package/dist/src/utils/options.d.ts +14 -20
- package/dist/src/utils/options.js +26 -27
- package/dist/src/utils/package-root.js +5 -14
- package/dist/src/utils/paths.d.ts +4 -4
- package/dist/src/utils/paths.js +4 -4
- package/dist/src/utils/platform.d.ts +0 -4
- package/dist/src/utils/process-group.d.ts +10 -9
- package/dist/src/utils/process-group.js +37 -36
- package/dist/src/utils/process.d.ts +70 -55
- package/dist/src/utils/process.js +129 -179
- package/dist/src/utils/ps-duration.d.ts +4 -4
- package/dist/src/utils/ps-duration.js +9 -9
- package/dist/src/utils/regex.d.ts +4 -4
- package/dist/src/utils/regex.js +7 -7
- package/dist/src/utils/sleep.d.ts +26 -0
- package/dist/src/utils/sleep.js +31 -0
- package/dist/src/utils/stdio-drain.d.ts +7 -7
- package/dist/src/utils/stdio-drain.js +8 -8
- package/dist/src/utils/validation.d.ts +12 -49
- package/dist/src/utils/validation.js +26 -36
- package/docs/README.md +2 -2
- package/docs/configuration.md +163 -69
- package/docs/exit-codes.md +66 -49
- package/docs/furnace.md +20 -19
- package/docs/lifecycle-invariants.md +414 -247
- package/docs/machine-output.md +58 -34
- package/docs/patch-workflow.md +48 -44
- package/docs/run-logs.md +72 -28
- package/docs/testing.md +105 -98
- package/docs/verification-trees.md +23 -22
- package/package.json +7 -6
- package/dist/src/commands/rebase.d.ts +0 -4
- package/dist/src/commands/rebase.js +0 -5
- package/dist/src/core/patch-artifact-normalize.d.ts +0 -21
- package/dist/src/core/patch-artifact-normalize.js +0 -24
- package/dist/src/core/patch-lint-reexports.d.ts +0 -7
- package/dist/src/core/patch-lint-reexports.js +0 -8
- package/dist/src/core/wire-targets.d.ts +0 -7
- package/dist/src/core/wire-targets.js +0 -8
package/CHANGELOG.md
CHANGED
|
@@ -1,623 +1,589 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.46.0
|
|
4
|
+
|
|
5
|
+
### Packaging audit
|
|
6
|
+
|
|
7
|
+
- The post-build audit no longer warns about files it was never going to package. It now skips unselected branding trees, directories gated off-platform by an ancestor `moz.build`, Storybook `*.stories.mjs`/`*.stories.js` files, and paths declared in `buildAudit.unpackaged` in `fireforge.json`. The `Packaged:` line counts every skip reason so the numbers can be checked.
|
|
8
|
+
- A declared carve-out that does resolve to a packaged artifact is reported as stale rather than hidden. `**` in a carve-out path is refused.
|
|
9
|
+
|
|
10
|
+
### Patch queue and lint
|
|
11
|
+
|
|
12
|
+
- New `forward-registration` lint error: a test manifest that registers a file only a later patch creates. On a 338-patch queue this finds 48 real cases in three shared manifests. Each message prints the `patch staged-dependency --add --kind registration` command that fixes it.
|
|
13
|
+
- The command that rule prints now quotes the manifest line the way the patch actually writes it, including multi-line and multi-entry arrays. Before this it produced declarations that immediately warned as unused.
|
|
14
|
+
- The `staged-dependency-unused` warning prints the full removal command instead of one that refuses without its arguments.
|
|
15
|
+
- `lint --per-patch --patches 102` accepts a bare order number, padded or not.
|
|
16
|
+
- Staged-dependency registration checks now see binary files. A patch creating a binary through `GIT binary patch` used to be invisible to the resolver.
|
|
17
|
+
- `patch compact` refuses if the queue changed between the confirmation prompt and the lock, the same gate `patch reorder` already had.
|
|
18
|
+
|
|
19
|
+
### Patch bodies
|
|
20
|
+
|
|
21
|
+
- Fixed corruption of new non-UTF-8 text files on export. The body was built from a UTF-8 decode while the blob hash came from the real bytes, so the patch wrote different bytes than the tree held and drift detection flagged the file forever. Text vs binary is now decided by a NUL byte or invalid UTF-8, and the binary arm forces a byte-faithful `GIT binary patch`.
|
|
22
|
+
- Worktree-side renames no longer produce a phantom status entry. Git emits an unstaged rename as ` R new\0old\0`, and the old path was parsed as its own entry.
|
|
23
|
+
|
|
24
|
+
### Integrity
|
|
25
|
+
|
|
26
|
+
- Checksum verification fails closed. An unreachable `SHA256SUMS` used to accept the tarball on TLS alone. Ways out: fix connectivity, pin `firefox.sha256`, or set `firefox.allowUnverifiedDownload: true`. The checksum request now uses the same timeout and retry as the tarball fetch.
|
|
27
|
+
- Archive extraction rejects any member with a `.git` path segment. `.gitmodules` and `.gitignore` still pass.
|
|
28
|
+
- The mach `PYTHONPATH` shim directory is now per-user, created `0700`, and checked for ownership and mode before it joins `PYTHONPATH`. It used to be a fixed shared temp path any local account could pre-create.
|
|
29
|
+
- Run logs are redacted. `KEY=value` pairs matching `TOKEN|SECRET|PASSWORD|PASSWD|API_KEY|AUTH`, `--password=` style flags, and `Authorization:` headers are masked in the log file only. `docs/run-logs.md` states what is and is not masked.
|
|
30
|
+
|
|
31
|
+
### Locks
|
|
32
|
+
|
|
33
|
+
- A failed owner-record write no longer lets two builds into the critical section. The write is verified, and on failure the lock directory is removed and the run refuses.
|
|
34
|
+
- A recycled PID no longer keeps a dead lock honoured. On Linux the owner record carries the holder's start tick from `/proc`, so a different process with the same PID reads as stale. macOS and Windows keep PID-only liveness.
|
|
35
|
+
|
|
36
|
+
### Exit codes
|
|
37
|
+
|
|
38
|
+
- Commander usage errors exit 8 as documented, with a JSON envelope under `--json`. `--help`, `--version`, and a command group with no subcommand still exit 0.
|
|
39
|
+
- `GitNotFoundError` exits 7 like its siblings. A contract test now checks every error class against the table in `docs/exit-codes.md` in both directions.
|
|
40
|
+
- Manifest invariant failures raise `InternalInvariantError` and render as a bug report instead of a bare stack.
|
|
41
|
+
|
|
42
|
+
### Diagnostics
|
|
43
|
+
|
|
44
|
+
- A timed-out command keeps what it captured. `ExecTimeoutError` carries stdout, stderr, and a truncation flag, and shows the last 20 lines.
|
|
45
|
+
- `exec()` used to accept `processGroup` and `mirror` and ignore both. The options type is split so it cannot admit them.
|
|
46
|
+
- `test --help` lists all seven verdict reasons.
|
|
47
|
+
|
|
48
|
+
### Tooling
|
|
49
|
+
|
|
50
|
+
- `@types/node` moves to `^22` to match the supported Node floor, and a `node-floor` CI job runs the suite on Node 22, 24, and `.nvmrc`.
|
|
51
|
+
- Three copy-pasted mach test wrappers became one `runMachTestSuite(kind, options)`. Several other duplicated helpers collapsed the same way.
|
|
52
|
+
- `ReturnType<typeof X>` on local imports is now a lint error; every site uses the named exported type.
|
|
53
|
+
- Two new lint rules: `no-unnecessary-type-conversion` and `prefer-object-has-own`. Both were already satisfied when they landed.
|
|
54
|
+
- The spawned-CLI test helper settles on `'close'` and rejects on `'error'`.
|
|
55
|
+
- Wall-clock test budgets replaced with ratio checks and fake timers.
|
|
56
|
+
|
|
57
|
+
### Dead code
|
|
58
|
+
|
|
59
|
+
- Twenty-two exports that only tests referenced are gone, along with those tests and the barrel lines. `deadcode:check:production` resolves from the two real entry points and runs in `release:check`, so it cannot come back.
|
|
60
|
+
- Three impossible-state fallbacks removed rather than documented.
|
|
61
|
+
- `fireforge import --stop-at` is removed. It was an alias added in the same commit as `--until`.
|
|
62
|
+
|
|
63
|
+
### Duplication
|
|
64
|
+
|
|
65
|
+
- One `sleep(ms, { unref })` replaces nine copies that disagreed on whether the timer keeps the event loop alive.
|
|
66
|
+
- Eight `--order` parsers now share `parsePositiveIntegerFlag`, so `--order 12abc` is refused instead of becoming 12.
|
|
67
|
+
- `normalizePatchArtifact` was an identity function on every patch write path; it is gone and its warning moved to the export write site.
|
|
68
|
+
- `ensureGit()` is memoised and called inside `git()` instead of before 32 of the 38 call sites.
|
|
69
|
+
- Single helpers now cover repeated shapes: `sha256Hex`, `normalizePathSlashes`, `formatPatchOrder`, `appendHistoryBestEffort`, `proceedAfterDecision`, `deriveTestStem`, and others.
|
|
70
|
+
- `--dry-run`, `--yes`, and `--force-unsafe` are documented once each through five option mixins.
|
|
71
|
+
|
|
72
|
+
### Test suite
|
|
73
|
+
|
|
74
|
+
- Eleven test files and about 5,600 lines are gone with no assertion lost. They tested barrels, layers, and coverage thresholds rather than behaviour.
|
|
75
|
+
- Twenty-one full-text help snapshots became one inventory snapshot of commands and sorted flag names.
|
|
76
|
+
- `process-boundary.test.ts` is replaced by the lint rule that already enforced it.
|
|
77
|
+
- Four tests that asserted less than their titles claimed now assert what they say.
|
|
78
|
+
|
|
3
79
|
## 0.45.0
|
|
4
80
|
|
|
5
81
|
### Patch bodies
|
|
6
82
|
|
|
7
|
-
-
|
|
8
|
-
|
|
9
|
-
Worth recording that the reported symptom was narrower than stated in one direction and wider in another. Plain `fireforge export` of a new binary always worked; the export half fails only behind a placement flag (`--order`/`--before`/`--after`), which is what routes it through `projectPlacementForLint`. But the same projection sits under `patch move-files-into` and `patch split`, so a binary could not be moved between patches or split out either.
|
|
10
|
-
- **The new-file conflict recovery could not handle a binary target, and restored text where it should have restored bytes.** When `git apply` fails because a patch creates a file that is already on disk, FireForge resolves the conflict by putting the patch's intended content in place and retrying. For a binary there is nothing to extract — but nothing needs to be: `git apply` decodes the payload itself, so the resolution is to REMOVE the blocking file and let the retry create it. A `Binary files … differ` body, which records that the bytes changed and carries none of them, is refused instead of deleted, because nothing could put the file back. The saved originals are now raw `Buffer`s rather than utf-8 text, which also closes a latent corruption on the pre-existing path: a binary file overwritten by this recovery was previously restored through a `readText`/`writeText` round-trip that mangles it.
|
|
83
|
+
- A new binary file can be vendored into a patch. The export was always correct; the forward-import projection refused to decode the binary body. The five duplicated projection loops became one helper that skips binary sections.
|
|
84
|
+
- New-file conflict recovery handles binary targets by removing the blocking file and letting `git apply` recreate it. Saved originals are buffers now, which also fixes a latent corruption on the existing path.
|
|
11
85
|
|
|
12
86
|
### Refusals
|
|
13
87
|
|
|
14
|
-
-
|
|
15
|
-
-
|
|
16
|
-
-
|
|
88
|
+
- The `--expect` "showed no drift" warning now says what it compares and when, and names the two cases that legitimately produce no drift.
|
|
89
|
+
- The coverage refusal names the test manifests that changed since the recorded build.
|
|
90
|
+
- New `--expect-unmanaged <path>` records an approved exception to `--refuse-adjacent-unmanaged`. Approved paths are always listed, and one that is never met is reported.
|
|
17
91
|
|
|
18
92
|
### Diagnostics
|
|
19
93
|
|
|
20
|
-
-
|
|
21
|
-
-
|
|
22
|
-
-
|
|
23
|
-
-
|
|
24
|
-
-
|
|
25
|
-
-
|
|
26
|
-
|
|
27
|
-
- **`fireforge source set` wrote a pin that a routine revert silently lost.** The pin lands in `fireforge.json` beside hand-maintained policy sections, so `git checkout -- fireforge.json` — undoing an accidental whole-file reformat, say — also reverts an uncommitted pin, and nothing afterwards reported that the pin and the engine checkout had diverged. The field tell was a gate flipping green with no change that should have made it green. `fireforge doctor` now reports the configured pin beside what the checkout actually is — the engine's own `browser/config/version.txt` and the version the last download recorded into state — and warns when they disagree. A report, not a lock and not a new refusal: a tree may legitimately be mid-migration, and the only thing missing was visibility. Scope is limited by what is actually recorded: `product`, `sha256` and `candidate` have no counterpart on disk (state holds only `downloadedVersion` and `baseCommit`), so the check says nothing about them rather than implying it verified them. A blank or whitespace-only `version.txt` — a truncated write, a partial extraction — reads as absent rather than as a mismatch against the empty string. The check reuses `getFirefoxVersion`, which had been sitting in `firefox-extract.ts` with no production caller.
|
|
94
|
+
- `run --smoke-exit` treats `Missing chrome or resource URL:` as a smoke error. It used to exit 0 on a build that hung every browser-chrome run.
|
|
95
|
+
- The no-output-stall triage records the real mechanism: the crash lands in a content process with no crash reporter, so the harness log carries only the timeout. The census names the `.ips` diagnostic report to look for.
|
|
96
|
+
- The green-suite teardown belt names the first condition that rejected a run.
|
|
97
|
+
- The undefined-identifier hint recognises an unmanaged companion file loaded by a managed head and points at `re-export --scan --scan-file` instead of the globals shim.
|
|
98
|
+
- A failing test now raises `TestFailureError` with test-shaped remedies. Exit code stays 5; the `--json` code moves to `test-failure`.
|
|
99
|
+
- The build path prints a recognised teardown traceback verbatim with one labelled line naming it, rather than filtering it like the test path does.
|
|
100
|
+
- `fireforge doctor` reports the configured source pin beside the engine's actual `version.txt` and warns when they disagree.
|
|
28
101
|
|
|
29
102
|
### Builds
|
|
30
103
|
|
|
31
|
-
-
|
|
32
|
-
-
|
|
104
|
+
- The jar-only full-build escalation is narrowed to a new `jar.mn` or a jar declaration with a bracketed base directory. Everything else stays incremental. Probe failures still escalate.
|
|
105
|
+
- Post-build packaging notices name the owning patch, or mark the file `unmanaged`.
|
|
33
106
|
|
|
34
107
|
### Test harness
|
|
35
108
|
|
|
36
|
-
-
|
|
109
|
+
- Every `fireforge test` runs a preflight census of leftover harness processes anchored to this objdir, naming each with its elapsed time and the kill command. `--reap-orphans` terminates them. It never refuses a run.
|
|
37
110
|
|
|
38
111
|
### Patch lint
|
|
39
112
|
|
|
40
|
-
-
|
|
41
|
-
-
|
|
113
|
+
- `patchLint.prettier` (off by default) runs Prettier over patch-owned `.sys.mjs` modules with `cwd` set to `engine/`, which is the only place the check is meaningful.
|
|
114
|
+
- `patchLint.fileSizeThresholds` makes the file-size bands configurable. The message drops the soft/hard wording and says a gate at `--max-warnings 0` treats a warning as a failure.
|
|
42
115
|
|
|
43
116
|
## 0.44.0
|
|
44
117
|
|
|
45
118
|
### Gates
|
|
46
119
|
|
|
47
|
-
-
|
|
48
|
-
- Branch-protection contexts are stable
|
|
49
|
-
-
|
|
50
|
-
-
|
|
120
|
+
- `release:check` runs once per release instead of twice. `prepublishOnly` is the single gate.
|
|
121
|
+
- Branch-protection contexts are stable, and `setup-rulesets.sh` reconciles instead of blindly POSTing.
|
|
122
|
+
- All workflows read the Node version from `.nvmrc`. The old pin was one patch below the floor `eslint-plugin-jsdoc` requires, and `npm ci` only warns about that.
|
|
123
|
+
- A test repo now sets `user.name` as well as `user.email`, so it stops failing only on CI runners. Its git calls reject on non-zero instead of continuing against an empty repo.
|
|
51
124
|
|
|
52
125
|
### Multi-session contention
|
|
53
126
|
|
|
54
|
-
-
|
|
55
|
-
-
|
|
56
|
-
-
|
|
57
|
-
-
|
|
58
|
-
|
|
59
|
-
-
|
|
60
|
-
`binaryStagingLock` never covered it — it is a module-level promise chain, so it serializes within one process while `--parallel-verify` lanes are separate processes. The staging now writes a per-call PRIVATE index (`mintDisposableGitIndex`) and throws it away, so the primary `.git/index` never moves, nothing is restored because nothing shared changed, and two concurrent callers get two indexes rather than contending. The 0.43.0 private-index work closed this for read-only commands; this path is the deliberate writer it did not cover, and it could not have been fixed by leaning on that scope — `export` and `re-export` install none, and `withPrivateGitIndex` is fail-open by design, which on a write path means silently mutating the primary checkout.
|
|
61
|
-
The seed is load-bearing rather than tidy: a tracked, unmodified binary reaches the same branch (its `diff HEAD` is empty), and against an empty index it would report as a fresh add. The shared-index path survives as a fallback for when no private index can be minted — refusing there would fail an export over an optimisation. A real-git test polls `git status` throughout the call and asserts the transient entry is never observable; it fails on the old implementation, which is what makes it worth having.
|
|
62
|
-
|
|
63
|
-
- **`--wait-lock` governed only ONE of the two locks a furnace mutation takes.** `furnace apply`/`deploy`/`sync` routed the resolved budget into the engine session lock and stopped there. `runFurnaceMutation` then acquired `.fireforge/furnace.lock` through `withFileLock`, passing `timeoutMs` only when `options.lockTimeoutMs` was set — and **no production caller ever set it**: the field's only other occurrences were its own declaration and one test, and its doc comment cited a watch-mode caller that does not exist. So the file lock always fell to `DEFAULT_LOCK_TIMEOUT_MS`, a fixed 30 s. A contended `deploy --wait-lock 1800` therefore died at 30 s while its operator believed a half-hour budget was in force, which is the worst shape a budget can have: it pays the entire advertised wait and still refuses. `FIREFORGE_WAIT_LOCK` did not help — it feeds the same resolver into the same single sink.
|
|
64
|
-
The resolved budget now reaches both. It is threaded explicitly into the three commands that declare the flag (`waitLockMutationOptions` does the seconds-to-milliseconds conversion once, rather than at three call sites where dropping the factor is a silent 1000× error), and `runFurnaceMutation` falls back to `sessionWaitLockMs()` — the environment budget — so the twelve furnace mutators with no flag to thread (`create`, `remove`, `rename`, `refresh`, `scan`, `override`, `chrome-doc`, …) are covered too. An explicit `lockTimeoutMs` still wins, and absent both the ~1 s fail-fast and the 30 s default are untouched.
|
|
65
|
-
The invisibility was the other half of the defect: the flag's help text said "the contended lock", singular, and the furnace refusal named neither the lock nor the flag — it advised removing a stale lock directory. The help now says the budget covers every lock the command takes, and the refusal names the FURNACE lock, says it is the second of two, and points at `--wait-lock`/`FIREFORGE_WAIT_LOCK`. A test asserts the budget reaches the command options, and a sibling asserts nothing is threaded without the flag.
|
|
127
|
+
- `--wait-lock` is a budget against a stalled queue. Each improvement in queue position grants a fresh budget, up to four times the request and one hour. The refusal names the position reached.
|
|
128
|
+
- `FIREFORGE_WAIT_LOCK=<seconds>` supplies the budget for any lock-taking command without an explicit `--wait-lock`.
|
|
129
|
+
- SIGTERM and SIGINT emit `FIREFORGE-VERDICT: FAIL reason=killed signal=…` before the shutdown drain, but only if a test run was in flight.
|
|
130
|
+
- The signal sweep releases every lock this process holds, not just furnace ones.
|
|
131
|
+
- Binary-patch staging writes to a private git index. It used to touch the shared index, which made a concurrent `fireforge test` see files flapping between `A` and `??` and fail as inconclusive.
|
|
132
|
+
- `--wait-lock` now reaches both locks a furnace mutation takes. The furnace file lock always used a fixed 30 s, so `deploy --wait-lock 1800` died at 30 s. The refusal names which lock it is and how to raise the budget.
|
|
66
133
|
|
|
67
134
|
### Exit codes
|
|
68
135
|
|
|
69
|
-
-
|
|
136
|
+
- `reason=inconclusive` exits 14 instead of sharing 1 with real failures. `LockContentionError` moves to 15, since the run never started.
|
|
70
137
|
|
|
71
138
|
### Diagnostics
|
|
72
139
|
|
|
73
|
-
-
|
|
74
|
-
-
|
|
75
|
-
-
|
|
76
|
-
-
|
|
77
|
-
-
|
|
78
|
-
-
|
|
79
|
-
|
|
80
|
-
-
|
|
81
|
-
-
|
|
82
|
-
-
|
|
83
|
-
-
|
|
84
|
-
-
|
|
85
|
-
|
|
86
|
-
- **A run's only copy of its own diagnosis died with the pipe.** `fireforge test … 2>&1 | tail -40` keeps the summary and discards the `TEST-UNEXPECTED-FAIL` lines that say WHAT broke; it also launders the exit code. Nothing else held the output — `runMachCapture` keeps a 2 MB in-memory tail that dies with the process, and the shard retry loop discards earlier attempts outright — so one downstream failure is now permanently undiagnosable and cost two further full runs to pin as "unreproduced". The operator rule ("never pipe a run") had been written down three times and broken after each writing, which is the tell that it is not an operator problem: piping is the ergonomic default when output is long, and the tool is the only party that can make the log survive the mistake.
|
|
87
|
-
`test` and `build` now write their own complete output to `.fireforge/logs/<command>-<timestamp>.log` as they stream, retained 20 deep per command kind (per-kind, so a busy `test` loop cannot evict the `build` log an operator needs to read beside it). The tee sits at the two mach capture funnels rather than at the commands, so it covers every dispatch — the three test dispatchers, `package`, and the stdio-inheriting path `mach build` uses, which rides the collectors' existing `mirror` hook rather than growing a second one. The log gets the RAW bytes, never the echo filter's collapsed form: the artifact exists to be re-read by whoever is diagnosing the run, so shortening it would reintroduce the loss it prevents.
|
|
88
|
-
The path rides the `FIREFORGE-VERDICT:` line as an additive `log=<path>` key. That is deliberate and not a free choice — the verdict must stay the run's LAST stdout write, so a separate announcement after it would break the contract and one before it is the first thing a `tail` cuts. `build`, which prints no verdict line, announces the path directly. Everything here is best-effort: a log that cannot be opened, written or pruned degrades to no log, because a run must never fail over a diagnostic. Opened before any preflight, so a refusal is logged too — those are exactly the runs whose only output a `tail` throws away.
|
|
89
|
-
- **Post-rebuild failure diagnosis promoted recognized teardown noise over the real assertion.** An export shard failed on its file-count assertion; the diagnosis named the known `AttributeError: 'SystemResourceMonitor' object has no attribute 'stop_time'` instead. The raw Error Summary had the assertion right, so the information was present and the SELECTION was wrong — the expensive kind, because the named cause is a real, documented, unrelated upstream defect and therefore reads as an answer.
|
|
90
|
-
0.44.0 already ships `mach-known-noise-filter.ts`, whose module doc says exactly the right thing about closing the presentation gap — but `findFirstUsefulFailureLine` never consulted it. It matched a bare `/AttributeError:\s+/` among its patterns and selected by first-matching-LINE, not first-matching-pattern, so that arm had precisely the same standing as `TEST-UNEXPECTED-FAIL` and whichever appeared earlier won. The selector now runs two passes: candidates excluding the recognized noise first, the full set only if that finds nothing. The narrowness is preserved exactly — the exclusion is gated on `hasKnownTeardownNoise` for the whole capture, so it still requires both the closed `stop_time`/`poll_interval` allowlist AND a `resourcemonitor.py` frame, and a novel attribute or a traceback from anywhere else stays a real failure. Three tests pin those escape hatches; the one that pins the fix fails on the old code.
|
|
91
|
-
Worth recording that the misdiagnosis was CONDITIONAL, not universal: the classifier reads stdout then stderr, and the traceback usually lands on stderr while the suite output lands on stdout, so a real `TEST-UNEXPECTED-*` normally won on ordering alone. It bites when the traceback shares or precedes the stream, or when the real failure matches none of the other patterns. The reporter could not have known that, and it does not change the fix — but a defect described as always-firing gets re-opened as "not reproducible" by the next reader.
|
|
92
|
-
- **mozbuild's AI-agent output limiter quieted test runs, not just builds.** `is_running_under_coding_agent()` keys on `CLAUDECODE`, which FireForge inherited into every mach dispatch verbatim — it had no handling of the variable anywhere. The build half of that quieting is genuinely useful; the test half removes `TEST_START` and console INFO, exactly the lines a hang diagnosis needs, and the ones FireForge's own classifier reads (`Ran N checks`, `Unexpected results:`, `TEST-UNEXPECTED-*`), so suppression pushes a run toward `reason=no-tests`. Unsetting the variable for the whole process gives up the build half too.
|
|
93
|
-
`fireforge test --full-output` now unsets the marker for TEST dispatches only; the build path is untouched. It is opt-in rather than automatic because it changes how much a third party prints, and an operator who wants the quieting should keep it. The exec layer gained an explicit `envUnset` for this: `env` can only add or overwrite, and a variable read for its PRESENCE is not unset by an empty value — and the removal is a real delete rather than a `Record<string, string | undefined>` widening, because relying on Node dropping `undefined` env entries would be a semantics gamble at the one layer that must not have any.
|
|
140
|
+
- A stale mochitest httpd on port 8888 is detected at preflight and named. It used to stall runs into a 370 s timeout with nothing pointing at a port.
|
|
141
|
+
- The stale-browser refusal reports elapsed time and the full command line, and offers `--kill-stale-marionette` only for a marionette-driven browser. A bare launch may be someone else's live window.
|
|
142
|
+
- The `--wait-lock` progress line reports the budget currently in force and announces extensions.
|
|
143
|
+
- `status --lock` reports the holder's CPU time, so a wedged holder looks different from a healthy long build. It is an observation, never a verdict.
|
|
144
|
+
- The inconclusive refusal names what moved in `engine/`: the HEAD SHAs and up to five worktree entries.
|
|
145
|
+
- A `moz.build` sort violation is translated instead of arriving as a Python traceback. Mozbuild lowercases before comparing, which is the opposite of the intuitive rule.
|
|
146
|
+
- A run whose only unexpected results are the time-driven `lastColdStartupCheck`/`globalprivacycontrol` pair says so and suggests halving the chunk.
|
|
147
|
+
- The packaging-coverage refusal offers `--extend-coverage` and states when it applies.
|
|
148
|
+
- The no-output-stall census hoists the known-good control step above the list and gives cause 3 a probe that separates it from the others.
|
|
149
|
+
- `test` and `build` write their full output to `.fireforge/logs/<command>-<timestamp>.log` as they stream, 20 deep per command kind. The path rides the verdict line as `log=<path>`. Opened before any preflight, so refusals are logged too.
|
|
150
|
+
- Failure diagnosis no longer promotes recognised teardown noise over the real assertion. The selector runs a pass that excludes known noise first.
|
|
151
|
+
- `fireforge test --full-output` unsets `CLAUDECODE` for test dispatches only, so mozbuild's agent output limiter stops hiding the lines the classifier reads.
|
|
94
152
|
|
|
95
153
|
### Build output resolution
|
|
96
154
|
|
|
97
|
-
-
|
|
155
|
+
- A second `obj-*` directory no longer refuses every command when `engine/mozconfig` declares `MOZ_OBJDIR`. Genuinely ambiguous cases still refuse.
|
|
98
156
|
|
|
99
157
|
### Correctness
|
|
100
158
|
|
|
101
|
-
-
|
|
102
|
-
|
|
103
|
-
-
|
|
104
|
-
-
|
|
105
|
-
|
|
106
|
-
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
-
|
|
110
|
-
-
|
|
111
|
-
-
|
|
112
|
-
-
|
|
113
|
-
-
|
|
114
|
-
-
|
|
115
|
-
-
|
|
116
|
-
-
|
|
117
|
-
- `killProcessTree`'s POSIX branch swallowed `ESRCH`/`EPERM` from the group kill without falling through to a direct `child.kill`, so a failed group kill left the child running.
|
|
118
|
-
|
|
119
|
-
- **A DELETION of an upstream file could not be made durable through `re-export`, and the failure was silent.** With eighteen retired files, `rm` left `fireforge status --json` reporting `"status": "D"` with `"classification": "unmanaged"` — correct as a description, fatal as a state, because `check-engine-clean` refuses an unmanaged file precisely because it is not durable through a reset, and a reset would restore every deleted file. No re-export path captured it: `--scan` pruned the path from `filesAffected` and emitted no deletion hunk, `--scan-file` refused it outright, and **`--files` accepted the path and emitted no hunk** — the dangerous shape, because the run reported success while writing a patch that silently CLAIMED a file it did not restore. On a fresh clone that patch applies cleanly and resurrects exactly what the change meant to remove.
|
|
120
|
-
The cause was one conflation. All three paths filtered "absent from disk" out of the diff scope, on a comment asserting the diff "would fail" on a missing path — true only for a path that was NEVER TRACKED. For a tracked file deleted in the worktree, `git diff HEAD -- <path>` emits a proper `deleted file mode` section, and every downstream consumer already branches on `isDeletedFile`. The two cases are now split by `listTrackedInHead`: a tracked absent path stays in the diff scope and is captured, an untracked one is refused rather than warned about, since the patch cannot express it either way. A captured deletion KEEPS its `filesAffected` entry — the patch is what performs the deletion, so pruning it would leave the body deleting a file the manifest says the patch has nothing to do with — and it still requires the confirmation, because the patch will now remove those files wherever it is applied.
|
|
121
|
-
The report's priority-1 item — make the silent success LOUD — turned out to need two words, not a feature: the `--files` path already refused when a requested path produced no hunk, but its domain was the post-filter subset, so anything dropped upstream was invisible to the check by construction. It now runs against the full requested list. A real-git test asserts the emitted patch contains `deleted file mode`; it fails on the old implementation.
|
|
122
|
-
Recorded because the report says otherwise and the next reader should not chase it: **`export` was never affected.** It accepts a `D` status from `getStatusWithCodes` and routes a HEAD-tracked path to `git diff --binary HEAD`, which has always carried the deletion. Only the batched `re-export` paths dropped it.
|
|
123
|
-
- **`token add --mode override` silently skipped a QUALIFIED `[data-theme="light"]` block.** The override path mirrors into both `:root[data-theme="dark"]` and `:root[data-theme="light"]`, guarded by `variantBlockExists` — and that guard compared canonically against a fragment sliced to the LAST `]` before the opening brace. For `:root[data-theme="light"]:not([data-private]) { }` the last `]` is the one inside `:not(…)`, so the computed fragment was `:root[data-theme="light"]:not([data-private]` and the comparison could never match. The unqualified dark block beside it matched fine. That asymmetry was the whole bug: the override wrote dark, skipped light, and said nothing — so a Light choice under a dark OS inherited the new dark token, and the operator met the gap as a theme bug rather than as tool output. `THEME_ATTRIBUTE_VARIANTS`' own doc comment names the failure this feature exists to prevent — "a guaranteed half-finished edit" — and the half-finished edit is what shipped.
|
|
124
|
-
The last-`]` slice was deliberate, not sloppy: it avoids a `js/polynomial-redos` regex, and taking the last `]` rather than the first keeps a multi-attribute selector comparing as a whole instead of colliding with a single-attribute variant that is its prefix. Both properties survive. The selector is now parsed structurally — consume consecutive `[…]` groups after `:root`, stop at the first character that is not `[` — which is still linear and still matches multi-attribute blocks whole, but excludes a pseudo-class tail instead of swallowing it. A regression test uses a two-attribute block to pin that.
|
|
125
|
-
The qualifier is reported rather than applied silently. `:not([data-private])` is semantically load-bearing — writing through it narrows where the declaration applies, and that may not be what the operator meant — but matching it is still the right call, because silently skipping it is the worse failure and the one that shipped. So the write happens and a warning names the selector it went through. The pinning test fails on the old matcher.
|
|
126
|
-
- **`token add --variant` required a flag that described nothing, rejected its companion, and reported a no-op as success.** Three separate frictions, all in the variant path. `--category` was an unconditional `requiredOption` that had to name a REAL category even under `--variant`, where the declaration is routed into a `:root<selector>` block and never into a category section — the requirement existed so the argument would not be "silently discarded", a fair goal whose effect was a mandatory argument saying nothing about where the token lands. It is now optional there (still validated when supplied, so a typo is not accepted just because the flag is inert), and its absence on a BASE declaration is refused with the REASON stated rather than commander's bare "required option not specified".
|
|
127
|
-
`--create-category` is still rejected with `--variant` — the two really are incompatible — but the working create-then-variant order (author the category with the base token, then add each variant) was discoverable only by failing twice. It is now in both the error and `--variant`'s help text.
|
|
128
|
-
And a token already present in the target variant block was skipped with a bare `{ added: false }`, so a re-run intending to CHANGE a value exited 0 having changed nothing, while the base path had been reporting the category and line for the same situation all along. The variant path now returns the location too, and the skip reads `already exists in :root[…] (line N), unchanged` — the block being the location, since a variant declaration has no category to name.
|
|
129
|
-
- **The CC0 public-domain dedication Mozilla puts on its test files was not a recognized license header.** `containsUpstreamLicenseText` knew MPL, Apache, MIT, GPL and a bare SPDX tag; nothing knew `Any copyright is dedicated to the Public Domain. http://creativecommons.org/publicdomain/zero/1.0/`. A modified upstream test whose notice was UNCHANGED therefore warned `modified-file-missing-header`, and the downstream workaround — two identifier-only edits, an `SPDX-License-Identifier: CC0-1.0` line above each untouched notice on patch 905 — was editing Mozilla's notice to satisfy FireForge's recognizer. Worse than filed: `hasThirdPartyPermissiveBanner` did not know it either, so a NEW file copied from the upstream test tree was neither "acceptable" nor "vendored", and `export -y` would have prepended the PROJECT's license header onto code Mozilla dedicated to the public domain — precisely the mislicensing the vendored carve-out (0.38.0) exists to prevent.
|
|
130
|
-
Both predicates now recognize the dedication in every spelling the tree carries — the prose, the `creativecommons.org/publicdomain/zero/1.0/` URL with either scheme, and the `CC0-1.0` SPDX identifier — through one shared matcher, so the two cannot drift. Deliberately narrow, with the negative controls pinned: a different Creative Commons license (`licenses/by/4.0/`, `CC-BY-4.0`), a made-up `publicdomain/zero/2.0/`, a bare "public domain" mention, and a dedication below the scanned head are all still refused.
|
|
159
|
+
- The failure-line classifier no longer matches the English word "assertion" or `TEST-KNOWN-FAIL`. Both arms are harness-shaped and case-sensitive now. A green run could previously be turned red by its own diagnostic.
|
|
160
|
+
- `fireforge test --build` accepts `--refuse-unexported-drift` and forwards it to the pre-test build. It is refused without `--build`.
|
|
161
|
+
- A `--wait-lock` waiter no longer gets a free extension on its first probe, so a stalled queue starves on exactly the budget asked for.
|
|
162
|
+
- `re-export` no longer rewrites a tracked binary patch into an un-appliable stub. `--binary` now covers every diff path, a new `binary-body-not-reconstructable` lint fails closed on a payload-less binary section, and classification no longer trusts a stub's index hash.
|
|
163
|
+
- `re-export` reports `Unchanged` for a patch whose body did not move, and does not rewrite the file.
|
|
164
|
+
- `fireforge test --doctor` no longer orphans a browser tree on Ctrl+C.
|
|
165
|
+
- Failures during a patch-queue mutation keep their own class, stack, and exit code instead of all rendering as a patch-compatibility problem.
|
|
166
|
+
- Esc or Ctrl+C at a confirmation exits 130. Answering "no" exits 0.
|
|
167
|
+
- `furnace validate` checks that the engine exists.
|
|
168
|
+
- `furnace create` escapes quotes, newlines, and `*/` in generated modules.
|
|
169
|
+
- The signal-time furnace lock sweeper checks ownership before removing a lock.
|
|
170
|
+
- `killProcessTree` falls through to a direct kill when the group kill fails.
|
|
171
|
+
- A deletion of an upstream file can now be captured through `re-export`. All three paths filtered absent files out of the diff scope; a tracked absent path is kept and produces a real `deleted file mode` section. `--files` refuses against the full requested list, so a path that produces no hunk is reported.
|
|
172
|
+
- `token add --mode override` writes qualified blocks such as `:root[data-theme="light"]:not([data-private])`. It used to write dark and silently skip light. The selector is parsed structurally, and the qualifier is reported in a warning.
|
|
173
|
+
- `token add --variant` no longer requires `--category`, explains the create-then-variant order, and reports an already-present token with its location instead of a silent no-op.
|
|
174
|
+
- Mozilla's CC0 dedication is recognised as a license header in both the modified-file and vendored-file checks. Without it, `export -y` would have prepended the project header onto public-domain code.
|
|
131
175
|
|
|
132
176
|
### Security
|
|
133
177
|
|
|
134
|
-
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
- The variant scanner's replacement deliberately spans to the LAST `]` before the opening brace rather than the first. Taking the first would have been the shorter fix and a silent behaviour change: `:root[data-skin=precision][data-private]` would then satisfy a request for the `[data-skin=precision]` variant it merely starts with, and the declaration would land in the wrong block. A test pins that, and it passes on both implementations — which is the point of it.
|
|
138
|
-
- The regression tests assert wall-clock, because the defect IS a running time; every one of these calls returns the same answer before and after. Each witness fails the old implementation by an order of magnitude or more, and the whole file now runs in ~26 ms.
|
|
139
|
-
- **The prototype-chain guard on `config <key> <value> --force` was correct and invisible** (`js/prototype-pollution-utility`). `mutateConfig` rejected `__proto__`, `constructor` and `prototype` — but once, up front, in a helper, against a `Set`; the descent and the leaf assignment two dozen lines below therefore read as unguarded to anything that is not interprocedural, CodeQL included. The check now happens at the point each segment is USED as a property name, spelled as explicit comparisons, with only the message factored out. That is not just to satisfy the query: a guard that lives at a distance from its write is one refactor of its caller away from being skipped, and the existing tests keep passing untouched because nothing about the behaviour moved.
|
|
140
|
-
- **Two `replace` calls read as incomplete escaping** (`js/incomplete-sanitization`), and both were in fact correct — which is exactly why they are rewritten rather than dismissed, since "correct, trust me" is not a property a scanner can re-derive next quarter. `patch-lint-checkjs` substituted a TypeScript `paths` wildcard with `target.replace('*', captured)`; a target carries at most one `*` and first-occurrence replacement IS the contract, now spelled as index arithmetic mirroring the prefix/suffix split already used on the pattern side, with a test pinning both the wildcard and wildcard-free target shapes. The pack smoke test hand-escaped a version string with `.replace(/\./g, '\\.')`; it now uses `escapeRegex` from `src/utils/regex.ts`, the helper ~40 other call sites already use.
|
|
178
|
+
- Six `tokens.css` scanners were super-linear in the length of a single line. One took 8.2 s on 4,000 repeated characters. Fixed by removing ambiguous adjacent quantifiers and anchoring unanchored prefixes; four became index arithmetic. Regression tests assert wall-clock, and the file now runs in about 26 ms.
|
|
179
|
+
- The prototype-chain guard on `config --force` moved to the point each segment is used as a property name.
|
|
180
|
+
- Two `replace` calls that read as incomplete escaping were rewritten as index arithmetic and the shared `escapeRegex`.
|
|
141
181
|
|
|
142
182
|
### Manifest repair
|
|
143
183
|
|
|
144
|
-
-
|
|
145
|
-
-
|
|
146
|
-
-
|
|
147
|
-
-
|
|
148
|
-
- **Two of the report's claims do not hold against this code, and are recorded rather than "fixed".** `lintIgnore`, `tier`, `description`, `category`, `createdAt` and `sourceEsrVersion` were all already preserved on an existing entry — the rebuild has been a merge, not a from-scratch rebuild, since the branding tier landed. Most of the 1823 deletions were `filesAffected` lists being re-sorted (the rebuild normalises them; the narrow repair does too, but only on rows that were already wrong) plus the `stagedDependencies` blocks above. And the three binary-asset patches the report flagged as possible mismatches were an artifact of its own scan: `getAllTargetFilesFromPatch` reads `diff --git` headers, so `GIT binary patch` sections with no `+++ b/` line have been counted correctly since the fix that put them there. Naming what the code actually does is how the next occurrence gets attributed quickly instead of inheriting a guess.
|
|
184
|
+
- `doctor --repair-patches-manifest` no longer drops `stagedDependencies`. The row is built by spreading the existing entry and overriding only `filesAffected` and `order`, so any future field survives too.
|
|
185
|
+
- An unparseable `patches.json` is no longer rebuilt into an invented one. Doctor refuses, names the parse error, and requires `--allow-metadata-loss`.
|
|
186
|
+
- Doctor prints what it wrote before the summary, including on a failing run.
|
|
187
|
+
- New narrow `doctor --repair-files-affected` recomputes only the drifted lists. Both repairs gained `--dry-run`.
|
|
149
188
|
|
|
150
189
|
### Performance
|
|
151
190
|
|
|
152
|
-
-
|
|
153
|
-
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
-
|
|
161
|
-
-
|
|
162
|
-
-
|
|
163
|
-
-
|
|
164
|
-
- `
|
|
165
|
-
- Two content-equality policies were split across five comparison sites, so on a CRLF checkout `furnace status` and `furnace validate` could report drift for files `apply` had just decided were identical. `normalizeForChecksum` moved to `furnace-checksum-utils.ts` and all five use it.
|
|
166
|
-
- The four manifest registrars each carried their own copy of the insert sequence. The two jar.mn ones (browser content, shared CSS) were byte-identical apart from a sort regex, a sort key and a refusal message; the two moz.build ones likewise. They route through `insertJarMnEntry` and `insertMozBuildListEntry` now — deliberately two family-specific helpers rather than one generic pair, because `after` and the section concept are meaningless on the moz.build side, and because `tokenizeMozBuildList` **mutates the line array in place** when it normalizes `FOO += []` into the multi-line form. That rewrite is what makes the caller's splice land inside the list body, so a wrapper tokenizing a copy would have silently reintroduced a fixed bug.
|
|
167
|
-
- `registerToolkitWidget` was the one jar.mn target still hand-scanning lines with its own section-bounds and sort-key regexes, so it never inherited fixes made to the shared tokenizer path. It uses the same helper as its three siblings now. The dead `findAlphabeticalPosition` (its last caller) went with it, and `findAlphabeticalTokenPosition` became module-private.
|
|
168
|
-
- `WIDGETS_DIR` moved out of `furnace-scanner.ts`; the seven-line `withParserFallback` rationale moved onto the shared predicate it explains (one of its three copies had already drifted); 18 open-coded `process.stdin.isTTY && process.stdout.isTTY` checks became `stdioIsInteractive()`.
|
|
169
|
-
|
|
170
|
-
### Structure
|
|
171
|
-
|
|
172
|
-
- `src/commands/doctor/` held a single file while six `doctor-*` siblings sat flat; it moved up to `doctor-post-rebase-audit.ts`, turning its lone `../doctor-check-core.js` reach-back into `./`.
|
|
173
|
-
- `furnace-validate-helpers.ts` was a 572-line spill file with three disjoint subjects and 18 of its 19 exports having exactly one consumer each. Each block moved to the validator that uses it; the module is now 20 lines holding the one export that genuinely had two consumers. **knip then revealed 16 of those exports as module-private** — they had only been exported to cross a boundary that no longer exists.
|
|
174
|
-
- Four ambiguous `manifest-*.ts` modules became `moz-manifest-*.ts` — "manifest" named both `patches.json` and Firefox build files — and `register-test-manifest.ts` became `register-browser-test.ts` so it reads as a `register-*` leaf. `lint-cache.ts` and `lint-projection.ts` joined the `patch-lint-*` family they belong to. The `register-*` family was deliberately left alone: `register-` names the `fireforge register` command those modules implement.
|
|
175
|
-
- The `Furnace manifest sync` doctor check does not look at a manifest — it compares component directories on disk against `furnace.json`. In a codebase where "manifest" already names `patches.json` and Firefox build files, that made the one referent visible to operators the most misleading one. Check, module and symbol are now `Furnace config sync`.
|
|
176
|
-
- Four modules reached for the same two drift predicates through two different paths — `furnace-apply-helpers.js` in two, the `furnace-apply.js` compat barrel in the others. They all use the defining module now, and the three names nothing else re-exported came off the barrel. The direction matters: `furnace-apply.ts` is 650 lines against a 500-line cap, and routing a consumer through it drags the whole apply graph into every suite that mocks it — which is exactly how the first attempt at this cleanup broke seven doctor tests, whose exhaustive `vi.mock` factory for the barrel listed one export. `mach.ts`'s re-export block now carries a comment saying it is a frozen compatibility list, not a barrel to grow.
|
|
177
|
-
- Dead exports deleted: `applyPatches`/`validatePatches` (superseded by `applyPatchesWithContinue`), six unused `platform.ts` helpers, `hasActiveRebaseSession` (every reference was a test using it as an assertion helper), `peekParserFallbackEvents`. knip could not see any of them, because tests count as consumers.
|
|
178
|
-
- Fifteen `await import()` calls became static imports. `patch-export.ts`'s `await import('./patch-manifest.js')` was the notable one: tracing the static graph showed no cycle, so the laziness bought nothing and hid a real edge from the `dpdm` gate — which still reports no cycles after the change.
|
|
191
|
+
- `getAllDiff` batches its `git hash-object` calls instead of one spawn per untracked file. Output bytes are unchanged and now pinned by a test.
|
|
192
|
+
- `last-build.json` carries content hashes for dirty `jar.mn`, `moz.build`, `moz.configure`, `Makefile.in`, and `mozbuild.in`, so a permanently dirty worktree stops escalating every build to a full one and re-running configure. `build --ui` records which kind of build it was.
|
|
193
|
+
|
|
194
|
+
### Cleanup
|
|
195
|
+
|
|
196
|
+
- The engine-precondition refusal was written out 15 times across 13 files; it is now `assertEngineGitReady` or `assertEngineExists`.
|
|
197
|
+
- The furnace two-rung ladder, the 15-line rollback catch, the four manifest registrars, and five legacy scanners all collapsed to shared helpers.
|
|
198
|
+
- `bootstrap.ts` uses the canonical bootstrap-issue scanner instead of a second copy whose regexes had drifted.
|
|
199
|
+
- Content-equality now goes through one `normalizeForChecksum`, so `furnace status` and `furnace validate` cannot disagree with `apply` on a CRLF checkout.
|
|
200
|
+
- 18 open-coded TTY checks became `stdioIsInteractive()`.
|
|
201
|
+
- Modules renamed for clarity: four `manifest-*.ts` became `moz-manifest-*.ts`, the `Furnace manifest sync` check became `Furnace config sync`, and the lint modules joined the `patch-lint-*` family.
|
|
202
|
+
- `furnace-validate-helpers.ts` was a 572-line spill file; each block moved to the validator that uses it and 16 exports turned out to be module-private.
|
|
203
|
+
- Fifteen `await import()` calls became static imports.
|
|
179
204
|
|
|
180
205
|
### Types
|
|
181
206
|
|
|
182
|
-
-
|
|
183
|
-
-
|
|
184
|
-
-
|
|
185
|
-
-
|
|
186
|
-
- `lintExportedPatch`
|
|
187
|
-
-
|
|
188
|
-
-
|
|
189
|
-
- **Nothing at the CLI boundary ever read an error's `cause`.** Nine classes declare one and 22 throw sites pass one, but a `FireForgeError` rendered as its `userMessage` and stopped, so the underlying git stderr or errno never reached the operator; `download.ts` had hand-rolled the rendering four times to make its own "--verbose for the underlying error" promise true. The boundary now walks the chain under `--verbose`.
|
|
207
|
+
- `DoctorCheck` encoded one ternary result in three fields. `severity` is now required and the only field.
|
|
208
|
+
- Three string unions are derived from their member lists through `makeEnumGuard`, so a stale allowlist is a compile error.
|
|
209
|
+
- `src/index.ts` no longer publishes 32 unreachable types, and gained `ApplyAllComponentsResult`.
|
|
210
|
+
- The per-component apply helpers take `Pick<ComponentApplyContext, …>` instead of four interchangeable strings in three different orders.
|
|
211
|
+
- `lintExportedPatch` takes its optional arguments in an options object.
|
|
212
|
+
- Twelve runtime flag checks raise `InvalidArgumentError` (exit 8) like the other 191.
|
|
213
|
+
- The CLI boundary walks the error `cause` chain under `--verbose`.
|
|
190
214
|
|
|
191
215
|
### CLI
|
|
192
216
|
|
|
193
|
-
-
|
|
194
|
-
- `import` and `setup` accept `-y, --yes`. On `
|
|
195
|
-
-
|
|
196
|
-
-
|
|
197
|
-
- `
|
|
198
|
-
-
|
|
199
|
-
The validator now runs the MATCHER'S parse and requires it to consume the whole fragment, rather than carrying a second grammar that can drift from the first again. Character safety stays a separate check, because that parse finds bracket boundaries and validates no characters at all — it is applied one bracket group at a time rather than as a repeated pattern, which is the shape that backtracks (`js/polynomial-redos`), and a linearity test pins that alongside the matcher's own. Normalization to `="value"` now covers every fragment in a run and the `:not(…)` argument, not just a trailing one.
|
|
200
|
-
`findVariantBlock` had to move with it: it compared a request against a block's ATTRIBUTE run only, so a variant carrying its own qualifier would have matched nothing and spliced a fresh duplicate block on every add. Request and candidate go through the same parse and are compared tail-to-tail. An UNqualified request still matches a qualified block — that is the 0.44.2 behaviour `variantBlockQualifier` exists to report out loud, since silently skipping the block is the worse failure — but a request that names a qualifier means it.
|
|
201
|
-
- `tree list --json` gained the failure envelope `status --json` already emitted, so a scripted consumer no longer gets a parseable refusal from one and a bare non-zero exit from the other. The contract is written down in `docs/machine-output.md`.
|
|
217
|
+
- `patch tier`, `patch lint-ignore`, and `patch staged-dependency` honour `--wait-lock` instead of claiming they take no lock. All seven patch-directory commands honour it now.
|
|
218
|
+
- `import` and `setup` accept `-y, --yes`. On `import` it waives the prompt but keeps the integrity gate armed.
|
|
219
|
+
- `test --doctor` prints its preflight line once.
|
|
220
|
+
- `status --json` outside a project writes one JSON envelope to stdout and the guidance to stderr.
|
|
221
|
+
- `token add --variant` accepts every selector the matcher can find, using the matcher's own parse rather than a second grammar.
|
|
222
|
+
- `tree list --json` emits the same failure envelope as `status --json`.
|
|
202
223
|
|
|
203
224
|
### More correctness
|
|
204
225
|
|
|
205
|
-
-
|
|
206
|
-
-
|
|
207
|
-
- `RebasePatchEntry`
|
|
208
|
-
-
|
|
209
|
-
-
|
|
210
|
-
- **`furnace create --test-dir` was honoured by the scaffolder and ignored by everything that told the operator where the files went.** `create.ts` resolved the override once and passed it to the scaffolders, but `formatDryRunPlan` and `formatSuccessNote` received only `binaryName` and recomputed the DEFAULT from it — so `--dry-run` planned `test/hominis/` plus `hominis/browser.toml` in `moz.build` for a command that would write to `test/hominis-tiles/`, and the success note after the real run named `hominis/` while the files sat in `hominis-tiles/`. The one message an operator gets as confirmation was the one thing that could not be trusted. Both formatters now take the resolved directory, and the default lives in one place: `resolveBrowserChromeTestDir` / `resolveXpcshellTestDir` in `furnace-constants.ts`, called by the scaffolders AND the formatters, so the two cannot disagree again. The moz.build registration line follows the override too (it is the path below `browser/base/content/test/`, which under `--test-dir` is not the binary name), and a test scaffolds for real and asserts the printed directory is the one on disk — default and overridden, browser-chrome and xpcshell.
|
|
226
|
+
- `furnace create`'s tag prompt shows the rule inline instead of dying on a typo. The message-returning validators are now named `describe*Problem`.
|
|
227
|
+
- `register --after` says so when a file type cannot honour it, instead of ignoring the flag.
|
|
228
|
+
- `RebasePatchEntry` is a discriminated union, so a status flip cannot strand the previous status's payload. Older session files still load.
|
|
229
|
+
- A `patches.json` from a newer FireForge is refused by name instead of being reported as malformed.
|
|
230
|
+
- `furnace create --test-dir` is honoured by the dry-run plan and the success note, not just the scaffolder.
|
|
211
231
|
|
|
212
232
|
### Windows
|
|
213
233
|
|
|
214
|
-
-
|
|
215
|
-
-
|
|
216
|
-
-
|
|
217
|
-
-
|
|
218
|
-
-
|
|
219
|
-
-
|
|
220
|
-
-
|
|
221
|
-
|
|
222
|
-
On the test side: path expectations and mock keys are rendered through a new `nativePath()` test helper rather than hard-coded POSIX literals; fixture repos pin `core.autocrlf=false` / `core.eol=lf`; the three modules that branch on `process.platform` directly now have that branch forced rather than inherited from the runner; and the doctor summary count is derived rather than pinned at 16, since the orphaned-harness check is `skipIf` win32. The genuinely POSIX-only suites — `tree`, `tree exec`, `run --smoke-exit`, and the `chmod`-as-refusal tests — are skipped explicitly, and each skip is paired with a new platform-stubbed test that pins the win32 refusal itself, which nothing did before.
|
|
223
|
-
|
|
224
|
-
`nativePath()` turned out to be the wrong tool for part of that job, and applying it uniformly produced failures of its own. It swaps separators only, which is correct for a value the code built with `join` but wrong for one it passed through `resolve`: on Windows `resolve` also prefixes the current drive, so the expectation has to be `D:\project\x`, not `\project\x`. A sibling `nativeAbsPath()` covers that case, and the assertions that were wrapped despite never touching a separator at all — pure suffix concatenation, a pass-through argument, and a suite whose `getProjectPaths` mock returns POSIX literals on every platform — go back to comparing the literal. Four doctor summary assertions had also kept their POSIX counts inline while the clean-run count next to them was already derived, so the derivation now covers every summary line in the suite. Two more `chmod`-as-refusal tests joined the skip list: they were skipped for `root` but not for Windows, where mode bits are ignored outright, so the "unreadable" setup was a no-op and the code correctly reported success.
|
|
234
|
+
- `fireforge lint`'s checkJs pass reported zero findings, silently: the path maps were keyed with backslashes while TypeScript hands out forward slashes. `typecheck` had the same defect.
|
|
235
|
+
- `furnace diff` reported every overridden file as new, because `git show ref:path` only understands forward slashes.
|
|
236
|
+
- Engine-relative paths were recorded in two spellings at once; normalised at the five producing sites.
|
|
237
|
+
- `build-audit` collapsed to one path segment, `removeTree` refused every removal, and `initRepository` never pinned `core.autocrlf`, which shifted every blob hash.
|
|
238
|
+
- `furnace init` accepted `--ftl-base-path ../escape/path`, because the traversal guard normalised to backslashes before testing for `../`.
|
|
239
|
+
- `furnace` jsconfig sync did nothing and reported a clean summary while doing it.
|
|
240
|
+
- On the test side: path expectations go through `nativePath()` and `nativeAbsPath()`, fixture repos pin `core.autocrlf=false`, platform branches are forced rather than inherited, and POSIX-only suites are skipped explicitly with a paired win32 refusal test.
|
|
225
241
|
|
|
226
242
|
### Test infrastructure
|
|
227
243
|
|
|
228
|
-
-
|
|
229
|
-
|
|
230
|
-
-
|
|
231
|
-
|
|
232
|
-
- Five rollback tests moved from asserting a module-level spy to asserting the persisted pending-repair marker. The spy stopped working when the sequence moved into `completeJournalRollback` (its call to the recorder is intra-module), and the outcome is the better assertion anyway.
|
|
233
|
-
- **Fourteen verdict assertions passed only because writing to a filesystem root fails.** The command suites pass `/project` as the project root and assert the `FIREFORGE-VERDICT:` line by exact string — which holds only while no run log is open, since the line carries an open log's path as a ` log=<path>` key. On POSIX `mkdir('/project/.fireforge/logs')` fails at the root, the best-effort open degrades to "no log", and the assertions passed for a reason none of them stated. On Windows the same path resolves against the CURRENT DRIVE, the mkdir succeeds, and all fourteen failed — while the run also created real `C:\project\.fireforge\logs` directories on the runner. `createRunLogMock()` joins the two factories in `module-mocks.ts` and the five suites state the precondition instead of inheriting it from a permission error. Because mocking the module away removes the suffix's only coverage, `test-verdict.test.ts` gains the opposite assertion: with a log open, the path rides the line, once, as the run's last stdout write.
|
|
234
|
-
- **A lock-wait test decided its result on a `readdir`.** `a wait whose queue position keeps improving > survives a drain longer than its budget` runs on real timers and a real filesystem, and gave each probe about 20 ms of slack inside a 100 ms budget; it also retired its simulated queue with un-awaited `rm` calls, so a retirement could land after the probe meant to observe it and a release could leave `mkdir` seeing `EEXIST` past the intended free. On a Windows runner the second probe missed the deadline, no extension was ever granted, and the wait expired still three from the head — the exact refusal the test exists to prove does NOT happen. The retirement and release are synchronous now (the callback returns `void` and cannot await), and the constants are scaled to ~100 ms of slack per probe while keeping the two invariants that fix them: the budget must span two probes, and the drain must outlast the budget or the sibling test would acquire instead of expiring. No production change — `withFileLock` checking its deadline before probing is correct, since a wait must not extend itself on a probe taken after it expired.
|
|
235
|
-
- `git-readonly-index.test.ts` carried a latent racy-clean flake: it edited `const b = 2;` to `const b = 3;` — the same byte length, within the same second as the index entry — without invalidating the stat cache, so git could report the file unmodified. Its sibling test already guarded for this.
|
|
244
|
+
- `createLoggerMock()` and `createFsMock()` replace hand-rolled `vi.mock` factories at 110 sites. Each old factory listed a subset of the real module, so adding an export broke a hundred suites at once. The new ones are typed, so `tsc` reports a missing export in one file.
|
|
245
|
+
- `test.test.ts` was 2,943 lines held together by a 190-line mock header. The header moved to `test-command-mocks.ts` and the file split into six. The split exposed a real isolation bug in a Marionette preflight test.
|
|
246
|
+
- Fourteen verdict assertions passed only because writing to a filesystem root fails on POSIX. They state the precondition now via `createRunLogMock()`.
|
|
247
|
+
- A lock-wait test decided its result on a `readdir`; its retirement and release are synchronous and its timing constants scaled.
|
|
236
248
|
|
|
237
249
|
### Documentation
|
|
238
250
|
|
|
239
|
-
-
|
|
240
|
-
-
|
|
241
|
-
-
|
|
242
|
-
-
|
|
243
|
-
-
|
|
251
|
+
- README's reference material moved to `docs/`, split by task: `patch-workflow.md`, `testing.md`, `furnace.md`, `verification-trees.md`, `configuration.md`, with `docs/README.md` as the index.
|
|
252
|
+
- New `docs/run-logs.md` states the `.fireforge/logs/` contract.
|
|
253
|
+
- `machine-output.md` and `lifecycle-invariants.md` were stale against the code and now match it.
|
|
254
|
+
- The published package ships `docs/`, so the README's relative links resolve after install. A smoke test asserts the tree is packed.
|
|
255
|
+
- The four environment variables FireForge reads are tabulated in `configuration.md`.
|
|
244
256
|
|
|
245
257
|
## 0.43.0
|
|
246
258
|
|
|
247
259
|
### Verdict correctness
|
|
248
260
|
|
|
249
|
-
- A suite that ends clean
|
|
250
|
-
- `engine/mozconfig` is written only when
|
|
251
|
-
-
|
|
261
|
+
- A suite that ends clean and then dies in the known mozsystemmonitor teardown traceback is a PASS with a note. Every hard-evidence veto still fails the run.
|
|
262
|
+
- `engine/mozconfig` is written only when its content changes, so mach stops re-running configure on every invocation. Consumers who raised hang-canary bounds for this can restore them.
|
|
263
|
+
- `verify`, `lint --per-patch`, and `typecheck` no longer write the primary engine checkout. They run git plumbing against a private `GIT_INDEX_FILE`, so they stop tripping a concurrent test run's inconclusive refusal.
|
|
252
264
|
|
|
253
265
|
### Diagnostics
|
|
254
266
|
|
|
255
|
-
- An xpcshell
|
|
256
|
-
- `fireforge verify`
|
|
257
|
-
-
|
|
258
|
-
- FireForge's own escalation
|
|
267
|
+
- An xpcshell SIGSEGV with no test evidence names its known cause: an `.sys.mjs` imported from a packaged module with no `EXTRA_JS_MODULES` registration.
|
|
268
|
+
- `fireforge verify` resolves every `resource://` specifier the queue-owned modules import, including lazy `defineESModuleGetters` ones, and names unregistered targets.
|
|
269
|
+
- A headed stall probes the display power state on macOS and reports it, and lists the three recorded causes of that signature. The old `caffeinate` advice was wrong: it prevents sleep, it cannot wake a display.
|
|
270
|
+
- FireForge's own escalation notices carry a `[FireForge] NOTICE:` prefix at warning severity, so agent output filters keep them.
|
|
259
271
|
|
|
260
272
|
### Messages and refusals
|
|
261
273
|
|
|
262
|
-
- The stale-build refusal suggests `--build` first and
|
|
263
|
-
- `--refuse-foreign-drift`
|
|
264
|
-
-
|
|
265
|
-
-
|
|
266
|
-
- `patch move-files --create`, `patch move-files`, and `patch split` refuse a prompt-less non-TTY run **up front**, naming `--yes`, instead of after minutes of diff and projected-lint work.
|
|
274
|
+
- The stale-build refusal suggests `--build` first and says plainly what `--allow-stale-build` accepts.
|
|
275
|
+
- `--refuse-foreign-drift` stops calling the operator's own additions foreign, and tags each file by whether it changed since their last export.
|
|
276
|
+
- Unknown patch identifiers suggest the nearest matches instead of printing the whole manifest.
|
|
277
|
+
- `patch move-files` and `patch split` refuse a prompt-less non-TTY run up front, naming `--yes`.
|
|
267
278
|
|
|
268
279
|
### Features
|
|
269
280
|
|
|
270
|
-
- `--wait-lock` is accepted by every command. Lock-
|
|
271
|
-
- `
|
|
272
|
-
- An export refused by projected cross-patch lint
|
|
273
|
-
- `fireforge typecheck` runs the per-patch checkJs pass
|
|
274
|
-
- The per-patch lint cache records the
|
|
275
|
-
-
|
|
281
|
+
- `--wait-lock` is accepted by every command. Lock-free commands accept and ignore it and say so.
|
|
282
|
+
- `status --lock` reports the engine session lock without acquiring it: holder, command, hold time, liveness, and queue depth. The wait progress line now states queue position.
|
|
283
|
+
- An export refused by projected cross-patch lint prints the working adopt-then-split sequence with real arguments.
|
|
284
|
+
- `fireforge typecheck` runs the per-patch checkJs pass, so a green typecheck means export-clean types.
|
|
285
|
+
- The per-patch lint cache records the waiver set that produced each entry and refuses a replay under a different one.
|
|
286
|
+
- Internal invariants are checked at runtime and exit 11 with a stack trace. Nothing an operator can misconfigure reaches this path.
|
|
276
287
|
|
|
277
288
|
### Hardening
|
|
278
289
|
|
|
279
|
-
- `build-prepare` warns
|
|
280
|
-
-
|
|
281
|
-
-
|
|
290
|
+
- `build-prepare` warns before overwriting engine content matching neither a patch body nor the baseline, and `build --refuse-unexported-drift` makes it a hard stop.
|
|
291
|
+
- A furnace mutation that throws now rolls back the engine, not just one that is interrupted. A rollback that itself fails leaves a `pendingRepair` marker and keeps the original error.
|
|
292
|
+
- The unexported-drift guard expands collapsed untracked directories, so it stops false-positiving on any wholly-untracked directory. It and `status --unmanaged` now answer about the same tree.
|
|
282
293
|
|
|
283
294
|
### Release hygiene
|
|
284
295
|
|
|
285
|
-
- The composed macOS bundle identity is
|
|
296
|
+
- The composed macOS bundle identity is pinned end to end: `MOZ_MACBUNDLE_ID` plus `--with-distribution-id` must equal the configured `appId`.
|
|
286
297
|
|
|
287
298
|
## 0.42.0
|
|
288
299
|
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
- `MOZ_MACBUNDLE_ID` in the generated branding `configure.sh` now carries only the LEAF segment of `appId`, and the generated mozconfig emits `ac_add_options --with-distribution-id=<appId prefix>` — upstream `toolkit/moz.configure` composes `CFBundleIdentifier` as `<distribution-id>.<MOZ_MACBUNDLE_ID>`, so writing the full reverse-domain `appId` double-prefixed the shipped bundle id (observed: `org.mozilla.org.hominis.browser`). A `configure.sh` carrying the full `appId` now reads as stale and is rewritten.
|
|
300
|
+
- `MOZ_MACBUNDLE_ID` carries only the leaf segment of `appId`, and the mozconfig emits `--with-distribution-id=<prefix>`. Upstream composes the two, so writing the full reverse-domain name double-prefixed the shipped bundle id.
|
|
292
301
|
|
|
293
302
|
## 0.41.0
|
|
294
303
|
|
|
295
304
|
### Release and build integrity
|
|
296
305
|
|
|
297
|
-
- Release publishing commits version bumps before building and enforces a clean tree
|
|
298
|
-
- Builds stamp `dist/build-info.json`;
|
|
299
|
-
- Build baselines
|
|
300
|
-
- `test --build` uses a full build for new `jar.mn` registrations
|
|
301
|
-
- `--extend-coverage` unions scoped
|
|
302
|
-
- Shared build and engine preflights
|
|
306
|
+
- Release publishing commits version bumps before building and enforces a clean tree.
|
|
307
|
+
- Builds stamp `dist/build-info.json`; `--version` includes the commit and dirty-content hash.
|
|
308
|
+
- Build baselines keep deletion tombstones, so removed files cannot look fresh.
|
|
309
|
+
- `test --build` uses a full build for new `jar.mn` registrations.
|
|
310
|
+
- `--extend-coverage` unions scoped coverage only while HEAD, packageable inputs, and mozconfig are unchanged.
|
|
311
|
+
- Shared build and engine preflights reject incomplete builds and unborn engine repositories consistently.
|
|
303
312
|
|
|
304
313
|
### Tests and verification trees
|
|
305
314
|
|
|
306
|
-
- Tests emit exactly one final `FIREFORGE-VERDICT:` line with the
|
|
307
|
-
- `tree exec` preserves the child verdict as the
|
|
308
|
-
-
|
|
309
|
-
-
|
|
310
|
-
-
|
|
311
|
-
-
|
|
312
|
-
-
|
|
313
|
-
- Tree freshness covers dirty engine content and patch bodies.
|
|
314
|
-
- Tree creation skips unwanted `obj-*` directories before cloning and uses bounded concurrency.
|
|
315
|
-
- `tree create --wait-lock` now matches its lock-refusal guidance.
|
|
316
|
-
- Verification trees permit `re-export --dry-run`; mutating operations remain blocked.
|
|
317
|
-
- Test assertion lint now recognizes real assertion calls, and critical modules have explicit coverage floors.
|
|
315
|
+
- Tests emit exactly one final `FIREFORGE-VERDICT:` line with the right reason, including sharded, lock-timeout, crash, and inconclusive runs.
|
|
316
|
+
- `tree exec` preserves the child verdict as the last stdout line.
|
|
317
|
+
- Browser preflight detects stale apps from the same objdir even after they release Marionette.
|
|
318
|
+
- Mach commands use process groups and reap surviving descendants.
|
|
319
|
+
- `tree create --with-objdir` supports build-less tests, with relocation and reconfiguration checks.
|
|
320
|
+
- Tree creation refuses symlinked objdirs, cleans failed clones, and handles unreadable locks fail-closed.
|
|
321
|
+
- Verification trees permit `re-export --dry-run`; mutating operations stay blocked.
|
|
318
322
|
|
|
319
323
|
### Status and diagnostics
|
|
320
324
|
|
|
321
|
-
- Status classification reuses one patch context and
|
|
322
|
-
- `status --json --summary` returns counts and offenders without the
|
|
323
|
-
-
|
|
324
|
-
-
|
|
325
|
-
- Multi-owner files remain conflicts even when Furnace-managed or generated branding paths.
|
|
326
|
-
- Lock contention and unreadable/corrupt state now produce concise, accurate diagnostics.
|
|
325
|
+
- Status classification reuses one patch context and runs through a bounded pool.
|
|
326
|
+
- `status --json --summary` returns counts and offenders without the file payload; `--include-ownership` adds ownership without a second scan.
|
|
327
|
+
- JSON output drains fully through slow pipes, and machine-mode refusals go to stderr.
|
|
328
|
+
- Multi-owner files stay conflicts even when Furnace-managed or branding-generated.
|
|
327
329
|
|
|
328
330
|
### Patch, export, and lint workflow
|
|
329
331
|
|
|
330
|
-
- `export-all --exclude-furnace` keeps its
|
|
331
|
-
- `re-export --expect <path>` permits intended drift and reports paths skipped by earlier refusals
|
|
332
|
-
- Missing drift baselines fail closed, binary patches compare by content, and partial
|
|
333
|
-
-
|
|
334
|
-
-
|
|
335
|
-
-
|
|
336
|
-
- Patch lint rejects new imported system modules without a projected `moz.build` registration.
|
|
337
|
-
- The checkJs cache hashes both configurable shims.
|
|
338
|
-
- Export placement refusals print projected errors and identify renumbering consequences.
|
|
332
|
+
- `export-all --exclude-furnace` keeps its scope after license-header repair.
|
|
333
|
+
- `re-export --expect <path>` permits intended drift and reports paths skipped by earlier refusals.
|
|
334
|
+
- Missing drift baselines fail closed, binary patches compare by content, and partial re-exports exit non-zero.
|
|
335
|
+
- Re-export builds checkJs once per run and reuses the per-patch cache.
|
|
336
|
+
- Patch lint rejects new imported system modules with no projected `moz.build` registration.
|
|
337
|
+
- Export placement refusals print projected errors and name renumbering consequences.
|
|
339
338
|
- `patch rename` can recategorize and renumber atomically.
|
|
340
|
-
- `patch move-files` and `patch split` use whole-queue projection lint
|
|
341
|
-
-
|
|
342
|
-
- Queue-mutating patch commands support `--wait-lock` and avoid unsafe stale-lock advice.
|
|
343
|
-
- Staged-dependency declarations reject patch-name-shaped file arguments.
|
|
344
|
-
- `CommandError` passes through the top-level handler without duplicate or JSON-corrupting output.
|
|
339
|
+
- `patch move-files` and `patch split` use whole-queue projection lint.
|
|
340
|
+
- Queue-mutating patch commands support `--wait-lock`.
|
|
345
341
|
|
|
346
342
|
### Furnace and validation
|
|
347
343
|
|
|
348
344
|
- Furnace computes checksums once per apply and warns before overwriting divergent patch-owned files.
|
|
349
|
-
- Furnace jsconfig synchronization includes `register: false` components.
|
|
350
345
|
- Manifest-sync failures are visible, and repairs run under the Furnace lock.
|
|
351
346
|
- `furnace validate --fix` changes only reported components and detects missing custom-element registrations.
|
|
352
347
|
- Localization validation recognizes non-Latin text while exempting emoji and punctuation.
|
|
353
348
|
- `furnace rename` uses single-pass, boundary-aware substitutions.
|
|
354
|
-
- Rollback failures
|
|
355
|
-
- The reported no-change/apply-state disagreement was not reproducible and is regression-tested.
|
|
349
|
+
- Rollback failures leave repair breadcrumbs for `doctor --repair-furnace`.
|
|
356
350
|
|
|
357
351
|
### Safety, performance, and maintenance
|
|
358
352
|
|
|
359
353
|
- Nano ID 3.3.18 resolves a high-severity audit finding.
|
|
360
|
-
- Rebase loading distinguishes absent
|
|
361
|
-
- PID liveness treats `EPERM` as alive
|
|
362
|
-
- The moz.build parser handles comments, quoted brackets
|
|
363
|
-
- Parser failures no longer silently certify validation success
|
|
364
|
-
- Toolchain probes, baseline fingerprints,
|
|
365
|
-
- Existing Git tuning remains enabled; fsmonitor stays disabled because of stale-daemon risk.
|
|
366
|
-
- A persistent checkJs daemon remains deferred until safe invalidation is cheaper; see `docs/lint-daemon-design.md`.
|
|
367
|
-
- Shared helpers replace duplicated preflights, error conversion, regex escaping, option parsing, object guards, and ESTree casts.
|
|
354
|
+
- Rebase loading distinguishes absent from corrupt sessions; `rebase --abort` can recover invalid state.
|
|
355
|
+
- PID liveness treats `EPERM` as alive.
|
|
356
|
+
- The moz.build parser handles comments, quoted brackets and apostrophes, and unterminated lists.
|
|
357
|
+
- Parser failures no longer silently certify validation success.
|
|
358
|
+
- Toolchain probes, baseline fingerprints, and manifest reads use bounded concurrency.
|
|
368
359
|
- Four local ESLint rules prevent unsafe error casts, duplicate regex escaping, and empty JSDoc.
|
|
369
|
-
- Oversized modules were split or simplified, silent degradations documented, and stale dead-code suppressions removed.
|
|
370
360
|
- The release gate pins weak critical modules so aggregate coverage cannot hide local regressions.
|
|
371
361
|
|
|
372
362
|
## 0.40.0
|
|
373
363
|
|
|
374
|
-
-
|
|
375
|
-
-
|
|
376
|
-
-
|
|
377
|
-
-
|
|
378
|
-
-
|
|
379
|
-
-
|
|
380
|
-
-
|
|
381
|
-
-
|
|
382
|
-
-
|
|
383
|
-
-
|
|
384
|
-
-
|
|
385
|
-
-
|
|
386
|
-
-
|
|
387
|
-
-
|
|
388
|
-
-
|
|
389
|
-
-
|
|
390
|
-
-
|
|
391
|
-
- **`export --before/--after` no longer refuses placements whose renumber never actually reaches a reserved range** (bug — `computePlacementPlan` shifted every patch at or above the insertion point by +1, so any positional insert below a `patchPolicy.reservedRanges` block dragged the reserved patches into the rename map and tripped the up-front refusal even with free ordinals in between; in a ~230-patch tree with a 900-999 reserved block, `--before`/`--after` were effectively unavailable and every insert needed an explicit `--order`): the +1 cascade now stops at the first unoccupied ordinal — a gap absorbs the insert, so the tail beyond it (including any reserved block) keeps its numbering — while a genuinely contiguous run into the block still refuses with the same single up-front error. The same cascade serves `patch split` and `patch move-files --create` placements. Pinned by the stop-at-gap and contiguous-refusal cases in `export-placement-policy.test.ts` and the rewritten sparse-queue case in `export-flow.test.ts`.
|
|
364
|
+
- Adopted all five open dependabot PRs after a TypeScript 6 compatibility review. Production: `acorn` 8.18.0 and `magic-string` 1.1.0 (a major that only drops the CJS/UMD builds). Dev tooling and SHA-pinned actions bumped alongside. knip 6.29's stricter re-export tracking found seven dead type re-exports, now removed.
|
|
365
|
+
- New `fireforge tree`: copy-on-write verification clones for concurrent read-only work. `tree create <name>` snapshots the project into `.fireforge/trees/<name>` via APFS clonefile or btrfs/XFS reflink, taken under the engine session lock. Read-only commands run inside a tree unmodified; every mutating command is refused through a default-deny table. Filesystems without CoW refuse honestly, with `--force-copy` as the explicit opt-in. `tree list`, `tree remove`, and `tree exec` round it out. Windows is not supported.
|
|
366
|
+
- Concurrent xpcshell runs no longer collide on Firefox's fixed profile directory. Every dispatch that can run xpcshell exports a fresh `mkdtemp` profile dir and removes it afterwards. An operator-supplied `XPCSHELL_TEST_PROFILE_DIR` is respected and never deleted.
|
|
367
|
+
- Per-patch lint can typecheck patch-adopted test `.js` files through `patchLint.checkJsTestFiles` and `patchLint.checkJsTestShim`. Test files were never in the checkJs program at all before, so a harness global that does not exist could not fail at the patch boundary.
|
|
368
|
+
- Patch size metrics are on the public API (`countNonBinaryDiffLines`, `resolvePatchSizeTier`, `getPatchSizeThresholds`), and `lint --per-patch --report <path>` writes a machine-readable per-patch report.
|
|
369
|
+
- A size finding waived by `lintIgnore` still reports its measurement as a NOTICE, so a waived patch's current size can be read back from the tool that enforces it.
|
|
370
|
+
- Smoke-run summaries attribute allowlist hits per entry and flag zero-hit entries as removal candidates.
|
|
371
|
+
- `lint --per-patch <patch…>` accepts positional arguments through the same alias resolution as `--patches`.
|
|
372
|
+
- `patch staged-dependency --remove` accepts `--file` plus `--specifier` and infers `--creates` from a unique match. Error messages name the missing flag instead of restating the command.
|
|
373
|
+
- `token add` can no longer strand or skip a token when its category is wrong. Category banners match exactly, idempotency is checked per category, and `--variant` validates `--category` instead of discarding it.
|
|
374
|
+
- Patch-lint `raw-color-value` no longer fires on hex colors inside comments that open on a context line and close on an added one.
|
|
375
|
+
- `export --name ui-foo --category ui` lands manifest `name: "foo"` in one step, and a `.patch` suffix no longer trips the dot validator.
|
|
376
|
+
- New `status --check` and `--fail-on <class,…>` turn classification drift into a non-zero exit, so CI no longer has to parse `--json` and reimplement the rules.
|
|
377
|
+
- `status --json` file entries carry a `patch` field naming the owning patch.
|
|
378
|
+
- The scan-less `re-export` adjacency notice is classification-aware, and `--refuse-adjacent-unmanaged` upgrades it to a refusal that skips the write.
|
|
379
|
+
- `re-export` retries once after 300 ms on transient git `index.lock` contention.
|
|
380
|
+
- `export --before/--after` no longer refuses placements whose renumber never reaches a reserved range.
|
|
392
381
|
|
|
393
382
|
## 0.39.0
|
|
394
383
|
|
|
395
|
-
-
|
|
396
|
-
-
|
|
397
|
-
-
|
|
398
|
-
-
|
|
399
|
-
-
|
|
400
|
-
-
|
|
401
|
-
-
|
|
402
|
-
-
|
|
403
|
-
-
|
|
404
|
-
-
|
|
405
|
-
-
|
|
406
|
-
-
|
|
407
|
-
-
|
|
408
|
-
-
|
|
409
|
-
-
|
|
410
|
-
-
|
|
411
|
-
- **Headed macOS no-output timeouts hint at display sleep and `caffeinate`** (message-only — a headed single-file run with no `caffeinate` wrapper timed out at 370 s before the first TEST-START; every subsequent `caffeinate -dimsu`-wrapped run passed): when a harness crash with the no-output-timeout shape came from a HEADED run on macOS, the failure message appends: "Hint: this was a HEADED run on macOS that died at the no-output timeout. A common cause is the display going to sleep mid-run, which freezes the headed browser before any test starts. Wrap headed runs in `caffeinate -dimsu <command>` to keep the display awake, or pass --headless." Auto-wrapping dispatches in `caffeinate` was evaluated and DEFERRED — the message half is the clearly-correct, cheap half.
|
|
384
|
+
- `fireforge discard` restores patch-claimed paths to their patch-applied baseline and re-materializes patch-created files. It used to return upstream Firefox artwork and drop every fork line from `jar.mn`.
|
|
385
|
+
- New per-patch check `mozbuild-unsorted-list` catches unsorted `EXTRA_JS_MODULES` before any build is dispatched.
|
|
386
|
+
- Forward-import detection catches a bare getter line added to an existing `defineESModuleGetters` map, and every refusal names the `patch staged-dependency` command to paste.
|
|
387
|
+
- `patch move-files <from> <to>` into an existing patch is a real transaction rather than a printed preview with the two commands in the wrong order.
|
|
388
|
+
- `patch lint-ignore --add` warns that the waiver is subject to the project's patch-policy review.
|
|
389
|
+
- The mixed-harness refusal runs before the pre-test build instead of after it.
|
|
390
|
+
- `token add --mode override` also writes existing `:root[data-theme="dark"]` and `:root[data-theme="light"]` blocks.
|
|
391
|
+
- A `.patch` extension on a patch-name argument no longer double-suffixes, and `patch rename` explains its no-ops.
|
|
392
|
+
- xpcshell-only runs skip the Marionette port preflight and the mochitest client flags.
|
|
393
|
+
- New `fireforge status --test-coverage` reports the last build baseline's packaging coverage.
|
|
394
|
+
- `typecheck` and the checkJs pass no longer suppress undefined free identifiers (TS2304/TS2552).
|
|
395
|
+
- `reset` and `import` warn when `components.conf` diverged from the last full build.
|
|
396
|
+
- The forward-import "closest legal ordinal" hint is suppressed when no legal ordinal exists.
|
|
397
|
+
- `export` never offers to prepend the project license header onto a vendored third-party file.
|
|
398
|
+
- Signal-shaped configure and build exits are labeled as external interruptions.
|
|
399
|
+
- Headed macOS no-output timeouts hint at display sleep.
|
|
412
400
|
|
|
413
401
|
## 0.38.0
|
|
414
402
|
|
|
415
|
-
-
|
|
416
|
-
-
|
|
417
|
-
-
|
|
418
|
-
-
|
|
419
|
-
-
|
|
420
|
-
-
|
|
421
|
-
-
|
|
422
|
-
-
|
|
423
|
-
-
|
|
424
|
-
-
|
|
403
|
+
- `status --ownership` reports a furnace-deployed file whose owning patch body went stale as drift.
|
|
404
|
+
- Scoped `test --build` and build-less runs refuse a `components.conf` changed since the last full build, since those entries bake into the compiled static component table.
|
|
405
|
+
- Per-patch size lint agrees with `wc -l` and fires only above the soft limit.
|
|
406
|
+
- Patch lint accepts both established upstream MPL header wraps.
|
|
407
|
+
- The packaged-test coverage guard accepts same-manifest siblings instead of demanding the exact recorded path set.
|
|
408
|
+
- Positional inserts refuse with one actionable error when they would renumber a reserved range, `patch move-files --create --order <n>` bootstraps a split in one step, and `re-export --scan` refuses forward-import adoptions.
|
|
409
|
+
- Engine-mutating commands can wait for the engine lock instead of failing fast.
|
|
410
|
+
- `furnace validate` credits the implicit wrapping `<label>` association.
|
|
411
|
+
- `furnace create --shared-ftl <path>` validation is pinned by tests.
|
|
412
|
+
- `source set --candidate <buildN>` fetches release-candidate archives.
|
|
425
413
|
|
|
426
414
|
## 0.37.0
|
|
427
415
|
|
|
428
|
-
-
|
|
429
|
-
-
|
|
430
|
-
-
|
|
431
|
-
-
|
|
432
|
-
-
|
|
433
|
-
-
|
|
434
|
-
-
|
|
435
|
-
-
|
|
436
|
-
- **Mach dispatches reap their whole process GROUP, and `doctor` detects pre-existing orphaned harness workers** (friction-log item 9, severe — a mach that died at harness startup stranded a Python `multiprocessing` spawn worker that busy-spun at 100% CPU for ~26 days): (a) every mach-wrapping dispatch (test suites, protected builds, bootstrap, watch, package, run) now spawns mach as a POSIX process-group leader, forwards parent SIGINT/SIGTERM to the group (with the existing grace→SIGKILL escalation), group-kills on abort, and sweeps the group after every exit — survivors are named (multiprocessing workers highlighted), group-SIGTERMed, and SIGKILLed after a 2s grace, so a startup death leaves zero surviving multiprocessing children; a healthy run costs one `pgrep`. Windows stays best-effort tree-kill via `taskkill /T /F`. (b) A new `doctor` check ("Orphaned harness workers") scans `ps` for the detection recipe that found the incident — PPID 1 + ≥10 min accumulated CPU time + a `multiprocessing.spawn`/`forkserver`/`resource_tracker` command line, parsing both linux `dd-hh:mm:ss` and darwin `mm:ss.cc` TIME dialects — and reports each match with its PID, CPU time, command line, and a `kill <pid>` suggestion; report-only by design (FireForge never kills pre-existing processes), warning severity so it cannot fail doctor, skipped on Windows.
|
|
437
|
-
- **Follow-up findings** (pre-release review of the items above; the behavioral corrections are folded into their bullets): the packaging-coverage refusal now guards EVERY non-`--build` run, not just `--allow-stale-build` ones, with a path-less `test --doctor` exempted since it dispatches no test (item 3 — a plain run over an unchanged tree after a scoped `test --build` sailed through the gate into the very fixture hang the feature targets, while the widened gate would otherwise have refused a doctor-only Marionette probe as an uncovered full-suite request); the stale-furnace export gate attributes a localized component's deployed `<ftlDir>/<name>.ftl` (item 4 — exporting only the deployed FTL file never probed its component source); registration-kind staged dependencies validate `creates`/`owner`/ordering like the import kind (item 5 — metadata naming a nonexistent file or wrong owner linted clean); the teardown-noise echo filter is narrowed to the exact `stop_time`/`poll_interval` signature with a resourcemonitor.py frame after a seen `SUITE_END` (item 8 — it previously collapsed ANY traceback mentioning resourcemonitor.py, hiding novel upstream defects from live output); and the process-group reaper's grace timer is no longer `unref()`'d (item 9a — the timer was awaited from a child `close` handler after the signal forwarder was disposed, so Node could exit mid-grace and skip the SIGKILL escalation; a regression test pins the timer's ref-ness).
|
|
416
|
+
- `fireforge test --build` records the stale-build baseline, so a plain `test` right afterwards is not refused.
|
|
417
|
+
- Every non-`--build` test run tracks packaged-runtime coverage, not just tree state.
|
|
418
|
+
- `export` and `re-export` refuse to capture a stale furnace deploy, with `--allow-stale-furnace` to downgrade it to a warning.
|
|
419
|
+
- `stagedDependencies` gains a registration-kind entry shape for jar.mn lines, customElements registrations, and actor registrations.
|
|
420
|
+
- `furnace validate` accepts `kind: "library"` components.
|
|
421
|
+
- The failure summary echoes the first five `TEST-UNEXPECTED-*` lines with their assertion text.
|
|
422
|
+
- The known mozsystemmonitor teardown traceback is collapsed to one labeled line.
|
|
423
|
+
- Mach dispatches reap their whole process group, and `doctor` detects pre-existing orphaned harness workers.
|
|
438
424
|
|
|
439
425
|
## 0.36.0
|
|
440
426
|
|
|
441
|
-
-
|
|
442
|
-
-
|
|
443
|
-
-
|
|
444
|
-
-
|
|
445
|
-
-
|
|
446
|
-
-
|
|
447
|
-
-
|
|
448
|
-
-
|
|
449
|
-
-
|
|
450
|
-
-
|
|
451
|
-
-
|
|
452
|
-
-
|
|
453
|
-
-
|
|
454
|
-
-
|
|
455
|
-
-
|
|
456
|
-
-
|
|
457
|
-
-
|
|
458
|
-
-
|
|
459
|
-
-
|
|
460
|
-
-
|
|
461
|
-
-
|
|
462
|
-
-
|
|
463
|
-
- **Performance**: `validatePatchIntegrity` batches HEAD-existence checks through one chunked `ls-tree` (one spawn instead of one per patch × file), and import's dirty-file classification loads the manifest/patch set once with bounded concurrency instead of O(files × patches) IO.
|
|
464
|
-
- **Structure**: `escapeRegex` (6 copies), `getPrimaryStatusCode` (2), the untracked-directory expander (2 — the shared one now carries the 5000-per-dir cap, and `reset`/`discard` gained status's unborn-HEAD guidance), the pendingRepair-preserving state reset (4 copies → `clearAppliedFurnaceState`), and the cross-patch claim multimap (3 copies → `buildPatchClaims`) are each single implementations; the second patch-delete implementation (`deletePatch`) is gone in favor of `removePatchFileAndManifest`; the furnace batch-apply loops take an `ApplyBatchContext` instead of 12–13 positional parameters; `stripJsComments` tokenizes with acorn so regex literals survive (legacy regex fallback for preprocessor-laden chrome sources).
|
|
465
|
-
- **Follow-up findings** (same review, second pass): `doctor --repair-patches-manifest` now rebuilds `patches.json` **under the patch-directory lock** — the repair used to write the manifest lock-free, so it could race a concurrent export/reorder and clobber the other writer (a lock-wait regression test pins the serialization, alongside the existing `stampPatchVersions` pin). `patch tier` and `patch lint-ignore` now follow the full destructive-operation contract via `confirmDestructive` (summary, `--dry-run`, confirmation or `--yes`, non-TTY refusal with `--yes` guidance) — both accepted `--yes` without ever prompting, so the flag only appeared in the history record; suppressing lint findings in particular is a mutation an operator should consciously approve. The root `--version` edge case flagged in the same pass (`fireforge --verbose --version` failing on the argv-length-3 fast path) was already fixed above; two CLI tests now pin both the multi-flag form and the non-hijacking of `source set --version`.
|
|
466
|
-
- **Infrastructure**: all GitHub Actions are SHA-pinned (release workflow included); `coverage.include: ['src/**']` closes the Vitest 4 hole where never-imported modules were invisible to thresholds (with new per-module pins for the fuzz/state-persist/step-error modules); the ~2-minute pack smoke test runs once via `pack:verify` (own config) instead of in every `npm test` and twice per release:check; CI has concurrency groups and a stable `quality (ubuntu)` job name that `setup-rulesets.sh` now matches (the Node version embedded in the name silently invalidated the required check on every bump); the full-integration runner's masked-build-failure detection works (its `ls obj-*` glob never expanded under spawn); the coverage-pin matcher requires a path-separator boundary; husky hooks only prepend Homebrew paths that exist; `docs/*.md` and `knip.json` are formatted; `isolatedModules` + `verbatimModuleSyntax` are on (zero fallout); the published tarball no longer ships dangling `sourceMappingURL` comments (build emits no maps); machine-mode logging and the lock races have dedicated unit suites; `docs/lifecycle-invariants.md` records the new lock-ownership, manifest-corruption, and state-persistence invariants with their enforcing tests.
|
|
427
|
+
- `fireforge test` with no path requires `--auto`, `--doctor`, or `--canary`, and stale packaged-engine drift fails fast unless `--build` or `--allow-stale-build` is given.
|
|
428
|
+
- A SIGSEGV-truncated run is no longer reported as PASSED.
|
|
429
|
+
- The build toolchain preflight probes the cbindgen mach actually resolves, which is the mozbuild state directory first.
|
|
430
|
+
- Exact-directory test selection was cosmetic on Firefox 153's mach and its exclusion echo was wrong; both fixed.
|
|
431
|
+
- Verbatim upstream MPL-2.0 block headers are accepted on non-JS files too.
|
|
432
|
+
- `rebase --max-fuzz` was dead code: `git apply` has no `--fuzz` flag, so every escalation failed with a swallowed usage error. Reimplemented, and the flag now rejects invalid numbers.
|
|
433
|
+
- A corrupt `patches.json` is no longer silently destroyed on the next export.
|
|
434
|
+
- `furnace apply <name>` no longer wipes every other component's checksum state.
|
|
435
|
+
- Ordinary `config <key> <value>` no longer deletes `--force`-written keys.
|
|
436
|
+
- Downloads verify against Mozilla's published SHA256SUMS by default, failing closed on mismatch.
|
|
437
|
+
- Archive-safety preflight streams tar listings instead of scanning a truncated capture, and `--dry-run` exports are genuinely read-only.
|
|
438
|
+
- `applyPatchIdempotent` checks git exit codes, chunks pathspecs against `E2BIG`, and threads a protected-files set through both apply loops.
|
|
439
|
+
- File locks are race-hardened: PID plus per-acquisition token, rename-aside stale reaping, and a stale probe that re-runs while waiting.
|
|
440
|
+
- The bin signal handler waits up to 12 s for spawned children, making the SIGTERM to SIGKILL escalation reachable. Windows smoke-run cleanup kills the whole tree.
|
|
441
|
+
- `writeFileAtomic` retries its final rename on transient Windows errors.
|
|
442
|
+
- `status --json` and `--raw` own stdout exclusively; every diagnostic goes to stderr as plain text.
|
|
443
|
+
- All captured child output decodes through `StringDecoder`, and patch parsing is CRLF-tolerant through one shared diff walker.
|
|
444
|
+
- `--version` works alongside other root flags, and option parse errors print one clean line.
|
|
445
|
+
- `furnace remove` deletes only the files the component deployed, and `furnace rename` journals the new-name side.
|
|
446
|
+
- `validatePatchIntegrity` batches HEAD-existence checks through one chunked `ls-tree`.
|
|
447
|
+
- `doctor --repair-patches-manifest` runs under the patch-directory lock.
|
|
448
|
+
- All GitHub Actions are SHA-pinned, and `coverage.include` closes the Vitest 4 hole where never-imported modules were invisible to thresholds.
|
|
467
449
|
|
|
468
450
|
## 0.35.0
|
|
469
451
|
|
|
470
|
-
-
|
|
471
|
-
-
|
|
472
|
-
-
|
|
473
|
-
-
|
|
474
|
-
-
|
|
475
|
-
-
|
|
476
|
-
-
|
|
477
|
-
- The installed-package smoke tests
|
|
478
|
-
- The release workflow
|
|
479
|
-
-
|
|
480
|
-
-
|
|
481
|
-
-
|
|
482
|
-
-
|
|
483
|
-
-
|
|
484
|
-
-
|
|
485
|
-
- Added targeted tests and per-module coverage threshold pins for under-covered edge modules that the global threshold was masking: `signal-critical.ts` (first direct tests: body passthrough/cleanup, multi-section waits, bounded timeout, throwing sections), `bootstrap-checks.ts` (bootstrap output pattern detection incl. traceback/403 collapse and all origin-remote phrasings; SDK-probe branching), `discard.ts` (directory-recursion fallback incl. sibling-prefix safety, batch partial failures, dry-run/confirmation paths, Furnace-managed warnings), and the `furnace-validate-compatibility.ts` compose/CSS-hygiene warnings (`compose-not-referenced`/`compose-not-registered`, `excessive-important`, `missing-reduced-motion`).
|
|
452
|
+
- The patch symlink-escape guard was dead code: it normalized the path text but never followed the link. Target validation now resolves the link.
|
|
453
|
+
- `stampPatchVersions` runs under the shared patch-directory lock.
|
|
454
|
+
- Authoritative-state probes use `pathExistsStrict`, so an EACCES surfaces as an error instead of "missing".
|
|
455
|
+
- `extractTarXz` validates the archive listing before writing anything, rejecting absolute members, `..` segments, and escaping link targets.
|
|
456
|
+
- The CI matrix gained a cross-platform unit-test subset on macOS and Windows. The README's "never tested on Windows" claim was replaced with what CI actually covers.
|
|
457
|
+
- New `docs/lifecycle-invariants.md` records the six invariants the destructive-operation contract upholds.
|
|
458
|
+
- `discard <directory>/` no longer produces doubled slashes, which also broke the Furnace fallback.
|
|
459
|
+
- The installed-package smoke tests skip with a clear message when npm is unavailable.
|
|
460
|
+
- The release workflow installs the exact npm version pinned in `packageManager`.
|
|
461
|
+
- New toolchain preflight for Firefox source hops, after a build died 8 s into configure on an out-of-date cbindgen.
|
|
462
|
+
- The per-patch Firefox-globals shim is extensible: `ChromeUtils` and `Localization` are named interfaces a project can add to.
|
|
463
|
+
- `fireforge test <directory>` selects exactly that directory. Mach matches test paths by string prefix, so a bare directory used to sweep in prefix-named siblings.
|
|
464
|
+
- Per-file test sharding announces itself, and `--no-shard` runs a single combined instance.
|
|
465
|
+
- A headed smoke run on a non-CI host warns that input during the window contaminates the console capture. New `fireforge run --headless`.
|
|
466
|
+
- The verbatim upstream MPL-2.0 header is accepted on new JS files regardless of the project license.
|
|
486
467
|
|
|
487
468
|
## 0.34.0
|
|
488
469
|
|
|
489
|
-
-
|
|
490
|
-
-
|
|
491
|
-
-
|
|
492
|
-
-
|
|
493
|
-
-
|
|
494
|
-
-
|
|
495
|
-
-
|
|
496
|
-
-
|
|
497
|
-
-
|
|
498
|
-
-
|
|
499
|
-
-
|
|
500
|
-
-
|
|
501
|
-
- Added `furnace create --test-dir <dir>` to redirect the `--with-tests` scaffold (browser-chrome and xpcshell styles) to any engine-relative directory under `browser/base/content/test/` — nested manifests register correctly — and made all test scaffolds collision-safe: existing `browser.toml`/`xpcshell.toml`/`chrome.toml` manifests are appended to (with a shared-manifest notice) instead of scaffolded over, and existing `head.js`/test implementation files are never overwritten.
|
|
502
|
-
- Fixed the degraded-psutil guard wedging `mach build` at exit on flapping hosts (0.34.1 post-upgrade field report: psutil's vm/swap syscalls flap between working and degraded, the fallback swap reading arrived svmem-shaped (8 fields) where mozsystemmonitor's parent reconstructs a 6-field `sswap` via `self._swap_type(*swap_mem)`, so every collector sample was rejected — `resourcemonitor.py:766: UserWarning: failed to read the received data` — upstream's handler breaks its drain loop, the pipe fills, the collector child blocks in `send()` and never reads the terminate sentinel, and mach hangs forever in its atexit `waitpid`). The guard's fallback readings are now **per-function, arity-correct, module-level namedtuples** (svmem 8 / sswap 6 / scputimes 4 / sdiskio 6; psutil's own result classes are still preferred when resolvable) that pickle by reference across the collector pipe and survive `type(reading)(*values)` reconstruction in **either** flapping direction (real type + degraded reading, or degraded type + real reading); `cpu_percent`/`cpu_times` fallbacks honour `percpu=True` (return `[]`) for the collector child's per-CPU sampling, and the last-resort `_DegradedReading` now tolerates positional-field construction. The report's "factory resolution bypassed in the collector child" observation is consistent with the two-copy load (`sitecustomize` via PYTHONPATH plus the in-venv `.pth`) or degraded-import-time `psutil._psplatform` resolution — the fix no longer depends on psutil internals resolving, so it is robust to both.
|
|
503
|
-
- Added **collector suppression on degradation** to the guard: any observed psutil degradation sets a process-wide flag, after which monitors are kept inert — `start` never spawns the mozsystemmonitor collector child — and a degraded transition (any wrapped monitor method raising) or a raising `stop` best-effort terminates a live collector child (`_process.terminate()` + bounded join) and drains the parent end of the pipe, so a malformed sample stream can never fail the command or wedge shutdown even if a future shape mismatch slips through. (The upstream enabler — mozsystemmonitor warning then `break`ing out of its drain loop without draining, leaving the pipe to fill — is worth reporting to Mozilla but is not FireForge-fixable.)
|
|
504
|
-
- Fixed the same degradation **failing `mach build` after a fully successful compile** ("Error running mach" with complete, valid `dist/` artifacts): degraded aggregate methods now return zeroed shapes instead of `None` where callers subscript the result (`aggregate_io` → zeroed io namedtuple, so mozbuild's `log_resource_usage` no longer dies on `usage["io"].read_bytes` at `mozbuild/controller/building.py:526`; `aggregate_cpu_percent`/`aggregate_cpu_times` return `[]`/`0.0`/zeroed shapes per their `per_cpu` mode), and the guard additionally wraps `mozbuild.controller.building.BuildMonitor.log_resource_usage` to warn-and-continue on any exception. Runtime-verified by new python3-executed regression tests covering per-function fallback arity, pickle/`type(*values)` round-trips in both flapping directions, collector suppression (stub monitor with upstream-named `_process`/`_pipe`), and the BuildMonitor wrap.
|
|
505
|
-
- Taught the harness-crash classifier the post-success `AttributeError: 'NoneType' object has no attribute 'read_bytes'` traceback (protected builds retry it as crash-not-failure — with the fixed guard the incremental retry is cheap and green; real test failures still take precedence), and exempted the upstream drain-loop `failed to read the received data` warning from crash evidence so runs that complete despite the rejected-sample stream never classify as crashes.
|
|
470
|
+
- The macOS resource-monitor crash mitigation is now an in-process guard installed into every discovered mach virtualenv before each dispatch.
|
|
471
|
+
- Every mach build dispatch goes through one protected path with a uniform recognized-crash retry budget.
|
|
472
|
+
- Fixed the degraded-psutil fallback crashing mozsystemmonitor on itself, and taught the crash classifier its two signatures.
|
|
473
|
+
- A fully green run is no longer marked `CRASH (N attempts)`: a completed green summary vetoes signature-based classification.
|
|
474
|
+
- `fireforge test <directory>` dispatches xpcshell-only directories to `mach xpcshell-test`.
|
|
475
|
+
- New `fireforge register --create-manifest` scaffolds a directory `moz.build` and wires the parent `DIRS` chain.
|
|
476
|
+
- `re-export <patch> --files` accepts the space-separated path shape, with clearer dry-run previews.
|
|
477
|
+
- `furnace deploy` no longer leaves a stale toolkit `jar.mn` line after a helper file rename.
|
|
478
|
+
- New `furnace scan --track` persists discovered untracked components non-interactively.
|
|
479
|
+
- New `furnace chrome-doc create --browser-window` scaffolds a browser.xhtml-like main window document.
|
|
480
|
+
- New `furnace create --test-dir <dir>` redirects the test scaffold, and all test scaffolds are collision-safe.
|
|
481
|
+
- Fixed the degraded-psutil guard wedging `mach build` at exit and failing a build after a fully successful compile.
|
|
506
482
|
|
|
507
483
|
## 0.33.0
|
|
508
484
|
|
|
509
|
-
-
|
|
510
|
-
-
|
|
511
|
-
-
|
|
512
|
-
-
|
|
513
|
-
-
|
|
514
|
-
-
|
|
515
|
-
-
|
|
516
|
-
-
|
|
485
|
+
- `furnace deploy` and `apply` prune a dangling per-widget locale `jar.mn` entry for a `sharedFtl` widget, which used to fail the build outright.
|
|
486
|
+
- New `fireforge token add --variant '[data-skin=precision]'` authors a declaration inside an attribute-keyed `:root` block, creating it if absent.
|
|
487
|
+
- `fireforge register` sorts `EXTRA_JS_MODULES` case-insensitively, matching mozbuild's rule.
|
|
488
|
+
- `fireforge typecheck` regenerates the Furnace-managed jsconfig before running, so a stale shim stops reporting phantom errors.
|
|
489
|
+
- `patch split --dry-run` models the forward edge the split introduces, so the preview matches the real gate.
|
|
490
|
+
- `fireforge test <one xpcshell .js>` recognizes the xpcshell result-summary block as an execution signal.
|
|
491
|
+
- `fireforge build` injects a resource-monitor degrade shim so a host `psutil` failure warns instead of aborting the build.
|
|
492
|
+
- New per-project `typecheck.projectOverrides` to override or opt out of the shared shim.
|
|
517
493
|
|
|
518
494
|
## 0.32.0
|
|
519
495
|
|
|
520
|
-
-
|
|
521
|
-
-
|
|
522
|
-
-
|
|
523
|
-
-
|
|
524
|
-
-
|
|
525
|
-
-
|
|
526
|
-
-
|
|
527
|
-
-
|
|
496
|
+
- `fireforge lint <files>` evaluates `large-patch-files` against each file's owning patch instead of the file-list size.
|
|
497
|
+
- The ad-hoc `lint <files>` path honours each file's owning-patch `lintIgnore`, so all three lint modes agree.
|
|
498
|
+
- New `lint --per-patch --patches <name…>` lints a named subset of the queue.
|
|
499
|
+
- The per-patch checkJs pass builds the queue-wide program once per run instead of once per patch.
|
|
500
|
+
- Cross-patch `resource:///` and `chrome://` imports resolve during export and re-export lint.
|
|
501
|
+
- `furnace sync` emits `./`-prefixed relative `compilerOptions.paths` values.
|
|
502
|
+
- `fireforge test` auto-dispatches a single-suite run to the suite-specific mach command.
|
|
503
|
+
- The crash classifier and `--harness-retries` budget cover the pre-test `--build` step.
|
|
528
504
|
|
|
529
505
|
## 0.31.0
|
|
530
506
|
|
|
531
|
-
-
|
|
532
|
-
-
|
|
533
|
-
-
|
|
534
|
-
-
|
|
535
|
-
-
|
|
536
|
-
- Added `ChromeUtils.getClassName`, `ChromeUtils.defineLazyGetter`, and the `Localization` constructor to the shipped
|
|
537
|
-
-
|
|
538
|
-
-
|
|
539
|
-
-
|
|
540
|
-
-
|
|
541
|
-
-
|
|
542
|
-
-
|
|
543
|
-
-
|
|
544
|
-
-
|
|
545
|
-
-
|
|
546
|
-
-
|
|
547
|
-
-
|
|
548
|
-
- Internalized 45 exports
|
|
549
|
-
- Refactored the twelve functions
|
|
550
|
-
-
|
|
551
|
-
-
|
|
552
|
-
- Bumped the TypeScript `target`/`lib` from ES2022 to ES2023 (Node ≥ 22.22.1 fully implements it) and dropped the redundant `@typescript-eslint/eslint-plugin` / `@typescript-eslint/parser` devDependencies already provided by the `typescript-eslint` meta-package.
|
|
507
|
+
- `patch compact` is range-aware: each configured category range compacts independently.
|
|
508
|
+
- Staged-dependency `owner` references are rewritten during every renumber instead of dangling.
|
|
509
|
+
- New `fireforge patch split <source> --files <paths…> --name <name>` moves files into a new patch as one transaction.
|
|
510
|
+
- Plain `re-export --scan` is scoped to the patch's exact directory footprint. Git pathspecs recurse, so a shallow claimed file used to sweep the whole subtree.
|
|
511
|
+
- The per-patch checkJs pass resolves imports of patch-owned modules to their real sources, so JSDoc type guards and generics survive module boundaries.
|
|
512
|
+
- Added `ChromeUtils.getClassName`, `ChromeUtils.defineLazyGetter`, and the `Localization` constructor to the shipped shim.
|
|
513
|
+
- The JSDoc `@param` extractor scans balanced braces, so nested generics parse.
|
|
514
|
+
- `observer-topic-naming` parses balanced multi-line call sites and inspects the actual topic argument, with a known-Firefox-topics allowlist.
|
|
515
|
+
- `fireforge test` classifies harness runs from their output rather than trusting exit codes.
|
|
516
|
+
- Multi-path test runs are sharded into sequential single-file runs with per-shard retries. `--no-shard` restores the combined invocation.
|
|
517
|
+
- New `fireforge test --perf-samples <path>` publishes the artifact path to the harness.
|
|
518
|
+
- Named `furnace deploy <component>` runs the same pipeline as deploy-all, so renames and deletions prune their engine copies.
|
|
519
|
+
- Shared CSS fragments for Furnace widgets through a `/* @fireforge-include <fragment>.css */` directive.
|
|
520
|
+
- Automatic jsconfig `paths` maintenance for multi-file components.
|
|
521
|
+
- `token add` no longer double-prefixes a name that already starts with the configured prefix.
|
|
522
|
+
- New `token add --create-category` declares the banner and inserts the token in one write.
|
|
523
|
+
- Two new release gates: `deadcode:check` (knip) and `cycles:check` (dpdm).
|
|
524
|
+
- Internalized 45 exports with no outside consumers and untangled seven type-only import cycles.
|
|
525
|
+
- Refactored the twelve functions above cyclomatic complexity 30 and now enforce the limit.
|
|
526
|
+
- `process.exit()` is restricted to `bin/fireforge.ts` by lint.
|
|
527
|
+
- TypeScript `target`/`lib` moved from ES2022 to ES2023.
|
|
553
528
|
|
|
554
529
|
## 0.30.0
|
|
555
530
|
|
|
556
|
-
- Added
|
|
531
|
+
- Added repo-local per-patch lint result caching, with `--no-cache` and `lint cache clear`. Warm hits skip diff generation as well as rule execution.
|
|
557
532
|
|
|
558
533
|
## 0.29.0
|
|
559
534
|
|
|
560
|
-
-
|
|
535
|
+
- `test --build` failure reporting names the rebuild command, requested paths, and first failure line separately from stale-artifact advice.
|
|
561
536
|
|
|
562
537
|
## 0.28.0
|
|
563
538
|
|
|
564
|
-
- Restored mach lint compatibility
|
|
565
|
-
-
|
|
566
|
-
-
|
|
567
|
-
-
|
|
568
|
-
-
|
|
569
|
-
-
|
|
570
|
-
-
|
|
571
|
-
-
|
|
572
|
-
- Fixed partial `re-export` manifest writes so legacy source metadata is preserved on unselected patch rows unless `--stamp` or another source metadata update explicitly targets them.
|
|
573
|
-
- Added regression coverage for targeted and full stamped re-export round-trips with blank context lines.
|
|
539
|
+
- Restored mach lint compatibility by materializing a `.hgignore` copy of `.gitignore` when Firefox's ignorefile linter config is present.
|
|
540
|
+
- `source set` prints the resolved archive URL so a pinned checksum can be verified before download.
|
|
541
|
+
- `re-export --dry-run` takes a lock so parallel previews serialize instead of racing on `.git/index.lock`.
|
|
542
|
+
- New `re-export --scan --scan-files <manifest>` for bulk generated-file assignment.
|
|
543
|
+
- Better `fireforge test` diagnostics for harness startup failures and zero-tests-run.
|
|
544
|
+
- Build failure summaries put real make and mach failures above trailing warnings.
|
|
545
|
+
- Blank context lines keep their unified-diff marker, so generated patches stop producing false drift warnings.
|
|
546
|
+
- Partial `re-export` writes preserve legacy source metadata on unselected rows.
|
|
574
547
|
|
|
575
548
|
## 0.27.3
|
|
576
549
|
|
|
577
|
-
-
|
|
578
|
-
-
|
|
579
|
-
-
|
|
550
|
+
- `firefox-devedition` downloads resolve against `/pub/devedition/releases`.
|
|
551
|
+
- `download --force` keeps the existing `engine/` tree until the replacement extracts successfully.
|
|
552
|
+
- Checksum mismatch diagnostics include the resolved URL and product.
|
|
580
553
|
|
|
581
554
|
## 0.27.0
|
|
582
555
|
|
|
583
|
-
-
|
|
584
|
-
-
|
|
585
|
-
-
|
|
586
|
-
-
|
|
587
|
-
-
|
|
588
|
-
-
|
|
589
|
-
-
|
|
590
|
-
- Added cache metadata progress for archive validation, SHA-256 calculation, and sidecar JSON writes.
|
|
591
|
-
- Added elapsed progress for extraction, initial source commits, and rebase/re-export patch refreshes.
|
|
592
|
-
- Added `re-export --files --allow-shrink` so patch ownership shrinkage is refused unless explicitly acknowledged, with clearer dry-run previews.
|
|
593
|
-
- Surfaced likely new sibling files during plain re-export and aligned verify/status ownership reporting for unowned worktree changes.
|
|
556
|
+
- First-class `firefox-devedition` support and atomic `fireforge source set`.
|
|
557
|
+
- `source set --version` accepts both space and equals forms without colliding with the root version flag.
|
|
558
|
+
- New `sourceProduct` and `sourceVersion` patch metadata; `sourceEsrVersion` stays as a deprecated alias.
|
|
559
|
+
- Unified status, ownership, doctor, and verify worktree classification, including an explained patch-owned drift state.
|
|
560
|
+
- Build diagnostics carry exit codes, tails, log hints, and verbose rerun suggestions.
|
|
561
|
+
- Progress output for git indexing, archive validation, extraction, and rebase refreshes.
|
|
562
|
+
- New `re-export --files --allow-shrink`, so ownership shrinkage must be acknowledged.
|
|
594
563
|
- Preserved patch-owned branding `configure.sh` settings during build preflight.
|
|
595
|
-
-
|
|
596
|
-
-
|
|
597
|
-
- Improved rebase conflict summaries and added `doctor --post-rebase-audit` for common registration surfaces.
|
|
564
|
+
- Custom element registration support for Furnace validate and apply.
|
|
565
|
+
- Improved rebase conflict summaries and new `doctor --post-rebase-audit`.
|
|
598
566
|
|
|
599
567
|
## 0.26.0
|
|
600
568
|
|
|
601
|
-
-
|
|
602
|
-
-
|
|
603
|
-
- Kept generated patch context lines unchanged while making release checks use the FireForge whitespace gate.
|
|
569
|
+
- New targeted `re-export --scan --scan-file <path>` for reviewed single-patch new-file assignment.
|
|
570
|
+
- A FireForge-owned whitespace gate excludes generated `patches/*.patch` diff syntax from repository whitespace checks.
|
|
604
571
|
|
|
605
572
|
## 0.25.0
|
|
606
573
|
|
|
607
|
-
- Kept `MOZ_APP_VENDOR` in `browser/moz.configure` for Firefox ESR 140
|
|
608
|
-
- Added a regression for stale xpcshell install symlink repair
|
|
574
|
+
- Kept `MOZ_APP_VENDOR` in `browser/moz.configure` for Firefox ESR 140 trees instead of generated branding `configure.sh`.
|
|
575
|
+
- Added a regression for stale xpcshell install symlink repair.
|
|
609
576
|
|
|
610
577
|
## 0.24.0
|
|
611
578
|
|
|
612
|
-
- Moved branding vendor identity into generated branding configure scripts
|
|
613
|
-
- Added metadata-backed staged forward-import declarations
|
|
579
|
+
- Moved branding vendor identity into generated branding configure scripts.
|
|
580
|
+
- Added metadata-backed staged forward-import declarations and `patch staged-dependency`.
|
|
614
581
|
- Added stale xpcshell `_tests` symlink repair with a single safe retry.
|
|
615
|
-
- Added `patch move-files` for previewable ownership-transfer
|
|
616
|
-
- Improved queue self-containment guidance for staged dependencies and patch repairs.
|
|
582
|
+
- Added `patch move-files` for previewable ownership-transfer plans.
|
|
617
583
|
|
|
618
584
|
## 0.23.0
|
|
619
585
|
|
|
620
|
-
- Improved xpcshell
|
|
586
|
+
- Improved xpcshell argument filtering and mixed-harness diagnostics.
|
|
621
587
|
- Locked pre-test build phases and improved stale harness diagnostics.
|
|
622
588
|
- Fixed binary-safe re-export for new untracked files.
|
|
623
589
|
- Improved additive `re-export --files` and lint warning guidance.
|
|
@@ -628,7 +594,6 @@ On the test side: path expectations and mock keys are rendered through a new `na
|
|
|
628
594
|
- Shared patch queue health checks between `verify` and doctor recovery.
|
|
629
595
|
- Improved Furnace repair for empty custom orphan directories.
|
|
630
596
|
- Enforced patch policy during `patch compact`.
|
|
631
|
-
- Shortened README and changelog into maintainer-facing docs.
|
|
632
597
|
|
|
633
598
|
## 0.21.0
|
|
634
599
|
|
|
@@ -636,7 +601,6 @@ On the test side: path expectations and mock keys are rendered through a new `na
|
|
|
636
601
|
- Added versioned `status --json` output.
|
|
637
602
|
- Added configurable patch queue policy.
|
|
638
603
|
- Hardened export, Furnace deploy, and UI build preflights.
|
|
639
|
-
- Improved Furnace rename, override removal, and interrupt diagnostics.
|
|
640
604
|
|
|
641
605
|
## 0.20.0
|
|
642
606
|
|
|
@@ -668,12 +632,11 @@ On the test side: path expectations and mock keys are rendered through a new `na
|
|
|
668
632
|
- Added `patch tier` and per-patch lint-ignore editing.
|
|
669
633
|
- Fixed `export-all` ownership and Furnace exclusion cases.
|
|
670
634
|
- Improved build, test, and status diagnostics.
|
|
671
|
-
- Cleaned up fork-specific examples.
|
|
672
635
|
|
|
673
636
|
## 0.16.0
|
|
674
637
|
|
|
675
638
|
- Hardened release and config security paths.
|
|
676
|
-
- Fixed `config --force` read
|
|
639
|
+
- Fixed `config --force` read and write behaviour.
|
|
677
640
|
- Improved download, status, and setup feedback.
|
|
678
641
|
- Added safer Furnace init, create, preview, and chrome-doc behaviour.
|
|
679
642
|
- Improved lint, build audit, and rebase reliability.
|
|
@@ -700,7 +663,7 @@ On the test side: path expectations and mock keys are rendered through a new `na
|
|
|
700
663
|
- Added tiered lint severity for large files and patches.
|
|
701
664
|
- Added raw-colour allowlists and inline suppression.
|
|
702
665
|
- Added `fireforge patch compact`.
|
|
703
|
-
- Improved register support for XHTML
|
|
666
|
+
- Improved register support for XHTML and CSS.
|
|
704
667
|
|
|
705
668
|
## 0.12.0
|
|
706
669
|
|