@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
package/dist/bin/fireforge.d.ts
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* FireForge CLI entry point, and the only file that may call process.exit().
|
|
4
4
|
* Library code propagates errors via CommandError or FireForgeError instead.
|
|
5
5
|
*
|
|
6
|
-
* The signal pipeline below composes several lifecycle modules
|
|
6
|
+
* The signal pipeline below composes several lifecycle modules. See
|
|
7
7
|
* docs/lifecycle-invariants.md for who owns what.
|
|
8
8
|
*/
|
|
9
9
|
export {};
|
package/dist/bin/fireforge.js
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* FireForge CLI entry point, and the only file that may call process.exit().
|
|
5
5
|
* Library code propagates errors via CommandError or FireForgeError instead.
|
|
6
6
|
*
|
|
7
|
-
* The signal pipeline below composes several lifecycle modules
|
|
7
|
+
* The signal pipeline below composes several lifecycle modules. See
|
|
8
8
|
* docs/lifecycle-invariants.md for who owns what.
|
|
9
9
|
*/
|
|
10
10
|
import { installBrokenPipeHandler, main } from '../src/cli.js';
|
|
@@ -28,22 +28,22 @@ const SIGNAL_CRITICAL_SECTION_TIMEOUT_MS = 5_000;
|
|
|
28
28
|
* under `run`/`test`, mach under `build`) to shut down after the signal was
|
|
29
29
|
* forwarded to them. Must exceed the largest child grace window
|
|
30
30
|
* (execSmokeRun's killGraceMs default of 10 s) so the SIGTERM → grace →
|
|
31
|
-
* SIGKILL escalation can complete
|
|
31
|
+
* SIGKILL escalation can complete. Exiting earlier orphans hung Firefox
|
|
32
32
|
* trees. A second Ctrl+C escalates to SIGKILL immediately.
|
|
33
33
|
*/
|
|
34
34
|
const CHILD_SHUTDOWN_TIMEOUT_MS = 12_000;
|
|
35
35
|
/**
|
|
36
36
|
* Upper bound (ms) a delayed exit waits for stdout/stderr to drain. A pipe
|
|
37
|
-
* is
|
|
38
|
-
* kernel buffer
|
|
39
|
-
* a stalled reader cannot wedge a failing process
|
|
40
|
-
* releases the wait immediately.
|
|
37
|
+
* is async, so `process.exit()` discards anything queued past the 64 KiB
|
|
38
|
+
* kernel buffer, which is enough to truncate a JSON payload mid-object.
|
|
39
|
+
* Bounded so a stalled reader cannot wedge a failing process. An
|
|
40
|
+
* EPIPE'd/closed pipe releases the wait immediately.
|
|
41
41
|
*/
|
|
42
42
|
const STDIO_FLUSH_TIMEOUT_MS = 5_000;
|
|
43
43
|
/**
|
|
44
|
-
* Drains stdio, then exits. Every delayed exit routes through here
|
|
45
|
-
* the second-Ctrl+C force-exit (an explicit
|
|
46
|
-
* own call terminate directly.
|
|
44
|
+
* Drains stdio, then exits. Every delayed exit routes through here. Only
|
|
45
|
+
* the second-Ctrl+C force-exit (an explicit request to quit at once) and
|
|
46
|
+
* this helper's own call terminate directly.
|
|
47
47
|
*/
|
|
48
48
|
function exitAfterStdioFlush(code) {
|
|
49
49
|
void waitForStdioDrain(STDIO_FLUSH_TIMEOUT_MS).finally(() => {
|
|
@@ -76,9 +76,9 @@ function installFurnaceSignalHandler(signal, exitCode) {
|
|
|
76
76
|
// A diagnostic must never keep the process from exiting.
|
|
77
77
|
}
|
|
78
78
|
if (isSignalRollbackInFlight()) {
|
|
79
|
-
// A second Ctrl+C while we're already rolling back
|
|
80
|
-
// out now
|
|
81
|
-
//
|
|
79
|
+
// A second Ctrl+C while we're already rolling back means the user
|
|
80
|
+
// wants out now, so let it terminate the process forcefully rather
|
|
81
|
+
// than queueing another rollback that will race the first.
|
|
82
82
|
process.exit(exitCode);
|
|
83
83
|
}
|
|
84
84
|
// Rollback, critical-section drain, and child shutdown run in parallel.
|
|
@@ -87,7 +87,7 @@ function installFurnaceSignalHandler(signal, exitCode) {
|
|
|
87
87
|
// applied to the engine but a stale session file that mis-tracks progress
|
|
88
88
|
// on `--continue`. Waiting on child shutdown keeps the parent alive through
|
|
89
89
|
// the SIGTERM → grace → SIGKILL escalation execInherit/execSmokeRun forward
|
|
90
|
-
// to Firefox/mach
|
|
90
|
+
// to Firefox/mach. Exiting first orphans those trees.
|
|
91
91
|
void Promise.allSettled([
|
|
92
92
|
rollbackActiveOperationsForSignal(signal).catch((error) => {
|
|
93
93
|
console.error(`Furnace rollback after ${signal} failed:`, error instanceof Error ? error.message : error);
|
|
@@ -98,15 +98,15 @@ function installFurnaceSignalHandler(signal, exitCode) {
|
|
|
98
98
|
// `withFileLock`'s `finally { rm }` never runs across `process.exit`,
|
|
99
99
|
// so both sweeps exist for the same reason. The generic one covers
|
|
100
100
|
// every lock this process holds (engine session, patch directory,
|
|
101
|
-
// build)
|
|
101
|
+
// build). The furnace one stays because it carries rollback
|
|
102
102
|
// bookkeeping the generic sweep does not, and runs after it so the
|
|
103
103
|
// ownership checks see a settled tree.
|
|
104
104
|
.then(() => forceReleaseHeldLocksForSignal())
|
|
105
105
|
.then(() => forceReleaseFurnaceLocksForActiveOperations())
|
|
106
106
|
// The run log's held partial line and queued writes do not survive
|
|
107
|
-
// `process.exit
|
|
107
|
+
// `process.exit`. The command's own `finally` that would close it is
|
|
108
108
|
// racing this handler and usually loses. Best-effort like the log
|
|
109
|
-
// itself
|
|
109
|
+
// itself: a diagnostic must never keep the process from exiting.
|
|
110
110
|
.then(() => closeActiveRunLog().catch(() => undefined))
|
|
111
111
|
.finally(() => {
|
|
112
112
|
exitAfterStdioFlush(exitCode);
|
|
@@ -120,7 +120,7 @@ main().catch((error) => {
|
|
|
120
120
|
exitAfterStdioFlush(error.exitCode);
|
|
121
121
|
return;
|
|
122
122
|
}
|
|
123
|
-
//
|
|
123
|
+
// Unexpected: withErrorHandling should have thrown a CommandError.
|
|
124
124
|
console.error('Fatal error:', error);
|
|
125
125
|
exitAfterStdioFlush(1);
|
|
126
126
|
});
|
package/dist/build-info.json
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
{
|
|
2
2
|
"schemaVersion": 1,
|
|
3
|
-
"version": "0.46.
|
|
4
|
-
"commit": "
|
|
5
|
-
"shortCommit": "
|
|
3
|
+
"version": "0.46.1",
|
|
4
|
+
"commit": "821990fd7d076a205f37618055c0a01a95180aed",
|
|
5
|
+
"shortCommit": "821990fd7d07",
|
|
6
6
|
"dirty": false,
|
|
7
7
|
"dirtyHash": null,
|
|
8
|
-
"buildTime": "2026-09-
|
|
8
|
+
"buildTime": "2026-09-05T22:29:34.415Z"
|
|
9
9
|
}
|
|
@@ -14,7 +14,7 @@ export declare function machineErrorCode(error: FireForgeError): string;
|
|
|
14
14
|
* Whether the invocation asked for machine-readable output.
|
|
15
15
|
*
|
|
16
16
|
* Reading the flag from argv is blunt but exact: if the invocation asked for
|
|
17
|
-
* machine output, stdout belongs to the payload from the first byte
|
|
17
|
+
* machine output, stdout belongs to the payload from the first byte, before
|
|
18
18
|
* commander has parsed anything.
|
|
19
19
|
*
|
|
20
20
|
* @param argv - Process argv (defaults to `process.argv`)
|
|
@@ -30,14 +30,14 @@ export declare function wantsMachineOutput(argv?: readonly string[]): boolean;
|
|
|
30
30
|
* already written their output, so those simply return. So does
|
|
31
31
|
* `commander.help`: a command group invoked with no subcommand (`fireforge`,
|
|
32
32
|
* `fireforge tree`), for which commander prints the group's help and would
|
|
33
|
-
* exit 1. That is an informational invocation
|
|
34
|
-
* `token` and `furnace` already answer it with help and exit 0
|
|
35
|
-
* explicit action, and the groups without one must not exit 8 (or
|
|
36
|
-
* commander's `(outputHelp)` placeholder into a `--json` envelope)
|
|
37
|
-
* for lacking it. A genuine usage error has already had its message
|
|
38
|
-
* to stderr by commander
|
|
39
|
-
* gets the standard refusal envelope on stdout so a scripted consumer
|
|
40
|
-
* parseable failure.
|
|
33
|
+
* exit 1. That is an informational invocation rather than a wrong flag.
|
|
34
|
+
* `patch`, `token` and `furnace` already answer it with help and exit 0
|
|
35
|
+
* through an explicit action, and the groups without one must not exit 8 (or
|
|
36
|
+
* leak commander's `(outputHelp)` placeholder into a `--json` envelope)
|
|
37
|
+
* merely for lacking it. A genuine usage error has already had its message
|
|
38
|
+
* written to stderr by commander. It becomes exit 8, and under `--json` it
|
|
39
|
+
* also gets the standard refusal envelope on stdout so a scripted consumer
|
|
40
|
+
* sees a parseable failure.
|
|
41
41
|
*
|
|
42
42
|
* @param error - Whatever `parseAsync` rejected with
|
|
43
43
|
* @param machineOutput - Whether the invocation asked for `--json`/`--raw`
|
|
@@ -5,8 +5,8 @@
|
|
|
5
5
|
* Commander terminates the process itself on a usage error (unknown option,
|
|
6
6
|
* missing argument, unknown command) with exit 1, which contradicts the
|
|
7
7
|
* documented `INVALID_ARGUMENT` (8) in `docs/exit-codes.md` and bypasses the
|
|
8
|
-
* `--json` refusal envelope because no action
|
|
9
|
-
* `withErrorHandling` wrapper
|
|
8
|
+
* `--json` refusal envelope because no action (and therefore no
|
|
9
|
+
* `withErrorHandling` wrapper) ever runs. `createProgram` installs
|
|
10
10
|
* `exitOverride()` so those failures surface as a thrown `CommanderError`,
|
|
11
11
|
* and `main` routes them through here.
|
|
12
12
|
*/
|
|
@@ -33,7 +33,7 @@ export function machineErrorCode(error) {
|
|
|
33
33
|
* Whether the invocation asked for machine-readable output.
|
|
34
34
|
*
|
|
35
35
|
* Reading the flag from argv is blunt but exact: if the invocation asked for
|
|
36
|
-
* machine output, stdout belongs to the payload from the first byte
|
|
36
|
+
* machine output, stdout belongs to the payload from the first byte, before
|
|
37
37
|
* commander has parsed anything.
|
|
38
38
|
*
|
|
39
39
|
* @param argv - Process argv (defaults to `process.argv`)
|
|
@@ -51,14 +51,14 @@ export function wantsMachineOutput(argv = process.argv) {
|
|
|
51
51
|
* already written their output, so those simply return. So does
|
|
52
52
|
* `commander.help`: a command group invoked with no subcommand (`fireforge`,
|
|
53
53
|
* `fireforge tree`), for which commander prints the group's help and would
|
|
54
|
-
* exit 1. That is an informational invocation
|
|
55
|
-
* `token` and `furnace` already answer it with help and exit 0
|
|
56
|
-
* explicit action, and the groups without one must not exit 8 (or
|
|
57
|
-
* commander's `(outputHelp)` placeholder into a `--json` envelope)
|
|
58
|
-
* for lacking it. A genuine usage error has already had its message
|
|
59
|
-
* to stderr by commander
|
|
60
|
-
* gets the standard refusal envelope on stdout so a scripted consumer
|
|
61
|
-
* parseable failure.
|
|
54
|
+
* exit 1. That is an informational invocation rather than a wrong flag.
|
|
55
|
+
* `patch`, `token` and `furnace` already answer it with help and exit 0
|
|
56
|
+
* through an explicit action, and the groups without one must not exit 8 (or
|
|
57
|
+
* leak commander's `(outputHelp)` placeholder into a `--json` envelope)
|
|
58
|
+
* merely for lacking it. A genuine usage error has already had its message
|
|
59
|
+
* written to stderr by commander. It becomes exit 8, and under `--json` it
|
|
60
|
+
* also gets the standard refusal envelope on stdout so a scripted consumer
|
|
61
|
+
* sees a parseable failure.
|
|
62
62
|
*
|
|
63
63
|
* @param error - Whatever `parseAsync` rejected with
|
|
64
64
|
* @param machineOutput - Whether the invocation asked for `--json`/`--raw`
|
|
@@ -71,7 +71,7 @@ export function handleParseError(error, machineOutput) {
|
|
|
71
71
|
if (error.exitCode === 0 || error.code === 'commander.help') {
|
|
72
72
|
return;
|
|
73
73
|
}
|
|
74
|
-
// Commander's message carries its own `error: ` prefix
|
|
74
|
+
// Commander's message carries its own `error: ` prefix. Strip it so the
|
|
75
75
|
// envelope text matches how every other refusal reads.
|
|
76
76
|
const usage = new InvalidArgumentError(error.message.replace(/^error:\s*/, ''));
|
|
77
77
|
if (machineOutput) {
|
package/dist/src/cli.d.ts
CHANGED
|
@@ -9,14 +9,15 @@ export declare function installBrokenPipeHandler(): void;
|
|
|
9
9
|
/**
|
|
10
10
|
* Removes the broken-pipe handler installed for CLI tests.
|
|
11
11
|
*
|
|
12
|
-
* @internal Exported only so tests can reach it
|
|
12
|
+
* @internal Exported only so tests can reach it. It is not part of the
|
|
13
|
+
* public surface.
|
|
13
14
|
*/
|
|
14
15
|
export declare function resetBrokenPipeHandlerForTests(): void;
|
|
15
16
|
/**
|
|
16
17
|
* Gets the project root directory.
|
|
17
18
|
* Walks up from the current working directory until a fireforge.json is found.
|
|
18
19
|
* Throws a {@link ConfigNotFoundError} (code: CONFIG_ERROR) when no
|
|
19
|
-
* fireforge.json is found within the walk depth limit
|
|
20
|
+
* fireforge.json is found within the walk depth limit. The error is
|
|
20
21
|
* user-facing so `withErrorHandling` can print the guidance without
|
|
21
22
|
* the stack dump that a plain `Error` would trigger.
|
|
22
23
|
*/
|
package/dist/src/cli.js
CHANGED
|
@@ -36,8 +36,8 @@ function getBrokenPipeHandler(state) {
|
|
|
36
36
|
/**
|
|
37
37
|
* Prints an error's `cause` chain under `--verbose`.
|
|
38
38
|
*
|
|
39
|
-
* Nine error classes declare a `cause` and twenty-two throw sites pass one
|
|
40
|
-
*
|
|
39
|
+
* Nine error classes declare a `cause` and twenty-two throw sites pass one.
|
|
40
|
+
* Without this the underlying git stderr, errno or parse failure never
|
|
41
41
|
* reaches the operator, because a `FireForgeError` renders as its
|
|
42
42
|
* `userMessage` and stops.
|
|
43
43
|
*
|
|
@@ -81,7 +81,8 @@ export function installBrokenPipeHandler() {
|
|
|
81
81
|
/**
|
|
82
82
|
* Removes the broken-pipe handler installed for CLI tests.
|
|
83
83
|
*
|
|
84
|
-
* @internal Exported only so tests can reach it
|
|
84
|
+
* @internal Exported only so tests can reach it. It is not part of the
|
|
85
|
+
* public surface.
|
|
85
86
|
*/
|
|
86
87
|
export function resetBrokenPipeHandlerForTests() {
|
|
87
88
|
const state = getProcessState();
|
|
@@ -97,14 +98,14 @@ export function resetBrokenPipeHandlerForTests() {
|
|
|
97
98
|
* Maximum number of directory levels to walk when searching for
|
|
98
99
|
* `fireforge.json`. `dirname()` walking is pure string manipulation and
|
|
99
100
|
* cannot cycle (the `parent === current` check already terminates at the
|
|
100
|
-
* root)
|
|
101
|
+
* root). This cap only bounds the cost on pathologically deep paths.
|
|
101
102
|
*/
|
|
102
103
|
const MAX_PROJECT_ROOT_WALK_DEPTH = 50;
|
|
103
104
|
/**
|
|
104
105
|
* Gets the project root directory.
|
|
105
106
|
* Walks up from the current working directory until a fireforge.json is found.
|
|
106
107
|
* Throws a {@link ConfigNotFoundError} (code: CONFIG_ERROR) when no
|
|
107
|
-
* fireforge.json is found within the walk depth limit
|
|
108
|
+
* fireforge.json is found within the walk depth limit. The error is
|
|
108
109
|
* user-facing so `withErrorHandling` can print the guidance without
|
|
109
110
|
* the stack dump that a plain `Error` would trigger.
|
|
110
111
|
*/
|
|
@@ -132,9 +133,9 @@ export function getProjectRoot() {
|
|
|
132
133
|
*/
|
|
133
134
|
export function withErrorHandling(handler) {
|
|
134
135
|
return async (...args) => {
|
|
135
|
-
// Rule 3 of docs/machine-output.md: machine mode engages
|
|
136
|
-
// output. Anything that throws on the way in
|
|
137
|
-
// `getProjectRoot`'s ConfigNotFoundError
|
|
136
|
+
// Rule 3 of docs/machine-output.md: machine mode engages before any
|
|
137
|
+
// output. Anything that throws on the way in (most visibly
|
|
138
|
+
// `getProjectRoot`'s ConfigNotFoundError) would otherwise render a
|
|
138
139
|
// clack-styled block to stdout and leave a `--json` consumer with
|
|
139
140
|
// un-parseable output. Reading the flag from argv is blunt but exact: if
|
|
140
141
|
// the invocation asked for machine output, stdout belongs to the payload
|
|
@@ -155,9 +156,9 @@ export function withErrorHandling(handler) {
|
|
|
155
156
|
}
|
|
156
157
|
if (error instanceof CancellationError) {
|
|
157
158
|
cancel('Operation cancelled');
|
|
158
|
-
// 130 (128+SIGINT) is the conventional "user interrupted" code
|
|
159
|
-
// scripts/CI can distinguish a
|
|
160
|
-
//
|
|
159
|
+
// 130 (128+SIGINT) is the conventional "user interrupted" code, so
|
|
160
|
+
// scripts/CI can distinguish a prompt cancellation from a real
|
|
161
|
+
// failure (which exits 1).
|
|
161
162
|
throw new CommandError(ExitCode.USER_CANCELLED);
|
|
162
163
|
}
|
|
163
164
|
// An invariant failure is the one FireForgeError whose stack is part
|
|
@@ -178,7 +179,7 @@ export function withErrorHandling(handler) {
|
|
|
178
179
|
logError(error.userMessage);
|
|
179
180
|
printCauseChain(error);
|
|
180
181
|
// Not when a payload already owns stdout: `status --json --fail-on`
|
|
181
|
-
// writes its full document and
|
|
182
|
+
// writes its full document and then refuses, and appending an
|
|
182
183
|
// envelope would make that two JSON documents.
|
|
183
184
|
if (machineOutput && !isStdoutSealed()) {
|
|
184
185
|
emitMachineError(machineErrorCode(error), error.message, error.code);
|
|
@@ -194,9 +195,9 @@ export function withErrorHandling(handler) {
|
|
|
194
195
|
}
|
|
195
196
|
finally {
|
|
196
197
|
// Central machine-mode and stdout-seal reset. Commands leave both
|
|
197
|
-
//
|
|
198
|
+
// engaged while an error propagates (a mid-throw restore would route
|
|
198
199
|
// the styled error to stdout, corrupting the `--json`/`--raw` payload
|
|
199
|
-
// stream or displacing the FIREFORGE-VERDICT line)
|
|
200
|
+
// stream or displacing the FIREFORGE-VERDICT line). The reset happens
|
|
200
201
|
// here, after logError has picked its stream, so no state leaks into a
|
|
201
202
|
// subsequent in-process invocation.
|
|
202
203
|
setMachineOutputMode(false);
|
|
@@ -244,9 +245,9 @@ function buildGroupedHelpFormatter(manifest) {
|
|
|
244
245
|
return formatHelpLine(term, desc, termWidth, helpWidth);
|
|
245
246
|
});
|
|
246
247
|
// -V/--version is handled in main() before commander parses (a real
|
|
247
|
-
// root-level `.version()` option would claim `--version`
|
|
248
|
+
// root-level `.version()` option would claim `--version` anywhere in
|
|
248
249
|
// argv under commander's default parsing, breaking subcommand flags
|
|
249
|
-
// like `source set --version <v>`)
|
|
250
|
+
// like `source set --version <v>`). Advertise it here so root help
|
|
250
251
|
// stays truthful.
|
|
251
252
|
optionLines.unshift(formatHelpLine('-V, --version', 'output the version number', termWidth, helpWidth));
|
|
252
253
|
if (optionLines.length > 0) {
|
|
@@ -328,7 +329,7 @@ export function createProgram() {
|
|
|
328
329
|
const program = new Command();
|
|
329
330
|
program
|
|
330
331
|
.name('fireforge')
|
|
331
|
-
// Usage errors must
|
|
332
|
+
// Usage errors must not let commander call process.exit(1) itself: the
|
|
332
333
|
// documented code is INVALID_ARGUMENT (8) and `--json` owes a refusal
|
|
333
334
|
// envelope. Installed before any subcommand registers, because
|
|
334
335
|
// `.command()` copies the override into the child at creation time.
|
|
@@ -342,9 +343,9 @@ export function createProgram() {
|
|
|
342
343
|
setVerbose(true);
|
|
343
344
|
}
|
|
344
345
|
})
|
|
345
|
-
// Verification-tree guard: when the cwd resolves into a
|
|
346
|
-
//
|
|
347
|
-
//
|
|
346
|
+
// Verification-tree guard: when the cwd resolves into a tree snapshot,
|
|
347
|
+
// refuse mutating commands before their action runs. One hook covers
|
|
348
|
+
// every command regardless of how the cwd got there.
|
|
348
349
|
.hook('preAction', async (thisCommand, actionCommand) => {
|
|
349
350
|
await runTreeGuardHook(thisCommand.name(), actionCommand);
|
|
350
351
|
});
|
|
@@ -359,7 +360,7 @@ export function createProgram() {
|
|
|
359
360
|
// Uniform `--wait-lock`: scripted sequences blanket-append the flag, and a
|
|
360
361
|
// subcommand that rejects it with "unknown option" kills the sequence with
|
|
361
362
|
// a usage error instead of a lock message. Applied after registration so it
|
|
362
|
-
// covers every subcommand at every depth
|
|
363
|
+
// covers every subcommand at every depth. Commands that already declare the
|
|
363
364
|
// honoring flag keep it untouched.
|
|
364
365
|
ensureWaitLockOptionEverywhere(program);
|
|
365
366
|
return program;
|
|
@@ -368,13 +369,13 @@ export function createProgram() {
|
|
|
368
369
|
* Main CLI entry point.
|
|
369
370
|
*/
|
|
370
371
|
export async function main() {
|
|
371
|
-
// Root-level --version/-V handling.
|
|
372
|
-
//
|
|
373
|
-
//
|
|
374
|
-
//
|
|
375
|
-
//
|
|
376
|
-
//
|
|
377
|
-
//
|
|
372
|
+
// Root-level --version/-V handling. This is not a commander `.version()`
|
|
373
|
+
// option, because under commander's default (non-positional) parsing a
|
|
374
|
+
// root version option claims `--version` anywhere in argv and hijacks
|
|
375
|
+
// subcommand flags like `source set --version <v>`. The rule here: when no
|
|
376
|
+
// subcommand was given, any -V/--version among the root flags prints the
|
|
377
|
+
// version, so `fireforge --verbose --version` works and
|
|
378
|
+
// `fireforge source set --version 152` is untouched.
|
|
378
379
|
const userArgs = process.argv.slice(2);
|
|
379
380
|
const hasSubcommand = userArgs.some((arg) => !arg.startsWith('-'));
|
|
380
381
|
if (!hasSubcommand && userArgs.some((arg) => arg === '--version' || arg === '-V')) {
|
|
@@ -13,7 +13,8 @@ export function detectBootstrapIssues(output) {
|
|
|
13
13
|
const hasTraceback = /traceback \(most recent call last\):/i.test(normalized);
|
|
14
14
|
const has403 = /\bhttp(?:\s+error)?\s*403\b/i.test(normalized) || /\b403\b.*forbidden/i.test(normalized);
|
|
15
15
|
if (has403) {
|
|
16
|
-
// The traceback is just the stack trace from the HTTP error
|
|
16
|
+
// The traceback is just the stack trace from the HTTP error, so report
|
|
17
|
+
// it once.
|
|
17
18
|
issues.push('sdk-fetch-403');
|
|
18
19
|
}
|
|
19
20
|
else if (hasTraceback) {
|
|
@@ -23,7 +23,7 @@ const BOOTSTRAP_FAILURE_SENTENCES = {
|
|
|
23
23
|
function buildBootstrapFailureMessage(output) {
|
|
24
24
|
// Delegates detection to the canonical scanner rather than keeping a
|
|
25
25
|
// second copy of its six regexes. The copies had already disagreed: this
|
|
26
|
-
// one reported a traceback
|
|
26
|
+
// one reported a traceback and a 403 separately, while
|
|
27
27
|
// `detectBootstrapIssues` collapses them, because a bootstrap traceback
|
|
28
28
|
// accompanying a 403 is just the stack trace from that HTTP error.
|
|
29
29
|
const issues = detectBootstrapIssues(output).map((issue) => BOOTSTRAP_FAILURE_SENTENCES[issue]);
|
|
@@ -79,7 +79,7 @@ export async function bootstrapCommand(projectRoot) {
|
|
|
79
79
|
if (hasErrors) {
|
|
80
80
|
outro('Build dependencies installed with errors');
|
|
81
81
|
// Propagate the failure (mirroring doctor's exit-code handling)
|
|
82
|
-
// instead of exiting 0
|
|
82
|
+
// instead of exiting 0. CI gating on bootstrap used to proceed to a
|
|
83
83
|
// build that could not succeed because error-severity check results
|
|
84
84
|
// were discarded here.
|
|
85
85
|
return checksExitCode;
|
|
@@ -30,9 +30,9 @@ function parseJobCount(value) {
|
|
|
30
30
|
* Patches `mozinfo.json` under the active obj-* directory so its recorded
|
|
31
31
|
* paths match the current engine checkout, then runs `mach configure` to
|
|
32
32
|
* regenerate every other generated path alongside it. Throws with the
|
|
33
|
-
* original mismatch guidance when the rewriter refuses to proceed
|
|
34
|
-
*
|
|
35
|
-
*
|
|
33
|
+
* original mismatch guidance when the rewriter refuses to proceed. That
|
|
34
|
+
* covers the unsafe cases, so the operator still gets the correct fallback
|
|
35
|
+
* recovery instruction.
|
|
36
36
|
*/
|
|
37
37
|
async function rewriteAndReconfigure(engineDir, objDir, mismatchMessage) {
|
|
38
38
|
const rewriteSpinner = spinner('Rewriting mozinfo.json paths...');
|
|
@@ -201,7 +201,7 @@ async function runBuildCommandBody(projectRoot, options) {
|
|
|
201
201
|
// and fail fast naming `fireforge bootstrap` instead of dying ~8s into
|
|
202
202
|
// configure with mach's "./mach bootstrap" remediation text. Fail-soft by
|
|
203
203
|
// design: only a definitively parsed minimum vs a definitively probed host
|
|
204
|
-
// version can fail here
|
|
204
|
+
// version can fail here. Anything uncertain proceeds to mach, where the
|
|
205
205
|
// mach-error-hints translator still names the right remedy.
|
|
206
206
|
const toolchainMismatches = await runToolchainPreflight(paths.engine);
|
|
207
207
|
if (toolchainMismatches.length > 0) {
|
|
@@ -217,7 +217,7 @@ async function runBuildCommandBody(projectRoot, options) {
|
|
|
217
217
|
// Safe-relocation rewrite path: patch mozinfo.json paths in place so
|
|
218
218
|
// `mach configure` can regenerate the backend without scrubbing the
|
|
219
219
|
// whole obj tree. The rewriter refuses anything that is not a pure
|
|
220
|
-
// prefix-move
|
|
220
|
+
// prefix-move. On refusal we surface the refusal reason alongside
|
|
221
221
|
// the original mismatch guidance and abort.
|
|
222
222
|
await rewriteAndReconfigure(paths.engine, buildCheck.objDir, mismatchMessage);
|
|
223
223
|
}
|
|
@@ -275,7 +275,7 @@ async function runBuildCommandBody(projectRoot, options) {
|
|
|
275
275
|
// overlapping `fireforge build` / `fireforge build --ui` commands
|
|
276
276
|
// against the same engine tree serialise instead of racing through the
|
|
277
277
|
// same obj-*. A `build --ui` launched during an in-progress full build
|
|
278
|
-
// otherwise hits `No rule to make target 'XUL'` in mach
|
|
278
|
+
// otherwise hits `No rule to make target 'XUL'` in mach, the
|
|
279
279
|
// downstream consequence of an incomplete backend, with no clue that a
|
|
280
280
|
// concurrent build caused it. The lock turns the second invocation's
|
|
281
281
|
// failure into an explicit refusal naming the holder PID.
|
|
@@ -313,9 +313,10 @@ async function runBuildCommandBody(projectRoot, options) {
|
|
|
313
313
|
// Matching only (1) leaves operators on the (2) path seeing mach's own
|
|
314
314
|
// "Configure complete!" and "run |mach build|" lines unexplained between
|
|
315
315
|
// mach's "Your build was successful!" and FireForge's "Build completed in
|
|
316
|
-
// Xm Ys" outro
|
|
317
|
-
// annotation, emitted
|
|
318
|
-
// terminal line is the explanation
|
|
316
|
+
// Xm Ys" outro, a contradictory tail. Both shapes route through the same
|
|
317
|
+
// annotation, emitted before FireForge's outro so the operator's last
|
|
318
|
+
// terminal line is the explanation instead of the confusing mach guard
|
|
319
|
+
// text.
|
|
319
320
|
const staleConfigurePatterns = [
|
|
320
321
|
/config\.status is out of date/i,
|
|
321
322
|
/Config object not found by mach\.[\s\S]*Configure complete!/i,
|
|
@@ -329,7 +330,7 @@ async function runBuildCommandBody(projectRoot, options) {
|
|
|
329
330
|
}
|
|
330
331
|
// Warn-only post-build audit: surfaces silent packaging drops (files
|
|
331
332
|
// edited in engine/ but never registered for packaging) against the
|
|
332
|
-
// previous-build baseline. Never fails the build
|
|
333
|
+
// previous-build baseline. Never fails the build. The worst case is a
|
|
333
334
|
// warning an operator chooses to investigate.
|
|
334
335
|
try {
|
|
335
336
|
await auditBuildArtifacts(projectRoot, paths.engine, previousBaseline, {
|
|
@@ -346,7 +347,7 @@ async function runBuildCommandBody(projectRoot, options) {
|
|
|
346
347
|
outro(`Build completed in ${timeStr}!`);
|
|
347
348
|
}
|
|
348
349
|
/**
|
|
349
|
-
* Persists the full-coverage baseline
|
|
350
|
+
* Persists the full-coverage baseline. A failed write never fails the build.
|
|
350
351
|
* `--ui` is a `mach build faster`, so it is recorded as such: its `jar.mn`
|
|
351
352
|
* fingerprints are carried forward from the previous baseline rather than
|
|
352
353
|
* refreshed, which is why that baseline is threaded through.
|
|
@@ -89,7 +89,7 @@ export async function configCommand(projectRoot, key, value, options = {}) {
|
|
|
89
89
|
throw new GeneralError('No fireforge.json found. Run "fireforge setup" to create a project.');
|
|
90
90
|
}
|
|
91
91
|
if (value === undefined) {
|
|
92
|
-
// Get mode
|
|
92
|
+
// Get mode: read the raw document rather than the validated config so
|
|
93
93
|
// keys persisted via `fireforge config <key> --force` remain readable.
|
|
94
94
|
// `validateConfig` builds a typed clone containing only the known schema
|
|
95
95
|
// fields, so relying on it here would hide forced-write keys and surface
|
|
@@ -110,7 +110,7 @@ export async function configCommand(projectRoot, key, value, options = {}) {
|
|
|
110
110
|
}
|
|
111
111
|
}
|
|
112
112
|
else {
|
|
113
|
-
// Set mode
|
|
113
|
+
// Set mode: validate key prefix
|
|
114
114
|
const topLevelKey = key.split('.')[0] ?? key;
|
|
115
115
|
if (!SUPPORTED_CONFIG_ROOT_KEYS.includes(topLevelKey) &&
|
|
116
116
|
!options.force) {
|
|
@@ -126,7 +126,7 @@ export async function configCommand(projectRoot, key, value, options = {}) {
|
|
|
126
126
|
// Serialise the read → mutate → write round-trip behind the sidecar
|
|
127
127
|
// config lock so two concurrent `fireforge config` invocations cannot
|
|
128
128
|
// each read the pre-state, mutate their own copy, and clobber each
|
|
129
|
-
// other on write
|
|
129
|
+
// other on write, both exiting 0 with one key silently lost. Atomic
|
|
130
130
|
// file writes (temp + rename) are not enough on their own: the lost
|
|
131
131
|
// update happens before the rename, inside the read-modify step.
|
|
132
132
|
// Readers stay lock-free (see `withConfigFileLock`).
|
|
@@ -143,12 +143,12 @@ export async function configCommand(projectRoot, key, value, options = {}) {
|
|
|
143
143
|
if (deepEqual(currentValue, parsedValue)) {
|
|
144
144
|
return true;
|
|
145
145
|
}
|
|
146
|
-
// `--force` is an escape hatch for
|
|
147
|
-
// let the user write a structurally invalid value for a
|
|
146
|
+
// `--force` is an escape hatch for unknown keys. It must not also
|
|
147
|
+
// let the user write a structurally invalid value for a known key.
|
|
148
148
|
// Strict validation applies whenever the key is listed in
|
|
149
149
|
// SUPPORTED_CONFIG_PATHS, regardless of --force.
|
|
150
150
|
//
|
|
151
|
-
//
|
|
151
|
+
// Both branches seed the mutation from the raw on-disk document.
|
|
152
152
|
// Round-tripping the known-key branch through `loadConfig` →
|
|
153
153
|
// `validateConfig` builds a typed clone containing only the known
|
|
154
154
|
// schema fields, so any ordinary `fireforge config <key> <value>`
|
|
@@ -160,7 +160,7 @@ export async function configCommand(projectRoot, key, value, options = {}) {
|
|
|
160
160
|
}
|
|
161
161
|
else {
|
|
162
162
|
// Mutate the raw document (preserving unknown keys), then run
|
|
163
|
-
// strict validation on the
|
|
163
|
+
// strict validation on the result. validateConfig checks the
|
|
164
164
|
// known schema fields and ignores unknown keys, so this keeps
|
|
165
165
|
// exactly the old validation strength while writing the
|
|
166
166
|
// unstripped document.
|
|
@@ -174,7 +174,7 @@ export async function configCommand(projectRoot, key, value, options = {}) {
|
|
|
174
174
|
catch (error) {
|
|
175
175
|
// Only value/validation problems are the user's "invalid value".
|
|
176
176
|
// Lock-acquisition timeouts and I/O failures must keep their own
|
|
177
|
-
// types and messages
|
|
177
|
+
// types and messages. Re-labelling a lock timeout as `Invalid value
|
|
178
178
|
// for "<key>"` points diagnosis at the value (and returns the wrong
|
|
179
179
|
// exit-code class) when the real problem is a concurrent fireforge
|
|
180
180
|
// process holding the config lock.
|
|
@@ -195,7 +195,7 @@ export async function configCommand(projectRoot, key, value, options = {}) {
|
|
|
195
195
|
/**
|
|
196
196
|
* Structural equality check covering the shapes `fireforge config` accepts:
|
|
197
197
|
* primitives (strings, numbers, booleans), `null`, arrays of primitives, and
|
|
198
|
-
* nested objects. Used to short-circuit no-op writes
|
|
198
|
+
* nested objects. Used to short-circuit no-op writes: when the parsed value
|
|
199
199
|
* matches the current on-disk value, the mutate + write step is skipped
|
|
200
200
|
* entirely.
|
|
201
201
|
*/
|
|
@@ -6,12 +6,12 @@ import type { DestructiveOpResult } from '../core/destructive.js';
|
|
|
6
6
|
* Eleven commands had copied the same tail: `if (decision === 'dry-run') {
|
|
7
7
|
* outro(…); return; } if (decision === 'declined') { outro(…); return; }`.
|
|
8
8
|
* The dry-run wording is a user-facing contract that must not drift between
|
|
9
|
-
* commands, so it lives here
|
|
10
|
-
* parameter.
|
|
9
|
+
* commands, so it lives here. The declined wording is per-command and stays
|
|
10
|
+
* a parameter.
|
|
11
11
|
*
|
|
12
12
|
* `confirmDestructive` never mutates on its own, so a caller that forgets this
|
|
13
|
-
* check silently performs a "dry run" for real
|
|
14
|
-
* caller must act on
|
|
13
|
+
* check silently performs a "dry run" for real. That is why this returns a
|
|
14
|
+
* boolean the caller must act on instead of being a helper that returns void.
|
|
15
15
|
* @param decision - The result from `confirmDestructive`.
|
|
16
16
|
* @param declinedOutro - Outro to print when the operator answered "no".
|
|
17
17
|
* @returns True when the caller should proceed with the mutation.
|
|
@@ -8,12 +8,12 @@ const DRY_RUN_OUTRO = 'Dry run complete — no changes made';
|
|
|
8
8
|
* Eleven commands had copied the same tail: `if (decision === 'dry-run') {
|
|
9
9
|
* outro(…); return; } if (decision === 'declined') { outro(…); return; }`.
|
|
10
10
|
* The dry-run wording is a user-facing contract that must not drift between
|
|
11
|
-
* commands, so it lives here
|
|
12
|
-
* parameter.
|
|
11
|
+
* commands, so it lives here. The declined wording is per-command and stays
|
|
12
|
+
* a parameter.
|
|
13
13
|
*
|
|
14
14
|
* `confirmDestructive` never mutates on its own, so a caller that forgets this
|
|
15
|
-
* check silently performs a "dry run" for real
|
|
16
|
-
* caller must act on
|
|
15
|
+
* check silently performs a "dry run" for real. That is why this returns a
|
|
16
|
+
* boolean the caller must act on instead of being a helper that returns void.
|
|
17
17
|
* @param decision - The result from `confirmDestructive`.
|
|
18
18
|
* @param declinedOutro - Outro to print when the operator answered "no".
|
|
19
19
|
* @returns True when the caller should proceed with the mutation.
|
|
@@ -103,7 +103,7 @@ async function discardDirectoryEntries(projectRoot, engineDir, patchesDir, dirPa
|
|
|
103
103
|
}
|
|
104
104
|
}
|
|
105
105
|
catch {
|
|
106
|
-
// Furnace config may not exist
|
|
106
|
+
// Furnace config may not exist, so skip silently.
|
|
107
107
|
}
|
|
108
108
|
if (failures.length > 0) {
|
|
109
109
|
throw new GeneralError(`Failed to discard ${failures.length} file(s) under ${dirPath}/. See warnings above.`);
|
|
@@ -131,7 +131,7 @@ export async function discardCommand(projectRoot, file, options = {}) {
|
|
|
131
131
|
const statusEntries = await expandUntrackedDirectoryEntries(paths.engine, await getWorkingTreeStatus(paths.engine));
|
|
132
132
|
const statusEntry = statusEntries.find((entry) => entry.file === file || entry.originalPath === file);
|
|
133
133
|
// Directory recursion fallback: when the explicit path does not match a
|
|
134
|
-
// single status entry but
|
|
134
|
+
// single status entry but does correspond to one or more entries below it,
|
|
135
135
|
// treat the input as a directory and discard everything inside. Otherwise
|
|
136
136
|
// `discard <dir> --yes` fails with "no changes to discard" even though
|
|
137
137
|
// `status --unmanaged` lists files under that directory, forcing the
|
|
@@ -159,8 +159,8 @@ export async function discardCommand(projectRoot, file, options = {}) {
|
|
|
159
159
|
throw new GeneralError(`File "${file}" has no changes to discard.`);
|
|
160
160
|
}
|
|
161
161
|
if (options.dryRun) {
|
|
162
|
-
// Show the rename pair regardless of which side the operator passed
|
|
163
|
-
//
|
|
162
|
+
// Show the rename pair regardless of which side the operator passed.
|
|
163
|
+
// Passing the new path of a rename used to hide that discarding also
|
|
164
164
|
// resurrects the old path, exactly when the full picture matters most.
|
|
165
165
|
info(`Would discard changes to: ${dryRunLabel(plan)}`);
|
|
166
166
|
outro('Dry run complete — no changes made');
|
|
@@ -182,7 +182,7 @@ export async function discardCommand(projectRoot, file, options = {}) {
|
|
|
182
182
|
}
|
|
183
183
|
}
|
|
184
184
|
catch {
|
|
185
|
-
// Furnace config may not exist
|
|
185
|
+
// Furnace config may not exist, so skip silently.
|
|
186
186
|
}
|
|
187
187
|
outro(describeDiscardOutcome(plan, options.toUpstream === true));
|
|
188
188
|
}
|