@hominis/fireforge 0.43.1 → 0.44.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +153 -0
- package/README.md +3 -3
- 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 +13 -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-patch-manifest.d.ts +8 -0
- package/dist/src/commands/doctor-patch-manifest.js +155 -0
- 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.d.ts +1 -1
- package/dist/src/commands/doctor.js +64 -96
- 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 +15 -10
- 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 +14 -17
- 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 +48 -37
- 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 +39 -36
- 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 +17 -27
- package/dist/src/core/build-prepare.d.ts +2 -2
- package/dist/src/core/build-prepare.js +8 -9
- package/dist/src/core/config-mutate.js +20 -19
- 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 +16 -13
- package/dist/src/core/furnace-apply-helpers.d.ts +7 -7
- package/dist/src/core/furnace-apply-helpers.js +30 -21
- 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 +21 -9
- package/dist/src/core/git-base.js +24 -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 +57 -71
- 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 +41 -20
- 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 +57 -6
- package/dist/src/core/patch-manifest-consistency.js +111 -40
- package/dist/src/core/patch-manifest-files-affected.d.ts +43 -0
- package/dist/src/core/patch-manifest-files-affected.js +77 -0
- 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-manifest.d.ts +2 -1
- package/dist/src/core/patch-manifest.js +2 -1
- 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 +66 -14
- 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 +29 -13
- package/dist/src/core/token-docs.d.ts +2 -0
- package/dist/src/core/token-docs.js +3 -1
- 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 +28 -6
- 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 +68 -43
- 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 +15 -9
- 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 +111 -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 +3 -3
- 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
package/dist/src/commands/run.js
CHANGED
|
@@ -4,6 +4,7 @@ import { readdir, readFile } from 'node:fs/promises';
|
|
|
4
4
|
import { join } from 'node:path';
|
|
5
5
|
import { Command } from 'commander';
|
|
6
6
|
import { getProjectPaths, loadConfig } from '../core/config.js';
|
|
7
|
+
import { assertEngineExists } from '../core/engine-precondition.js';
|
|
7
8
|
import { warnIfFurnaceStale } from '../core/furnace-staleness.js';
|
|
8
9
|
import { hasBuildArtifacts, hasRunnableBundle, run, runMachSmoke } from '../core/mach.js';
|
|
9
10
|
import { assertBuildArtifacts } from '../core/mach-build-artifacts.js';
|
|
@@ -78,9 +79,7 @@ export async function runCommand(projectRoot, options = {}) {
|
|
|
78
79
|
intro('FireForge Run');
|
|
79
80
|
const paths = getProjectPaths(projectRoot);
|
|
80
81
|
// Check if engine exists
|
|
81
|
-
|
|
82
|
-
throw new GeneralError('Firefox source not found. Run "fireforge download" first.');
|
|
83
|
-
}
|
|
82
|
+
await assertEngineExists(paths.engine);
|
|
84
83
|
const buildCheck = await hasBuildArtifacts(paths.engine);
|
|
85
84
|
assertBuildArtifacts(paths.engine, buildCheck, {
|
|
86
85
|
label: 'Run',
|
|
@@ -88,16 +87,14 @@ export async function runCommand(projectRoot, options = {}) {
|
|
|
88
87
|
remediation: "Run 'fireforge build' first, then rerun 'fireforge run'.",
|
|
89
88
|
requireExisting: true,
|
|
90
89
|
});
|
|
91
|
-
// `hasBuildArtifacts` only checks for an `obj-*/dist/` directory; a
|
|
92
|
-
//
|
|
93
|
-
//
|
|
94
|
-
//
|
|
95
|
-
//
|
|
96
|
-
//
|
|
97
|
-
//
|
|
98
|
-
//
|
|
99
|
-
// suffix; watch is supposed to drive rebuilds of partially-built
|
|
100
|
-
// trees, so blocking there would defeat the feature.
|
|
90
|
+
// `hasBuildArtifacts` only checks for an `obj-*/dist/` directory; a build
|
|
91
|
+
// that configured but has not yet produced the launchable binary passes
|
|
92
|
+
// that check, and `mach run` then fails on the missing binary path.
|
|
93
|
+
// `hasRunnableBundle` narrows the probe to the actual executable so
|
|
94
|
+
// `fireforge run` refuses with a targeted message before handing control
|
|
95
|
+
// to mach. `fireforge watch` stays permissive and surfaces the same
|
|
96
|
+
// information as a banner suffix; watch exists to drive rebuilds of
|
|
97
|
+
// partially-built trees, so blocking there would defeat it.
|
|
101
98
|
if (buildCheck.objDir) {
|
|
102
99
|
const config = await loadConfig(projectRoot);
|
|
103
100
|
const bundleCheck = await hasRunnableBundle(paths.engine, config.binaryName, buildCheck.objDir);
|
|
@@ -142,7 +139,7 @@ async function runSmokeExit(engineDir, options) {
|
|
|
142
139
|
// SIGTERM the whole mach → python → firefox tree. Running through anyway
|
|
143
140
|
// would only kill the top-level wrapper and orphan Firefox content
|
|
144
141
|
// processes, so reject the flag up front to match the documented contract
|
|
145
|
-
// in
|
|
142
|
+
// in the README.
|
|
146
143
|
if (process.platform === 'win32') {
|
|
147
144
|
throw new InvalidArgumentError('--smoke-exit is POSIX-only; process-group semantics do not map cleanly onto Windows.', 'smokeExit');
|
|
148
145
|
}
|
|
@@ -187,14 +184,13 @@ async function runSmokeExit(engineDir, options) {
|
|
|
187
184
|
const sink = stream === 'stdout' ? process.stdout : process.stderr;
|
|
188
185
|
sink.write(`${line}\n`);
|
|
189
186
|
// Count allowlist hits up-front, regardless of error-pattern match.
|
|
190
|
-
//
|
|
191
|
-
//
|
|
192
|
-
// `console.warn
|
|
193
|
-
//
|
|
194
|
-
//
|
|
195
|
-
//
|
|
196
|
-
//
|
|
197
|
-
// exit contract cares about). The exit contract itself is unchanged.
|
|
187
|
+
// Incrementing only when the line ALSO matches an error pattern makes an
|
|
188
|
+
// allowlist regex that visibly matches `console.warn: RSLoader:` report 0
|
|
189
|
+
// hits, because `console.warn:` is not a smoke error class — confusing
|
|
190
|
+
// for operators tuning their allowlist. Two numbers are surfaced: the
|
|
191
|
+
// total set of allowlisted lines (what the operator sees in the console)
|
|
192
|
+
// and the subset that were error-class (what the smoke exit contract
|
|
193
|
+
// cares about). The exit contract itself is unchanged.
|
|
198
194
|
const matchIndex = allowlist.length > 0 ? matchAllowlist(line, allowlist) : -1;
|
|
199
195
|
const isAllowlisted = matchIndex !== -1;
|
|
200
196
|
if (isAllowlisted) {
|
|
@@ -209,12 +205,12 @@ async function runSmokeExit(engineDir, options) {
|
|
|
209
205
|
}
|
|
210
206
|
findings.push({ stream, line });
|
|
211
207
|
};
|
|
212
|
-
// A headed smoke window on a developer desktop absorbs live input:
|
|
213
|
-
//
|
|
214
|
-
// password-manager import scan
|
|
215
|
-
//
|
|
216
|
-
//
|
|
217
|
-
//
|
|
208
|
+
// A headed smoke window on a developer desktop absorbs live input: a human
|
|
209
|
+
// interacting with the window mid-run can trigger console errors — a
|
|
210
|
+
// password-manager import scan probing an unreadable profile dir, say —
|
|
211
|
+
// that fail the smoke run looking like a product regression. CI hosts (CI
|
|
212
|
+
// env var set) are assumed display-free and unattended, so the notice
|
|
213
|
+
// stays quiet there.
|
|
218
214
|
if (!options.headless && !process.env['CI']) {
|
|
219
215
|
warn('Headed smoke window: keyboard/mouse input during the window will contaminate the ' +
|
|
220
216
|
'console capture and can fail the run. Pass --headless (or run on an unattended host) ' +
|
|
@@ -303,12 +299,11 @@ function reportSmokeSummary(args) {
|
|
|
303
299
|
info('');
|
|
304
300
|
info(`Smoke run complete: ${seconds}s elapsed of ${windowSeconds}s window${suffix}`);
|
|
305
301
|
info(` Unallowed errors: ${String(args.findings.length)}`);
|
|
306
|
-
// The "suppressed errors" count is what the exit contract cares about —
|
|
307
|
-
//
|
|
308
|
-
//
|
|
309
|
-
//
|
|
310
|
-
//
|
|
311
|
-
// reports on visibly matching regexes.
|
|
302
|
+
// The "suppressed errors" count is what the exit contract cares about — the
|
|
303
|
+
// subset of allowlisted hits that would otherwise have been tallied as
|
|
304
|
+
// findings. The "all allowlisted lines" count answers the operator's mental
|
|
305
|
+
// model ("my --console-allow pattern matched N console lines"), without
|
|
306
|
+
// which a visibly matching regex reports 0 hits.
|
|
312
307
|
info(` Allowlisted error hits (suppressed): ${String(args.allowlistedErrorHits)}`);
|
|
313
308
|
info(` Allowlisted lines total: ${String(args.allowlistedTotalHits)}`);
|
|
314
309
|
info(` Child exit code: ${String(args.exitCode)}`);
|
|
@@ -351,7 +346,10 @@ export function registerRun(program, { getProjectRoot, withErrorHandling }) {
|
|
|
351
346
|
.option('--console-allow-file <path>', 'Newline-delimited allowlist regex file. Blank lines and # comments are ignored.')
|
|
352
347
|
.option('--capture-console <file>', 'Mirror captured console output to <file> for post-exit inspection.')
|
|
353
348
|
.option('--headless', 'Launch the browser with --headless. Recommended for --smoke-exit on a shared desktop: input into a headed smoke window contaminates the console capture.')
|
|
354
|
-
.action(withErrorHandling(
|
|
349
|
+
.action(withErrorHandling(
|
|
350
|
+
// `args` is the variadic positional, not a Commander flag, so it
|
|
351
|
+
// never appears in this object.
|
|
352
|
+
async (options) => {
|
|
355
353
|
await runCommand(getProjectRoot(), pickDefined(options));
|
|
356
354
|
}));
|
|
357
355
|
}
|
|
@@ -8,7 +8,7 @@ import { CancellationError, InvalidArgumentError } from '../errors/base.js';
|
|
|
8
8
|
import { ensureDir, pathExists, readText, writeText } from '../utils/fs.js';
|
|
9
9
|
import { cancel } from '../utils/logger.js';
|
|
10
10
|
import { getPackageRoot } from '../utils/package-root.js';
|
|
11
|
-
import { inferProductFromVersion, isValidAppId, isValidFirefoxVersion, isValidProjectLicense, } from '../utils/validation.js';
|
|
11
|
+
import { FIREFOX_PRODUCTS, inferProductFromVersion, isValidAppId, isValidFirefoxProduct, isValidFirefoxVersion, isValidProjectLicense, } from '../utils/validation.js';
|
|
12
12
|
function getTemplatesDir() {
|
|
13
13
|
return join(getPackageRoot(), 'templates');
|
|
14
14
|
}
|
|
@@ -19,13 +19,13 @@ function renderLicenseTemplate(license, template, vendor, now = new Date()) {
|
|
|
19
19
|
return template.replace(/\[year\]/g, String(now.getFullYear())).replace(/\[fullname\]/g, vendor);
|
|
20
20
|
}
|
|
21
21
|
function resolveFirefoxProduct(value, field) {
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
22
|
+
// Matches the sibling `resolveProjectLicense`, which already delegates to
|
|
23
|
+
// its guard. The `||` chain this replaced spelled the member list twice —
|
|
24
|
+
// once as the predicate and once in the message.
|
|
25
|
+
if (typeof value === 'string' && isValidFirefoxProduct(value)) {
|
|
26
26
|
return value;
|
|
27
27
|
}
|
|
28
|
-
throw new InvalidArgumentError(
|
|
28
|
+
throw new InvalidArgumentError(`Invalid product (use: ${FIREFOX_PRODUCTS.join(', ')})`, field);
|
|
29
29
|
}
|
|
30
30
|
function resolveProjectLicense(value, field) {
|
|
31
31
|
if (typeof value === 'string' && isValidProjectLicense(value)) {
|
|
@@ -269,14 +269,11 @@ export function buildSetupConfig(inputs) {
|
|
|
269
269
|
}
|
|
270
270
|
/**
|
|
271
271
|
* Creates or updates the root `package.json` so its `license` field matches
|
|
272
|
-
* the project license selected during setup. When the file already exists
|
|
273
|
-
* ONLY
|
|
274
|
-
* `dependencies`, `scripts`, and every other author-editorial field
|
|
275
|
-
*
|
|
276
|
-
*
|
|
277
|
-
* then disagreed with `fireforge.json` (the motivating eval finding:
|
|
278
|
-
* setup rewrote fireforge.json but left the original package.json
|
|
279
|
-
* untouched, so the two files described different projects).
|
|
272
|
+
* the project license selected during setup. When the file already exists
|
|
273
|
+
* ONLY the `license` field is touched — preserving `name`, `description`,
|
|
274
|
+
* `dependencies`, `scripts`, and every other author-editorial field. Without
|
|
275
|
+
* this sync, a `fireforge setup --force` that picks a new license leaves the
|
|
276
|
+
* old one in `package.json`, so the two files describe different projects.
|
|
280
277
|
*
|
|
281
278
|
* Preserves the file's trailing newline state so a hand-edited
|
|
282
279
|
* `package.json` with a specific EOL convention is not silently
|
|
@@ -307,12 +304,11 @@ async function syncRootPackageJson(projectRoot, license) {
|
|
|
307
304
|
if (typeof parsed !== 'object' || parsed === null || Array.isArray(parsed)) {
|
|
308
305
|
return;
|
|
309
306
|
}
|
|
310
|
-
// Treat the object as a typed shape with only the one field
|
|
307
|
+
// Treat the object as a typed shape with only the one field modified.
|
|
311
308
|
// Keeping it narrowly typed rather than `Record<string, unknown>` avoids
|
|
312
|
-
// eslint's `dot-notation` / `noPropertyAccessFromIndexSignature`
|
|
313
|
-
//
|
|
314
|
-
//
|
|
315
|
-
// fields.
|
|
309
|
+
// eslint's `dot-notation` / `noPropertyAccessFromIndexSignature` friction,
|
|
310
|
+
// and the rest of the package.json body is preserved via object spread at
|
|
311
|
+
// the write site.
|
|
316
312
|
const packageJson = parsed;
|
|
317
313
|
if (packageJson.license === license) {
|
|
318
314
|
return;
|
|
@@ -3,10 +3,11 @@ import { resolve } from 'node:path';
|
|
|
3
3
|
import { confirm } from '@clack/prompts';
|
|
4
4
|
import { Command, Option } from 'commander';
|
|
5
5
|
import { configExists } from '../core/config.js';
|
|
6
|
+
import { stdioIsInteractive } from '../core/destructive.js';
|
|
6
7
|
import { ConfigError } from '../errors/config.js';
|
|
7
8
|
import { cancel, intro, isCancel, note, outro, spinner } from '../utils/logger.js';
|
|
8
9
|
import { pickDefined } from '../utils/options.js';
|
|
9
|
-
import { PROJECT_LICENSES } from '../utils/validation.js';
|
|
10
|
+
import { FIREFOX_PRODUCTS, PROJECT_LICENSES } from '../utils/validation.js';
|
|
10
11
|
import { buildSetupConfig, parseFirefoxProductOption, parseProjectLicenseOption, resolveSetupInputs, validateSetupOptions, writeSetupProjectFiles, } from './setup-support.js';
|
|
11
12
|
/**
|
|
12
13
|
* Runs the setup command.
|
|
@@ -17,7 +18,7 @@ export async function setupCommand(projectRoot, options = {}) {
|
|
|
17
18
|
// Validate any CLI-provided options first
|
|
18
19
|
validateSetupOptions(options);
|
|
19
20
|
// Determine if we can run interactively
|
|
20
|
-
const isInteractive =
|
|
21
|
+
const isInteractive = stdioIsInteractive();
|
|
21
22
|
intro('FireForge Setup');
|
|
22
23
|
// Check if config already exists
|
|
23
24
|
if (await configExists(projectRoot)) {
|
|
@@ -67,17 +68,20 @@ export function registerSetup(program, { withErrorHandling }) {
|
|
|
67
68
|
.option('--app-id <appId>', 'Application ID (reverse-domain format)')
|
|
68
69
|
.option('--binary-name <binaryName>', 'Binary name (executable name)')
|
|
69
70
|
.option('--firefox-version <version>', 'Firefox version to base on')
|
|
70
|
-
.addOption(new Option('--product <product>', 'Firefox product').choices([
|
|
71
|
-
'firefox',
|
|
72
|
-
'firefox-esr',
|
|
73
|
-
'firefox-beta',
|
|
74
|
-
'firefox-devedition',
|
|
75
|
-
]))
|
|
71
|
+
.addOption(new Option('--product <product>', 'Firefox product').choices([...FIREFOX_PRODUCTS]))
|
|
76
72
|
.addOption(new Option('--license <license>', 'Project license').choices([...PROJECT_LICENSES]))
|
|
77
73
|
.option('-f, --force', 'Overwrite existing configuration without prompting')
|
|
74
|
+
// `--yes` is a plain alias here: `setup`'s only bypass is the overwrite
|
|
75
|
+
// prompt, so the two flags mean exactly the same thing. Seventeen other
|
|
76
|
+
// commands spell this bypass `--yes`; accepting it means a scripted
|
|
77
|
+
// sequence can use one spelling throughout.
|
|
78
|
+
.option('-y, --yes', 'Alias for --force: skip the overwrite confirmation')
|
|
78
79
|
.action(withErrorHandling(async (options) => {
|
|
79
|
-
const { product, license, ...rest } = options;
|
|
80
|
+
const { product, license, yes, ...rest } = options;
|
|
80
81
|
const setupOptions = { ...pickDefined(rest) };
|
|
82
|
+
// `--yes` is an alias, so either flag sets the same bypass.
|
|
83
|
+
if (yes === true)
|
|
84
|
+
setupOptions.force = true;
|
|
81
85
|
if (product !== undefined) {
|
|
82
86
|
const parsedProduct = parseFirefoxProductOption(product);
|
|
83
87
|
if (parsedProduct !== undefined) {
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* `status --check` enforcement policy. Turns the classified
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
2
|
+
* `status --check` enforcement policy. Turns the classified status view into
|
|
3
|
+
* a CI-enforceable non-zero exit: the default policy fails on any
|
|
4
|
+
* classification outside {patch-backed, branding, furnace}, and
|
|
5
|
+
* `--fail-on <class,...>` replaces that set for finer control.
|
|
6
6
|
*
|
|
7
|
-
* Helper module consumed by status.ts (which sits at the max-lines
|
|
8
|
-
*
|
|
7
|
+
* Helper module consumed by status.ts (which sits at the max-lines budget);
|
|
8
|
+
* no top-level registrar is exported and none is wanted.
|
|
9
9
|
*/
|
|
10
10
|
import type { ClassifiedFile, FileClassification } from '../core/status-classify.js';
|
|
11
11
|
/** Resolved `--check`/`--fail-on` policy for one status invocation. */
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* `status --json` payload rendering (schemaVersion 1). Helper module
|
|
3
|
-
* consumed by status.ts (which sits at the max-lines budget); no
|
|
4
|
-
*
|
|
3
|
+
* consumed by status.ts (which sits at the max-lines budget); no top-level
|
|
4
|
+
* registrar is exported and none is wanted.
|
|
5
5
|
*
|
|
6
6
|
* Two shapes share one counting pass:
|
|
7
7
|
* - the full payload (`renderJsonStatus`) with the per-file `files[]` list;
|
|
8
|
-
* - the `--summary` gate payload (`renderJsonSummaryStatus`),
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
8
|
+
* - the `--summary` gate payload (`renderJsonSummaryStatus`), which omits
|
|
9
|
+
* `files[]` entirely — engine-clean gates need the verdict, per-class
|
|
10
|
+
* counts, and offender names, not a payload that grows with the queue
|
|
11
|
+
* (175 KB+ on a large one).
|
|
12
12
|
*/
|
|
13
13
|
import type { ClassifiedFile } from '../core/status-classify.js';
|
|
14
14
|
import { type StatusCheckPolicy } from './status-check.js';
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { setStdoutSealed } from '../utils/logger.js';
|
|
1
2
|
import { collectStatusCheckOffenders, } from './status-check.js';
|
|
2
3
|
function countByClassification(classified) {
|
|
3
4
|
const byClassification = {
|
|
@@ -43,6 +44,8 @@ export function renderJsonStatus(classified, ownership) {
|
|
|
43
44
|
...(ownership !== undefined ? { ownership } : {}),
|
|
44
45
|
};
|
|
45
46
|
process.stdout.write(JSON.stringify(output, null, 2) + '\n');
|
|
47
|
+
// Payload written: stdout is now spoken for. See docs/machine-output.md.
|
|
48
|
+
setStdoutSealed(true);
|
|
46
49
|
}
|
|
47
50
|
/**
|
|
48
51
|
* Summary-only `--json --summary` payload: counts always; when the
|
|
@@ -73,4 +76,6 @@ export function renderJsonSummaryStatus(classified, policy, ownership) {
|
|
|
73
76
|
output.ownership = ownership;
|
|
74
77
|
}
|
|
75
78
|
process.stdout.write(JSON.stringify(output, null, 2) + '\n');
|
|
79
|
+
// Payload written: stdout is now spoken for. See docs/machine-output.md.
|
|
80
|
+
setStdoutSealed(true);
|
|
76
81
|
}
|
|
@@ -14,10 +14,10 @@ export declare function renderUnmanagedOnly(unmanagedFiles: ClassifiedFile[], to
|
|
|
14
14
|
/** Renders the default classified status buckets. */
|
|
15
15
|
export declare function renderDefaultStatus(totalModified: number, buckets: ClassifiedBuckets, projectRoot: string, binaryName: string): Promise<void>;
|
|
16
16
|
/**
|
|
17
|
-
* Renders `fireforge status --test-coverage`: a READ-ONLY view
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
*
|
|
17
|
+
* Renders `fireforge status --test-coverage`: a READ-ONLY view of the last
|
|
18
|
+
* build baseline's test-packaging coverage. Without it, the only way to
|
|
19
|
+
* learn the recorded coverage scope — which concurrent sessions sharing one
|
|
20
|
+
* engine tree overwrite constantly — is to trip the out-of-coverage refusal
|
|
21
|
+
* on a real test run.
|
|
22
22
|
*/
|
|
23
23
|
export declare function renderTestCoverageStatus(baseline: BuildBaseline | undefined): void;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { isFileRegistered, matchesRegistrablePattern } from '../core/manifest-rules.js';
|
|
1
|
+
import { isFileRegistered, matchesRegistrablePattern } from '../core/moz-manifest-rules.js';
|
|
2
2
|
import { getPrimaryStatusCode } from '../core/status-classify.js';
|
|
3
3
|
import { GeneralError } from '../errors/base.js';
|
|
4
4
|
import { info, outro, warn } from '../utils/logger.js';
|
|
@@ -191,11 +191,11 @@ export async function renderDefaultStatus(totalModified, buckets, projectRoot, b
|
|
|
191
191
|
outro(parts.join(', '));
|
|
192
192
|
}
|
|
193
193
|
/**
|
|
194
|
-
* Renders `fireforge status --test-coverage`: a READ-ONLY view
|
|
195
|
-
*
|
|
196
|
-
*
|
|
197
|
-
*
|
|
198
|
-
*
|
|
194
|
+
* Renders `fireforge status --test-coverage`: a READ-ONLY view of the last
|
|
195
|
+
* build baseline's test-packaging coverage. Without it, the only way to
|
|
196
|
+
* learn the recorded coverage scope — which concurrent sessions sharing one
|
|
197
|
+
* engine tree overwrite constantly — is to trip the out-of-coverage refusal
|
|
198
|
+
* on a real test run.
|
|
199
199
|
*/
|
|
200
200
|
export function renderTestCoverageStatus(baseline) {
|
|
201
201
|
if (baseline === undefined) {
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Ownership-table assembly for `status`, split out of `status.ts`
|
|
3
|
-
*
|
|
4
|
-
*
|
|
2
|
+
* Ownership-table assembly for `status`, split out of `status.ts` so the
|
|
3
|
+
* human `--ownership` mode and the additive `ownership` block on the
|
|
4
|
+
* `--json` payload build the SAME rows from the SAME scan.
|
|
5
5
|
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
6
|
+
* A separate `--ownership` branch re-implements the shared scan and inlines
|
|
7
|
+
* a second copy of the classification call, then discards everything but
|
|
8
|
+
* each file's classification — so three back-to-back `status` invocations in
|
|
9
|
+
* a gate pay three full worktree scans. Both callers hand this module the
|
|
10
|
+
* already-classified files instead.
|
|
11
11
|
*
|
|
12
12
|
* No renderer lives here: `renderOwnershipTable` (human) and the JSON
|
|
13
13
|
* serializer stay with their respective output layers.
|
|
@@ -29,13 +29,15 @@ export interface OwnershipJsonBlock {
|
|
|
29
29
|
/**
|
|
30
30
|
* Builds the flat path→owning-patch rows. Sources are the manifest's
|
|
31
31
|
* `filesAffected`, worktree drift, and the cross-patch
|
|
32
|
-
* duplicate-new-file-creation map produced by walking each patch body —
|
|
33
|
-
*
|
|
34
|
-
*
|
|
35
|
-
*
|
|
36
|
-
* @param
|
|
37
|
-
* @param
|
|
32
|
+
* duplicate-new-file-creation map produced by walking each patch body — the
|
|
33
|
+
* last being what keeps `status --ownership` aligned with `fireforge verify`
|
|
34
|
+
* (see `buildOwnershipTable`'s header).
|
|
35
|
+
*
|
|
36
|
+
* @param patchesDir - Absolute path to the patches directory
|
|
37
|
+
* @param manifestPatches - Manifest rows, each with its `filesAffected`
|
|
38
|
+
* @param files - Raw worktree status entries
|
|
38
39
|
* @param classified - The same entries, already classified
|
|
40
|
+
* @returns The flat ownership rows
|
|
39
41
|
*/
|
|
40
42
|
export declare function collectOwnershipRows(patchesDir: string, manifestPatches: readonly PatchMetadata[], files: StatusFile[], classified: readonly ClassifiedFile[]): Promise<OwnershipRow[]>;
|
|
41
43
|
/**
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
// SPDX-License-Identifier: EUPL-1.2
|
|
2
2
|
/**
|
|
3
|
-
* Ownership-table assembly for `status`, split out of `status.ts`
|
|
4
|
-
*
|
|
5
|
-
*
|
|
3
|
+
* Ownership-table assembly for `status`, split out of `status.ts` so the
|
|
4
|
+
* human `--ownership` mode and the additive `ownership` block on the
|
|
5
|
+
* `--json` payload build the SAME rows from the SAME scan.
|
|
6
6
|
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
7
|
+
* A separate `--ownership` branch re-implements the shared scan and inlines
|
|
8
|
+
* a second copy of the classification call, then discards everything but
|
|
9
|
+
* each file's classification — so three back-to-back `status` invocations in
|
|
10
|
+
* a gate pay three full worktree scans. Both callers hand this module the
|
|
11
|
+
* already-classified files instead.
|
|
12
12
|
*
|
|
13
13
|
* No renderer lives here: `renderOwnershipTable` (human) and the JSON
|
|
14
14
|
* serializer stay with their respective output layers.
|
|
@@ -19,13 +19,15 @@ import { pathExists } from '../utils/fs.js';
|
|
|
19
19
|
/**
|
|
20
20
|
* Builds the flat path→owning-patch rows. Sources are the manifest's
|
|
21
21
|
* `filesAffected`, worktree drift, and the cross-patch
|
|
22
|
-
* duplicate-new-file-creation map produced by walking each patch body —
|
|
23
|
-
*
|
|
24
|
-
*
|
|
25
|
-
*
|
|
26
|
-
* @param
|
|
27
|
-
* @param
|
|
22
|
+
* duplicate-new-file-creation map produced by walking each patch body — the
|
|
23
|
+
* last being what keeps `status --ownership` aligned with `fireforge verify`
|
|
24
|
+
* (see `buildOwnershipTable`'s header).
|
|
25
|
+
*
|
|
26
|
+
* @param patchesDir - Absolute path to the patches directory
|
|
27
|
+
* @param manifestPatches - Manifest rows, each with its `filesAffected`
|
|
28
|
+
* @param files - Raw worktree status entries
|
|
28
29
|
* @param classified - The same entries, already classified
|
|
30
|
+
* @returns The flat ownership rows
|
|
29
31
|
*/
|
|
30
32
|
export async function collectOwnershipRows(patchesDir, manifestPatches, files, classified) {
|
|
31
33
|
// Only walk patch bodies when the directory actually exists: a fresh
|
|
@@ -2,17 +2,19 @@
|
|
|
2
2
|
import { Command } from 'commander';
|
|
3
3
|
import { readBuildBaseline } from '../core/build-baseline.js';
|
|
4
4
|
import { getProjectPaths, loadConfig } from '../core/config.js';
|
|
5
|
+
import { assertEngineExists } from '../core/engine-precondition.js';
|
|
5
6
|
import { formatEngineSessionLockStatus, readEngineSessionLockStatus, } from '../core/engine-session-lock.js';
|
|
6
7
|
import { collectFurnaceManagedPrefixes } from '../core/furnace-config.js';
|
|
7
8
|
import { getHead, getStatusWithCodes, isGitRepository, isMissingHeadError } from '../core/git.js';
|
|
8
9
|
import { getUntrackedFilesInDir, resolveMaxUntrackedFilesPerDir } from '../core/git-status.js';
|
|
9
10
|
import { renderOwnershipTable } from '../core/ownership-table.js';
|
|
10
11
|
import { loadPatchesManifest } from '../core/patch-manifest.js';
|
|
12
|
+
import { readProcessCpuSeconds } from '../core/process-cpu-time.js';
|
|
11
13
|
import { classifyFiles } from '../core/status-classify.js';
|
|
12
|
-
import {
|
|
13
|
-
import { ExitCode } from '../errors/codes.js';
|
|
14
|
+
import { GeneralError, InvalidArgumentError } from '../errors/base.js';
|
|
14
15
|
import { FIREFORGE_TMP_PATH_PATTERN, pathExists } from '../utils/fs.js';
|
|
15
16
|
import { info, intro, isMachineOutputMode, outro, setMachineOutputMode, warn, } from '../utils/logger.js';
|
|
17
|
+
import { emitMachineError } from '../utils/machine-output.js';
|
|
16
18
|
import { resolveStatusCheckPolicy, runStatusCheck } from './status-check.js';
|
|
17
19
|
import { renderJsonStatus, renderJsonSummaryStatus } from './status-json.js';
|
|
18
20
|
import { renderDefaultStatus, renderTestCoverageStatus, renderUnmanagedOnly, } from './status-output.js';
|
|
@@ -96,12 +98,13 @@ async function classifyStatusFiles(files, paths, projectRoot, binaryName) {
|
|
|
96
98
|
/**
|
|
97
99
|
* The one worktree scan every classifying mode shares: porcelain status,
|
|
98
100
|
* collapsed-directory expansion, atomic-temp-file filtering, and the
|
|
99
|
-
* truncation banner.
|
|
100
|
-
*
|
|
101
|
-
*
|
|
101
|
+
* truncation banner. A non-git engine degrades to an empty list for
|
|
102
|
+
* `--ownership`, which is why the git probe is a parameter rather than a
|
|
103
|
+
* hard guard.
|
|
104
|
+
*
|
|
102
105
|
* @param engineDir - Path to the engine directory
|
|
103
106
|
* @param requireGitRepository - When false, a non-git engine yields `[]`
|
|
104
|
-
* instead of being probed
|
|
107
|
+
* instead of being probed
|
|
105
108
|
*/
|
|
106
109
|
async function scanEngineStatusFiles(engineDir, requireGitRepository) {
|
|
107
110
|
if (!requireGitRepository && !(await isGitRepository(engineDir))) {
|
|
@@ -112,12 +115,13 @@ async function scanEngineStatusFiles(engineDir, requireGitRepository) {
|
|
|
112
115
|
return filterFireForgeTempFiles(entries);
|
|
113
116
|
}
|
|
114
117
|
/**
|
|
115
|
-
* Emits the `--json` payload (full or `--summary`) and applies the
|
|
116
|
-
*
|
|
118
|
+
* Emits the `--json` payload (full or `--summary`) and applies the `--check`
|
|
119
|
+
* policy, which stays the SOLE exit driver on this path.
|
|
120
|
+
*
|
|
121
|
+
* `--include-ownership` is a MODIFIER, not a mode: it appends an ownership
|
|
122
|
+
* block without touching exit semantics, so an ownership conflict still
|
|
123
|
+
* fails only the human `--ownership` mode.
|
|
117
124
|
*
|
|
118
|
-
* `--include-ownership` is a MODIFIER, not a mode: it appends an
|
|
119
|
-
* ownership block without touching exit semantics, so an ownership conflict
|
|
120
|
-
* still fails only the human `--ownership` mode.
|
|
121
125
|
* @param classified - Classified worktree entries
|
|
122
126
|
* @param files - The same entries pre-classification, for ownership rows
|
|
123
127
|
* @param paths - Resolved project paths
|
|
@@ -187,8 +191,8 @@ export async function statusCommand(projectRoot, options = {}) {
|
|
|
187
191
|
}
|
|
188
192
|
// On a throw, machine mode deliberately stays ENGAGED: withErrorHandling
|
|
189
193
|
// routes the styled error to stderr while the mode is on and resets it
|
|
190
|
-
// centrally
|
|
191
|
-
//
|
|
194
|
+
// centrally. A mid-throw restore here would put the refusal on stdout
|
|
195
|
+
// after the JSON payload.
|
|
192
196
|
await runStatusCommandBody(projectRoot, options);
|
|
193
197
|
if (isMachineOutputMode() !== previousMachineOutputMode) {
|
|
194
198
|
setMachineOutputMode(previousMachineOutputMode);
|
|
@@ -229,7 +233,11 @@ async function runStatusCommandBody(projectRoot, options) {
|
|
|
229
233
|
// concurrent command is busy with, and that answer must not depend on
|
|
230
234
|
// engine/ being readable.
|
|
231
235
|
if (options.lock === true) {
|
|
232
|
-
|
|
236
|
+
const snapshot = await readEngineSessionLockStatus(projectRoot);
|
|
237
|
+
const holderCpuSeconds = snapshot.holder?.alive === true
|
|
238
|
+
? await readProcessCpuSeconds(snapshot.holder.pid)
|
|
239
|
+
: undefined;
|
|
240
|
+
for (const line of formatEngineSessionLockStatus(snapshot, holderCpuSeconds)) {
|
|
233
241
|
info(line);
|
|
234
242
|
}
|
|
235
243
|
outro('Lock status');
|
|
@@ -243,24 +251,22 @@ async function runStatusCommandBody(projectRoot, options) {
|
|
|
243
251
|
}
|
|
244
252
|
const paths = getProjectPaths(projectRoot);
|
|
245
253
|
const config = await loadConfig(projectRoot);
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
};
|
|
254
|
+
// Shared envelope: see src/utils/machine-output.ts and
|
|
255
|
+
// docs/machine-output.md. `status` was the only command that had one.
|
|
256
|
+
const emitJsonError = emitMachineError;
|
|
250
257
|
// Ownership mode is a flat file→patch table; sources are the manifest's
|
|
251
258
|
// filesAffected, any worktree drift, and the cross-patch
|
|
252
|
-
// duplicate-new-file-creation map produced by walking each patch
|
|
253
|
-
//
|
|
254
|
-
//
|
|
255
|
-
//
|
|
256
|
-
// without computing patch-backed state.
|
|
259
|
+
// duplicate-new-file-creation map produced by walking each patch body. The
|
|
260
|
+
// last is what keeps `status --ownership` aligned with `fireforge verify`
|
|
261
|
+
// — see buildOwnershipTable's header. Runs before the default classify
|
|
262
|
+
// path so it can short-circuit without computing patch-backed state.
|
|
257
263
|
if (options.ownership) {
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
264
|
+
// Rung 1 only, deliberately — see the note below on why this branch
|
|
265
|
+
// does not take the full assertEngineGitReady ladder.
|
|
266
|
+
await assertEngineExists(paths.engine);
|
|
261
267
|
const manifest = await loadPatchesManifest(paths.patches);
|
|
262
|
-
// Same scan and the SAME classification pass as every other mode
|
|
263
|
-
|
|
268
|
+
// Same scan and the SAME classification pass as every other mode.
|
|
269
|
+
// This branch keeps its historical guard shape on purpose:
|
|
264
270
|
// no baseline-commit assertion, and a non-git engine degrades to an
|
|
265
271
|
// empty table rather than the recovery banner.
|
|
266
272
|
const rawFilesOwnership = await scanEngineStatusFiles(paths.engine, false);
|
|
@@ -280,7 +286,10 @@ async function runStatusCommandBody(projectRoot, options) {
|
|
|
280
286
|
}
|
|
281
287
|
return;
|
|
282
288
|
}
|
|
283
|
-
//
|
|
289
|
+
// Not routed through assertEngineExists: the --json contract requires a
|
|
290
|
+
// machine-readable payload on stdout BEFORE the throw, so scripted
|
|
291
|
+
// consumers get a parseable refusal instead of a bare non-zero exit. The
|
|
292
|
+
// message is kept identical to the helper's on purpose.
|
|
284
293
|
if (!(await pathExists(paths.engine))) {
|
|
285
294
|
if (options.json) {
|
|
286
295
|
emitJsonError('engine-missing', 'Firefox source not found. Run "fireforge download" first.');
|
|
@@ -297,11 +306,10 @@ async function runStatusCommandBody(projectRoot, options) {
|
|
|
297
306
|
await assertEngineHasBaselineCommit(paths.engine, options);
|
|
298
307
|
const files = await scanEngineStatusFiles(paths.engine, true);
|
|
299
308
|
// `--json` callers expect machine-parseable output on every invocation,
|
|
300
|
-
// including the clean-tree case.
|
|
301
|
-
//
|
|
302
|
-
//
|
|
303
|
-
//
|
|
304
|
-
// nothing to report. Emit `[]` here and return before the human fallback.
|
|
309
|
+
// including the clean-tree case. Falling through to the human branch below
|
|
310
|
+
// silently ignores `--json` and breaks scripts that pipe the output
|
|
311
|
+
// through a JSON parser precisely when there is nothing to report. Emit
|
|
312
|
+
// `[]` here and return before the human fallback.
|
|
305
313
|
if (options.json) {
|
|
306
314
|
const classified = await classifyStatusFiles(files, paths, projectRoot, config.binaryName);
|
|
307
315
|
await renderJsonMode(classified, files, paths, options, checkPolicy);
|