@hominis/fireforge 0.43.0 → 0.44.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +127 -0
- package/README.md +10 -1
- package/dist/bin/fireforge.d.ts +4 -9
- package/dist/bin/fireforge.js +42 -40
- package/dist/build-info.json +4 -4
- package/dist/src/cli.js +74 -8
- package/dist/src/commands/bootstrap.js +17 -20
- package/dist/src/commands/build.js +25 -32
- package/dist/src/commands/config.js +34 -41
- package/dist/src/commands/discard.js +8 -9
- package/dist/src/commands/doctor-check-core.d.ts +4 -18
- package/dist/src/commands/doctor-check-core.js +8 -35
- package/dist/src/commands/doctor-external-toolchains.js +2 -2
- package/dist/src/commands/doctor-furnace-config-sync.d.ts +18 -0
- package/dist/src/commands/{doctor-furnace-manifest-sync.js → doctor-furnace-config-sync.js} +27 -26
- package/dist/src/commands/doctor-furnace-jar.d.ts +7 -9
- package/dist/src/commands/doctor-furnace-jar.js +7 -9
- package/dist/src/commands/doctor-furnace.js +21 -24
- package/dist/src/commands/doctor-orphaned-harness.d.ts +16 -20
- package/dist/src/commands/doctor-orphaned-harness.js +18 -44
- package/dist/src/commands/doctor-post-rebase-audit.d.ts +2 -0
- package/dist/src/commands/{doctor/post-rebase-audit.js → doctor-post-rebase-audit.js} +3 -3
- package/dist/src/commands/doctor-working-tree.d.ts +10 -12
- package/dist/src/commands/doctor-working-tree.js +11 -18
- package/dist/src/commands/doctor.js +35 -53
- package/dist/src/commands/download.js +32 -48
- package/dist/src/commands/export-all.js +29 -33
- package/dist/src/commands/export-flow.js +6 -6
- package/dist/src/commands/export-placement-conflicts.js +10 -9
- package/dist/src/commands/export-placement-gate.js +5 -5
- package/dist/src/commands/export-shared.d.ts +30 -33
- package/dist/src/commands/export-shared.js +45 -43
- package/dist/src/commands/export.js +21 -27
- package/dist/src/commands/furnace/apply.js +14 -23
- package/dist/src/commands/furnace/chrome-doc-remove.js +14 -21
- package/dist/src/commands/furnace/chrome-doc-templates.d.ts +23 -23
- package/dist/src/commands/furnace/chrome-doc-templates.js +23 -23
- package/dist/src/commands/furnace/chrome-doc-tests.js +26 -29
- package/dist/src/commands/furnace/chrome-doc.d.ts +16 -17
- package/dist/src/commands/furnace/chrome-doc.js +31 -41
- package/dist/src/commands/furnace/create-browser-test.d.ts +4 -4
- package/dist/src/commands/furnace/create-browser-test.js +8 -8
- package/dist/src/commands/furnace/create-mochikit.d.ts +6 -7
- package/dist/src/commands/furnace/create-mochikit.js +8 -9
- package/dist/src/commands/furnace/create-readback.d.ts +12 -13
- package/dist/src/commands/furnace/create-readback.js +12 -13
- package/dist/src/commands/furnace/create-templates.d.ts +22 -28
- package/dist/src/commands/furnace/create-templates.js +35 -30
- package/dist/src/commands/furnace/create-xpcshell.js +2 -2
- package/dist/src/commands/furnace/create.js +33 -23
- package/dist/src/commands/furnace/deploy.js +16 -24
- package/dist/src/commands/furnace/diff.js +9 -9
- package/dist/src/commands/furnace/init.js +33 -36
- package/dist/src/commands/furnace/override.js +23 -25
- package/dist/src/commands/furnace/preview.js +47 -67
- package/dist/src/commands/furnace/refresh.js +12 -16
- package/dist/src/commands/furnace/remove-mutations.d.ts +3 -6
- package/dist/src/commands/furnace/remove-mutations.js +9 -16
- package/dist/src/commands/furnace/remove-state.js +1 -1
- package/dist/src/commands/furnace/remove.js +33 -38
- package/dist/src/commands/furnace/rename-xpcshell.d.ts +8 -11
- package/dist/src/commands/furnace/rename-xpcshell.js +8 -11
- package/dist/src/commands/furnace/rename.js +59 -69
- package/dist/src/commands/furnace/scan.js +19 -33
- package/dist/src/commands/furnace/status.js +12 -9
- package/dist/src/commands/furnace/sync.js +9 -16
- package/dist/src/commands/furnace/validate.js +20 -20
- package/dist/src/commands/import.js +42 -35
- package/dist/src/commands/lint-per-patch.js +15 -10
- package/dist/src/commands/lint-per-run-checkjs.d.ts +13 -13
- package/dist/src/commands/lint-per-run-checkjs.js +13 -13
- package/dist/src/commands/lint-report.js +6 -7
- package/dist/src/commands/lint.d.ts +15 -16
- package/dist/src/commands/lint.js +86 -102
- package/dist/src/commands/package.js +6 -11
- package/dist/src/commands/patch/compact.js +1 -1
- package/dist/src/commands/patch/delete.js +24 -33
- package/dist/src/commands/patch/index.d.ts +5 -6
- package/dist/src/commands/patch/index.js +10 -12
- package/dist/src/commands/patch/lint-ignore.js +14 -13
- package/dist/src/commands/patch/move-files-create.d.ts +6 -6
- package/dist/src/commands/patch/move-files-create.js +8 -8
- package/dist/src/commands/patch/move-files-into.d.ts +6 -6
- package/dist/src/commands/patch/move-files-into.js +8 -8
- package/dist/src/commands/patch/patch-context.d.ts +2 -3
- package/dist/src/commands/patch/patch-context.js +2 -3
- package/dist/src/commands/patch/rename.d.ts +10 -11
- package/dist/src/commands/patch/rename.js +11 -12
- package/dist/src/commands/patch/reorder.js +8 -9
- package/dist/src/commands/patch/split-plan.js +1 -1
- package/dist/src/commands/patch/split.d.ts +8 -10
- package/dist/src/commands/patch/split.js +9 -11
- package/dist/src/commands/patch/staged-dependency-validate.js +8 -8
- package/dist/src/commands/patch/staged-dependency.js +7 -3
- package/dist/src/commands/patch/tier.d.ts +9 -9
- package/dist/src/commands/patch/tier.js +18 -15
- package/dist/src/commands/re-export-adjacent.js +9 -8
- package/dist/src/commands/re-export-bulk-scan.d.ts +9 -9
- package/dist/src/commands/re-export-bulk-scan.js +22 -21
- package/dist/src/commands/re-export-drift.js +10 -10
- package/dist/src/commands/re-export-files.d.ts +6 -7
- package/dist/src/commands/re-export-files.js +34 -44
- package/dist/src/commands/re-export-lint.d.ts +10 -13
- package/dist/src/commands/re-export-lint.js +16 -14
- package/dist/src/commands/re-export-options.d.ts +6 -6
- package/dist/src/commands/re-export-options.js +6 -6
- package/dist/src/commands/re-export-register.d.ts +4 -10
- package/dist/src/commands/re-export-register.js +5 -11
- package/dist/src/commands/re-export-scan.js +1 -1
- package/dist/src/commands/re-export-single.d.ts +3 -3
- package/dist/src/commands/re-export-single.js +33 -25
- package/dist/src/commands/re-export.js +13 -21
- package/dist/src/commands/rebase/abort.js +3 -3
- package/dist/src/commands/rebase/confirm.js +2 -1
- package/dist/src/commands/rebase/continue.d.ts +1 -1
- package/dist/src/commands/rebase/continue.js +14 -9
- package/dist/src/commands/rebase/index.js +11 -11
- package/dist/src/commands/rebase/patch-loop.d.ts +7 -1
- package/dist/src/commands/rebase/patch-loop.js +60 -39
- package/dist/src/commands/rebase/summary.js +1 -1
- package/dist/src/commands/register.js +5 -7
- package/dist/src/commands/reset.js +2 -1
- package/dist/src/commands/resolve.d.ts +16 -13
- package/dist/src/commands/resolve.js +30 -33
- package/dist/src/commands/run.js +33 -35
- package/dist/src/commands/setup-support.js +15 -19
- package/dist/src/commands/setup.js +13 -9
- package/dist/src/commands/status-check.d.ts +6 -6
- package/dist/src/commands/status-json.d.ts +6 -6
- package/dist/src/commands/status-json.js +5 -0
- package/dist/src/commands/status-output.d.ts +5 -5
- package/dist/src/commands/status-output.js +6 -6
- package/dist/src/commands/status-ownership.d.ts +16 -14
- package/dist/src/commands/status-ownership.js +16 -14
- package/dist/src/commands/status.js +42 -34
- package/dist/src/commands/test-build-phase.js +26 -13
- package/dist/src/commands/test-diagnose.js +44 -44
- package/dist/src/commands/test-register.js +1 -0
- package/dist/src/commands/test-run.d.ts +14 -16
- package/dist/src/commands/test-run.js +21 -13
- package/dist/src/commands/test-stale-gate.d.ts +15 -16
- package/dist/src/commands/test-stale-gate.js +15 -16
- package/dist/src/commands/test-verdict.d.ts +20 -3
- package/dist/src/commands/test-verdict.js +30 -0
- package/dist/src/commands/test.js +83 -76
- package/dist/src/commands/token-coverage.js +3 -4
- package/dist/src/commands/token.js +16 -18
- package/dist/src/commands/tree.js +47 -31
- package/dist/src/commands/typecheck.d.ts +10 -12
- package/dist/src/commands/typecheck.js +24 -27
- package/dist/src/commands/verify.js +13 -15
- package/dist/src/commands/watch.js +21 -23
- package/dist/src/commands/wire.js +52 -62
- package/dist/src/core/ast-utils.d.ts +8 -7
- package/dist/src/core/ast-utils.js +8 -7
- package/dist/src/core/branding.d.ts +9 -14
- package/dist/src/core/branding.js +7 -11
- package/dist/src/core/browser-wire.d.ts +1 -1
- package/dist/src/core/browser-wire.js +14 -19
- package/dist/src/core/build-audit-platform.js +25 -33
- package/dist/src/core/build-audit-registration.js +17 -25
- package/dist/src/core/build-audit-resolve.d.ts +15 -17
- package/dist/src/core/build-audit-resolve.js +27 -33
- package/dist/src/core/build-audit-transforms.js +18 -19
- package/dist/src/core/build-audit.js +28 -42
- package/dist/src/core/build-baseline-types.d.ts +29 -35
- package/dist/src/core/build-baseline.d.ts +5 -4
- package/dist/src/core/build-baseline.js +14 -14
- package/dist/src/core/build-overwrite-guard.d.ts +7 -14
- package/dist/src/core/build-overwrite-guard.js +62 -19
- package/dist/src/core/build-prepare.d.ts +2 -2
- package/dist/src/core/build-prepare.js +8 -9
- package/dist/src/core/config-state.js +12 -4
- package/dist/src/core/config-validate.js +8 -5
- package/dist/src/core/config.d.ts +5 -8
- package/dist/src/core/config.js +7 -16
- package/dist/src/core/coverage-extend.d.ts +15 -13
- package/dist/src/core/coverage-extend.js +15 -13
- package/dist/src/core/destructive.d.ts +31 -9
- package/dist/src/core/destructive.js +29 -26
- package/dist/src/core/diff-hunks.js +10 -12
- package/dist/src/core/discard-baseline.d.ts +8 -8
- package/dist/src/core/discard-baseline.js +16 -15
- package/dist/src/core/display-state.d.ts +12 -14
- package/dist/src/core/display-state.js +12 -14
- package/dist/src/core/engine-changes.d.ts +2 -4
- package/dist/src/core/engine-changes.js +2 -4
- package/dist/src/core/engine-precondition.d.ts +28 -13
- package/dist/src/core/engine-precondition.js +25 -10
- package/dist/src/core/engine-session-lock.d.ts +47 -21
- package/dist/src/core/engine-session-lock.js +168 -33
- package/dist/src/core/export-moved-code-shape.d.ts +10 -10
- package/dist/src/core/export-moved-code-shape.js +10 -10
- package/dist/src/core/file-lock.d.ts +62 -5
- package/dist/src/core/file-lock.js +196 -59
- package/dist/src/core/firefox-cache.js +1 -3
- package/dist/src/core/firefox-extract.js +10 -14
- package/dist/src/core/firefox.d.ts +7 -5
- package/dist/src/core/firefox.js +4 -5
- package/dist/src/core/furnace-apply-dry-run.d.ts +2 -2
- package/dist/src/core/furnace-apply-dry-run.js +3 -2
- package/dist/src/core/furnace-apply-ftl.d.ts +7 -9
- package/dist/src/core/furnace-apply-ftl.js +12 -12
- package/dist/src/core/furnace-apply-helpers.d.ts +7 -7
- package/dist/src/core/furnace-apply-helpers.js +19 -16
- package/dist/src/core/furnace-apply-overwrite-warn.d.ts +8 -9
- package/dist/src/core/furnace-apply-overwrite-warn.js +8 -9
- package/dist/src/core/furnace-apply-undeploy-actions.d.ts +3 -4
- package/dist/src/core/furnace-apply-undeploy-actions.js +3 -4
- package/dist/src/core/furnace-apply.d.ts +5 -8
- package/dist/src/core/furnace-apply.js +19 -24
- package/dist/src/core/furnace-checksum-utils.d.ts +14 -0
- package/dist/src/core/furnace-checksum-utils.js +16 -0
- package/dist/src/core/furnace-config.d.ts +21 -30
- package/dist/src/core/furnace-config.js +32 -54
- package/dist/src/core/furnace-constants.d.ts +8 -0
- package/dist/src/core/furnace-constants.js +10 -2
- package/dist/src/core/furnace-css-fragments.d.ts +5 -5
- package/dist/src/core/furnace-css-fragments.js +5 -5
- package/dist/src/core/furnace-jsconfig.d.ts +11 -12
- package/dist/src/core/furnace-jsconfig.js +11 -12
- package/dist/src/core/furnace-marker.d.ts +7 -8
- package/dist/src/core/furnace-marker.js +7 -8
- package/dist/src/core/furnace-operation.d.ts +31 -0
- package/dist/src/core/furnace-operation.js +54 -17
- package/dist/src/core/furnace-precondition.d.ts +61 -0
- package/dist/src/core/furnace-precondition.js +67 -0
- package/dist/src/core/furnace-registration-remove.d.ts +5 -6
- package/dist/src/core/furnace-registration-remove.js +6 -7
- package/dist/src/core/furnace-registration-validate.d.ts +13 -0
- package/dist/src/core/furnace-registration-validate.js +20 -1
- package/dist/src/core/furnace-registration.d.ts +5 -6
- package/dist/src/core/furnace-registration.js +10 -12
- package/dist/src/core/furnace-rollback.js +7 -7
- package/dist/src/core/furnace-scanner.d.ts +1 -0
- package/dist/src/core/furnace-scanner.js +1 -2
- package/dist/src/core/furnace-stale-export.d.ts +10 -10
- package/dist/src/core/furnace-stale-export.js +10 -10
- package/dist/src/core/furnace-state-persist.d.ts +6 -8
- package/dist/src/core/furnace-state-persist.js +6 -8
- package/dist/src/core/furnace-validate-accessibility.d.ts +22 -0
- package/dist/src/core/furnace-validate-accessibility.js +310 -1
- package/dist/src/core/furnace-validate-compatibility.js +141 -1
- package/dist/src/core/furnace-validate-helpers.d.ts +5 -116
- package/dist/src/core/furnace-validate-helpers.js +0 -491
- package/dist/src/core/furnace-validate-registration.d.ts +7 -0
- package/dist/src/core/furnace-validate-registration.js +115 -41
- package/dist/src/core/furnace-validate.d.ts +16 -0
- package/dist/src/core/furnace-validate.js +188 -145
- package/dist/src/core/furnace-version-drift.d.ts +10 -11
- package/dist/src/core/furnace-version-drift.js +10 -11
- package/dist/src/core/git-base.d.ts +7 -9
- package/dist/src/core/git-base.js +7 -9
- package/dist/src/core/git-diff.d.ts +20 -9
- package/dist/src/core/git-diff.js +148 -63
- package/dist/src/core/git-file-ops.d.ts +19 -19
- package/dist/src/core/git-file-ops.js +19 -19
- package/dist/src/core/git-readonly-index.d.ts +53 -19
- package/dist/src/core/git-readonly-index.js +75 -31
- package/dist/src/core/git-status.d.ts +5 -6
- package/dist/src/core/git-status.js +5 -6
- package/dist/src/core/git.d.ts +9 -10
- package/dist/src/core/git.js +54 -70
- package/dist/src/core/license-headers.d.ts +17 -23
- package/dist/src/core/license-headers.js +17 -23
- package/dist/src/core/mach-build-artifacts.d.ts +9 -9
- package/dist/src/core/mach-build-artifacts.js +57 -19
- package/dist/src/core/mach-error-hints.js +42 -29
- package/dist/src/core/mach-known-noise-filter.d.ts +15 -16
- package/dist/src/core/mach-known-noise-filter.js +18 -20
- package/dist/src/core/mach-mozconfig.d.ts +14 -0
- package/dist/src/core/mach-mozconfig.js +30 -0
- package/dist/src/core/mach-resource-shim.d.ts +43 -58
- package/dist/src/core/mach-resource-shim.js +50 -67
- package/dist/src/core/mach.d.ts +37 -41
- package/dist/src/core/mach.js +50 -51
- package/dist/src/core/marionette-port.d.ts +36 -1
- package/dist/src/core/marionette-port.js +96 -31
- package/dist/src/core/marionette-preflight.d.ts +8 -12
- package/dist/src/core/marionette-preflight.js +86 -52
- package/dist/src/core/mochitest-server-port.d.ts +42 -0
- package/dist/src/core/mochitest-server-port.js +119 -0
- package/dist/src/core/module-resolution-preflight.d.ts +9 -11
- package/dist/src/core/module-resolution-preflight.js +9 -11
- package/dist/src/core/moz-manifest-helpers.d.ts +79 -0
- package/dist/src/core/moz-manifest-helpers.js +163 -0
- package/dist/src/core/{manifest-register.d.ts → moz-manifest-register.d.ts} +1 -1
- package/dist/src/core/{manifest-register.js → moz-manifest-register.js} +13 -28
- package/dist/src/core/{manifest-rules.d.ts → moz-manifest-rules.d.ts} +10 -1
- package/dist/src/core/{manifest-rules.js → moz-manifest-rules.js} +31 -24
- package/dist/src/core/{manifest-tokenizers.d.ts → moz-manifest-tokenizers.d.ts} +3 -5
- package/dist/src/core/{manifest-tokenizers.js → moz-manifest-tokenizers.js} +9 -12
- package/dist/src/core/ownership-table.d.ts +14 -16
- package/dist/src/core/ownership-table.js +14 -16
- package/dist/src/core/parser-fallback.d.ts +15 -1
- package/dist/src/core/parser-fallback.js +22 -3
- package/dist/src/core/patch-apply-fuzz.d.ts +10 -12
- package/dist/src/core/patch-apply-fuzz.js +15 -18
- package/dist/src/core/patch-apply.d.ts +13 -34
- package/dist/src/core/patch-apply.js +16 -76
- package/dist/src/core/patch-artifact-normalize.d.ts +13 -15
- package/dist/src/core/patch-artifact-normalize.js +13 -15
- package/dist/src/core/patch-export-metadata.d.ts +12 -2
- package/dist/src/core/patch-export-metadata.js +13 -4
- package/dist/src/core/patch-export-update.d.ts +13 -1
- package/dist/src/core/patch-export-update.js +25 -8
- package/dist/src/core/patch-export.d.ts +15 -8
- package/dist/src/core/patch-export.js +10 -11
- package/dist/src/core/patch-files.d.ts +5 -6
- package/dist/src/core/patch-files.js +5 -6
- package/dist/src/core/patch-identifier-suggest.d.ts +7 -12
- package/dist/src/core/patch-identifier-suggest.js +14 -19
- package/dist/src/core/patch-lint-binary.d.ts +51 -0
- package/dist/src/core/patch-lint-binary.js +39 -0
- package/dist/src/core/{lint-cache.d.ts → patch-lint-cache.d.ts} +5 -5
- package/dist/src/core/{lint-cache.js → patch-lint-cache.js} +21 -23
- package/dist/src/core/patch-lint-checkjs.d.ts +16 -16
- package/dist/src/core/patch-lint-checkjs.js +16 -16
- package/dist/src/core/patch-lint-chrome-jsdoc.d.ts +6 -9
- package/dist/src/core/patch-lint-chrome-jsdoc.js +10 -14
- package/dist/src/core/patch-lint-creators.d.ts +8 -8
- package/dist/src/core/patch-lint-creators.js +8 -8
- package/dist/src/core/patch-lint-cross.d.ts +17 -20
- package/dist/src/core/patch-lint-cross.js +16 -16
- package/dist/src/core/patch-lint-css.d.ts +3 -5
- package/dist/src/core/patch-lint-css.js +17 -22
- package/dist/src/core/patch-lint-diff-tag.d.ts +14 -16
- package/dist/src/core/patch-lint-diff-tag.js +14 -16
- package/dist/src/core/patch-lint-jsdoc.d.ts +7 -8
- package/dist/src/core/patch-lint-jsdoc.js +26 -19
- package/dist/src/core/patch-lint-mozbuild.js +20 -20
- package/dist/src/core/patch-lint-observer.d.ts +7 -7
- package/dist/src/core/patch-lint-observer.js +7 -7
- package/dist/src/core/patch-lint.d.ts +38 -29
- package/dist/src/core/patch-lint.js +89 -121
- package/dist/src/core/patch-lock.d.ts +1 -1
- package/dist/src/core/patch-lock.js +45 -9
- package/dist/src/core/patch-manifest-consistency.d.ts +2 -1
- package/dist/src/core/patch-manifest-consistency.js +25 -27
- package/dist/src/core/patch-manifest-io.js +14 -18
- package/dist/src/core/patch-manifest-resolve.d.ts +9 -12
- package/dist/src/core/patch-manifest-resolve.js +9 -12
- package/dist/src/core/patch-manifest-validate.d.ts +6 -1
- package/dist/src/core/patch-manifest-validate.js +25 -13
- package/dist/src/core/patch-parse.d.ts +24 -13
- package/dist/src/core/patch-parse.js +19 -14
- package/dist/src/core/patch-policy.d.ts +2 -2
- package/dist/src/core/patch-policy.js +2 -2
- package/dist/src/core/patch-registration-refs.d.ts +7 -8
- package/dist/src/core/patch-registration-refs.js +9 -9
- package/dist/src/core/process-cpu-time.d.ts +12 -0
- package/dist/src/core/process-cpu-time.js +52 -0
- package/dist/src/core/rebase-session.d.ts +38 -26
- package/dist/src/core/rebase-session.js +55 -28
- package/dist/src/core/register-browser-content.js +9 -74
- package/dist/src/core/{register-test-manifest.js → register-browser-test.js} +7 -42
- package/dist/src/core/register-module.js +10 -43
- package/dist/src/core/register-scaffold.d.ts +8 -8
- package/dist/src/core/register-scaffold.js +10 -10
- package/dist/src/core/register-shared-css.d.ts +9 -12
- package/dist/src/core/register-shared-css.js +17 -87
- package/dist/src/core/register-xpcshell-test.d.ts +6 -7
- package/dist/src/core/register-xpcshell-test.js +7 -8
- package/dist/src/core/shared-ftl.js +12 -4
- package/dist/src/core/state-file.d.ts +45 -0
- package/dist/src/core/state-file.js +34 -0
- package/dist/src/core/status-binary.d.ts +18 -11
- package/dist/src/core/status-binary.js +19 -12
- package/dist/src/core/status-classify.d.ts +30 -36
- package/dist/src/core/status-classify.js +21 -26
- package/dist/src/core/test-changed-prefs.d.ts +30 -0
- package/dist/src/core/test-changed-prefs.js +78 -0
- package/dist/src/core/test-harness-crash.d.ts +25 -63
- package/dist/src/core/test-harness-crash.js +121 -142
- package/dist/src/core/test-harness-signature.d.ts +18 -0
- package/dist/src/core/test-harness-signature.js +13 -0
- package/dist/src/core/test-path-scope.d.ts +12 -15
- package/dist/src/core/test-path-scope.js +15 -18
- package/dist/src/core/test-stale-check.d.ts +17 -17
- package/dist/src/core/test-stale-check.js +50 -43
- package/dist/src/core/test-stall-triage.d.ts +51 -0
- package/dist/src/core/test-stall-triage.js +126 -0
- package/dist/src/core/token-category.js +5 -7
- package/dist/src/core/token-coverage.js +9 -9
- package/dist/src/core/token-dark-mode.d.ts +9 -11
- package/dist/src/core/token-dark-mode.js +9 -11
- package/dist/src/core/token-docs.d.ts +2 -0
- package/dist/src/core/token-docs.js +2 -0
- package/dist/src/core/token-manager.d.ts +10 -2
- package/dist/src/core/token-manager.js +17 -8
- package/dist/src/core/token-scaffold.d.ts +7 -7
- package/dist/src/core/token-scaffold.js +7 -7
- package/dist/src/core/token-variant.d.ts +4 -4
- package/dist/src/core/token-variant.js +4 -4
- package/dist/src/core/toolchain-preflight.d.ts +20 -21
- package/dist/src/core/toolchain-preflight.js +28 -31
- package/dist/src/core/tree-guard.js +12 -2
- package/dist/src/core/tree-store.d.ts +41 -27
- package/dist/src/core/tree-store.js +63 -42
- package/dist/src/core/typecheck-shim.d.ts +23 -24
- package/dist/src/core/typecheck-shim.js +23 -24
- package/dist/src/core/typecheck.js +8 -8
- package/dist/src/core/wire-destroy.d.ts +3 -3
- package/dist/src/core/wire-destroy.js +7 -15
- package/dist/src/core/wire-dom-fragment.d.ts +9 -17
- package/dist/src/core/wire-dom-fragment.js +11 -44
- package/dist/src/core/wire-init.d.ts +2 -3
- package/dist/src/core/wire-init.js +8 -19
- package/dist/src/core/wire-subscript.d.ts +2 -3
- package/dist/src/core/wire-subscript.js +4 -13
- package/dist/src/core/wire-utils.d.ts +7 -8
- package/dist/src/core/wire-utils.js +7 -8
- package/dist/src/core/xpcshell-appdir.d.ts +38 -45
- package/dist/src/core/xpcshell-appdir.js +38 -45
- package/dist/src/errors/base.d.ts +37 -16
- package/dist/src/errors/base.js +37 -16
- package/dist/src/errors/build.d.ts +13 -1
- package/dist/src/errors/build.js +14 -2
- package/dist/src/errors/codes.d.ts +16 -0
- package/dist/src/errors/codes.js +16 -0
- package/dist/src/errors/furnace.d.ts +4 -4
- package/dist/src/errors/git.d.ts +6 -10
- package/dist/src/errors/git.js +6 -10
- package/dist/src/errors/patch.d.ts +7 -7
- package/dist/src/errors/patch.js +7 -7
- package/dist/src/errors/rebase.d.ts +4 -4
- package/dist/src/errors/rebase.js +4 -4
- package/dist/src/index.d.ts +7 -1
- package/dist/src/index.js +5 -0
- package/dist/src/types/commands/index.d.ts +2 -2
- package/dist/src/types/commands/options.d.ts +88 -70
- package/dist/src/types/commands/patches.d.ts +24 -34
- package/dist/src/types/commands/project.d.ts +5 -34
- package/dist/src/types/config.d.ts +25 -23
- package/dist/src/types/config.js +6 -1
- package/dist/src/types/furnace.d.ts +37 -13
- package/dist/src/types/furnace.js +19 -1
- package/dist/src/types/index.d.ts +3 -3
- package/dist/src/utils/build-info.d.ts +7 -8
- package/dist/src/utils/build-info.js +12 -11
- package/dist/src/utils/errors.d.ts +6 -8
- package/dist/src/utils/errors.js +6 -8
- package/dist/src/utils/logger.d.ts +27 -10
- package/dist/src/utils/logger.js +28 -16
- package/dist/src/utils/machine-output.d.ts +12 -0
- package/dist/src/utils/machine-output.js +33 -0
- package/dist/src/utils/options.d.ts +31 -14
- package/dist/src/utils/options.js +86 -30
- package/dist/src/utils/paths.d.ts +10 -8
- package/dist/src/utils/paths.js +10 -8
- package/dist/src/utils/platform.d.ts +0 -25
- package/dist/src/utils/platform.js +1 -42
- package/dist/src/utils/process-group.d.ts +9 -4
- package/dist/src/utils/process-group.js +19 -5
- package/dist/src/utils/process.d.ts +42 -7
- package/dist/src/utils/process.js +44 -17
- package/dist/src/utils/ps-duration.d.ts +31 -0
- package/dist/src/utils/ps-duration.js +70 -0
- package/dist/src/utils/regex.d.ts +9 -10
- package/dist/src/utils/regex.js +9 -10
- package/dist/src/utils/validation.d.ts +58 -28
- package/dist/src/utils/validation.js +60 -33
- package/package.json +2 -2
- package/dist/src/commands/doctor/post-rebase-audit.d.ts +0 -2
- package/dist/src/commands/doctor-furnace-manifest-sync.d.ts +0 -18
- package/dist/src/core/manifest-helpers.d.ts +0 -38
- package/dist/src/core/manifest-helpers.js +0 -120
- /package/dist/src/core/{lint-projection.d.ts → patch-lint-projection.d.ts} +0 -0
- /package/dist/src/core/{lint-projection.js → patch-lint-projection.js} +0 -0
- /package/dist/src/core/{register-test-manifest.d.ts → register-browser-test.d.ts} +0 -0
|
@@ -2,8 +2,10 @@
|
|
|
2
2
|
import { Command } from 'commander';
|
|
3
3
|
import { isBrandingManagedPath } from '../core/branding.js';
|
|
4
4
|
import { getProjectPaths, loadConfig } from '../core/config.js';
|
|
5
|
+
import { stdioIsInteractive } from '../core/destructive.js';
|
|
6
|
+
import { assertEngineGitReady } from '../core/engine-precondition.js';
|
|
5
7
|
import { collectFurnaceManagedPrefixes, furnaceConfigExists, loadFurnaceConfig, } from '../core/furnace-config.js';
|
|
6
|
-
import { hasChanges
|
|
8
|
+
import { hasChanges } from '../core/git.js';
|
|
7
9
|
import { getAllDiff, getDiffForFilesAgainstHead } from '../core/git-diff.js';
|
|
8
10
|
import { expandUntrackedDirectoryEntries, getWorkingTreeStatus } from '../core/git-status.js';
|
|
9
11
|
import { extractAffectedFiles } from '../core/patch-apply.js';
|
|
@@ -14,7 +16,7 @@ import { buildPatchSourceMetadata } from '../core/patch-source-metadata.js';
|
|
|
14
16
|
import { GeneralError } from '../errors/base.js';
|
|
15
17
|
import { ensureDir, pathExists } from '../utils/fs.js';
|
|
16
18
|
import { info, intro, outro, spinner } from '../utils/logger.js';
|
|
17
|
-
import { pickDefined } from '../utils/options.js';
|
|
19
|
+
import { addWaitLockOption, pickDefined, resolveWaitLockSeconds } from '../utils/options.js';
|
|
18
20
|
import { renderDryRunPreview } from './export-flow.js';
|
|
19
21
|
import { autoFixLicenseHeaders, promptExportPatchMetadata, runPatchLint, runSupersedeAndOverlapGates, } from './export-shared.js';
|
|
20
22
|
async function checkBrandingManagedFiles(paths, config) {
|
|
@@ -46,9 +48,7 @@ async function resolveFurnaceExclusionPolicy(paths, projectRoot, excludeFurnace)
|
|
|
46
48
|
// Expand collapsed `?? dir/` entries before matching against Furnace
|
|
47
49
|
// prefixes — otherwise a Furnace-introduced directory slips past the
|
|
48
50
|
// filter and later lands in the non-Furnace path list that feeds the
|
|
49
|
-
// aggregate diff, where `getDiffForFilesAgainstHead` crashes with
|
|
50
|
-
// EISDIR (eval finding: export-all unusable on a fresh project with
|
|
51
|
-
// Furnace scaffolding).
|
|
51
|
+
// aggregate diff, where `getDiffForFilesAgainstHead` crashes with EISDIR.
|
|
52
52
|
const rawStatus = await getWorkingTreeStatus(paths.engine);
|
|
53
53
|
const changedFiles = await expandUntrackedDirectoryEntries(paths.engine, rawStatus);
|
|
54
54
|
const furnaceManagedFiles = changedFiles
|
|
@@ -66,20 +66,19 @@ async function resolveFurnaceExclusionPolicy(paths, projectRoot, excludeFurnace)
|
|
|
66
66
|
}
|
|
67
67
|
/**
|
|
68
68
|
* Refuses the export when the resulting patch would register furnace
|
|
69
|
-
* component source files it does not itself carry.
|
|
70
|
-
*
|
|
71
|
-
* `
|
|
72
|
-
*
|
|
73
|
-
*
|
|
74
|
-
*
|
|
75
|
-
*
|
|
76
|
-
*
|
|
77
|
-
*
|
|
78
|
-
* before exporting.
|
|
69
|
+
* component source files it does not itself carry.
|
|
70
|
+
*
|
|
71
|
+
* `export-all --exclude-furnace` after `furnace create --localized
|
|
72
|
+
* --with-tests` otherwise produces a patch that adds
|
|
73
|
+
* `toolkit/content/widgets/<tag>/*` via jar.mn / customElements.js / locale
|
|
74
|
+
* jar.mn while excluding the component source files themselves — a
|
|
75
|
+
* structurally broken queue that `fireforge verify` stays silent about. The
|
|
76
|
+
* operator is asked to either include the component sources (skip
|
|
77
|
+
* `--exclude-furnace`) or revert the furnace changes before exporting.
|
|
79
78
|
*
|
|
80
79
|
* The check runs against the synthesised patch body before
|
|
81
|
-
* `commitExportedPatch` writes anything, so no broken patch is left on
|
|
82
|
-
*
|
|
80
|
+
* `commitExportedPatch` writes anything, so no broken patch is left on disk
|
|
81
|
+
* when the refusal fires.
|
|
83
82
|
*/
|
|
84
83
|
async function checkDanglingFurnaceRegistrations(projectRoot, diff, furnaceExcluded) {
|
|
85
84
|
if (furnaceExcluded.size === 0)
|
|
@@ -171,14 +170,7 @@ export async function exportAllCommand(projectRoot, options = {}) {
|
|
|
171
170
|
const isDryRun = options.dryRun === true;
|
|
172
171
|
intro(isDryRun ? 'FireForge Export All (dry run)' : 'FireForge Export All');
|
|
173
172
|
const paths = getProjectPaths(projectRoot);
|
|
174
|
-
|
|
175
|
-
if (!(await pathExists(paths.engine))) {
|
|
176
|
-
throw new GeneralError('Firefox source not found. Run "fireforge download" first.');
|
|
177
|
-
}
|
|
178
|
-
// Check if it's a git repository
|
|
179
|
-
if (!(await isGitRepository(paths.engine))) {
|
|
180
|
-
throw new GeneralError('Engine directory is not a git repository. Run "fireforge download" to initialize.');
|
|
181
|
-
}
|
|
173
|
+
await assertEngineGitReady(paths.engine);
|
|
182
174
|
// Check for changes
|
|
183
175
|
if (!(await hasChanges(paths.engine))) {
|
|
184
176
|
info('No changes to export');
|
|
@@ -228,13 +220,13 @@ export async function exportAllCommand(projectRoot, options = {}) {
|
|
|
228
220
|
// the aggregate would newly create, so it runs here instead of alongside
|
|
229
221
|
// the branding / furnace guards that operate on the raw status list.
|
|
230
222
|
await checkDuplicateNewFileCreations(paths, diff);
|
|
231
|
-
// Dangling-furnace-registration preflight
|
|
232
|
-
//
|
|
233
|
-
//
|
|
234
|
-
//
|
|
223
|
+
// Dangling-furnace-registration preflight. Runs after the diff is
|
|
224
|
+
// assembled so it can inspect the exact hunks the operator is about to
|
|
225
|
+
// land, and BEFORE any write so a refusal leaves the patches directory
|
|
226
|
+
// untouched.
|
|
235
227
|
await checkDanglingFurnaceRegistrations(projectRoot, diff, furnaceExcluded);
|
|
236
228
|
// Check for non-interactive mode
|
|
237
|
-
const isInteractive =
|
|
229
|
+
const isInteractive = stdioIsInteractive();
|
|
238
230
|
// Auto-fix missing license headers on new files (interactive only;
|
|
239
231
|
// report-only under --dry-run so the preview never mutates engine/)
|
|
240
232
|
const headersAdded = await autoFixLicenseHeaders(paths.engine, diff, config, isInteractive, isDryRun);
|
|
@@ -308,6 +300,10 @@ export async function exportAllCommand(projectRoot, options = {}) {
|
|
|
308
300
|
config,
|
|
309
301
|
policyCommand: 'export-all',
|
|
310
302
|
forceUnsafe: options.forceUnsafe === true,
|
|
303
|
+
lockOptions: {
|
|
304
|
+
waitLockSeconds: resolveWaitLockSeconds(options.waitLock),
|
|
305
|
+
command: 'export-all',
|
|
306
|
+
},
|
|
311
307
|
});
|
|
312
308
|
for (const oldPatch of superseded) {
|
|
313
309
|
info(`Superseded: ${oldPatch.filename}`);
|
|
@@ -326,7 +322,7 @@ export async function exportAllCommand(projectRoot, options = {}) {
|
|
|
326
322
|
}
|
|
327
323
|
/** Registers the export-all command on the CLI program. */
|
|
328
324
|
export function registerExportAll(program, { getProjectRoot, withErrorHandling }) {
|
|
329
|
-
program
|
|
325
|
+
const command = program
|
|
330
326
|
.command('export-all')
|
|
331
327
|
.description('Export all changes as a patch')
|
|
332
328
|
.option('--name <name>', 'Name for the patch')
|
|
@@ -337,8 +333,8 @@ export function registerExportAll(program, { getProjectRoot, withErrorHandling }
|
|
|
337
333
|
.option('--exclude-furnace', 'Export the non-Furnace subset of the aggregate diff instead of refusing when Furnace-managed files are modified. Furnace-managed files are still deployed by "fireforge furnace apply"; this flag only changes whether export-all aborts or filters in their presence.')
|
|
338
334
|
.option('--allow-overlap', 'Acknowledge cross-patch ownership overlap with non-superseded patches (the resulting queue fails verify). Does not bypass the new-file creation guard — two patches creating the same path is structurally unrecoverable, so that case still refuses regardless of this flag.')
|
|
339
335
|
.option('--dry-run', 'Print the export-all plan (filename, metadata, files affected, supersede preview) without writing anything to patches/. Lint still runs so the operator sees the same lint output a real run would produce.')
|
|
340
|
-
.option('--force-unsafe', 'Bypass force-mode patchPolicy refusals')
|
|
341
|
-
|
|
336
|
+
.option('--force-unsafe', 'Bypass force-mode patchPolicy refusals');
|
|
337
|
+
addWaitLockOption(command).action(withErrorHandling(async (options) => {
|
|
342
338
|
const { category, ...rest } = options;
|
|
343
339
|
await exportAllCommand(getProjectRoot(), {
|
|
344
340
|
...pickDefined(rest),
|
|
@@ -195,12 +195,12 @@ export async function projectPlacementForLint(patchesDir, plan, diff, config) {
|
|
|
195
195
|
return entry;
|
|
196
196
|
return { ...entry, filename: rename.newFilename, order: rename.newOrder };
|
|
197
197
|
});
|
|
198
|
-
// Synthetic entry for the pending patch, populated with both its
|
|
199
|
-
//
|
|
200
|
-
//
|
|
201
|
-
//
|
|
202
|
-
//
|
|
203
|
-
//
|
|
198
|
+
// Synthetic entry for the pending patch, populated with both its new-file
|
|
199
|
+
// content AND its added-line content for files it modifies, so the
|
|
200
|
+
// forward-import rule can inspect imports the patch *itself* authors —
|
|
201
|
+
// whether they live in a brand-new file or are added to an existing one.
|
|
202
|
+
// Leaving either map empty lets a patch land before one of its own
|
|
203
|
+
// dependencies and still pass the gate.
|
|
204
204
|
projectedEntries.push({
|
|
205
205
|
filename: plan.newFilename,
|
|
206
206
|
order: plan.insertionOrder,
|
|
@@ -1,16 +1,17 @@
|
|
|
1
1
|
// SPDX-License-Identifier: EUPL-1.2
|
|
2
2
|
/**
|
|
3
3
|
* Attribution of projected placement lint errors, split out of
|
|
4
|
-
* export-flow.ts for the line budget.
|
|
5
|
-
* merged queue — the renumbered existing patches plus a synthetic entry
|
|
6
|
-
* for the pending patch — so its errors used to render as one flat list
|
|
7
|
-
* that read as though the NEW patch caused every one of them. A
|
|
8
|
-
* renumbering that re-evaluates pre-existing staged relationships (455
|
|
9
|
-
* importing a module created by 456, legal only at their current
|
|
10
|
-
* ordinals) then sent the operator auditing a perfectly fine export.
|
|
4
|
+
* export-flow.ts for the line budget.
|
|
11
5
|
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
6
|
+
* A placement projection lints one merged queue — the renumbered existing
|
|
7
|
+
* patches plus a synthetic entry for the pending patch — so a flat error
|
|
8
|
+
* list reads as though the NEW patch caused every one of them. A renumbering
|
|
9
|
+
* that re-evaluates pre-existing staged relationships (patch 455 importing a
|
|
10
|
+
* module created by 456, legal only at their current ordinals) then sends
|
|
11
|
+
* the operator auditing a perfectly fine export.
|
|
12
|
+
*
|
|
13
|
+
* Consumed by export-flow.ts; no top-level registrar is exported and none is
|
|
14
|
+
* wanted.
|
|
14
15
|
*/
|
|
15
16
|
import { formatPatchLintIssue } from '../core/patch-lint.js';
|
|
16
17
|
/**
|
|
@@ -70,10 +70,10 @@ export async function gatePlacementPlan(args) {
|
|
|
70
70
|
const summary = placementSummary(placementPlan);
|
|
71
71
|
const renameCount = placementPlan.renameMap.size;
|
|
72
72
|
// Route through confirmDestructive when the operation is destructive
|
|
73
|
-
// enough to warrant a prompt (more than one rename) OR when the user
|
|
74
|
-
//
|
|
75
|
-
//
|
|
76
|
-
//
|
|
73
|
+
// enough to warrant a prompt (more than one rename) OR when the user asked
|
|
74
|
+
// for a dry-run. The dry-run branch must always print the placement
|
|
75
|
+
// summary; otherwise single-rename and no-rename dry-runs exit silently
|
|
76
|
+
// with no filename or projected layout.
|
|
77
77
|
if (renameCount > 1 || isDryRun) {
|
|
78
78
|
s.stop();
|
|
79
79
|
const decision = await confirmDestructive({
|
|
@@ -89,7 +89,7 @@ export async function gatePlacementPlan(args) {
|
|
|
89
89
|
outro('Dry run complete — no changes made');
|
|
90
90
|
return 'stop';
|
|
91
91
|
}
|
|
92
|
-
if (decision === '
|
|
92
|
+
if (decision === 'declined') {
|
|
93
93
|
outro('Export cancelled');
|
|
94
94
|
return 'stop';
|
|
95
95
|
}
|
|
@@ -3,26 +3,26 @@ import type { ExportOptions, PatchCategory } from '../types/commands/index.js';
|
|
|
3
3
|
import type { FireForgeConfig } from '../types/config.js';
|
|
4
4
|
import type { SpinnerHandle } from '../utils/logger.js';
|
|
5
5
|
/**
|
|
6
|
-
* Runs the full patch lint pipeline and reports results.
|
|
7
|
-
*
|
|
6
|
+
* Runs the full patch lint pipeline and reports results. Warnings are always
|
|
7
|
+
* displayed. Errors block the export unless skipLint is true.
|
|
8
8
|
*
|
|
9
9
|
* @param engineDir - Engine root directory
|
|
10
10
|
* @param filesAffected - Files touched by the patch
|
|
11
11
|
* @param diffContent - Raw unified diff string
|
|
12
12
|
* @param config - Project configuration
|
|
13
13
|
* @param skipLint - If true, downgrade errors to warnings
|
|
14
|
-
* @param patchQueueCtx - Optional cross-patch context for ownership
|
|
14
|
+
* @param patchQueueCtx - Optional cross-patch context for ownership
|
|
15
|
+
* resolution
|
|
15
16
|
* @param ignoreChecks - Optional per-patch set of `check` IDs to suppress
|
|
16
17
|
* (threaded from `PatchMetadata.lintIgnore`). Surgical alternative to
|
|
17
18
|
* `--skip-lint` when exactly one advisory rule does not apply to a
|
|
18
|
-
* specific patch — e.g. `large-patch-lines` on a cohesive branding
|
|
19
|
-
*
|
|
19
|
+
* specific patch — e.g. `large-patch-lines` on a cohesive branding bundle
|
|
20
|
+
* that genuinely cannot be split.
|
|
20
21
|
* @param patchTier - Optional explicit tier override (threaded from
|
|
21
|
-
* `PatchMetadata.tier`). Forces the branding-tier thresholds when
|
|
22
|
-
*
|
|
23
|
-
*
|
|
24
|
-
*
|
|
25
|
-
* visible rather than silent.
|
|
22
|
+
* `PatchMetadata.tier`). Forces the branding-tier thresholds when set,
|
|
23
|
+
* independent of the auto-detect allowlist. When the branding tier is
|
|
24
|
+
* applied, a single `info()` line surfaces the choice so the tier decision
|
|
25
|
+
* is visible rather than silent.
|
|
26
26
|
*/
|
|
27
27
|
export declare function runPatchLint(engineDir: string, filesAffected: string[], diffContent: string, config: FireForgeConfig, skipLint?: boolean, patchQueueCtx?: import('../core/patch-lint-cross.js').PatchQueueContext, ignoreChecks?: ReadonlySet<string>, patchTier?: 'branding'): Promise<void>;
|
|
28
28
|
/**
|
|
@@ -55,18 +55,18 @@ export declare function confirmSupersedePatches(patchesDir: string, filesAffecte
|
|
|
55
55
|
/**
|
|
56
56
|
* Detects new files missing license headers and offers to add them.
|
|
57
57
|
*
|
|
58
|
-
* In interactive mode the user is prompted before any files are modified.
|
|
59
|
-
*
|
|
60
|
-
*
|
|
58
|
+
* In interactive mode the user is prompted before any files are modified. In
|
|
59
|
+
* non-interactive mode the function is a no-op — the existing lint error
|
|
60
|
+
* blocks the export instead.
|
|
61
61
|
*
|
|
62
62
|
* @param engineDir - Absolute path to engine directory
|
|
63
63
|
* @param diffContent - Current unified diff
|
|
64
64
|
* @param config - Project configuration
|
|
65
65
|
* @param isInteractive - Whether interactive prompts are available
|
|
66
66
|
* @param dryRun - When true, only REPORT missing headers, never prompt or
|
|
67
|
-
* write. Dry-run must stay read-only:
|
|
68
|
-
*
|
|
69
|
-
*
|
|
67
|
+
* write. Dry-run must stay read-only: without this flag an interactive
|
|
68
|
+
* `export --dry-run` prompts (default Yes), writes license headers into
|
|
69
|
+
* engine/ files, and then closes with "no changes made".
|
|
70
70
|
* @returns true if files were modified on disk (caller must regenerate diff)
|
|
71
71
|
*/
|
|
72
72
|
export declare function autoFixLicenseHeaders(engineDir: string, diffContent: string, config: FireForgeConfig, isInteractive: boolean, dryRun?: boolean): Promise<boolean>;
|
|
@@ -83,19 +83,17 @@ export declare function autoFixLicenseHeaders(engineDir: string, diffContent: st
|
|
|
83
83
|
export declare function findPartialOwnershipOverlap(manifest: PatchesManifest, filesAffected: string[], excludeFilenames: ReadonlySet<string>): Map<string, string[]>;
|
|
84
84
|
/**
|
|
85
85
|
* Gate that refuses the default export path when the new patch would
|
|
86
|
-
* silently claim files
|
|
87
|
-
*
|
|
88
|
-
*
|
|
89
|
-
*
|
|
90
|
-
* `browser/themes/shared/jar.inc.mn` after a second export with
|
|
91
|
-
* `--before`).
|
|
86
|
+
* silently claim files already tracked by other non-superseded patches.
|
|
87
|
+
* `findAllPatchesForFiles` catches the full-coverage supersede case; this
|
|
88
|
+
* fills the gap for PARTIAL overlap — two patches both claiming e.g.
|
|
89
|
+
* `browser/themes/shared/jar.inc.mn` after a second export with `--before`.
|
|
92
90
|
*
|
|
93
91
|
* Proceeds silently when there is no overlap, or when the caller passed
|
|
94
92
|
* `--allow-overlap`. In interactive mode the caller is prompted to
|
|
95
93
|
* acknowledge the overlap (the proper fix path is `re-export --files` to
|
|
96
94
|
* repartition ownership, so the prompt surfaces that pointer). In
|
|
97
|
-
* non-interactive mode
|
|
98
|
-
*
|
|
95
|
+
* non-interactive mode it throws — better to fail fast than let the queue
|
|
96
|
+
* fall out of sync with verify.
|
|
99
97
|
*/
|
|
100
98
|
export declare function guardOwnershipOverlap(args: {
|
|
101
99
|
patchesDir: string;
|
|
@@ -107,13 +105,12 @@ export declare function guardOwnershipOverlap(args: {
|
|
|
107
105
|
}): Promise<boolean>;
|
|
108
106
|
/**
|
|
109
107
|
* Runs the two pre-commit gates shared by `export` and `export-all` in
|
|
110
|
-
* order: the supersede confirmation, then the cross-patch ownership
|
|
111
|
-
*
|
|
112
|
-
*
|
|
113
|
-
*
|
|
114
|
-
*
|
|
115
|
-
*
|
|
116
|
-
* patches both claimed the file and `verify` failed immediately).
|
|
108
|
+
* order: the supersede confirmation, then the cross-patch ownership overlap
|
|
109
|
+
* guard. The overlap guard receives the filenames of the patches the export
|
|
110
|
+
* would fully supersede so it does not flag a file claimed by a patch that
|
|
111
|
+
* is about to be removed. Catching only FULL-coverage supersedes leaves a
|
|
112
|
+
* second export targeting a shared file creating a queue where two patches
|
|
113
|
+
* both claim it and `verify` fails immediately.
|
|
117
114
|
*
|
|
118
115
|
* @param args - Gate inputs shared by both export commands
|
|
119
116
|
* @param args.patchesDir - Absolute path of the patches directory
|
|
@@ -122,8 +119,8 @@ export declare function guardOwnershipOverlap(args: {
|
|
|
122
119
|
* @param args.allowOverlap - The command's `--allow-overlap` flag
|
|
123
120
|
* @param args.isInteractive - Whether prompting the operator is possible
|
|
124
121
|
* @param args.s - Active spinner, stopped before any prompt
|
|
125
|
-
* @returns `true` when both gates passed; `false` when the operator
|
|
126
|
-
*
|
|
122
|
+
* @returns `true` when both gates passed; `false` when the operator declined
|
|
123
|
+
* (the caller returns without committing)
|
|
127
124
|
*/
|
|
128
125
|
export declare function runSupersedeAndOverlapGates(args: {
|
|
129
126
|
patchesDir: string;
|
|
@@ -10,36 +10,36 @@ import { getPatchPolicyCategories, isCategoryAllowedByConfig } from '../core/pat
|
|
|
10
10
|
import { GeneralError, InvalidArgumentError } from '../errors/base.js';
|
|
11
11
|
import { pathExists, readText } from '../utils/fs.js';
|
|
12
12
|
import { cancel, info, isCancel, warn } from '../utils/logger.js';
|
|
13
|
-
import { normalizePatchDisplayName, PATCH_CATEGORIES,
|
|
13
|
+
import { describePatchNameProblem, normalizePatchDisplayName, PATCH_CATEGORIES, } from '../utils/validation.js';
|
|
14
14
|
/**
|
|
15
|
-
* Runs the full patch lint pipeline and reports results.
|
|
16
|
-
*
|
|
15
|
+
* Runs the full patch lint pipeline and reports results. Warnings are always
|
|
16
|
+
* displayed. Errors block the export unless skipLint is true.
|
|
17
17
|
*
|
|
18
18
|
* @param engineDir - Engine root directory
|
|
19
19
|
* @param filesAffected - Files touched by the patch
|
|
20
20
|
* @param diffContent - Raw unified diff string
|
|
21
21
|
* @param config - Project configuration
|
|
22
22
|
* @param skipLint - If true, downgrade errors to warnings
|
|
23
|
-
* @param patchQueueCtx - Optional cross-patch context for ownership
|
|
23
|
+
* @param patchQueueCtx - Optional cross-patch context for ownership
|
|
24
|
+
* resolution
|
|
24
25
|
* @param ignoreChecks - Optional per-patch set of `check` IDs to suppress
|
|
25
26
|
* (threaded from `PatchMetadata.lintIgnore`). Surgical alternative to
|
|
26
27
|
* `--skip-lint` when exactly one advisory rule does not apply to a
|
|
27
|
-
* specific patch — e.g. `large-patch-lines` on a cohesive branding
|
|
28
|
-
*
|
|
28
|
+
* specific patch — e.g. `large-patch-lines` on a cohesive branding bundle
|
|
29
|
+
* that genuinely cannot be split.
|
|
29
30
|
* @param patchTier - Optional explicit tier override (threaded from
|
|
30
|
-
* `PatchMetadata.tier`). Forces the branding-tier thresholds when
|
|
31
|
-
*
|
|
32
|
-
*
|
|
33
|
-
*
|
|
34
|
-
* visible rather than silent.
|
|
31
|
+
* `PatchMetadata.tier`). Forces the branding-tier thresholds when set,
|
|
32
|
+
* independent of the auto-detect allowlist. When the branding tier is
|
|
33
|
+
* applied, a single `info()` line surfaces the choice so the tier decision
|
|
34
|
+
* is visible rather than silent.
|
|
35
35
|
*/
|
|
36
36
|
export async function runPatchLint(engineDir, filesAffected, diffContent, config, skipLint, patchQueueCtx, ignoreChecks, patchTier) {
|
|
37
|
-
// Compute the tier decision independently of the lint pipeline so
|
|
38
|
-
//
|
|
39
|
-
//
|
|
40
|
-
//
|
|
41
|
-
//
|
|
42
|
-
//
|
|
37
|
+
// Compute the tier decision independently of the lint pipeline so it can
|
|
38
|
+
// be surfaced even when the rule body emitted no issues — a branding patch
|
|
39
|
+
// under the soft threshold still benefits from operators knowing which
|
|
40
|
+
// tier governed the run. The same helper is reused inside `lintPatchSize`,
|
|
41
|
+
// so the surfaced tier and the tier that actually drove the thresholds
|
|
42
|
+
// never drift.
|
|
43
43
|
const tierDecision = resolvePatchSizeTier(filesAffected, patchTier);
|
|
44
44
|
if (tierDecision.tier === 'branding') {
|
|
45
45
|
info(tierDecision.source === 'explicit'
|
|
@@ -54,7 +54,12 @@ export async function runPatchLint(engineDir, filesAffected, diffContent, config
|
|
|
54
54
|
const checkJsReportScope = patchQueueCtx
|
|
55
55
|
? resolvePatchOwnedSysMjs(detectNewFilesInDiff(diffContent))
|
|
56
56
|
: undefined;
|
|
57
|
-
const issues = await lintExportedPatch(engineDir, filesAffected, diffContent, config,
|
|
57
|
+
const issues = await lintExportedPatch(engineDir, filesAffected, diffContent, config, {
|
|
58
|
+
...(patchQueueCtx ? { patchQueueCtx } : {}),
|
|
59
|
+
...(ignoreChecks ? { ignoreChecks } : {}),
|
|
60
|
+
...(patchTier ? { patchTier } : {}),
|
|
61
|
+
...(checkJsReportScope ? { checkJsReportScope } : {}),
|
|
62
|
+
});
|
|
58
63
|
reportPatchLintOutcome(issues, skipLint);
|
|
59
64
|
}
|
|
60
65
|
/**
|
|
@@ -115,7 +120,7 @@ export async function promptExportPatchMetadata(options, isInteractive, commandN
|
|
|
115
120
|
// both name shapes.
|
|
116
121
|
let patchName = options.name?.trim().replace(/\.patch$/i, '');
|
|
117
122
|
if (patchName) {
|
|
118
|
-
const validationError =
|
|
123
|
+
const validationError = describePatchNameProblem(patchName);
|
|
119
124
|
if (validationError) {
|
|
120
125
|
throw new InvalidArgumentError(validationError, '--name');
|
|
121
126
|
}
|
|
@@ -127,7 +132,7 @@ export async function promptExportPatchMetadata(options, isInteractive, commandN
|
|
|
127
132
|
const nameResult = await text({
|
|
128
133
|
message: 'Enter a name for this patch:',
|
|
129
134
|
placeholder: commandName === 'export' ? 'my-change' : 'my-changes',
|
|
130
|
-
validate: (value) =>
|
|
135
|
+
validate: (value) => describePatchNameProblem((value ?? '').trim()),
|
|
131
136
|
});
|
|
132
137
|
if (isCancel(nameResult)) {
|
|
133
138
|
cancel('Export cancelled');
|
|
@@ -217,18 +222,18 @@ export async function confirmSupersedePatches(patchesDir, filesAffected, superse
|
|
|
217
222
|
/**
|
|
218
223
|
* Detects new files missing license headers and offers to add them.
|
|
219
224
|
*
|
|
220
|
-
* In interactive mode the user is prompted before any files are modified.
|
|
221
|
-
*
|
|
222
|
-
*
|
|
225
|
+
* In interactive mode the user is prompted before any files are modified. In
|
|
226
|
+
* non-interactive mode the function is a no-op — the existing lint error
|
|
227
|
+
* blocks the export instead.
|
|
223
228
|
*
|
|
224
229
|
* @param engineDir - Absolute path to engine directory
|
|
225
230
|
* @param diffContent - Current unified diff
|
|
226
231
|
* @param config - Project configuration
|
|
227
232
|
* @param isInteractive - Whether interactive prompts are available
|
|
228
233
|
* @param dryRun - When true, only REPORT missing headers, never prompt or
|
|
229
|
-
* write. Dry-run must stay read-only:
|
|
230
|
-
*
|
|
231
|
-
*
|
|
234
|
+
* write. Dry-run must stay read-only: without this flag an interactive
|
|
235
|
+
* `export --dry-run` prompts (default Yes), writes license headers into
|
|
236
|
+
* engine/ files, and then closes with "no changes made".
|
|
232
237
|
* @returns true if files were modified on disk (caller must regenerate diff)
|
|
233
238
|
*/
|
|
234
239
|
export async function autoFixLicenseHeaders(engineDir, diffContent, config, isInteractive, dryRun = false) {
|
|
@@ -324,19 +329,17 @@ export function findPartialOwnershipOverlap(manifest, filesAffected, excludeFile
|
|
|
324
329
|
}
|
|
325
330
|
/**
|
|
326
331
|
* Gate that refuses the default export path when the new patch would
|
|
327
|
-
* silently claim files
|
|
328
|
-
*
|
|
329
|
-
*
|
|
330
|
-
*
|
|
331
|
-
* `browser/themes/shared/jar.inc.mn` after a second export with
|
|
332
|
-
* `--before`).
|
|
332
|
+
* silently claim files already tracked by other non-superseded patches.
|
|
333
|
+
* `findAllPatchesForFiles` catches the full-coverage supersede case; this
|
|
334
|
+
* fills the gap for PARTIAL overlap — two patches both claiming e.g.
|
|
335
|
+
* `browser/themes/shared/jar.inc.mn` after a second export with `--before`.
|
|
333
336
|
*
|
|
334
337
|
* Proceeds silently when there is no overlap, or when the caller passed
|
|
335
338
|
* `--allow-overlap`. In interactive mode the caller is prompted to
|
|
336
339
|
* acknowledge the overlap (the proper fix path is `re-export --files` to
|
|
337
340
|
* repartition ownership, so the prompt surfaces that pointer). In
|
|
338
|
-
* non-interactive mode
|
|
339
|
-
*
|
|
341
|
+
* non-interactive mode it throws — better to fail fast than let the queue
|
|
342
|
+
* fall out of sync with verify.
|
|
340
343
|
*/
|
|
341
344
|
export async function guardOwnershipOverlap(args) {
|
|
342
345
|
const { patchesDir, filesAffected, supersedingFilenames, allowOverlap, isInteractive, s } = args;
|
|
@@ -373,13 +376,12 @@ export async function guardOwnershipOverlap(args) {
|
|
|
373
376
|
}
|
|
374
377
|
/**
|
|
375
378
|
* Runs the two pre-commit gates shared by `export` and `export-all` in
|
|
376
|
-
* order: the supersede confirmation, then the cross-patch ownership
|
|
377
|
-
*
|
|
378
|
-
*
|
|
379
|
-
*
|
|
380
|
-
*
|
|
381
|
-
*
|
|
382
|
-
* patches both claimed the file and `verify` failed immediately).
|
|
379
|
+
* order: the supersede confirmation, then the cross-patch ownership overlap
|
|
380
|
+
* guard. The overlap guard receives the filenames of the patches the export
|
|
381
|
+
* would fully supersede so it does not flag a file claimed by a patch that
|
|
382
|
+
* is about to be removed. Catching only FULL-coverage supersedes leaves a
|
|
383
|
+
* second export targeting a shared file creating a queue where two patches
|
|
384
|
+
* both claim it and `verify` fails immediately.
|
|
383
385
|
*
|
|
384
386
|
* @param args - Gate inputs shared by both export commands
|
|
385
387
|
* @param args.patchesDir - Absolute path of the patches directory
|
|
@@ -388,8 +390,8 @@ export async function guardOwnershipOverlap(args) {
|
|
|
388
390
|
* @param args.allowOverlap - The command's `--allow-overlap` flag
|
|
389
391
|
* @param args.isInteractive - Whether prompting the operator is possible
|
|
390
392
|
* @param args.s - Active spinner, stopped before any prompt
|
|
391
|
-
* @returns `true` when both gates passed; `false` when the operator
|
|
392
|
-
*
|
|
393
|
+
* @returns `true` when both gates passed; `false` when the operator declined
|
|
394
|
+
* (the caller returns without committing)
|
|
393
395
|
*/
|
|
394
396
|
export async function runSupersedeAndOverlapGates(args) {
|
|
395
397
|
const { patchesDir, filesAffected, supersede, allowOverlap, isInteractive, s } = args;
|
|
@@ -3,11 +3,12 @@ import { stat } from 'node:fs/promises';
|
|
|
3
3
|
import { join } from 'node:path';
|
|
4
4
|
import { Command, Option } from 'commander';
|
|
5
5
|
import { getProjectPaths, loadConfig } from '../core/config.js';
|
|
6
|
-
import { appendHistory } from '../core/destructive.js';
|
|
6
|
+
import { appendHistory, stdioIsInteractive } from '../core/destructive.js';
|
|
7
|
+
import { assertEngineGitReady } from '../core/engine-precondition.js';
|
|
7
8
|
import { withEngineSessionLock } from '../core/engine-session-lock.js';
|
|
8
9
|
import { collectFurnaceManagedPrefixes } from '../core/furnace-config.js';
|
|
9
10
|
import { enforceFreshFurnaceSources } from '../core/furnace-stale-export.js';
|
|
10
|
-
import { getStatusWithCodes
|
|
11
|
+
import { getStatusWithCodes } from '../core/git.js';
|
|
11
12
|
import { generateBinaryFilePatch, generateFullFilePatch } from '../core/git-diff.js';
|
|
12
13
|
import { isBinaryFile } from '../core/git-file-ops.js';
|
|
13
14
|
import { getModifiedFilesInDir, getUntrackedFiles, getUntrackedFilesInDir, } from '../core/git-status.js';
|
|
@@ -33,11 +34,10 @@ async function collectExportFiles(paths, files) {
|
|
|
33
34
|
let untrackedFiles;
|
|
34
35
|
// Accept both repo-root-relative (`engine/browser/...`) and engine-relative
|
|
35
36
|
// (`browser/...`) paths for every input, matching `register`/`test`/`lint`.
|
|
36
|
-
//
|
|
37
|
-
// `File "engine/..." has no changes to export
|
|
38
|
-
//
|
|
39
|
-
//
|
|
40
|
-
// a no-op for the lookup pipeline.
|
|
37
|
+
// Without the strip, an `engine/`-prefixed path falls through to
|
|
38
|
+
// `File "engine/..." has no changes to export.`: the status lookup sees
|
|
39
|
+
// paths relative to `paths.engine`, so the explicit prefix double-roots the
|
|
40
|
+
// candidate.
|
|
41
41
|
for (const rawInputPath of files) {
|
|
42
42
|
const inputPath = stripEnginePrefix(rawInputPath);
|
|
43
43
|
const fullInputPath = join(paths.engine, inputPath);
|
|
@@ -88,13 +88,14 @@ async function collectExportFiles(paths, files) {
|
|
|
88
88
|
return { files: [...collectedFiles].sort(), fromDirectory };
|
|
89
89
|
}
|
|
90
90
|
/**
|
|
91
|
-
* Auto-excludes directory-derived files already owned by OTHER patches
|
|
92
|
-
*
|
|
93
|
-
*
|
|
94
|
-
*
|
|
95
|
-
* the wrong tool for "leave
|
|
96
|
-
* files are never excluded (the
|
|
97
|
-
* with those). Prints one notice
|
|
91
|
+
* Auto-excludes directory-derived files already owned by OTHER patches.
|
|
92
|
+
*
|
|
93
|
+
* A directory export otherwise plans files owned by earlier patches into the
|
|
94
|
+
* new patch, and the duplicate-new-file-creation refusal surfaces only at
|
|
95
|
+
* placement lint, suggesting `--force-unsafe` — the wrong tool for "leave
|
|
96
|
+
* that file with its owner". Explicitly named files are never excluded (the
|
|
97
|
+
* overlap gates still confront the operator with those). Prints one notice
|
|
98
|
+
* per exclusion.
|
|
98
99
|
*/
|
|
99
100
|
async function excludeFilesOwnedByOtherPatches(patchesDir, collected) {
|
|
100
101
|
if (collected.fromDirectory.size === 0)
|
|
@@ -169,14 +170,7 @@ async function prepareExport(projectRoot, files, options) {
|
|
|
169
170
|
throw new InvalidArgumentError('--order, --before, and --after are mutually exclusive.', 'export placement');
|
|
170
171
|
}
|
|
171
172
|
const paths = getProjectPaths(projectRoot);
|
|
172
|
-
|
|
173
|
-
if (!(await pathExists(paths.engine))) {
|
|
174
|
-
throw new GeneralError('Firefox source not found. Run "fireforge download" first.');
|
|
175
|
-
}
|
|
176
|
-
// Check if it's a git repository
|
|
177
|
-
if (!(await isGitRepository(paths.engine))) {
|
|
178
|
-
throw new GeneralError('Engine directory is not a git repository. Run "fireforge download" to initialize.');
|
|
179
|
-
}
|
|
173
|
+
await assertEngineGitReady(paths.engine);
|
|
180
174
|
const collected = await collectExportFiles(paths, files);
|
|
181
175
|
let allFiles = await excludeFilesOwnedByOtherPatches(paths.patches, collected);
|
|
182
176
|
const ownershipExclusions = collected.files.length - allFiles.length;
|
|
@@ -202,10 +196,10 @@ async function prepareExport(projectRoot, files, options) {
|
|
|
202
196
|
throw new GeneralError(`Paths "${pathList}" have no changes to export.\n\n` +
|
|
203
197
|
'Run "fireforge status" to see modified files.');
|
|
204
198
|
}
|
|
205
|
-
// Stale-furnace-source gate
|
|
206
|
-
//
|
|
207
|
-
//
|
|
208
|
-
//
|
|
199
|
+
// Stale-furnace-source gate: the export captures deployed engine copies,
|
|
200
|
+
// so refuse (or warn under --allow-stale-furnace) when a covered
|
|
201
|
+
// component's source changed since the last furnace apply. Runs after
|
|
202
|
+
// --exclude-furnace so excluded furnace files never trigger it.
|
|
209
203
|
await enforceFreshFurnaceSources(projectRoot, allFiles, options.allowStaleFurnace === true, 'export');
|
|
210
204
|
let diff = await generatePatchDiff(paths.engine, allFiles);
|
|
211
205
|
if (!diff.trim()) {
|
|
@@ -222,7 +216,7 @@ async function prepareExport(projectRoot, files, options) {
|
|
|
222
216
|
await ensureDir(paths.patches);
|
|
223
217
|
}
|
|
224
218
|
const config = await loadConfig(projectRoot);
|
|
225
|
-
const isInteractive =
|
|
219
|
+
const isInteractive = stdioIsInteractive();
|
|
226
220
|
// Auto-fix missing license headers on new files (interactive only;
|
|
227
221
|
// report-only under --dry-run so the preview never mutates engine/)
|
|
228
222
|
const headersAdded = await autoFixLicenseHeaders(paths.engine, diff, config, isInteractive, options.dryRun ?? false);
|