@hominis/fireforge 0.46.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 +381 -498
- package/dist/bin/fireforge.d.ts +1 -1
- package/dist/bin/fireforge.js +17 -17
- package/dist/build-info.json +4 -4
- package/dist/src/cli-usage-error.d.ts +9 -9
- package/dist/src/cli-usage-error.js +12 -12
- package/dist/src/cli.d.ts +3 -2
- package/dist/src/cli.js +29 -28
- package/dist/src/commands/bootstrap-checks.js +2 -1
- package/dist/src/commands/bootstrap.js +2 -2
- package/dist/src/commands/build.js +12 -11
- package/dist/src/commands/config.js +9 -9
- package/dist/src/commands/destructive-decision.d.ts +4 -4
- package/dist/src/commands/destructive-decision.js +4 -4
- package/dist/src/commands/discard.js +5 -5
- package/dist/src/commands/doctor-check-core.d.ts +4 -4
- 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 -11
- package/dist/src/commands/doctor-orphaned-harness.js +10 -11
- 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 +2 -2
- 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 +2 -2
- package/dist/src/commands/doctor.js +9 -9
- package/dist/src/commands/download.js +15 -13
- package/dist/src/commands/export-all.js +8 -8
- package/dist/src/commands/export-flow.d.ts +5 -5
- package/dist/src/commands/export-flow.js +14 -14
- package/dist/src/commands/export-placement-conflicts.d.ts +3 -3
- package/dist/src/commands/export-placement-conflicts.js +9 -9
- package/dist/src/commands/export-placement-gate.d.ts +2 -2
- package/dist/src/commands/export-placement-gate.js +5 -5
- package/dist/src/commands/export-placement-policy.d.ts +1 -1
- package/dist/src/commands/export-placement-policy.js +1 -1
- package/dist/src/commands/export-shared.d.ts +10 -10
- package/dist/src/commands/export-shared.js +13 -13
- package/dist/src/commands/export.js +4 -4
- package/dist/src/commands/furnace/apply.js +16 -16
- package/dist/src/commands/furnace/chrome-doc-remove.d.ts +1 -1
- package/dist/src/commands/furnace/chrome-doc-remove.js +1 -1
- 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 +4 -4
- package/dist/src/commands/furnace/create-dry-run.d.ts +4 -4
- package/dist/src/commands/furnace/create-dry-run.js +4 -4
- 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 +14 -14
- package/dist/src/commands/furnace/create-templates.js +18 -18
- 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 +10 -10
- package/dist/src/commands/furnace/deploy.js +4 -4
- 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 +15 -15
- 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 +15 -15
- package/dist/src/commands/furnace/preview.js +17 -17
- package/dist/src/commands/furnace/refresh.js +6 -6
- package/dist/src/commands/furnace/remove-mutations.d.ts +3 -3
- package/dist/src/commands/furnace/remove-mutations.js +19 -18
- 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 +2 -2
- package/dist/src/commands/furnace/rename-browser-test.js +9 -8
- 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 +9 -9
- package/dist/src/commands/furnace/scan.js +3 -3
- package/dist/src/commands/furnace/status.js +7 -7
- package/dist/src/commands/furnace/sync.js +6 -6
- package/dist/src/commands/furnace/test-file-name.d.ts +2 -2
- package/dist/src/commands/furnace/test-file-name.js +2 -2
- package/dist/src/commands/furnace/validate.js +11 -12
- package/dist/src/commands/import.js +20 -20
- package/dist/src/commands/lint-per-patch.js +8 -8
- package/dist/src/commands/lint-per-run-checkjs.d.ts +12 -13
- 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 +3 -3
- package/dist/src/commands/lint.js +35 -35
- package/dist/src/commands/manifest.d.ts +4 -4
- package/dist/src/commands/package.js +2 -2
- package/dist/src/commands/patch/compact.d.ts +2 -2
- package/dist/src/commands/patch/compact.js +8 -8
- package/dist/src/commands/patch/delete.d.ts +1 -1
- package/dist/src/commands/patch/delete.js +8 -8
- package/dist/src/commands/patch/lint-ignore.d.ts +3 -4
- package/dist/src/commands/patch/lint-ignore.js +14 -15
- package/dist/src/commands/patch/move-files-create.d.ts +2 -2
- package/dist/src/commands/patch/move-files-create.js +5 -5
- package/dist/src/commands/patch/move-files-into.d.ts +2 -2
- package/dist/src/commands/patch/move-files-into.js +3 -3
- package/dist/src/commands/patch/move-files.js +1 -1
- 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 +8 -8
- package/dist/src/commands/patch/reorder.js +10 -10
- package/dist/src/commands/patch/split-plan.d.ts +3 -3
- package/dist/src/commands/patch/split-plan.js +6 -5
- package/dist/src/commands/patch/split.d.ts +2 -2
- package/dist/src/commands/patch/split.js +5 -5
- 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 +6 -6
- package/dist/src/commands/patch/tier.d.ts +2 -2
- package/dist/src/commands/patch/tier.js +5 -5
- package/dist/src/commands/patch-rename-map.d.ts +1 -1
- package/dist/src/commands/patch-rename-map.js +1 -1
- package/dist/src/commands/pending-resolution.d.ts +5 -5
- package/dist/src/commands/pending-resolution.js +5 -5
- package/dist/src/commands/re-export-adjacent.d.ts +3 -3
- package/dist/src/commands/re-export-adjacent.js +8 -8
- package/dist/src/commands/re-export-bulk-scan.d.ts +3 -3
- package/dist/src/commands/re-export-bulk-scan.js +17 -17
- package/dist/src/commands/re-export-drift.d.ts +10 -10
- package/dist/src/commands/re-export-drift.js +29 -29
- package/dist/src/commands/re-export-files.js +14 -15
- package/dist/src/commands/re-export-lint.d.ts +26 -26
- package/dist/src/commands/re-export-lint.js +27 -27
- 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 +7 -7
- package/dist/src/commands/re-export-single.d.ts +1 -1
- package/dist/src/commands/re-export-single.js +20 -20
- package/dist/src/commands/re-export.js +7 -6
- package/dist/src/commands/rebase/abort.js +6 -6
- package/dist/src/commands/rebase/continue.js +8 -7
- package/dist/src/commands/rebase/index.d.ts +1 -1
- package/dist/src/commands/rebase/index.js +3 -3
- package/dist/src/commands/rebase/patch-loop.js +18 -17
- 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 +3 -3
- package/dist/src/commands/run.js +26 -26
- package/dist/src/commands/setup-support.js +4 -4
- package/dist/src/commands/setup.js +1 -1
- package/dist/src/commands/source.js +1 -1
- package/dist/src/commands/status-check.d.ts +3 -3
- package/dist/src/commands/status-check.js +4 -4
- 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 +3 -3
- 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 +22 -22
- package/dist/src/commands/test-build-phase.d.ts +1 -1
- package/dist/src/commands/test-build-phase.js +17 -17
- 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 +2 -2
- package/dist/src/commands/test-modes.js +4 -4
- package/dist/src/commands/test-run.d.ts +11 -11
- package/dist/src/commands/test-run.js +15 -15
- package/dist/src/commands/test-stale-gate.d.ts +12 -12
- package/dist/src/commands/test-stale-gate.js +13 -13
- package/dist/src/commands/test-verdict.d.ts +6 -6
- package/dist/src/commands/test-verdict.js +11 -11
- package/dist/src/commands/test.d.ts +3 -3
- package/dist/src/commands/test.js +36 -36
- package/dist/src/commands/token-coverage.js +3 -3
- package/dist/src/commands/token-list.js +5 -5
- package/dist/src/commands/token.js +9 -9
- package/dist/src/commands/tree.js +19 -19
- package/dist/src/commands/typecheck.d.ts +6 -6
- package/dist/src/commands/typecheck.js +7 -7
- 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 +13 -13
- 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 -5
- package/dist/src/core/branding.js +3 -3
- package/dist/src/core/browser-wire.d.ts +1 -1
- package/dist/src/core/browser-wire.js +4 -4
- package/dist/src/core/build-audit-platform.d.ts +6 -6
- package/dist/src/core/build-audit-platform.js +26 -26
- package/dist/src/core/build-audit-registration.d.ts +5 -5
- package/dist/src/core/build-audit-registration.js +7 -7
- 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 +8 -8
- package/dist/src/core/build-audit-skip.js +12 -12
- 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 +8 -8
- package/dist/src/core/build-audit.js +39 -37
- 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 +8 -8
- package/dist/src/core/build-baseline.js +14 -14
- package/dist/src/core/build-jar-escalation.d.ts +8 -8
- package/dist/src/core/build-jar-escalation.js +15 -15
- package/dist/src/core/build-overwrite-guard.d.ts +4 -4
- package/dist/src/core/build-overwrite-guard.js +13 -13
- package/dist/src/core/build-prepare.d.ts +4 -4
- package/dist/src/core/build-prepare.js +16 -15
- package/dist/src/core/config-mutate.js +4 -4
- package/dist/src/core/config-state.js +2 -2
- package/dist/src/core/config-validate-build-audit.js +3 -3
- package/dist/src/core/config-validate-file-size.d.ts +1 -1
- package/dist/src/core/config-validate-file-size.js +2 -2
- package/dist/src/core/config-validate.js +8 -9
- package/dist/src/core/config.d.ts +10 -10
- package/dist/src/core/config.js +10 -10
- package/dist/src/core/coverage-extend.d.ts +16 -16
- package/dist/src/core/coverage-extend.js +16 -16
- 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 +15 -16
- 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 +4 -4
- package/dist/src/core/engine-precondition.js +2 -2
- package/dist/src/core/engine-session-lock.d.ts +18 -18
- package/dist/src/core/engine-session-lock.js +37 -37
- package/dist/src/core/export-moved-code-shape.d.ts +7 -7
- package/dist/src/core/export-moved-code-shape.js +8 -8
- package/dist/src/core/file-lock-owner.d.ts +11 -11
- package/dist/src/core/file-lock-owner.js +18 -18
- package/dist/src/core/file-lock.d.ts +12 -12
- package/dist/src/core/file-lock.js +52 -39
- package/dist/src/core/firefox-cache.d.ts +1 -1
- package/dist/src/core/firefox-cache.js +10 -10
- package/dist/src/core/firefox-download.d.ts +3 -3
- package/dist/src/core/firefox-download.js +6 -6
- package/dist/src/core/firefox-extract.d.ts +2 -2
- package/dist/src/core/firefox-extract.js +13 -13
- package/dist/src/core/firefox.d.ts +5 -5
- package/dist/src/core/firefox.js +8 -8
- package/dist/src/core/furnace-apply-dry-run.js +1 -1
- 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 -9
- package/dist/src/core/furnace-apply-helpers.js +21 -21
- 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 +9 -9
- 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 +3 -3
- package/dist/src/core/furnace-apply.js +22 -21
- 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 +4 -4
- package/dist/src/core/furnace-config.js +18 -18
- package/dist/src/core/furnace-constants.d.ts +6 -6
- package/dist/src/core/furnace-constants.js +6 -6
- 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 +1 -1
- package/dist/src/core/furnace-dir-entry.js +1 -1
- 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 +21 -20
- package/dist/src/core/furnace-operation.js +36 -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.js +2 -2
- package/dist/src/core/furnace-registration-ast.d.ts +2 -2
- package/dist/src/core/furnace-registration-ast.js +9 -9
- 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 +5 -5
- package/dist/src/core/furnace-registration.js +7 -7
- package/dist/src/core/furnace-rollback.d.ts +1 -1
- package/dist/src/core/furnace-rollback.js +5 -5
- 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 +10 -10
- 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 +13 -13
- 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 +4 -4
- package/dist/src/core/git-base.js +9 -9
- package/dist/src/core/git-diff-new-file.d.ts +4 -4
- package/dist/src/core/git-diff-new-file.js +8 -8
- package/dist/src/core/git-diff.d.ts +4 -4
- package/dist/src/core/git-diff.js +35 -34
- package/dist/src/core/git-file-ops.d.ts +6 -6
- package/dist/src/core/git-file-ops.js +7 -7
- package/dist/src/core/git-readonly-index.d.ts +12 -12
- package/dist/src/core/git-readonly-index.js +12 -12
- package/dist/src/core/git-status.d.ts +4 -4
- package/dist/src/core/git-status.js +4 -4
- package/dist/src/core/git.d.ts +3 -3
- package/dist/src/core/git.js +14 -14
- package/dist/src/core/harness-orphans.d.ts +17 -17
- package/dist/src/core/harness-orphans.js +20 -20
- package/dist/src/core/history-log.d.ts +3 -3
- package/dist/src/core/history-log.js +3 -3
- 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 -5
- package/dist/src/core/mach-error-hints.js +13 -13
- package/dist/src/core/mach-known-noise-filter.d.ts +41 -38
- package/dist/src/core/mach-known-noise-filter.js +53 -50
- package/dist/src/core/mach-mozconfig.d.ts +6 -6
- package/dist/src/core/mach-mozconfig.js +15 -15
- package/dist/src/core/mach-python.d.ts +2 -1
- package/dist/src/core/mach-python.js +4 -3
- package/dist/src/core/mach-resource-shim.d.ts +12 -12
- package/dist/src/core/mach-resource-shim.js +20 -20
- package/dist/src/core/mach.d.ts +23 -23
- package/dist/src/core/mach.js +36 -36
- package/dist/src/core/marionette-port.d.ts +15 -13
- package/dist/src/core/marionette-port.js +34 -31
- package/dist/src/core/marionette-preflight.d.ts +6 -6
- package/dist/src/core/marionette-preflight.js +23 -23
- 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 +14 -14
- 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 +11 -11
- 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 +9 -9
- package/dist/src/core/patch-apply.d.ts +9 -9
- package/dist/src/core/patch-apply.js +30 -30
- package/dist/src/core/patch-export-update.d.ts +4 -4
- package/dist/src/core/patch-export-update.js +3 -3
- package/dist/src/core/patch-export.d.ts +10 -10
- package/dist/src/core/patch-export.js +13 -13
- 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 +7 -7
- package/dist/src/core/patch-lint-cache.d.ts +2 -2
- package/dist/src/core/patch-lint-cache.js +13 -13
- package/dist/src/core/patch-lint-checkjs.d.ts +26 -26
- package/dist/src/core/patch-lint-checkjs.js +42 -41
- 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 +3 -3
- package/dist/src/core/patch-lint-creators.js +3 -3
- package/dist/src/core/patch-lint-cross.d.ts +13 -13
- package/dist/src/core/patch-lint-cross.js +21 -21
- package/dist/src/core/patch-lint-css.d.ts +1 -1
- package/dist/src/core/patch-lint-css.js +5 -5
- 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 +3 -3
- package/dist/src/core/patch-lint-forward-registration.d.ts +4 -4
- package/dist/src/core/patch-lint-forward-registration.js +12 -12
- package/dist/src/core/patch-lint-jsdoc.d.ts +2 -2
- package/dist/src/core/patch-lint-jsdoc.js +11 -11
- package/dist/src/core/patch-lint-module-registration.d.ts +1 -1
- 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 +6 -6
- package/dist/src/core/patch-lint-queue-types.d.ts +1 -1
- package/dist/src/core/patch-lint-queue-types.js +1 -1
- package/dist/src/core/patch-lint-staged-registration.d.ts +2 -2
- package/dist/src/core/patch-lint-staged-registration.js +6 -6
- 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 +27 -26
- package/dist/src/core/patch-lint.js +48 -46
- package/dist/src/core/patch-lock.d.ts +1 -1
- package/dist/src/core/patch-lock.js +8 -8
- 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 +27 -27
- 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 +14 -14
- package/dist/src/core/patch-parse.js +16 -16
- 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-transform.d.ts +8 -8
- package/dist/src/core/patch-transform.js +13 -13
- package/dist/src/core/process-cpu-time.d.ts +1 -1
- package/dist/src/core/process-cpu-time.js +5 -5
- package/dist/src/core/rebase-session.d.ts +7 -7
- package/dist/src/core/rebase-session.js +8 -8
- 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 +3 -3
- package/dist/src/core/register-shared-css.d.ts +3 -3
- package/dist/src/core/register-shared-css.js +4 -4
- 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 +12 -12
- package/dist/src/core/run-log-redact.js +16 -16
- package/dist/src/core/run-log.d.ts +9 -9
- package/dist/src/core/run-log.js +14 -14
- 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 +2 -2
- package/dist/src/core/smoke-patterns.d.ts +5 -5
- package/dist/src/core/smoke-patterns.js +9 -9
- package/dist/src/core/state-file.d.ts +3 -3
- 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 +11 -11
- package/dist/src/core/test-changed-prefs.d.ts +12 -12
- package/dist/src/core/test-changed-prefs.js +15 -15
- package/dist/src/core/test-harness-crash.d.ts +39 -39
- package/dist/src/core/test-harness-crash.js +67 -67
- 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 -21
- package/dist/src/core/test-stale-check.js +29 -28
- 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/token-category.d.ts +4 -4
- package/dist/src/core/token-category.js +13 -12
- 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 +11 -11
- package/dist/src/core/token-docs.d.ts +1 -1
- package/dist/src/core/token-inventory.d.ts +6 -6
- package/dist/src/core/token-inventory.js +7 -7
- package/dist/src/core/token-manager.d.ts +3 -3
- package/dist/src/core/token-manager.js +21 -21
- 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 +32 -32
- package/dist/src/core/toolchain-preflight.d.ts +15 -15
- package/dist/src/core/toolchain-preflight.js +22 -22
- package/dist/src/core/tree-cow.d.ts +3 -3
- package/dist/src/core/tree-cow.js +6 -6
- 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 +35 -33
- 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 +31 -31
- 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 +6 -6
- 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 +11 -11
- package/dist/src/core/xpcshell-appdir.d.ts +20 -20
- package/dist/src/core/xpcshell-appdir.js +26 -26
- 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 +22 -21
- package/dist/src/errors/base.js +22 -21
- package/dist/src/errors/build.d.ts +6 -6
- package/dist/src/errors/build.js +6 -6
- package/dist/src/errors/codes.d.ts +10 -10
- package/dist/src/errors/codes.js +10 -10
- package/dist/src/errors/furnace.d.ts +2 -2
- package/dist/src/errors/git.d.ts +1 -1
- package/dist/src/errors/git.js +1 -1
- package/dist/src/errors/patch.d.ts +3 -3
- package/dist/src/errors/patch.js +3 -3
- package/dist/src/errors/rebase.d.ts +1 -1
- package/dist/src/errors/rebase.js +1 -1
- 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 +86 -85
- 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 +24 -23
- package/dist/src/types/furnace.d.ts +17 -17
- 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 +1 -1
- package/dist/src/utils/assert.js +6 -6
- package/dist/src/utils/build-info.d.ts +5 -5
- package/dist/src/utils/build-info.js +6 -6
- package/dist/src/utils/child-env.d.ts +5 -5
- 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 +1 -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 +8 -8
- package/dist/src/utils/line-dispatch.d.ts +3 -3
- package/dist/src/utils/line-dispatch.js +5 -5
- 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 +13 -13
- package/dist/src/utils/options.js +20 -20
- package/dist/src/utils/package-root.js +2 -2
- package/dist/src/utils/paths.d.ts +4 -4
- package/dist/src/utils/paths.js +4 -4
- package/dist/src/utils/process-group.d.ts +8 -8
- package/dist/src/utils/process-group.js +19 -19
- package/dist/src/utils/process.d.ts +34 -33
- package/dist/src/utils/process.js +20 -19
- package/dist/src/utils/ps-duration.d.ts +4 -4
- package/dist/src/utils/ps-duration.js +6 -6
- package/dist/src/utils/regex.d.ts +4 -4
- package/dist/src/utils/regex.js +7 -7
- package/dist/src/utils/sleep.d.ts +7 -7
- package/dist/src/utils/sleep.js +7 -7
- 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 +11 -12
- package/dist/src/utils/validation.js +20 -21
- package/docs/README.md +2 -2
- package/docs/configuration.md +120 -114
- package/docs/exit-codes.md +63 -58
- package/docs/furnace.md +20 -19
- package/docs/lifecycle-invariants.md +412 -251
- package/docs/machine-output.md +33 -32
- package/docs/patch-workflow.md +48 -45
- package/docs/run-logs.md +62 -58
- package/docs/testing.md +101 -101
- package/docs/verification-trees.md +23 -22
- package/package.json +2 -2
|
@@ -23,7 +23,7 @@ const GIT_INDEX_LOCK_RETRY_MS = 300;
|
|
|
23
23
|
* Retries a single patch re-export exactly once when the failure is
|
|
24
24
|
* transient git `index.lock` contention (an external git process holding
|
|
25
25
|
* the engine repo's index). The retry re-enters `reExportSinglePatch`
|
|
26
|
-
* from the top, so it re-reads clean state
|
|
26
|
+
* from the top, so it re-reads clean state. A second lock failure
|
|
27
27
|
* propagates to the loop's honest "N of M" accounting.
|
|
28
28
|
*/
|
|
29
29
|
export async function reExportSinglePatchWithIndexLockRetry(args) {
|
|
@@ -53,10 +53,10 @@ async function reExportSinglePatch(args) {
|
|
|
53
53
|
...(options.scanFiles !== undefined ? { scanFiles: options.scanFiles } : {}),
|
|
54
54
|
});
|
|
55
55
|
// Forward-import gate at adoption time (runs in dry-run too): refuse
|
|
56
|
-
// to adopt unmanaged files that import modules created by
|
|
57
|
-
// patches
|
|
58
|
-
// field-reported footgun. Applies to broad --scan, --scan-file,
|
|
59
|
-
// the --scan-files bulk assignments alike.
|
|
56
|
+
// to adopt unmanaged files that import modules created by later
|
|
57
|
+
// patches, because the after-the-fact lint failure this leaves behind
|
|
58
|
+
// is the field-reported footgun. Applies to broad --scan, --scan-file,
|
|
59
|
+
// and the --scan-files bulk assignments alike.
|
|
60
60
|
await assertScanAdoptionsHaveNoForwardImports({
|
|
61
61
|
patchesDir: paths.patches,
|
|
62
62
|
engineDir: paths.engine,
|
|
@@ -82,7 +82,7 @@ async function reExportSinglePatch(args) {
|
|
|
82
82
|
// When neither `--scan` nor `--files` is set and some of the manifest's
|
|
83
83
|
// claimed files no longer exist on disk, the re-export silently writes a
|
|
84
84
|
// refreshed body whose filesAffected still names the vanished paths.
|
|
85
|
-
// That is the documented contract, but it is also a footgun
|
|
85
|
+
// That is the documented contract, but it is also a footgun: a later
|
|
86
86
|
// `verify` then fails on manifest-consistency with no obvious trigger.
|
|
87
87
|
// Emit one advisory warning up-front when the drift is cheap to detect,
|
|
88
88
|
// so the operator can re-run with `--scan` or `--files` before the stale
|
|
@@ -92,9 +92,9 @@ async function reExportSinglePatch(args) {
|
|
|
92
92
|
return false;
|
|
93
93
|
}
|
|
94
94
|
// --- Explicit file-subset path ---
|
|
95
|
-
// When --files is given, the target filesAffected is authoritative
|
|
95
|
+
// When --files is given, the target filesAffected is authoritative: drop
|
|
96
96
|
// anything not in the list, add anything new. This is the surgical repair
|
|
97
|
-
// primitive that replaces hand-editing patches.json
|
|
97
|
+
// primitive that replaces hand-editing patches.json. The user has already
|
|
98
98
|
// acknowledged via confirmDestructive (done in the caller) that any drop
|
|
99
99
|
// is intentional.
|
|
100
100
|
if (options.files !== undefined) {
|
|
@@ -109,16 +109,16 @@ async function reExportSinglePatch(args) {
|
|
|
109
109
|
}
|
|
110
110
|
// Stale-furnace-source gate: re-export captures deployed engine copies, so
|
|
111
111
|
// a component source edited after the last furnace apply would land in the
|
|
112
|
-
// patch as its
|
|
112
|
+
// patch as its old deployed content. Refuse (or warn under
|
|
113
113
|
// --allow-stale-furnace) before diffing. Runs in dry-run too so the failure
|
|
114
114
|
// surfaces early.
|
|
115
115
|
await enforceFreshFurnaceSources(paths.root, currentFilesAffected, options.allowStaleFurnace === true, 're-export');
|
|
116
116
|
const absentFiles = await findMissingFiles(paths.engine, currentFilesAffected);
|
|
117
|
-
// A path absent from disk but tracked in engine HEAD is a
|
|
117
|
+
// A path absent from disk but tracked in engine HEAD is a deletion, and
|
|
118
118
|
// `git diff HEAD` renders it as a real `deleted file mode` section. Only
|
|
119
119
|
// a never-tracked path has nothing to diff. Skipping both alike meant a
|
|
120
120
|
// retired file quietly left the patch body while staying in its file
|
|
121
|
-
// list
|
|
121
|
+
// list, so the patch then claimed a file it could not restore.
|
|
122
122
|
const trackedAbsent = await listTrackedInHead(paths.engine, absentFiles);
|
|
123
123
|
const deletedFiles = absentFiles.filter((f) => trackedAbsent.has(f));
|
|
124
124
|
const untrackedAbsent = absentFiles.filter((f) => !trackedAbsent.has(f));
|
|
@@ -148,9 +148,9 @@ async function reExportSinglePatch(args) {
|
|
|
148
148
|
}
|
|
149
149
|
// Foreign-drift preview + optional hard stop: show which
|
|
150
150
|
// payload lines are about to enter the body that the old body did not
|
|
151
|
-
// carry
|
|
152
|
-
//
|
|
153
|
-
// dry-run and --scan)
|
|
151
|
+
// carry, the case where a concurrent session's uncommitted edits in
|
|
152
|
+
// owned files would be silently absorbed. Always previews (including
|
|
153
|
+
// dry-run and --scan). Refuses only under --refuse-foreign-drift.
|
|
154
154
|
if (await reportForeignDrift({
|
|
155
155
|
patch,
|
|
156
156
|
patchesDir: paths.patches,
|
|
@@ -167,7 +167,7 @@ async function reExportSinglePatch(args) {
|
|
|
167
167
|
command: 're-export',
|
|
168
168
|
forceUnsafe: options.forceUnsafe === true,
|
|
169
169
|
});
|
|
170
|
-
// Lint against the
|
|
170
|
+
// Lint against the once-per-invocation hoisted context (queue context +
|
|
171
171
|
// queue-wide checkJs program + per-patch result cache) instead of
|
|
172
172
|
// rebuilding ~37 s of setup for every patch in the loop.
|
|
173
173
|
const projectedMetadata = { ...patch, ...updates };
|
|
@@ -213,8 +213,8 @@ async function reExportSinglePatch(args) {
|
|
|
213
213
|
* directory lock (a split write would let a concurrent queue mutation
|
|
214
214
|
* leave body and `filesAffected` disagreeing), then keeps the run's
|
|
215
215
|
* in-memory state honest: the queue context entry is refreshed and the
|
|
216
|
-
* fresh lint result is stored keyed against the just-written body
|
|
217
|
-
* state a repeat invocation will observe
|
|
216
|
+
* fresh lint result is stored keyed against the just-written body (the
|
|
217
|
+
* state a repeat invocation will observe), and the in-memory
|
|
218
218
|
* manifest row mirrors the on-disk write for later loop iterations
|
|
219
219
|
* (notably `--all --scan`, where `getClaimedFiles` reads this manifest).
|
|
220
220
|
*/
|
|
@@ -246,8 +246,8 @@ async function commitRefreshedPatch(args) {
|
|
|
246
246
|
};
|
|
247
247
|
}
|
|
248
248
|
}
|
|
249
|
-
// A bulk run refreshes every patch
|
|
250
|
-
// did not move buries the patches that
|
|
249
|
+
// A bulk run refreshes every patch. Saying "Re-exported" for one whose body
|
|
250
|
+
// did not move buries the patches that did move. The run still counts this
|
|
251
251
|
// patch as successfully refreshed, so `--stamp` completeness is unaffected.
|
|
252
252
|
if (bodyChanged) {
|
|
253
253
|
success(`Re-exported ${patch.filename}`);
|
|
@@ -258,7 +258,7 @@ async function commitRefreshedPatch(args) {
|
|
|
258
258
|
}
|
|
259
259
|
/**
|
|
260
260
|
* Threads the patch's own `lintIgnore` list through so the per-patch
|
|
261
|
-
* suppression honoured by export/export-all is also honoured here
|
|
261
|
+
* suppression honoured by export/export-all is also honoured here. A
|
|
262
262
|
* re-export could otherwise not refresh an advisory-noisy but intentional
|
|
263
263
|
* patch without the blunt `--skip-lint`. The paired `patch.tier` threads the
|
|
264
264
|
* explicit branding-threshold opt-in the same way. The CLI flags `--tier`
|
|
@@ -26,15 +26,16 @@ async function resolveSelectedPatches(patches, options, manifest) {
|
|
|
26
26
|
for (const identifier of patches) {
|
|
27
27
|
const match = resolvePatchIdentifier(identifier, manifest.patches);
|
|
28
28
|
if (!match) {
|
|
29
|
-
// Suggest
|
|
30
|
-
// whole ~300-entry manifest, burying the
|
|
29
|
+
// Suggest close matches instead of dumping the queue: a wrong guess
|
|
30
|
+
// would otherwise print the whole ~300-entry manifest, burying the
|
|
31
|
+
// error it was reporting.
|
|
31
32
|
throw new InvalidArgumentError(formatPatchNotFoundError(identifier, manifest.patches), identifier);
|
|
32
33
|
}
|
|
33
34
|
selectedPatches.push(match);
|
|
34
35
|
}
|
|
35
36
|
return selectedPatches;
|
|
36
37
|
}
|
|
37
|
-
// No patches specified
|
|
38
|
+
// No patches specified: prompt or error
|
|
38
39
|
const isInteractive = stdioIsInteractive();
|
|
39
40
|
if (!isInteractive) {
|
|
40
41
|
throw new InvalidArgumentError('Specify patch identifiers or use --all in non-interactive mode.\n\n' +
|
|
@@ -176,7 +177,7 @@ export async function reExportCommand(projectRoot, patches, options) {
|
|
|
176
177
|
}
|
|
177
178
|
// `--stamp` only fires on a run where every selected patch refreshed
|
|
178
179
|
// cleanly. A partial success would leave some patches with a stale body
|
|
179
|
-
// but a new version
|
|
180
|
+
// but a new version, the opposite of the "what I tested, what the
|
|
180
181
|
// manifest says" invariant `sourceEsrVersion` exists to record. A
|
|
181
182
|
// non-empty `reExportedFilenames` with fewer entries than `selectedPatches`
|
|
182
183
|
// means a lint failure or missing-file skip landed somewhere in the loop,
|
|
@@ -214,7 +215,7 @@ function buildForeignDriftContext(options) {
|
|
|
214
215
|
/**
|
|
215
216
|
* Names `--expect-unmanaged` paths that were never met this run. A typo'd
|
|
216
217
|
* carve-out silently leaves the refusal armed for the path it was meant to
|
|
217
|
-
* admit
|
|
218
|
+
* admit, and reads as an approval that is in force when it is not.
|
|
218
219
|
* A warning rather than a refusal: an approved path legitimately goes unmet
|
|
219
220
|
* when the reviewed file has since been adopted into a patch, which is the
|
|
220
221
|
* outcome the carve-out exists to be retired by.
|
|
@@ -271,7 +272,7 @@ function throwRunLevelRefusals(adjacentCtx, driftCtx, progress) {
|
|
|
271
272
|
* Prints the end-of-run summary and enforces the exit contract: a partial run
|
|
272
273
|
* exits non-zero by default. "Re-exported 2 of 3" printing with exit 0 lets a
|
|
273
274
|
* partial refresh ride an `&&` chain as success. The summary still prints
|
|
274
|
-
* first so the honest "N of M" accounting stays visible
|
|
275
|
+
* first so the honest "N of M" accounting stays visible. The throw then
|
|
275
276
|
* carries the failed/skipped breakdown. Dry-run included: a preview
|
|
276
277
|
* reporting that the real run would partially fail must not read as a passing
|
|
277
278
|
* preview in scripts.
|
|
@@ -15,9 +15,9 @@ import { confirmDirtyEngineReset } from './confirm.js';
|
|
|
15
15
|
*/
|
|
16
16
|
export async function handleAbort(projectRoot, yes) {
|
|
17
17
|
intro('FireForge Rebase — Abort');
|
|
18
|
-
// Abort is the escape hatch, so it
|
|
19
|
-
//
|
|
20
|
-
//
|
|
18
|
+
// Abort is the escape hatch, so it does not require a valid session, only
|
|
19
|
+
// that one is present. Nothing below reads the session object (the restore
|
|
20
|
+
// works off `paths.engine` and `resetChanges`), and an
|
|
21
21
|
// `if (!session) throw` would refuse to run against a corrupt file, which
|
|
22
22
|
// is the only thing that could have cleared it.
|
|
23
23
|
const read = await readRebaseSession(projectRoot);
|
|
@@ -40,8 +40,8 @@ export async function handleAbort(projectRoot, yes) {
|
|
|
40
40
|
return;
|
|
41
41
|
}
|
|
42
42
|
const s = spinner('Restoring engine to pre-rebase state...');
|
|
43
|
-
// Step 1: git reset. If this fails, the rebase session
|
|
44
|
-
// so the user can retry the abort
|
|
43
|
+
// Step 1: git reset. If this fails, the rebase session must stay on disk
|
|
44
|
+
// so the user can retry the abort: resetChanges is the only irreversible
|
|
45
45
|
// operation in this handler and everything downstream assumes it ran.
|
|
46
46
|
try {
|
|
47
47
|
await resetChanges(paths.engine);
|
|
@@ -59,7 +59,7 @@ export async function handleAbort(projectRoot, yes) {
|
|
|
59
59
|
await clearAppliedFurnaceState(projectRoot);
|
|
60
60
|
// Step 3: clear pending resolution transactionally.
|
|
61
61
|
await clearPendingResolution(projectRoot);
|
|
62
|
-
// Step 4: clear the rebase session
|
|
62
|
+
// Step 4: clear the rebase session last so a failure in any prior step
|
|
63
63
|
// preserves the session on disk and a retry of --abort can succeed.
|
|
64
64
|
await clearRebaseSession(projectRoot);
|
|
65
65
|
success('Rebase aborted and session cleared.');
|
|
@@ -21,7 +21,7 @@ import { runPatchLoop } from './patch-loop.js';
|
|
|
21
21
|
*/
|
|
22
22
|
export async function handleContinue(projectRoot, maxFuzz, waitLockSeconds) {
|
|
23
23
|
intro('FireForge Rebase — Continue');
|
|
24
|
-
// A present-but-unreadable session is
|
|
24
|
+
// A present-but-unreadable session is not "no session in progress". That
|
|
25
25
|
// conflation is what made a corrupt file unrecoverable. Name the file and
|
|
26
26
|
// point at --abort, which can now clear it.
|
|
27
27
|
const read = await readRebaseSession(projectRoot);
|
|
@@ -34,10 +34,10 @@ export async function handleContinue(projectRoot, maxFuzz, waitLockSeconds) {
|
|
|
34
34
|
const paths = getProjectPaths(projectRoot);
|
|
35
35
|
// Special case: every patch has already applied but a previous run failed
|
|
36
36
|
// somewhere in the post-apply work (re-export, version stamping). In that
|
|
37
|
-
// state currentIndex is past the end of the queue
|
|
37
|
+
// state currentIndex is past the end of the queue. Jumping straight back
|
|
38
38
|
// into runPatchLoop replays the no-op apply loop and re-attempts the
|
|
39
|
-
// post-apply pipeline. Without this branch the user would be stuck
|
|
40
|
-
//
|
|
39
|
+
// post-apply pipeline. Without this branch the user would be stuck: there
|
|
40
|
+
// is no failed patch to resolve, but the session is still active.
|
|
41
41
|
if (session.currentIndex >= session.patches.length) {
|
|
42
42
|
info('All patches already applied; retrying post-apply re-export and version stamping.');
|
|
43
43
|
await runPatchLoop(projectRoot, session, paths, maxFuzz, waitLockSeconds);
|
|
@@ -99,9 +99,10 @@ export async function handleContinue(projectRoot, maxFuzz, waitLockSeconds) {
|
|
|
99
99
|
// clear is held until both writes land, matching the guarantee the apply
|
|
100
100
|
// loop in patch-loop.ts provides.
|
|
101
101
|
await runInSignalCriticalSection(`rebase-continue:${currentPatch.filename}`, async () => {
|
|
102
|
-
//
|
|
103
|
-
// failure's `error` and `conflictingFiles` on a
|
|
104
|
-
// persist that to the session file. The union
|
|
102
|
+
// The entry is replaced rather than mutated. Flipping `status` in place
|
|
103
|
+
// would leave the failure's `error` and `conflictingFiles` on a
|
|
104
|
+
// now-resolved entry and persist that to the session file. The union
|
|
105
|
+
// type rules that out.
|
|
105
106
|
session.patches[session.currentIndex] = {
|
|
106
107
|
filename: currentPatch.filename,
|
|
107
108
|
status: 'resolved',
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// SPDX-License-Identifier: EUPL-1.2
|
|
2
2
|
/**
|
|
3
|
-
* `fireforge rebase
|
|
3
|
+
* `fireforge rebase`: semi-automated Firefox source version upgrade.
|
|
4
4
|
*
|
|
5
5
|
* Orchestrates the full patch-rebase workflow:
|
|
6
6
|
* 1. Reset engine to baseline
|
|
@@ -33,7 +33,7 @@ async function handleFreshStart(projectRoot, options) {
|
|
|
33
33
|
const isDryRun = options.dryRun === true;
|
|
34
34
|
const maxFuzz = options.maxFuzz ?? 3;
|
|
35
35
|
intro(isDryRun ? 'FireForge Rebase (dry run)' : 'FireForge Rebase');
|
|
36
|
-
// One read decides liveness
|
|
36
|
+
// One read decides liveness and validity: a pathExists pre-probe here left
|
|
37
37
|
// a window where the file vanished between probe and read, reporting
|
|
38
38
|
// "already in progress" with no session on disk.
|
|
39
39
|
const existing = await readRebaseSession(projectRoot);
|
|
@@ -93,7 +93,7 @@ async function handleFreshStart(projectRoot, options) {
|
|
|
93
93
|
const resetSpinner = spinner('Resetting engine to baseline...');
|
|
94
94
|
await resetChanges(paths.engine);
|
|
95
95
|
resetSpinner.stop('Engine reset to baseline');
|
|
96
|
-
// Clear Furnace state
|
|
96
|
+
// Clear Furnace state: the engine no longer contains deployed components.
|
|
97
97
|
await clearAppliedFurnaceState(projectRoot);
|
|
98
98
|
// Create rebase session
|
|
99
99
|
const allPatches = await discoverPatches(paths.patches);
|
|
@@ -26,8 +26,8 @@ import { printSummary } from './summary.js';
|
|
|
26
26
|
/**
|
|
27
27
|
* Builds the session entry for a patch-apply outcome.
|
|
28
28
|
*
|
|
29
|
-
*
|
|
30
|
-
* discriminated union
|
|
29
|
+
* The entry is constructed whole rather than assigned field by field, so the
|
|
30
|
+
* discriminated union stops a status being flipped while the previous
|
|
31
31
|
* status's payload stays behind, which is how
|
|
32
32
|
* `{ status: 'resolved', error, conflictingFiles }` reaches the session file.
|
|
33
33
|
*
|
|
@@ -68,9 +68,10 @@ export async function runPatchLoop(projectRoot, session, paths, maxFuzz, waitLoc
|
|
|
68
68
|
const patchFile = allPatches.find((p) => p.filename === entry.filename);
|
|
69
69
|
if (!patchFile) {
|
|
70
70
|
warn(`Patch file not found for ${entry.filename}, skipping.`);
|
|
71
|
-
//
|
|
72
|
-
// change is a new value rather than a field
|
|
73
|
-
//
|
|
71
|
+
// The entry is replaced rather than mutated: it is a discriminated
|
|
72
|
+
// union, so a status change is a new value rather than a field
|
|
73
|
+
// assignment, and a status flip cannot strand the previous status's
|
|
74
|
+
// payload.
|
|
74
75
|
session.patches[i] = { filename: entry.filename, status: 'skipped' };
|
|
75
76
|
session.currentIndex = i + 1;
|
|
76
77
|
await saveRebaseSession(projectRoot, session);
|
|
@@ -101,9 +102,9 @@ export async function runPatchLoop(projectRoot, session, paths, maxFuzz, waitLoc
|
|
|
101
102
|
}
|
|
102
103
|
else {
|
|
103
104
|
// Set pendingResolution in state for visibility. Kept outside the
|
|
104
|
-
// critical section
|
|
105
|
-
// and its absence would at most cause `fireforge status`
|
|
106
|
-
// pending-conflict hint until the next state write.
|
|
105
|
+
// critical section, since it is advisory UX rather than a correctness
|
|
106
|
+
// invariant, and its absence would at most cause `fireforge status`
|
|
107
|
+
// to omit the pending-conflict hint until the next state write.
|
|
107
108
|
await updateState(projectRoot, (current) => ({
|
|
108
109
|
...current,
|
|
109
110
|
pendingResolution: {
|
|
@@ -145,7 +146,7 @@ export async function runPatchLoop(projectRoot, session, paths, maxFuzz, waitLoc
|
|
|
145
146
|
s.stop('All patches applied');
|
|
146
147
|
// Re-export all successfully applied patches. Failures here mean the
|
|
147
148
|
// engine has been rebased onto the new Firefox version but some .patch
|
|
148
|
-
// files were not refreshed
|
|
149
|
+
// files were not refreshed, so the queue would lie about what version each
|
|
149
150
|
// patch was tested against if we proceeded to stamp. Refuse to claim
|
|
150
151
|
// success and leave the session in place so the user can recover via
|
|
151
152
|
// `fireforge rebase --continue` after fixing the underlying cause.
|
|
@@ -164,7 +165,7 @@ export async function runPatchLoop(projectRoot, session, paths, maxFuzz, waitLoc
|
|
|
164
165
|
`still describe the pre-rebase source. Re-export them manually (e.g. ` +
|
|
165
166
|
`"fireforge re-export") and verify the overlapping hunks before the next import.`);
|
|
166
167
|
}
|
|
167
|
-
// Stamp versions
|
|
168
|
+
// Stamp versions, only for patches whose .patch file now actually
|
|
168
169
|
// reflects the new source (overlap-skipped ones keep their old stamp so
|
|
169
170
|
// the queue does not lie about what each patch was tested against).
|
|
170
171
|
const overlapSkippedSet = new Set(overlapSkipped);
|
|
@@ -177,19 +178,19 @@ export async function runPatchLoop(projectRoot, session, paths, maxFuzz, waitLoc
|
|
|
177
178
|
}
|
|
178
179
|
// Stamp every Furnace override's `baseVersion` to match the rebased
|
|
179
180
|
// Firefox source version. Without it, a successful source bump leaves
|
|
180
|
-
// overrides in a doctor-failing drift state
|
|
181
|
-
// pre-rebase source as its baseline
|
|
181
|
+
// overrides in a doctor-failing drift state, each still claiming the
|
|
182
|
+
// pre-rebase source as its baseline, and every subsequent
|
|
182
183
|
// `fireforge doctor` fails `Furnace component validation`. The stamp is
|
|
183
184
|
// unconditional per the helper's contract: rebase already succeeded on
|
|
184
185
|
// the patch side, so the operator is committing to the new source
|
|
185
|
-
// baseline
|
|
186
|
+
// baseline. Per-component health checking stays with
|
|
186
187
|
// `fireforge furnace validate` / `doctor --repair-furnace`.
|
|
187
188
|
//
|
|
188
189
|
// "Unconditional" means unconditional on component health, not on the
|
|
189
190
|
// value: `stampFurnaceOverrideBaseVersions` assigns and persists whatever
|
|
190
191
|
// string it is handed, so a session whose `toVersion` is not a real
|
|
191
192
|
// Firefox version would rewrite every override's baseline to that value.
|
|
192
|
-
// `isValidSession` rejects such a session at read time
|
|
193
|
+
// `isValidSession` rejects such a session at read time. This refuses to
|
|
193
194
|
// persist it even if a future caller reaches here another way.
|
|
194
195
|
if (!isValidFirefoxVersion(session.toVersion)) {
|
|
195
196
|
throw new RebaseError(`Refusing to stamp Furnace override baseVersion(s): the rebase session's target version ` +
|
|
@@ -220,13 +221,13 @@ async function reExportAppliedPatches(session, paths, waitLockSeconds) {
|
|
|
220
221
|
const manifest = await loadPatchesManifest(paths.patches);
|
|
221
222
|
if (!manifest)
|
|
222
223
|
return { failures, overlapSkipped };
|
|
223
|
-
// Re-export writes `getDiffForFilesAgainstHead(files)
|
|
224
|
+
// Re-export writes `getDiffForFilesAgainstHead(files)`, the cumulative
|
|
224
225
|
// diff of those files. For a file claimed by two patches (a supported
|
|
225
|
-
// `--allow-overlap` queue), that diff contains
|
|
226
|
+
// `--allow-overlap` queue), that diff contains both patches' hunks, so
|
|
226
227
|
// rewriting each patch with it would duplicate the shared file's hunks
|
|
227
228
|
// into every owner: the very next import then fails or silently
|
|
228
229
|
// double-materialises. Refuse to auto-re-export any patch whose files
|
|
229
|
-
// overlap another patch
|
|
230
|
+
// overlap another patch. The operator re-exports those manually where
|
|
230
231
|
// per-patch attribution is possible.
|
|
231
232
|
const fileOwners = new Map();
|
|
232
233
|
for (const patch of manifest.patches) {
|
|
@@ -17,8 +17,8 @@ import { stripEnginePrefix } from '../utils/paths.js';
|
|
|
17
17
|
*/
|
|
18
18
|
export async function registerCommand(projectRoot, filePath, options = {}) {
|
|
19
19
|
intro('Register');
|
|
20
|
-
// --after is matched as a substring against existing manifest lines
|
|
21
|
-
//
|
|
20
|
+
// --after is matched as a substring against existing manifest lines.
|
|
21
|
+
// Guard against control characters / line terminators that would either
|
|
22
22
|
// break the match logic or, worse, inject a second line if the value
|
|
23
23
|
// is ever echoed back to a manifest writer. Null bytes are explicitly
|
|
24
24
|
// rejected to mirror the hardening already applied to other user-
|
|
@@ -31,7 +31,7 @@ export async function registerCommand(projectRoot, filePath, options = {}) {
|
|
|
31
31
|
}
|
|
32
32
|
}
|
|
33
33
|
// Accept either repo-root-relative (`engine/browser/...`) or
|
|
34
|
-
// engine-relative (`browser/...`) inputs
|
|
34
|
+
// engine-relative (`browser/...`) inputs. Operators frequently paste
|
|
35
35
|
// the former from the output of tab completion or `git status`, and
|
|
36
36
|
// the mismatch used to produce a "File not found" error that named
|
|
37
37
|
// the original path with no hint that dropping `engine/` would fix it.
|
|
@@ -49,8 +49,8 @@ export async function registerCommand(projectRoot, filePath, options = {}) {
|
|
|
49
49
|
});
|
|
50
50
|
if (options.dryRun) {
|
|
51
51
|
// Dry-run must surface the idempotency decision too. Always saying
|
|
52
|
-
// "Would register"
|
|
53
|
-
// present
|
|
52
|
+
// "Would register", even when the rule already knows the entry is
|
|
53
|
+
// present, makes automation read the plan as "work to do" while the
|
|
54
54
|
// following real run reports "Already registered".
|
|
55
55
|
if (result.skipped) {
|
|
56
56
|
info(`[dry-run] Already registered: ${engineRelativePath} in ${result.manifest}`);
|
|
@@ -70,7 +70,7 @@ export async function resetCommand(projectRoot, options) {
|
|
|
70
70
|
await clearAppliedFurnaceState(projectRoot);
|
|
71
71
|
s.stop('Changes reset');
|
|
72
72
|
// The reset may have moved components.conf away from what the last full
|
|
73
|
-
// build compiled in
|
|
73
|
+
// build compiled in, so surface that now instead of at the next test
|
|
74
74
|
// refusal.
|
|
75
75
|
await warnIfStaticComponentsStale(projectRoot, paths.engine);
|
|
76
76
|
outro('Working tree restored to clean state');
|
|
@@ -15,7 +15,7 @@ export interface ResolveCommandOptions {
|
|
|
15
15
|
* and the command proceeds straight to the patch-refresh + state-clear
|
|
16
16
|
* path.
|
|
17
17
|
*
|
|
18
|
-
* The guard without `--yes` is preserved
|
|
18
|
+
* The guard without `--yes` is preserved: running `resolve` with no TTY
|
|
19
19
|
* and no `--yes` still refuses, so an accidental pipe-into invocation does
|
|
20
20
|
* not silently commit whatever the engine happens to contain.
|
|
21
21
|
*/
|
|
@@ -29,7 +29,7 @@ export interface ResolveCommandOptions {
|
|
|
29
29
|
/**
|
|
30
30
|
* Runs the resolve command to fix broken patches.
|
|
31
31
|
* @param projectRoot - Root directory of the project
|
|
32
|
-
* @param options - Optional flags
|
|
32
|
+
* @param options - Optional flags. See {@link ResolveCommandOptions}.
|
|
33
33
|
*/
|
|
34
34
|
export declare function resolveCommand(projectRoot: string, options?: ResolveCommandOptions): Promise<void>;
|
|
35
35
|
/** Registers the resolve command on the CLI program. */
|
|
@@ -20,7 +20,7 @@ import { clearPendingResolution } from './pending-resolution.js';
|
|
|
20
20
|
/**
|
|
21
21
|
* Runs the resolve command to fix broken patches.
|
|
22
22
|
* @param projectRoot - Root directory of the project
|
|
23
|
-
* @param options - Optional flags
|
|
23
|
+
* @param options - Optional flags. See {@link ResolveCommandOptions}.
|
|
24
24
|
*/
|
|
25
25
|
export async function resolveCommand(projectRoot, options = {}) {
|
|
26
26
|
intro('FireForge Resolve');
|
|
@@ -37,7 +37,7 @@ export async function resolveCommand(projectRoot, options = {}) {
|
|
|
37
37
|
// Non-interactive mode requires an explicit `--yes`: the operator is
|
|
38
38
|
// asserting the manual merge is complete and the refreshed diff is the one
|
|
39
39
|
// to record. Without it, an accidental pipe or CI shell could commit
|
|
40
|
-
// whatever the engine currently contains
|
|
40
|
+
// whatever the engine currently contains, but an unconditional TTY
|
|
41
41
|
// refusal dead-ends a scripted recovery flow.
|
|
42
42
|
if (!stdioIsInteractive() && !options.yes) {
|
|
43
43
|
throw new GeneralError('Cannot run "fireforge resolve" in non-interactive mode. Use a terminal with TTY support, or pass "--yes" to skip the interactive confirmation once the manual merge is complete.');
|
|
@@ -64,7 +64,7 @@ export async function resolveCommand(projectRoot, options = {}) {
|
|
|
64
64
|
// Refuse to proceed if the patch file was deleted between the conflict
|
|
65
65
|
// and the resolve. Without this check, `updatePatchAndMetadata` would
|
|
66
66
|
// throw a less actionable "patch file is missing" error from inside
|
|
67
|
-
// the lock
|
|
67
|
+
// the lock. The explicit precondition lets us point the user at the
|
|
68
68
|
// exact recovery path.
|
|
69
69
|
const patchPath = join(paths.patches, patchFilename);
|
|
70
70
|
if (!(await pathExists(patchPath))) {
|
package/dist/src/commands/run.js
CHANGED
|
@@ -25,10 +25,10 @@ const SMOKE_UNALLOWED_PREVIEW_MAX = 10;
|
|
|
25
25
|
* Cleans the dev profile to prevent stale-state startup failures.
|
|
26
26
|
*
|
|
27
27
|
* Removes two things:
|
|
28
|
-
* 1.
|
|
28
|
+
* 1. `startupCache/`: Firefox caches compiled chrome JS bytecode here.
|
|
29
29
|
* When chrome scripts change between builds, the stale cache causes silent
|
|
30
30
|
* crashes on startup.
|
|
31
|
-
* 2.
|
|
31
|
+
* 2. `.parentlock`: a zero-byte lock file that persists if the previous
|
|
32
32
|
* session was killed (Ctrl-C, crash, `kill`). Firefox checks this on
|
|
33
33
|
* startup and silently exits if it exists, assuming another instance owns
|
|
34
34
|
* the profile.
|
|
@@ -74,13 +74,13 @@ export async function runCommand(projectRoot, options = {}) {
|
|
|
74
74
|
remediation: "Run 'fireforge build' first, then rerun 'fireforge run'.",
|
|
75
75
|
requireExisting: true,
|
|
76
76
|
});
|
|
77
|
-
// `hasBuildArtifacts` only checks for an `obj-*/dist/` directory
|
|
77
|
+
// `hasBuildArtifacts` only checks for an `obj-*/dist/` directory. A build
|
|
78
78
|
// that configured but has not yet produced the launchable binary passes
|
|
79
79
|
// that check, and `mach run` then fails on the missing binary path.
|
|
80
80
|
// `hasRunnableBundle` narrows the probe to the actual executable so
|
|
81
81
|
// `fireforge run` refuses with a targeted message before handing control
|
|
82
82
|
// to mach. `fireforge watch` stays permissive and surfaces the same
|
|
83
|
-
// information as a banner suffix
|
|
83
|
+
// information as a banner suffix. Watch exists to drive rebuilds of
|
|
84
84
|
// partially-built trees, so blocking there would defeat it.
|
|
85
85
|
if (buildCheck.objDir) {
|
|
86
86
|
const config = await loadConfig(projectRoot);
|
|
@@ -104,12 +104,12 @@ export async function runCommand(projectRoot, options = {}) {
|
|
|
104
104
|
info('Launching browser...\n');
|
|
105
105
|
const exitCode = await run(paths.engine, options.headless ? ['--headless'] : []);
|
|
106
106
|
// Exit-code whitelist:
|
|
107
|
-
// 0
|
|
108
|
-
// 130
|
|
109
|
-
// 143
|
|
110
|
-
// SIGKILL (137) and other signal-induced codes are
|
|
111
|
-
//
|
|
112
|
-
//
|
|
107
|
+
// 0: clean shutdown
|
|
108
|
+
// 130: SIGINT (Ctrl+C), user-initiated termination
|
|
109
|
+
// 143: SIGTERM, graceful-shutdown termination
|
|
110
|
+
// SIGKILL (137) and other signal-induced codes are not whitelisted: those
|
|
111
|
+
// indicate abnormal termination the operator should see surface as a
|
|
112
|
+
// build-time error.
|
|
113
113
|
if (exitCode !== 0 && exitCode !== 130 && exitCode !== 143) {
|
|
114
114
|
throw new BuildError(`Browser exited with code ${exitCode}`, 'mach run');
|
|
115
115
|
}
|
|
@@ -141,7 +141,7 @@ async function runSmokeExit(engineDir, options) {
|
|
|
141
141
|
}
|
|
142
142
|
const smokeTimeoutMs = smokeExit * 1000;
|
|
143
143
|
if (smokeTimeoutMs < SMOKE_COLD_START_THRESHOLD_MS) {
|
|
144
|
-
// Not an error
|
|
144
|
+
// Not an error. Cold starts just tend to exceed the window. Surfacing
|
|
145
145
|
// the hint here instead of failing lets agents run shorter windows
|
|
146
146
|
// intentionally (e.g. warm-cache smoke checks).
|
|
147
147
|
verbose(`Smoke window is ${smokeExit}s; cold starts on slow machines often exceed 30s.`);
|
|
@@ -153,9 +153,9 @@ async function runSmokeExit(engineDir, options) {
|
|
|
153
153
|
// createWriteStream opens the fd asynchronously, so ENOENT / EACCES /
|
|
154
154
|
// EISDIR / EROFS surface as an 'error' event *after* the constructor
|
|
155
155
|
// returns. Without a listener Node re-throws as uncaughtException and
|
|
156
|
-
// kills the CLI mid-smoke-run
|
|
156
|
+
// kills the CLI mid-smoke-run, orphaning the mach → python → firefox
|
|
157
157
|
// tree because the deadline timer never fires. Swallow the event into a
|
|
158
|
-
// warning so the smoke run still terminates cleanly
|
|
158
|
+
// warning so the smoke run still terminates cleanly. Subsequent mirror
|
|
159
159
|
// writes on the errored stream are silent no-ops.
|
|
160
160
|
captureStream?.on('error', (err) => {
|
|
161
161
|
warn(`--capture-console stream error: ${err.message}`);
|
|
@@ -171,10 +171,10 @@ async function runSmokeExit(engineDir, options) {
|
|
|
171
171
|
const sink = stream === 'stdout' ? process.stdout : process.stderr;
|
|
172
172
|
sink.write(`${line}\n`);
|
|
173
173
|
// Count allowlist hits up-front, regardless of error-pattern match.
|
|
174
|
-
// Incrementing only when the line
|
|
174
|
+
// Incrementing only when the line also matches an error pattern makes an
|
|
175
175
|
// allowlist regex that visibly matches `console.warn: RSLoader:` report 0
|
|
176
|
-
// hits, because `console.warn:` is not a smoke error class
|
|
177
|
-
//
|
|
176
|
+
// hits, because `console.warn:` is not a smoke error class, which
|
|
177
|
+
// confuses operators tuning their allowlist. Two numbers are surfaced: the
|
|
178
178
|
// total set of allowlisted lines (what the operator sees in the console)
|
|
179
179
|
// and the subset that were error-class (what the smoke exit contract
|
|
180
180
|
// cares about). The exit contract itself is unchanged.
|
|
@@ -193,8 +193,8 @@ async function runSmokeExit(engineDir, options) {
|
|
|
193
193
|
findings.push({ stream, line });
|
|
194
194
|
};
|
|
195
195
|
// A headed smoke window on a developer desktop absorbs live input: a human
|
|
196
|
-
// interacting with the window mid-run can trigger console errors
|
|
197
|
-
// password-manager import scan probing an unreadable profile dir, say
|
|
196
|
+
// interacting with the window mid-run can trigger console errors (a
|
|
197
|
+
// password-manager import scan probing an unreadable profile dir, say)
|
|
198
198
|
// that fail the smoke run looking like a product regression. CI hosts (CI
|
|
199
199
|
// env var set) are assumed display-free and unattended, so the notice
|
|
200
200
|
// stays quiet there.
|
|
@@ -238,7 +238,7 @@ async function runSmokeExit(engineDir, options) {
|
|
|
238
238
|
throw new SmokeRunError(`Smoke run observed ${findings.length} unallowed console error(s).`, ExitCode.SMOKE_EXIT_FAILURE);
|
|
239
239
|
}
|
|
240
240
|
if (result.timedOut) {
|
|
241
|
-
// Clean window
|
|
241
|
+
// Clean window: SIGTERM came from us. Treat as success.
|
|
242
242
|
return;
|
|
243
243
|
}
|
|
244
244
|
if (result.exitCode === 0 || result.exitCode === 130 || result.exitCode === 143) {
|
|
@@ -248,9 +248,9 @@ async function runSmokeExit(engineDir, options) {
|
|
|
248
248
|
}
|
|
249
249
|
/**
|
|
250
250
|
* Compiles the active allowlist from `--console-allow` CLI values and
|
|
251
|
-
* the optional `--console-allow-file`. Fails fast on a bad regex
|
|
252
|
-
*
|
|
253
|
-
*
|
|
251
|
+
* the optional `--console-allow-file`. Fails fast on a bad regex, so the
|
|
252
|
+
* typo surfaces at parse time instead of silently matching nothing and
|
|
253
|
+
* turning every allowed hit into a smoke failure.
|
|
254
254
|
*/
|
|
255
255
|
async function buildAllowlist(options) {
|
|
256
256
|
const allow = [];
|
|
@@ -286,7 +286,7 @@ function reportSmokeSummary(args) {
|
|
|
286
286
|
info('');
|
|
287
287
|
info(`Smoke run complete: ${seconds}s elapsed of ${windowSeconds}s window${suffix}`);
|
|
288
288
|
info(` Unallowed errors: ${args.findings.length}`);
|
|
289
|
-
// The "suppressed errors" count is what the exit contract cares about
|
|
289
|
+
// The "suppressed errors" count is what the exit contract cares about: the
|
|
290
290
|
// subset of allowlisted hits that would otherwise have been tallied as
|
|
291
291
|
// findings. The "all allowlisted lines" count answers the operator's mental
|
|
292
292
|
// model ("my --console-allow pattern matched N console lines"), without
|
|
@@ -294,9 +294,9 @@ function reportSmokeSummary(args) {
|
|
|
294
294
|
info(` Allowlisted error hits (suppressed): ${args.allowlistedErrorHits}`);
|
|
295
295
|
info(` Allowlisted lines total: ${args.allowlistedTotalHits}`);
|
|
296
296
|
info(` Child exit code: ${args.exitCode}`);
|
|
297
|
-
// Per-entry attribution: first-match credit per line, with
|
|
298
|
-
//
|
|
299
|
-
//
|
|
297
|
+
// Per-entry attribution: first-match credit per line, with zero-hit
|
|
298
|
+
// entries always visible, since an allowlist entry whose suppressed shape
|
|
299
|
+
// changed upstream is only detectable as a 0× row.
|
|
300
300
|
if (args.allowlist.length > 0) {
|
|
301
301
|
info(' Allowlist attribution (first matching entry per line):');
|
|
302
302
|
args.allowlist.forEach((entry, index) => {
|
|
@@ -27,7 +27,7 @@ function renderLicenseTemplate(license, template, vendor, now = new Date()) {
|
|
|
27
27
|
*/
|
|
28
28
|
export function resolveFirefoxProduct(value, field) {
|
|
29
29
|
// Matches the sibling `resolveProjectLicense`, which already delegates to
|
|
30
|
-
// its guard. The `||` chain this replaced spelled the member list twice
|
|
30
|
+
// its guard. The `||` chain this replaced spelled the member list twice,
|
|
31
31
|
// once as the predicate and once in the message.
|
|
32
32
|
if (typeof value === 'string' && isValidFirefoxProduct(value)) {
|
|
33
33
|
return value;
|
|
@@ -194,7 +194,7 @@ function finalizePromptedSetupInputs(project) {
|
|
|
194
194
|
// Project names that contain no ASCII alphanumerics (e.g. "----", "漢字",
|
|
195
195
|
// emoji-only) collapse to an empty sanitised slug, which would silently
|
|
196
196
|
// produce an invalid `appId` ("org..browser") and an empty `binaryName`.
|
|
197
|
-
// Refuse to derive defaults from such names
|
|
197
|
+
// Refuse to derive defaults from such names. The user must supply
|
|
198
198
|
// explicit appId / binaryName values instead.
|
|
199
199
|
const explicitAppId = typeof project.appId === 'string' ? project.appId.trim() : '';
|
|
200
200
|
const explicitBinaryName = typeof project.binaryName === 'string' ? project.binaryName.trim() : '';
|
|
@@ -270,7 +270,7 @@ export function buildSetupConfig(inputs) {
|
|
|
270
270
|
/**
|
|
271
271
|
* Creates or updates the root `package.json` so its `license` field matches
|
|
272
272
|
* the project license selected during setup. When the file already exists
|
|
273
|
-
*
|
|
273
|
+
* only the `license` field is touched, preserving `name`, `description`,
|
|
274
274
|
* `dependencies`, `scripts`, and every other author-editorial field. Without
|
|
275
275
|
* this sync, a `fireforge setup --force` that picks a new license leaves the
|
|
276
276
|
* old one in `package.json`, so the two files describe different projects.
|
|
@@ -296,7 +296,7 @@ async function syncRootPackageJson(projectRoot, license) {
|
|
|
296
296
|
}
|
|
297
297
|
catch {
|
|
298
298
|
// Malformed package.json is the operator's editorial responsibility to
|
|
299
|
-
// repair
|
|
299
|
+
// repair. Rewriting it would risk clobbering hand-authored content that
|
|
300
300
|
// the parser happens to reject. Leave the file alone and rely on the
|
|
301
301
|
// doctor / lint paths that already surface invalid JSON.
|
|
302
302
|
return;
|