@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
|
@@ -4,39 +4,37 @@ import { join } from 'node:path';
|
|
|
4
4
|
import { Command } from 'commander';
|
|
5
5
|
import { isBrandingManagedPath } from '../core/branding.js';
|
|
6
6
|
import { getProjectPaths, loadConfig } from '../core/config.js';
|
|
7
|
+
import { assertEngineGitReady } from '../core/engine-precondition.js';
|
|
7
8
|
import { collectFurnaceManagedPrefixes } from '../core/furnace-config.js';
|
|
8
|
-
import { getStatusWithCodes, hasChanges
|
|
9
|
+
import { getStatusWithCodes, hasChanges } from '../core/git.js';
|
|
9
10
|
import { getAllDiff, getDiffForFilesAgainstHead } from '../core/git-diff.js';
|
|
10
11
|
import { expandUntrackedDirectoryEntries, getModifiedFilesInDir, getUntrackedFiles, getUntrackedFilesInDir, getWorkingTreeStatus, } from '../core/git-status.js';
|
|
11
|
-
import { clearPerPatchLintCache } from '../core/lint-cache.js';
|
|
12
12
|
import { extractAffectedFiles } from '../core/patch-apply.js';
|
|
13
13
|
import { buildPatchQueueContext, countNonBinaryDiffLines, formatPatchLintIssue, lintExportedPatch, lintPatchQueue, lintPatchSize, } from '../core/patch-lint.js';
|
|
14
|
+
import { clearPerPatchLintCache } from '../core/patch-lint-cache.js';
|
|
14
15
|
import { collectDiffFilePaths, tagLintIssues } from '../core/patch-lint-diff-tag.js';
|
|
15
|
-
import { GeneralError } from '../errors/base.js';
|
|
16
|
+
import { GeneralError, InvalidArgumentError } from '../errors/base.js';
|
|
16
17
|
import { pathExists } from '../utils/fs.js';
|
|
17
18
|
import { info, intro, outro, success, warn } from '../utils/logger.js';
|
|
18
19
|
import { stripEnginePrefix } from '../utils/paths.js';
|
|
19
20
|
import { lintPerPatch } from './lint-per-patch.js';
|
|
20
21
|
/**
|
|
21
22
|
* Resolves the diff the lint command should run against. Returns `null` when
|
|
22
|
-
* there is nothing to lint (
|
|
23
|
-
*
|
|
23
|
+
* there is nothing to lint (no matching files, clean tree, or empty diff
|
|
24
|
+
* content) — callers treat that as the early-exit signal and stop.
|
|
24
25
|
*
|
|
25
26
|
* Extracted from {@link lintCommand} so that function stays under the
|
|
26
|
-
* per-function LOC budget
|
|
27
|
-
*
|
|
28
|
-
* pipeline, so the split is a pure rename rather than a refactor.
|
|
27
|
+
* per-function LOC budget; the two file-mode and aggregate-mode branches
|
|
28
|
+
* share no state with the post-lint reporting pipeline.
|
|
29
29
|
*
|
|
30
|
-
* When `binaryName` is provided, the aggregate-mode branch (no
|
|
31
|
-
*
|
|
32
|
-
*
|
|
33
|
-
*
|
|
34
|
-
*
|
|
35
|
-
*
|
|
36
|
-
*
|
|
37
|
-
*
|
|
38
|
-
* previous behaviour: passing a branding file explicitly still lints
|
|
39
|
-
* it, so operators who need to audit branding content can do so.
|
|
30
|
+
* When `binaryName` is provided, the aggregate-mode branch (no explicit file
|
|
31
|
+
* list) excludes paths under `browser/branding/<binaryName>/` from the diff.
|
|
32
|
+
* `status` classifies those paths as `branding` — tool-managed material the
|
|
33
|
+
* operator did not author directly — and without the exclusion
|
|
34
|
+
* `fireforge lint` on a fresh project immediately fails `large-patch-lines`
|
|
35
|
+
* / `large-patch-files` / `missing-license-header` on the generated branding
|
|
36
|
+
* tree. File-list mode (explicit paths) is unaffected: passing a branding
|
|
37
|
+
* file explicitly still lints it.
|
|
40
38
|
*/
|
|
41
39
|
async function resolveLintDiff(engineDir, files, binaryName, furnacePrefixes) {
|
|
42
40
|
if (files.length > 0) {
|
|
@@ -44,12 +42,12 @@ async function resolveLintDiff(engineDir, files, binaryName, furnacePrefixes) {
|
|
|
44
42
|
let fileStatuses;
|
|
45
43
|
let untrackedFiles;
|
|
46
44
|
// Strip a leading `engine/` segment up-front so the rest of the lookup
|
|
47
|
-
// pipeline (directory stat, modified-files-in-dir, status probe)
|
|
48
|
-
//
|
|
49
|
-
// `engine/browser/base/content/foo.js`
|
|
50
|
-
// files found in the specified paths." because git sees every path
|
|
45
|
+
// pipeline (directory stat, modified-files-in-dir, status probe) sees the
|
|
46
|
+
// engine-relative form. Without it, passing
|
|
47
|
+
// `engine/browser/base/content/foo.js` falls through to "No modified
|
|
48
|
+
// files found in the specified paths.", because git sees every path
|
|
51
49
|
// relative to engine/. The same normalization runs in `register`,
|
|
52
|
-
// `test`, and `export
|
|
50
|
+
// `test`, and `export`.
|
|
53
51
|
const normalizedFiles = files.map((inputPath) => stripEnginePrefix(inputPath));
|
|
54
52
|
for (const inputPath of normalizedFiles) {
|
|
55
53
|
const fullInputPath = join(engineDir, inputPath);
|
|
@@ -98,21 +96,18 @@ async function resolveLintDiff(engineDir, files, binaryName, furnacePrefixes) {
|
|
|
98
96
|
outro('Nothing to lint');
|
|
99
97
|
return null;
|
|
100
98
|
}
|
|
101
|
-
// Aggregate-mode branding exclusion. A fresh-setup workspace
|
|
102
|
-
//
|
|
103
|
-
//
|
|
104
|
-
//
|
|
105
|
-
//
|
|
106
|
-
//
|
|
107
|
-
// `branding` bucket in `fireforge status` so the two views stay
|
|
108
|
-
// consistent.
|
|
99
|
+
// Aggregate-mode branding exclusion. A fresh-setup workspace carries a
|
|
100
|
+
// large tool-managed branding diff the operator did not author; running
|
|
101
|
+
// the default lint against it fires size and license-header rules on
|
|
102
|
+
// content that was never intended to survive in the patch queue as-is. The
|
|
103
|
+
// exclusion mirrors the `branding` bucket in `fireforge status` so the two
|
|
104
|
+
// views stay consistent.
|
|
109
105
|
//
|
|
110
|
-
// `expandUntrackedDirectoryEntries` promotes collapsed `?? dir/`
|
|
111
|
-
//
|
|
112
|
-
//
|
|
113
|
-
// `?? browser/modules/<fork>/` and `getDiffForFilesAgainstHead`
|
|
114
|
-
//
|
|
115
|
-
// (eval finding: aggregate lint unusable on a real imported queue).
|
|
106
|
+
// `expandUntrackedDirectoryEntries` promotes collapsed `?? dir/` status
|
|
107
|
+
// rows to individual file entries before the diff pass. Without it, a
|
|
108
|
+
// patch that introduces a new directory shows up as
|
|
109
|
+
// `?? browser/modules/<fork>/` and `getDiffForFilesAgainstHead` crashes
|
|
110
|
+
// with EISDIR reading the directory as if it were a file.
|
|
116
111
|
if (binaryName) {
|
|
117
112
|
const rawStatus = await getWorkingTreeStatus(engineDir);
|
|
118
113
|
const expanded = await expandUntrackedDirectoryEntries(engineDir, rawStatus);
|
|
@@ -120,12 +115,11 @@ async function resolveLintDiff(engineDir, files, binaryName, furnacePrefixes) {
|
|
|
120
115
|
const nonBrandingPaths = allPaths.filter((path) => !isBrandingManagedPath(path, binaryName));
|
|
121
116
|
const brandingExcluded = allPaths.length - nonBrandingPaths.length;
|
|
122
117
|
// Drop Furnace-managed paths the same way branding is dropped: their
|
|
123
|
-
// contents are tool output (overrides, custom widgets, preview-
|
|
124
|
-
//
|
|
125
|
-
//
|
|
126
|
-
//
|
|
127
|
-
//
|
|
128
|
-
// Finding 19) — each story is intentionally header-less because it's
|
|
118
|
+
// contents are tool output (overrides, custom widgets, preview-generated
|
|
119
|
+
// stories) that the operator did not author and never intended to land
|
|
120
|
+
// on the patch queue. Without the carve-out, a post-`furnace preview`
|
|
121
|
+
// aggregate `lint` fails with one `missing-license-header` error per
|
|
122
|
+
// generated story file — each is intentionally header-less because it is
|
|
129
123
|
// re-generated from component metadata on every preview run.
|
|
130
124
|
const filteredPaths = furnacePrefixes
|
|
131
125
|
? nonBrandingPaths.filter((path) => ![...furnacePrefixes].some((p) => path.startsWith(p)))
|
|
@@ -150,10 +144,8 @@ async function resolveLintDiff(engineDir, files, binaryName, furnacePrefixes) {
|
|
|
150
144
|
}
|
|
151
145
|
return diff;
|
|
152
146
|
}
|
|
153
|
-
// Fallback path: no binaryName available (
|
|
154
|
-
//
|
|
155
|
-
// linting the full diff so the lint surface is at least as broad
|
|
156
|
-
// as before.
|
|
147
|
+
// Fallback path: no binaryName available (a caller without a loaded
|
|
148
|
+
// config). Lint the full diff so the lint surface stays at least as broad.
|
|
157
149
|
const diff = await getAllDiff(engineDir);
|
|
158
150
|
if (!diff.trim()) {
|
|
159
151
|
info('No diff content to lint.');
|
|
@@ -169,25 +161,24 @@ function buildMaxWarningsMessage(count, maxWarnings, scope) {
|
|
|
169
161
|
' If this is a release gate, run with --per-patch to identify the owning patch. For intentional staged imports, use patch staged-dependency; for ownership repairs, preview patch move-files, patch reorder --dry-run, or re-export --files --dry-run; add scoped lintIgnore only after review.');
|
|
170
162
|
}
|
|
171
163
|
/**
|
|
172
|
-
* Filters aggregate-mode lint issues against per-patch `lintIgnore`
|
|
173
|
-
*
|
|
174
|
-
*
|
|
175
|
-
*
|
|
164
|
+
* Filters aggregate-mode lint issues against per-patch `lintIgnore` lists
|
|
165
|
+
* drawn from the manifest. An issue is dropped when at least one patch whose
|
|
166
|
+
* `filesAffected` covers `issue.file` lists `issue.check` in its
|
|
167
|
+
* `lintIgnore`.
|
|
176
168
|
*
|
|
177
|
-
* Mirrors the per-patch contract: `--per-patch` mode threads each
|
|
178
|
-
*
|
|
179
|
-
*
|
|
180
|
-
*
|
|
181
|
-
* warning every CI run
|
|
182
|
-
* with no patch-level scope. Attributing each issue's file to its
|
|
169
|
+
* Mirrors the per-patch contract: `--per-patch` mode threads each patch's
|
|
170
|
+
* `lintIgnore` directly into `lintExportedPatch`, so a check the operator
|
|
171
|
+
* explicitly waived in `patches.json` does not surface. Aggregate `--since`
|
|
172
|
+
* mode has no patch-level scope of its own and would otherwise rediscover
|
|
173
|
+
* the suppressed warning every CI run. Attributing each issue's file to its
|
|
183
174
|
* owning patch via `filesAffected` re-establishes the same suppression
|
|
184
|
-
* semantics. Cross-patch findings (forward-import, duplicate-creation)
|
|
185
|
-
*
|
|
186
|
-
*
|
|
175
|
+
* semantics. Cross-patch findings (forward-import, duplicate-creation) also
|
|
176
|
+
* attribute via `issue.file`, which is the offending site and is owned by
|
|
177
|
+
* some patch.
|
|
187
178
|
*
|
|
188
|
-
* Multiple owners: an issue is dropped if **any** owning patch waived
|
|
189
|
-
*
|
|
190
|
-
*
|
|
179
|
+
* Multiple owners: an issue is dropped if **any** owning patch waived the
|
|
180
|
+
* rule. Conservative — never adds new findings, only drops already-waived
|
|
181
|
+
* ones.
|
|
191
182
|
*
|
|
192
183
|
* @param issues - Issues collected from the aggregate lint run.
|
|
193
184
|
* @param ctx - Patch queue context used to attribute file → patch.
|
|
@@ -233,17 +224,17 @@ function validateLintFlags(options) {
|
|
|
233
224
|
}
|
|
234
225
|
if (options.maxWarnings !== undefined &&
|
|
235
226
|
(!Number.isInteger(options.maxWarnings) || options.maxWarnings < 0)) {
|
|
236
|
-
throw new
|
|
227
|
+
throw new InvalidArgumentError('--max-warnings must be a non-negative integer.', '--max-warnings');
|
|
237
228
|
}
|
|
238
229
|
// `--patches` only means something in per-patch mode (it filters the
|
|
239
230
|
// queue); in aggregate/file-list mode there is no patch loop to narrow.
|
|
240
231
|
if (options.patches !== undefined && !options.perPatch) {
|
|
241
|
-
throw new
|
|
232
|
+
throw new InvalidArgumentError('--patches requires --per-patch.', '--patches');
|
|
242
233
|
}
|
|
243
234
|
// The JSON report is a per-patch artifact (per-patch size metrics and
|
|
244
235
|
// suppressed issues); aggregate mode has no per-patch rows to report.
|
|
245
236
|
if (options.report !== undefined && !options.perPatch) {
|
|
246
|
-
throw new
|
|
237
|
+
throw new InvalidArgumentError('--report requires --per-patch.', '--report');
|
|
247
238
|
}
|
|
248
239
|
}
|
|
249
240
|
/**
|
|
@@ -272,17 +263,16 @@ function downgradeAggregateSizeRules(issues, files, ctx) {
|
|
|
272
263
|
* for an ad-hoc explicit-file-list lint, scoped to each file's **owning
|
|
273
264
|
* patch** rather than the combined file list.
|
|
274
265
|
*
|
|
275
|
-
*
|
|
276
|
-
*
|
|
277
|
-
*
|
|
278
|
-
*
|
|
279
|
-
*
|
|
280
|
-
*
|
|
281
|
-
*
|
|
282
|
-
* `
|
|
283
|
-
*
|
|
284
|
-
*
|
|
285
|
-
* oversized-change warning.
|
|
266
|
+
* Feeding every passed file to `lintExportedPatch` as one synthetic patch
|
|
267
|
+
* makes a cross-patch selection of eight files belonging to four patches
|
|
268
|
+
* report `Patch affects 8 files` even though no single owning patch is
|
|
269
|
+
* oversized. This helper groups the affected files by their owning patch
|
|
270
|
+
* (via the manifest's `filesAffected`), then runs `lintPatchSize` against
|
|
271
|
+
* each owner's real file count + diff, honouring that owner's `tier` and
|
|
272
|
+
* `lintIgnore` — so `lint <files>`, `lint --per-patch`, and
|
|
273
|
+
* `re-export --dry-run` agree on the same size findings for the same files.
|
|
274
|
+
* Files no patch claims are evaluated together as one prospective new patch,
|
|
275
|
+
* preserving the pre-export oversized-change warning.
|
|
286
276
|
*
|
|
287
277
|
* @param engineDir - Absolute engine directory
|
|
288
278
|
* @param filesAffected - Engine-relative files touched by the ad-hoc diff
|
|
@@ -382,7 +372,7 @@ async function reportLintOutcome(engineDir, issues, options) {
|
|
|
382
372
|
// Exit-code scope: `--only-introduced` narrows the failure criterion to
|
|
383
373
|
// issues tagged `introduced`. Cumulative errors still print so the
|
|
384
374
|
// operator sees the full queue state, but do not fail lint — the
|
|
385
|
-
//
|
|
375
|
+
// case this serves is a branch whose own diff is clean but whose repo
|
|
386
376
|
// already carries pre-existing queue errors from older patches.
|
|
387
377
|
const failingErrors = options.onlyIntroduced
|
|
388
378
|
? errors.filter((i) => i.tag === 'introduced')
|
|
@@ -398,13 +388,12 @@ async function reportLintOutcome(engineDir, issues, options) {
|
|
|
398
388
|
outro('Lint failed');
|
|
399
389
|
throw new GeneralError(buildMaxWarningsMessage(warnings.length, options.maxWarnings));
|
|
400
390
|
}
|
|
401
|
-
// Notices are advisory and
|
|
391
|
+
// Notices are advisory and do not count as warnings — emitting "passed
|
|
402
392
|
// with warnings" when only notices fired contradicts the preceding
|
|
403
|
-
// `0 warning(s)` summary line and reads as a regression.
|
|
404
|
-
//
|
|
405
|
-
//
|
|
406
|
-
//
|
|
407
|
-
// contract the operator gets from a real warning.
|
|
393
|
+
// `0 warning(s)` summary line and reads as a regression. Errors suppressed
|
|
394
|
+
// by --only-introduced still warrant the "with warnings" outro: they print
|
|
395
|
+
// as ERROR rows but no longer fail the run, which is the same contract the
|
|
396
|
+
// operator gets from a real warning.
|
|
408
397
|
const suppressedErrors = options.onlyIntroduced && errors.length > 0;
|
|
409
398
|
if (warnings.length > 0 || suppressedErrors) {
|
|
410
399
|
outro('Lint passed with warnings');
|
|
@@ -426,12 +415,7 @@ export async function lintCommand(projectRoot, files, options = {}) {
|
|
|
426
415
|
intro('FireForge Lint');
|
|
427
416
|
validateLintFlags(options);
|
|
428
417
|
const paths = getProjectPaths(projectRoot);
|
|
429
|
-
|
|
430
|
-
throw new GeneralError('Firefox source not found. Run "fireforge download" first.');
|
|
431
|
-
}
|
|
432
|
-
if (!(await isGitRepository(paths.engine))) {
|
|
433
|
-
throw new GeneralError('Engine directory is not a git repository. Run "fireforge download" to initialize.');
|
|
434
|
-
}
|
|
418
|
+
await assertEngineGitReady(paths.engine);
|
|
435
419
|
if (options.perPatch) {
|
|
436
420
|
// Positional arguments in per-patch mode select PATCHES through the
|
|
437
421
|
// same alias resolution as --patches — a non-matching
|
|
@@ -441,11 +425,8 @@ export async function lintCommand(projectRoot, files, options = {}) {
|
|
|
441
425
|
await lintPerPatch(projectRoot, paths, perPatchOptions);
|
|
442
426
|
return;
|
|
443
427
|
}
|
|
444
|
-
// Load the config before resolving the diff so
|
|
445
|
-
//
|
|
446
|
-
// `resolveLintDiff`. The config was previously loaded only after
|
|
447
|
-
// the diff was resolved; hoisting it is cheap and keeps the two
|
|
448
|
-
// call sites close together.
|
|
428
|
+
// Load the config before resolving the diff so `binaryName` can be passed
|
|
429
|
+
// into the aggregate-mode branding exclusion in `resolveLintDiff`.
|
|
449
430
|
const config = await loadConfig(projectRoot);
|
|
450
431
|
// Pull the Furnace-managed prefix set up-front so aggregate lint can
|
|
451
432
|
// mirror the branding exclusion for Furnace material — without it,
|
|
@@ -469,7 +450,10 @@ export async function lintCommand(projectRoot, files, options = {}) {
|
|
|
469
450
|
// selection synthesises a phantom oversized patch from the file count.
|
|
470
451
|
const fileListMode = files.length > 0 && ctx !== undefined;
|
|
471
452
|
let issues = [
|
|
472
|
-
...(await lintExportedPatch(paths.engine, filesAffected, diff, config,
|
|
453
|
+
...(await lintExportedPatch(paths.engine, filesAffected, diff, config, {
|
|
454
|
+
...(ctx ? { patchQueueCtx: ctx } : {}),
|
|
455
|
+
...(fileListMode ? { skipPatchSize: true } : {}),
|
|
456
|
+
})),
|
|
473
457
|
];
|
|
474
458
|
if (files.length > 0 && ctx) {
|
|
475
459
|
issues.push(...(await lintOwningPatchSizes(paths.engine, filesAffected, ctx)));
|
|
@@ -481,11 +465,11 @@ export async function lintCommand(projectRoot, files, options = {}) {
|
|
|
481
465
|
issues.push(...lintPatchQueue(ctx));
|
|
482
466
|
}
|
|
483
467
|
// Honor per-patch `lintIgnore` in aggregate mode by attributing each
|
|
484
|
-
// issue's file to its owning patches via the manifest's
|
|
485
|
-
//
|
|
486
|
-
//
|
|
487
|
-
//
|
|
488
|
-
//
|
|
468
|
+
// issue's file to its owning patches via the manifest's `filesAffected`.
|
|
469
|
+
// Per-patch mode threads `lintIgnore` directly into `lintExportedPatch`;
|
|
470
|
+
// aggregate mode has no patch-level scope to consult, so a check an
|
|
471
|
+
// operator explicitly waived in `patches.json` re-surfaces on every
|
|
472
|
+
// `--since` run (the CI default).
|
|
489
473
|
if (ctx) {
|
|
490
474
|
const result = applyAggregateLintIgnoreSuppression(issues, ctx);
|
|
491
475
|
issues = result.issues;
|
|
@@ -532,7 +516,7 @@ export function registerLint(program, { getProjectRoot, withErrorHandling }) {
|
|
|
532
516
|
if (options.maxWarnings !== undefined) {
|
|
533
517
|
const maxWarnings = Number(options.maxWarnings);
|
|
534
518
|
if (!Number.isInteger(maxWarnings) || maxWarnings < 0) {
|
|
535
|
-
throw new
|
|
519
|
+
throw new InvalidArgumentError('--max-warnings must be a non-negative integer.', '--max-warnings');
|
|
536
520
|
}
|
|
537
521
|
lintOptions.maxWarnings = maxWarnings;
|
|
538
522
|
}
|
|
@@ -3,12 +3,11 @@ import { Command } from 'commander';
|
|
|
3
3
|
import { validateBrandOverride } from '../core/brand-validation.js';
|
|
4
4
|
import { prepareBuildEnvironment } from '../core/build-prepare.js';
|
|
5
5
|
import { getProjectPaths, loadConfig } from '../core/config.js';
|
|
6
|
+
import { assertEngineExists } from '../core/engine-precondition.js';
|
|
6
7
|
import { hasBuildArtifacts, machPackageCapture } from '../core/mach.js';
|
|
7
8
|
import { assertBuildArtifacts } from '../core/mach-build-artifacts.js';
|
|
8
9
|
import { explainMachError } from '../core/mach-error-hints.js';
|
|
9
|
-
import { GeneralError } from '../errors/base.js';
|
|
10
10
|
import { BuildError } from '../errors/build.js';
|
|
11
|
-
import { pathExists } from '../utils/fs.js';
|
|
12
11
|
import { error, info, intro, outro, verbose } from '../utils/logger.js';
|
|
13
12
|
import { pickDefined } from '../utils/options.js';
|
|
14
13
|
/**
|
|
@@ -24,9 +23,7 @@ export async function packageCommand(projectRoot, options) {
|
|
|
24
23
|
const paths = getProjectPaths(projectRoot);
|
|
25
24
|
validateBrandOverride(config.binaryName, options.brand);
|
|
26
25
|
// Check if engine exists
|
|
27
|
-
|
|
28
|
-
throw new GeneralError('Firefox source not found. Run "fireforge download" first.');
|
|
29
|
-
}
|
|
26
|
+
await assertEngineExists(paths.engine);
|
|
30
27
|
const buildCheck = await hasBuildArtifacts(paths.engine);
|
|
31
28
|
assertBuildArtifacts(paths.engine, buildCheck, {
|
|
32
29
|
label: 'Package',
|
|
@@ -48,12 +45,10 @@ export async function packageCommand(projectRoot, options) {
|
|
|
48
45
|
let result;
|
|
49
46
|
try {
|
|
50
47
|
// `machPackageCapture` streams output live AND captures the tail for
|
|
51
|
-
// post-run diagnostics
|
|
52
|
-
//
|
|
53
|
-
//
|
|
54
|
-
//
|
|
55
|
-
// the evaluator hit on `mybrowser/`) get an actionable hint prepended
|
|
56
|
-
// to the raw mach output the operator already saw.
|
|
48
|
+
// post-run diagnostics; an inherit-only dispatch leaves the hint
|
|
49
|
+
// translator unable to see the failure text. The captured stderr is fed
|
|
50
|
+
// through `explainMachError` below so recognised failure modes get an
|
|
51
|
+
// actionable hint prepended to the raw mach output.
|
|
57
52
|
result = await machPackageCapture(paths.engine);
|
|
58
53
|
}
|
|
59
54
|
catch (error) {
|
|
@@ -143,7 +143,7 @@ export async function patchCompactCommand(projectRoot, options = {}) {
|
|
|
143
143
|
outro('Dry run complete — no changes made');
|
|
144
144
|
return;
|
|
145
145
|
}
|
|
146
|
-
if (decision === '
|
|
146
|
+
if (decision === 'declined') {
|
|
147
147
|
outro('Compact cancelled');
|
|
148
148
|
return;
|
|
149
149
|
}
|
|
@@ -35,15 +35,10 @@ export async function patchDeleteCommand(projectRoot, identifier, options = {})
|
|
|
35
35
|
// Build the full queue context once so we can scan each patch's newFiles
|
|
36
36
|
// without re-parsing for the dependency check below.
|
|
37
37
|
const baseCtx = await buildPatchQueueContext(paths.patches);
|
|
38
|
-
// Hard refusal:
|
|
39
|
-
//
|
|
40
|
-
//
|
|
41
|
-
//
|
|
42
|
-
// Simpler check: run the rule on the *original* context and look for
|
|
43
|
-
// imports that resolve into the target's new files from earlier patches.
|
|
44
|
-
// Even simpler: an import owned by a later patch pointing at any of the
|
|
45
|
-
// target's newly-created files is a dependency on the target. We build
|
|
46
|
-
// that check directly from baseCtx.
|
|
38
|
+
// Hard refusal: an import owned by a LATER patch that points at any of
|
|
39
|
+
// the target's newly-created files is a dependency on the target. That
|
|
40
|
+
// check is built directly from `baseCtx` rather than by diffing lint runs
|
|
41
|
+
// over a projected state.
|
|
47
42
|
const targetEntry = baseCtx.entries.find((e) => e.filename === target.filename);
|
|
48
43
|
const targetNewFileLeaves = new Set();
|
|
49
44
|
if (targetEntry) {
|
|
@@ -53,17 +48,15 @@ export async function patchDeleteCommand(projectRoot, identifier, options = {})
|
|
|
53
48
|
}
|
|
54
49
|
// Scan every later patch's new files AND its added lines on pre-existing
|
|
55
50
|
// files for import specifiers that resolve to a leaf owned by the target.
|
|
56
|
-
// Uses the shared specifier extractor so dynamic import() and
|
|
57
|
-
// ChromeUtils.defineESModuleGetters are picked up — the forward-import
|
|
58
|
-
// lint rule already covers those forms and delete safety must match the
|
|
51
|
+
// Uses the shared specifier extractor so dynamic `import()` and
|
|
52
|
+
// `ChromeUtils.defineESModuleGetters` are picked up — the forward-import
|
|
53
|
+
// lint rule already covers those forms, and delete safety must match the
|
|
59
54
|
// same set or it silently drops dependencies.
|
|
60
55
|
//
|
|
61
|
-
//
|
|
56
|
+
// Both source-site maps are covered: `newFiles` (files the later patch
|
|
62
57
|
// creates) and `modifiedFileAdditions` (added lines against files that
|
|
63
|
-
// already exist). Scanning only newFiles
|
|
64
|
-
//
|
|
65
|
-
// `import "./TargetHelper.sys.mjs"` to an existing file and the delete
|
|
66
|
-
// guard would never see the dependency.
|
|
58
|
+
// already exist). Scanning only newFiles misses a later patch adding
|
|
59
|
+
// `import "./TargetHelper.sys.mjs"` to an existing file.
|
|
67
60
|
const dependents = [];
|
|
68
61
|
const scanSite = (entryFilename, sitePath, content) => {
|
|
69
62
|
if (!isForwardImportableFile(sitePath))
|
|
@@ -117,14 +110,13 @@ export async function patchDeleteCommand(projectRoot, identifier, options = {})
|
|
|
117
110
|
const conflicts = dependents.length > 0
|
|
118
111
|
? {
|
|
119
112
|
// Wording deliberately clarifies the *runtime* impact: `git apply`
|
|
120
|
-
//
|
|
121
|
-
// imports a file the target created
|
|
122
|
-
//
|
|
123
|
-
//
|
|
124
|
-
//
|
|
125
|
-
//
|
|
126
|
-
//
|
|
127
|
-
// impact model, not a patch-application failure.
|
|
113
|
+
// does not resolve imports and succeeds even when a later patch
|
|
114
|
+
// imports a file the target created, so the queue re-imports
|
|
115
|
+
// cleanly. The breakage surfaces at browser startup when
|
|
116
|
+
// `ChromeUtils.importESModule` cannot locate the deleted module.
|
|
117
|
+
// Operators who deliberately plan to re-introduce the imported
|
|
118
|
+
// files (rename, refactor) need to know this is the impact model,
|
|
119
|
+
// not a patch-application failure.
|
|
128
120
|
reason: `${dependents.length} later patch(es) contain import statements that reference files created by ${target.filename}. Patch application itself will still succeed, but runtime imports will fail at browser startup until those files are re-introduced.`,
|
|
129
121
|
details: dependents,
|
|
130
122
|
}
|
|
@@ -150,19 +142,18 @@ export async function patchDeleteCommand(projectRoot, identifier, options = {})
|
|
|
150
142
|
outro('Dry run complete — no changes made');
|
|
151
143
|
return;
|
|
152
144
|
}
|
|
153
|
-
if (decision === '
|
|
145
|
+
if (decision === 'declined') {
|
|
154
146
|
outro('Delete cancelled');
|
|
155
147
|
return;
|
|
156
148
|
}
|
|
157
149
|
// Proceed: remove under the patch directory lock so concurrent exports
|
|
158
150
|
// cannot race us into the same manifest row. The history append lives
|
|
159
|
-
// inside the same lock so two concurrent deletes cannot interleave
|
|
160
|
-
//
|
|
161
|
-
//
|
|
162
|
-
//
|
|
163
|
-
//
|
|
164
|
-
// failure
|
|
165
|
-
// has committed and reporting failure to the caller would mislead.
|
|
151
|
+
// inside the same lock so two concurrent deletes cannot interleave history
|
|
152
|
+
// records beyond what POSIX O_APPEND guarantees for a single record, and
|
|
153
|
+
// so a crash between mutation and history write cannot leave a committed
|
|
154
|
+
// mutation with no audit trail. A history append failure is warned but not
|
|
155
|
+
// re-thrown: by that point the mutation has committed, and reporting
|
|
156
|
+
// failure to the caller would mislead.
|
|
166
157
|
await withPatchDirectoryLock(paths.patches, async () => {
|
|
167
158
|
await removePatchFileAndManifest(paths.patches, target.filename);
|
|
168
159
|
try {
|
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* `fireforge patch <verb>` parent command. Groups single-patch
|
|
3
|
-
*
|
|
4
|
-
* `
|
|
5
|
-
* list.
|
|
6
|
-
*
|
|
7
|
-
* flat.
|
|
2
|
+
* `fireforge patch <verb>` parent command. Groups single-patch mutations and
|
|
3
|
+
* planners (`compact`, `delete`, `lint-ignore`, `move-files`, `rename`,
|
|
4
|
+
* `reorder`, `staged-dependency`, `tier`) so they do not clutter the
|
|
5
|
+
* top-level command list. Queue-level verbs like `lint`, `export`, `verify`,
|
|
6
|
+
* and `status` stay flat.
|
|
8
7
|
*/
|
|
9
8
|
import { Command } from 'commander';
|
|
10
9
|
import type { CommandContext } from '../../types/cli.js';
|
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
// SPDX-License-Identifier: EUPL-1.2
|
|
2
2
|
/**
|
|
3
|
-
* `fireforge patch <verb>` parent command. Groups single-patch
|
|
4
|
-
*
|
|
5
|
-
* `
|
|
6
|
-
* list.
|
|
7
|
-
*
|
|
8
|
-
* flat.
|
|
3
|
+
* `fireforge patch <verb>` parent command. Groups single-patch mutations and
|
|
4
|
+
* planners (`compact`, `delete`, `lint-ignore`, `move-files`, `rename`,
|
|
5
|
+
* `reorder`, `staged-dependency`, `tier`) so they do not clutter the
|
|
6
|
+
* top-level command list. Queue-level verbs like `lint`, `export`, `verify`,
|
|
7
|
+
* and `status` stay flat.
|
|
9
8
|
*/
|
|
10
9
|
import { Command } from 'commander';
|
|
11
10
|
import { registerPatchCompact } from './compact.js';
|
|
@@ -27,12 +26,11 @@ export function registerPatch(program, context) {
|
|
|
27
26
|
const patch = program
|
|
28
27
|
.command('patch')
|
|
29
28
|
.description('Manage individual patches in the queue (compact, delete, lint-ignore, move-files, rename, reorder, staged-dependency, tier)')
|
|
30
|
-
// Match `fireforge furnace`'s no-args contract: print the group's help
|
|
31
|
-
// exit 0. Without this default action, commander routes
|
|
32
|
-
// (no subcommand) through its own help-then-exit-1
|
|
33
|
-
//
|
|
34
|
-
//
|
|
35
|
-
// would otherwise print, but returns successfully.
|
|
29
|
+
// Match `fireforge furnace`'s no-args contract: print the group's help
|
|
30
|
+
// and exit 0. Without this default action, commander routes
|
|
31
|
+
// `fireforge patch` (no subcommand) through its own help-then-exit-1
|
|
32
|
+
// path, so scripts probing the CLI surface see a misleading non-zero
|
|
33
|
+
// exit for a purely informational invocation.
|
|
36
34
|
.action(() => {
|
|
37
35
|
patch.outputHelp();
|
|
38
36
|
});
|
|
@@ -25,14 +25,14 @@ import { mutatePatchMetadata } from '../../core/patch-export.js';
|
|
|
25
25
|
import { GeneralError, InvalidArgumentError } from '../../errors/base.js';
|
|
26
26
|
import { toError } from '../../utils/errors.js';
|
|
27
27
|
import { info, intro, outro, warn } from '../../utils/logger.js';
|
|
28
|
-
import { stringListOption } from '../../utils/options.js';
|
|
28
|
+
import { addWaitLockOption, resolveWaitLockSeconds, stringListOption, } from '../../utils/options.js';
|
|
29
29
|
import { requirePatchQueue, requirePatchTarget } from './patch-context.js';
|
|
30
30
|
/**
|
|
31
31
|
* Printed whenever `--add` lands a new check id. The waiver this command
|
|
32
32
|
* writes turns per-patch lint green immediately, but consumer projects
|
|
33
|
-
* commonly audit lintIgnore lists against a reviewed allow-map —
|
|
34
|
-
*
|
|
35
|
-
*
|
|
33
|
+
* commonly audit lintIgnore lists against a reviewed allow-map — discovering
|
|
34
|
+
* that the map also needs updating otherwise costs a full downstream gate
|
|
35
|
+
* run.
|
|
36
36
|
*/
|
|
37
37
|
const LINT_IGNORE_REVIEW_WARNING = "This lint waiver is subject to the project's patch-policy review process. " +
|
|
38
38
|
'Downstream policy audits that mirror lintIgnore lists in a reviewed allow-map ' +
|
|
@@ -121,10 +121,9 @@ export async function patchLintIgnoreCommand(projectRoot, identifier, options =
|
|
|
121
121
|
const target = requirePatchTarget(identifier, manifest.patches);
|
|
122
122
|
// Destructive-operation contract (docs/lifecycle-invariants.md): manifest
|
|
123
123
|
// metadata mutations get summary + dry-run + confirmation/--yes + history
|
|
124
|
-
// uniformly.
|
|
125
|
-
//
|
|
126
|
-
//
|
|
127
|
-
// approve.
|
|
124
|
+
// uniformly. Accepting --yes without ever prompting makes the flag appear
|
|
125
|
+
// only in the history record — and suppressing lint findings is precisely
|
|
126
|
+
// the mutation an operator should consciously approve.
|
|
128
127
|
const currentList = target.lintIgnore ?? [];
|
|
129
128
|
const projectedList = applyMode(currentList, mode, values) ?? [];
|
|
130
129
|
const addsNewIds = mode === 'add' && projectedList.length > currentList.length;
|
|
@@ -143,7 +142,7 @@ export async function patchLintIgnoreCommand(projectRoot, identifier, options =
|
|
|
143
142
|
outro('Dry run complete — no changes made');
|
|
144
143
|
return;
|
|
145
144
|
}
|
|
146
|
-
if (decision === '
|
|
145
|
+
if (decision === 'declined') {
|
|
147
146
|
outro('Cancelled — no changes made');
|
|
148
147
|
return;
|
|
149
148
|
}
|
|
@@ -155,7 +154,7 @@ export async function patchLintIgnoreCommand(projectRoot, identifier, options =
|
|
|
155
154
|
// in the typed `Partial<PatchMetadata>`, and the unset list is
|
|
156
155
|
// applied via `delete` after spread.
|
|
157
156
|
return next !== undefined ? { set: { lintIgnore: next } } : { unset: ['lintIgnore'] };
|
|
158
|
-
});
|
|
157
|
+
}, { waitLockSeconds: resolveWaitLockSeconds(options.waitLock), command: 'patch lint-ignore' });
|
|
159
158
|
if (!result) {
|
|
160
159
|
// Race: target vanished between the manifest read above and the
|
|
161
160
|
// locked mutate. Surfacing as a hard error rather than a silent
|
|
@@ -195,15 +194,15 @@ export async function patchLintIgnoreCommand(projectRoot, identifier, options =
|
|
|
195
194
|
*/
|
|
196
195
|
export function registerPatchLintIgnore(parent, context) {
|
|
197
196
|
const { getProjectRoot, withErrorHandling } = context;
|
|
198
|
-
parent
|
|
197
|
+
const command = parent
|
|
199
198
|
.command('lint-ignore <name>')
|
|
200
199
|
.description('Edit PatchMetadata.lintIgnore on a single patch (no .patch body rewrite). One mode per invocation.')
|
|
201
200
|
.option('--add <check-id>', 'Lint check ID to add to the patch lintIgnore list (repeatable)', ...stringListOption())
|
|
202
201
|
.option('--remove <check-id>', 'Lint check ID to remove from the patch lintIgnore list (repeatable)', ...stringListOption())
|
|
203
202
|
.option('--clear', 'Drop the lintIgnore field entirely')
|
|
204
203
|
.option('--dry-run', 'Show what would change without writing')
|
|
205
|
-
.option('-y, --yes', 'Skip confirmation prompt (required for non-TTY)')
|
|
206
|
-
|
|
204
|
+
.option('-y, --yes', 'Skip confirmation prompt (required for non-TTY)');
|
|
205
|
+
addWaitLockOption(command).action(withErrorHandling(async (name, options) => {
|
|
207
206
|
// Commander defaults `--add`/`--remove` to `[]` so they appear in
|
|
208
207
|
// the options object even when unused. Strip empty arrays so
|
|
209
208
|
// `pickDefined` sees them as absent — otherwise the mode-count
|
|
@@ -219,6 +218,8 @@ export function registerPatchLintIgnore(parent, context) {
|
|
|
219
218
|
normalized.dryRun = true;
|
|
220
219
|
if (options.yes === true)
|
|
221
220
|
normalized.yes = true;
|
|
221
|
+
if (options.waitLock !== undefined)
|
|
222
|
+
normalized.waitLock = options.waitLock;
|
|
222
223
|
await patchLintIgnoreCommand(getProjectRoot(), name, normalized);
|
|
223
224
|
}));
|
|
224
225
|
}
|