@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
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
// SPDX-License-Identifier: EUPL-1.2
|
|
2
2
|
/**
|
|
3
|
-
* `doctor` check for stale furnace jar.mn registrations
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
* of `doctor-furnace.ts` to keep that file within the line budget.
|
|
3
|
+
* `doctor` check for stale furnace jar.mn registrations: a component-file
|
|
4
|
+
* rename can leave the old toolkit jar.mn line pointing at the deleted file,
|
|
5
|
+
* failing every build at packaging. Split out of `doctor-furnace.ts` to keep
|
|
6
|
+
* that file within the line budget.
|
|
8
7
|
*/
|
|
9
8
|
import { getFurnacePaths } from '../core/furnace-config.js';
|
|
10
9
|
import { findStaleJarMnEntries, pruneStaleJarMnEntries } from '../core/furnace-registration.js';
|
|
@@ -12,10 +11,9 @@ import { toError } from '../utils/errors.js';
|
|
|
12
11
|
import { failure, ok, warning } from './doctor-check-core.js';
|
|
13
12
|
/**
|
|
14
13
|
* "Furnace jar.mn registrations" check: detect widget registration lines
|
|
15
|
-
* pointing at component files that no longer exist in the workspace
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
* report: doctor --repair-furnace reported success without pruning).
|
|
14
|
+
* pointing at component files that no longer exist in the workspace,
|
|
15
|
+
* typically left by a rename. These break `mach build` at packaging;
|
|
16
|
+
* `--repair-furnace` prunes them.
|
|
19
17
|
*/
|
|
20
18
|
export const furnaceStaleJarRegistrationCheck = {
|
|
21
19
|
name: 'Furnace jar.mn registrations',
|
|
@@ -4,15 +4,15 @@ import { join } from 'node:path';
|
|
|
4
4
|
import { applyAllComponents } from '../core/furnace-apply.js';
|
|
5
5
|
import { hasCustomEngineDrift, hasOverrideEngineDrift } from '../core/furnace-apply-helpers.js';
|
|
6
6
|
import { getFurnacePaths, loadFurnaceConfig, loadFurnaceState, updateFurnaceState, } from '../core/furnace-config.js';
|
|
7
|
-
import { CUSTOM_ELEMENTS_JS, JAR_MN, resolveFtlDir } from '../core/furnace-constants.js';
|
|
7
|
+
import { CUSTOM_ELEMENTS_JS, JAR_MN, resolveFtlDir, WIDGETS_DIR, } from '../core/furnace-constants.js';
|
|
8
8
|
import { getFurnaceLockPath, runFurnaceMutation } from '../core/furnace-operation.js';
|
|
9
9
|
import { hasBlockingStepErrors } from '../core/furnace-step-errors.js';
|
|
10
10
|
import { validateAllComponents } from '../core/furnace-validate.js';
|
|
11
11
|
import { isProcessAlive, toError } from '../utils/errors.js';
|
|
12
12
|
import { pathExists } from '../utils/fs.js';
|
|
13
13
|
import { failure, ok, warning } from './doctor-check-core.js';
|
|
14
|
+
import { furnaceConfigSyncCheck } from './doctor-furnace-config-sync.js';
|
|
14
15
|
import { furnaceStaleJarRegistrationCheck } from './doctor-furnace-jar.js';
|
|
15
|
-
import { furnaceManifestSyncCheck } from './doctor-furnace-manifest-sync.js';
|
|
16
16
|
const ENGINE_REPAIRABLE_OPERATIONS = [
|
|
17
17
|
'preview-teardown',
|
|
18
18
|
'apply-rollback',
|
|
@@ -98,7 +98,7 @@ async function collectFurnaceDrift(projectRoot, engineDir, config, ftlDir) {
|
|
|
98
98
|
continue;
|
|
99
99
|
}
|
|
100
100
|
try {
|
|
101
|
-
if (await hasOverrideEngineDrift(engineDir, componentDir,
|
|
101
|
+
if (await hasOverrideEngineDrift({ engineDir, componentDir, ftlDir }, overrideConfig)) {
|
|
102
102
|
drifted.push(name);
|
|
103
103
|
}
|
|
104
104
|
}
|
|
@@ -115,7 +115,7 @@ async function collectFurnaceDrift(projectRoot, engineDir, config, ftlDir) {
|
|
|
115
115
|
continue;
|
|
116
116
|
}
|
|
117
117
|
try {
|
|
118
|
-
if (await hasCustomEngineDrift(projectRoot, name, componentDir,
|
|
118
|
+
if (await hasCustomEngineDrift({ root: projectRoot, name, componentDir, ftlDir }, customConfig)) {
|
|
119
119
|
drifted.push(name);
|
|
120
120
|
}
|
|
121
121
|
}
|
|
@@ -336,7 +336,7 @@ const furnaceEnginePathsCheck = {
|
|
|
336
336
|
const expectedPaths = [
|
|
337
337
|
CUSTOM_ELEMENTS_JS,
|
|
338
338
|
JAR_MN,
|
|
339
|
-
|
|
339
|
+
WIDGETS_DIR,
|
|
340
340
|
resolveFtlDir(ctx.furnaceConfig?.ftlBasePath),
|
|
341
341
|
...hostDocs,
|
|
342
342
|
];
|
|
@@ -437,18 +437,17 @@ async function readFurnaceLockPid(lockPath) {
|
|
|
437
437
|
}
|
|
438
438
|
}
|
|
439
439
|
/**
|
|
440
|
-
* "Furnace stale lock" check: detect and (under `--repair-furnace`)
|
|
441
|
-
*
|
|
442
|
-
*
|
|
440
|
+
* "Furnace stale lock" check: detect and (under `--repair-furnace`) remove a
|
|
441
|
+
* `.fireforge/furnace.lock` directory whose owner process is no longer
|
|
442
|
+
* alive.
|
|
443
443
|
*
|
|
444
444
|
* This is the recovery path when the signal-handler sweep
|
|
445
445
|
* (`forceReleaseFurnaceLocksForActiveOperations` in `bin/fireforge.ts`)
|
|
446
|
-
* misses —
|
|
447
|
-
*
|
|
448
|
-
*
|
|
449
|
-
*
|
|
450
|
-
*
|
|
451
|
-
* command runs immediately.
|
|
446
|
+
* misses — a SIGKILL'd process that never ran the handler, or a lock created
|
|
447
|
+
* by an older FireForge release without a PID file. SIGINT'ing `furnace
|
|
448
|
+
* preview` leaves the lock behind, and the next `fireforge test --build`
|
|
449
|
+
* then times out waiting for it; `doctor --repair-furnace` clears it so the
|
|
450
|
+
* next command runs immediately.
|
|
452
451
|
*/
|
|
453
452
|
const furnaceStaleLockCheck = {
|
|
454
453
|
name: 'Furnace lock',
|
|
@@ -466,16 +465,14 @@ const furnaceStaleLockCheck = {
|
|
|
466
465
|
// Two signals mark a lock as stale:
|
|
467
466
|
// 1. PID file says owner is dead → unambiguous, remove immediately.
|
|
468
467
|
// 2. PID file absent AND lock is older than 60s → older FireForge
|
|
469
|
-
// releases (or an externally-created lock directory) fall into
|
|
470
|
-
//
|
|
471
|
-
//
|
|
472
|
-
// written its PID yet.
|
|
468
|
+
// releases (or an externally-created lock directory) fall into this
|
|
469
|
+
// bucket; the age gate avoids false positives on a lock just
|
|
470
|
+
// acquired by a concurrent process that has not written its PID yet.
|
|
473
471
|
//
|
|
474
|
-
// `isProcessAlive` treats EPERM as ALIVE.
|
|
475
|
-
//
|
|
476
|
-
//
|
|
477
|
-
//
|
|
478
|
-
// concurrent furnace operation.
|
|
472
|
+
// `isProcessAlive` treats EPERM as ALIVE. Returning false for EPERM
|
|
473
|
+
// reports a furnace lock held by a live process owned by another uid as
|
|
474
|
+
// "owner is no longer running", and --repair-furnace then deletes it,
|
|
475
|
+
// dropping mutual exclusion under a concurrent furnace operation.
|
|
479
476
|
const ownerDead = pid !== null && !isProcessAlive(pid);
|
|
480
477
|
const pidMissingAndOld = pid === null && (ageMs ?? 0) > 60_000;
|
|
481
478
|
const isStale = ownerDead || pidMissingAndOld;
|
|
@@ -513,5 +510,5 @@ export const FURNACE_DOCTOR_CHECKS = [
|
|
|
513
510
|
furnaceStaleLockCheck,
|
|
514
511
|
furnaceEngineStateCheck,
|
|
515
512
|
furnaceComponentValidationCheck,
|
|
516
|
-
|
|
513
|
+
furnaceConfigSyncCheck,
|
|
517
514
|
];
|
|
@@ -1,23 +1,20 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Doctor check for PRE-EXISTING orphaned test-harness workers
|
|
3
|
-
* item 9b).
|
|
2
|
+
* Doctor check for PRE-EXISTING orphaned test-harness workers.
|
|
4
3
|
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
* accumulated CPU TIME + a `multiprocessing.spawn`/`resource_tracker`
|
|
13
|
-
* command line.
|
|
4
|
+
* A mach invocation that dies at harness startup can strand a Python
|
|
5
|
+
* `multiprocessing` spawn worker plus its resource tracker; the worker
|
|
6
|
+
* reparents to launchd (PPID 1) and busy-spins at 100% CPU indefinitely.
|
|
7
|
+
* The dispatch-side fix is the process-group reaping in `utils/process.ts`;
|
|
8
|
+
* this check covers orphans that predate it (or leaked from non-FireForge
|
|
9
|
+
* invocations), detecting them by PPID 1 + large accumulated CPU TIME + a
|
|
10
|
+
* `multiprocessing.spawn`/`resource_tracker` command line.
|
|
14
11
|
*
|
|
15
|
-
* Report-only by design: FireForge never kills pre-existing processes it
|
|
16
|
-
*
|
|
12
|
+
* Report-only by design: FireForge never kills pre-existing processes it did
|
|
13
|
+
* not spawn — the check names each candidate and suggests the kill.
|
|
17
14
|
*
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
*
|
|
15
|
+
* Deliberately not wired into `test --canary`: a system-wide process scan on
|
|
16
|
+
* the canary hot path buys no coverage the doctor check does not already
|
|
17
|
+
* give.
|
|
21
18
|
*/
|
|
22
19
|
import type { DoctorCheckDefinition } from './doctor-check-core.js';
|
|
23
20
|
/** One process matching the orphaned-harness-worker shape. */
|
|
@@ -31,10 +28,9 @@ export interface OrphanedHarnessWorker {
|
|
|
31
28
|
command: string;
|
|
32
29
|
}
|
|
33
30
|
/**
|
|
34
|
-
* Parses a `ps` TIME value in
|
|
35
|
-
*
|
|
36
|
-
*
|
|
37
|
-
* Returns NaN for unrecognized shapes.
|
|
31
|
+
* Parses a `ps` TIME (accumulated CPU) value. Implemented in terms of
|
|
32
|
+
* {@link parsePsDuration} — `time=` and `etime=` share one grammar, and a
|
|
33
|
+
* second copy is how the two would drift.
|
|
38
34
|
*/
|
|
39
35
|
export declare function parseCpuTime(time: string): number;
|
|
40
36
|
/**
|
|
@@ -1,27 +1,25 @@
|
|
|
1
1
|
// SPDX-License-Identifier: EUPL-1.2
|
|
2
2
|
/**
|
|
3
|
-
* Doctor check for PRE-EXISTING orphaned test-harness workers
|
|
4
|
-
* item 9b).
|
|
3
|
+
* Doctor check for PRE-EXISTING orphaned test-harness workers.
|
|
5
4
|
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
* accumulated CPU TIME + a `multiprocessing.spawn`/`resource_tracker`
|
|
14
|
-
* command line.
|
|
5
|
+
* A mach invocation that dies at harness startup can strand a Python
|
|
6
|
+
* `multiprocessing` spawn worker plus its resource tracker; the worker
|
|
7
|
+
* reparents to launchd (PPID 1) and busy-spins at 100% CPU indefinitely.
|
|
8
|
+
* The dispatch-side fix is the process-group reaping in `utils/process.ts`;
|
|
9
|
+
* this check covers orphans that predate it (or leaked from non-FireForge
|
|
10
|
+
* invocations), detecting them by PPID 1 + large accumulated CPU TIME + a
|
|
11
|
+
* `multiprocessing.spawn`/`resource_tracker` command line.
|
|
15
12
|
*
|
|
16
|
-
* Report-only by design: FireForge never kills pre-existing processes it
|
|
17
|
-
*
|
|
13
|
+
* Report-only by design: FireForge never kills pre-existing processes it did
|
|
14
|
+
* not spawn — the check names each candidate and suggests the kill.
|
|
18
15
|
*
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
*
|
|
16
|
+
* Deliberately not wired into `test --canary`: a system-wide process scan on
|
|
17
|
+
* the canary hot path buys no coverage the doctor check does not already
|
|
18
|
+
* give.
|
|
22
19
|
*/
|
|
23
20
|
import { toError } from '../utils/errors.js';
|
|
24
21
|
import { exec } from '../utils/process.js';
|
|
22
|
+
import { parsePsDuration } from '../utils/ps-duration.js';
|
|
25
23
|
import { ok, warning } from './doctor-check-core.js';
|
|
26
24
|
/**
|
|
27
25
|
* Command-line shapes of Python multiprocessing helper processes: the
|
|
@@ -32,36 +30,12 @@ const HARNESS_WORKER_COMMAND_PATTERN = /multiprocessing\.(?:spawn|forkserver)\b|
|
|
|
32
30
|
/** Minimum accumulated CPU time before a match is reported (10 minutes). */
|
|
33
31
|
const DEFAULT_MIN_CPU_SECONDS = 600;
|
|
34
32
|
/**
|
|
35
|
-
* Parses a `ps` TIME value in
|
|
36
|
-
*
|
|
37
|
-
*
|
|
38
|
-
* Returns NaN for unrecognized shapes.
|
|
33
|
+
* Parses a `ps` TIME (accumulated CPU) value. Implemented in terms of
|
|
34
|
+
* {@link parsePsDuration} — `time=` and `etime=` share one grammar, and a
|
|
35
|
+
* second copy is how the two would drift.
|
|
39
36
|
*/
|
|
40
37
|
export function parseCpuTime(time) {
|
|
41
|
-
|
|
42
|
-
let days = 0;
|
|
43
|
-
let rest = trimmed;
|
|
44
|
-
const dayMatch = /^(\d+)-(.*)$/.exec(trimmed);
|
|
45
|
-
if (dayMatch) {
|
|
46
|
-
days = Number(dayMatch[1]);
|
|
47
|
-
rest = dayMatch[2] ?? '';
|
|
48
|
-
}
|
|
49
|
-
const parts = rest.split(':');
|
|
50
|
-
if (parts.length === 3) {
|
|
51
|
-
// hh:mm:ss (linux; seconds may not carry fractions but tolerate them)
|
|
52
|
-
const [h, m, s] = parts.map(Number);
|
|
53
|
-
if ([h, m, s].some((n) => Number.isNaN(n)))
|
|
54
|
-
return NaN;
|
|
55
|
-
return days * 86400 + (h ?? 0) * 3600 + (m ?? 0) * 60 + (s ?? 0);
|
|
56
|
-
}
|
|
57
|
-
if (parts.length === 2) {
|
|
58
|
-
// mm:ss.cc (darwin — the minutes field accumulates without wrapping)
|
|
59
|
-
const [m, s] = parts.map(Number);
|
|
60
|
-
if ([m, s].some((n) => Number.isNaN(n)))
|
|
61
|
-
return NaN;
|
|
62
|
-
return days * 86400 + (m ?? 0) * 60 + (s ?? 0);
|
|
63
|
-
}
|
|
64
|
-
return NaN;
|
|
38
|
+
return parsePsDuration(time);
|
|
65
39
|
}
|
|
66
40
|
/**
|
|
67
41
|
* Scans `ps -axo pid=,ppid=,time=,command=` output for orphaned harness
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The patch-manifest consistency check and its two repair paths, split out of
|
|
3
|
+
* `doctor.ts` for the line budget. Exports a single `DoctorCheckDefinition`
|
|
4
|
+
* consumed by the doctor registry; no registrar is exported and none is wanted.
|
|
5
|
+
*/
|
|
6
|
+
import type { DoctorCheckDefinition } from './doctor-check-core.js';
|
|
7
|
+
/** Patch manifest consistency check, with its opt-in repair paths. */
|
|
8
|
+
export declare const PATCH_MANIFEST_CONSISTENCY_CHECK: DoctorCheckDefinition;
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
// SPDX-License-Identifier: EUPL-1.2
|
|
2
|
+
/**
|
|
3
|
+
* The patch-manifest consistency check and its two repair paths, split out of
|
|
4
|
+
* `doctor.ts` for the line budget. Exports a single `DoctorCheckDefinition`
|
|
5
|
+
* consumed by the doctor registry; no registrar is exported and none is wanted.
|
|
6
|
+
*/
|
|
7
|
+
import { rebuildPatchesManifest, recommendManifestRepair, repairPatchesFilesAffected, validatePatchesManifestConsistency, } from '../core/patch-manifest.js';
|
|
8
|
+
import { FireForgeError } from '../errors/base.js';
|
|
9
|
+
import { toError } from '../utils/errors.js';
|
|
10
|
+
import { pathExists } from '../utils/fs.js';
|
|
11
|
+
import { info, warn } from '../utils/logger.js';
|
|
12
|
+
import { resolveWaitLockSeconds } from '../utils/options.js';
|
|
13
|
+
import { failure, ok, warning } from './doctor-check-core.js';
|
|
14
|
+
const CHECK_NAME = 'Patch manifest consistency';
|
|
15
|
+
/** Runs the narrow `filesAffected` repair over the drifted rows. */
|
|
16
|
+
async function runFilesAffectedRepair(ctx, issues) {
|
|
17
|
+
const drifted = issues.filter((issue) => issue.code === 'files-affected-mismatch');
|
|
18
|
+
const otherCodes = [
|
|
19
|
+
...new Set(issues.filter((issue) => issue.code !== 'files-affected-mismatch').map((issue) => issue.code)),
|
|
20
|
+
].sort((left, right) => left.localeCompare(right));
|
|
21
|
+
if (drifted.length === 0) {
|
|
22
|
+
return failure(CHECK_NAME, `--repair-files-affected has nothing to repair: no filesAffected drift, but ${issues.length} ` +
|
|
23
|
+
`other issue(s) remain (${otherCodes.join(', ')}).`, recommendManifestRepair(issues));
|
|
24
|
+
}
|
|
25
|
+
const dryRun = ctx.options.dryRun === true;
|
|
26
|
+
const result = await repairPatchesFilesAffected(ctx.paths.patches, drifted.map((issue) => issue.filename), {
|
|
27
|
+
waitLockSeconds: resolveWaitLockSeconds(ctx.options.waitLock),
|
|
28
|
+
command: 'doctor --repair-files-affected',
|
|
29
|
+
dryRun,
|
|
30
|
+
});
|
|
31
|
+
for (const repair of result.repairs) {
|
|
32
|
+
info(` ${describeFilesAffectedRepair(repair, dryRun)}`);
|
|
33
|
+
}
|
|
34
|
+
for (const filename of result.skippedFilenames) {
|
|
35
|
+
warn(`Skipped ${filename}: it has no manifest row, or no patch file on disk. ` +
|
|
36
|
+
'That is a different consistency issue — re-run doctor without --repair-files-affected ' +
|
|
37
|
+
'to see it reported.');
|
|
38
|
+
}
|
|
39
|
+
if (result.written) {
|
|
40
|
+
ctx.mutations.push(`patches/patches.json — filesAffected corrected on ${describeCount(result.repairs.length)} (--repair-files-affected)`);
|
|
41
|
+
}
|
|
42
|
+
const remaining = otherCodes.length > 0
|
|
43
|
+
? ` ${otherCodes.length} other issue type(s) remain: ${otherCodes.join(', ')}.`
|
|
44
|
+
: '';
|
|
45
|
+
if (otherCodes.length > 0) {
|
|
46
|
+
return failure(CHECK_NAME, `${summarizeFilesAffected(result.repairs.length, dryRun)}${remaining}`, recommendManifestRepair(issues.filter((issue) => issue.code !== 'files-affected-mismatch')));
|
|
47
|
+
}
|
|
48
|
+
return warning(CHECK_NAME, summarizeFilesAffected(result.repairs.length, dryRun));
|
|
49
|
+
}
|
|
50
|
+
function describeFilesAffectedRepair(repair, dryRun) {
|
|
51
|
+
const verb = dryRun ? 'would set' : 'set';
|
|
52
|
+
return `${repair.filename}: ${verb} filesAffected to ${repair.after.length} file(s) (was ${repair.before.length}).`;
|
|
53
|
+
}
|
|
54
|
+
function summarizeFilesAffected(count, dryRun) {
|
|
55
|
+
if (count === 0)
|
|
56
|
+
return 'No filesAffected drift to repair.';
|
|
57
|
+
return dryRun
|
|
58
|
+
? `Dry run — would correct filesAffected on ${describeCount(count)}. Nothing was written.`
|
|
59
|
+
: `Corrected filesAffected on ${describeCount(count)}. No other manifest field was touched.`;
|
|
60
|
+
}
|
|
61
|
+
function describeCount(count) {
|
|
62
|
+
return `${count} patch${count === 1 ? '' : 'es'}`;
|
|
63
|
+
}
|
|
64
|
+
/** Runs the whole-manifest rebuild. */
|
|
65
|
+
async function runManifestRebuild(ctx) {
|
|
66
|
+
// Repair stamps sourceEsrVersion into every recovered entry. If the
|
|
67
|
+
// earlier "fireforge.json is valid" check failed, ctx.config is
|
|
68
|
+
// undefined and we must refuse rather than fabricate a fallback —
|
|
69
|
+
// persisting 'unknown' into manifest metadata is hard to reverse
|
|
70
|
+
// and would mislead every later command that reads it.
|
|
71
|
+
if (!ctx.config) {
|
|
72
|
+
return failure(CHECK_NAME, 'Cannot repair patches.json: fireforge.json could not be loaded, so the Firefox version to stamp into recovered manifest entries is unknown.', 'Fix the fireforge.json errors reported above and re-run "fireforge doctor --repair-patches-manifest". ' +
|
|
73
|
+
'If the drift is only in filesAffected, "fireforge doctor --repair-files-affected" needs no config.');
|
|
74
|
+
}
|
|
75
|
+
const dryRun = ctx.options.dryRun === true;
|
|
76
|
+
const repaired = await rebuildPatchesManifest(ctx.paths.patches, ctx.config.firefox.version, {
|
|
77
|
+
waitLockSeconds: resolveWaitLockSeconds(ctx.options.waitLock),
|
|
78
|
+
command: 'doctor --repair-patches-manifest',
|
|
79
|
+
dryRun,
|
|
80
|
+
...(ctx.options.allowMetadataLoss === true ? { allowMetadataLoss: true } : {}),
|
|
81
|
+
});
|
|
82
|
+
// The repair path must not silently overwrite human-written
|
|
83
|
+
// descriptions on recovered entries, which leaves the queue less
|
|
84
|
+
// trustworthy as an audit trail. The rebuilder returns the list of
|
|
85
|
+
// filenames whose metadata was entirely invented, named explicitly
|
|
86
|
+
// here so the operator knows which patches to review. Entries that
|
|
87
|
+
// WERE preserved (only `filesAffected` / ordering drifted) are not
|
|
88
|
+
// flagged.
|
|
89
|
+
for (const filename of repaired.recoveredFilenames) {
|
|
90
|
+
// Telling the operator to hand-edit patches.json contradicts the
|
|
91
|
+
// README and downstream docs, which treat the manifest as
|
|
92
|
+
// FireForge-owned. Point at the existing `re-export` / `export`
|
|
93
|
+
// workflow so the fix stays inside the tool: re-exporting the
|
|
94
|
+
// same files with an explicit `--description` overwrites the
|
|
95
|
+
// recovered entry with operator-supplied metadata and supersedes
|
|
96
|
+
// the mtime-based createdAt stamp.
|
|
97
|
+
warn(`Recovered manifest entry for ${filename} with generic description and mtime-based createdAt. ` +
|
|
98
|
+
'Re-export the affected files with `fireforge re-export <filename> --description "<your description>"` ' +
|
|
99
|
+
'(or `fireforge export <paths...> --name <name> --category <category> --description "<your description>"`) ' +
|
|
100
|
+
'to overwrite the reconstructed metadata, or accept the generic description if the original text is not recoverable. ' +
|
|
101
|
+
'Avoid hand-editing patches.json — FireForge owns that file and will regenerate it on the next manifest consistency pass.');
|
|
102
|
+
}
|
|
103
|
+
// A row whose patch file is gone is dropped by the rebuild. That is
|
|
104
|
+
// correct — the patch file is the source of truth — but a manifest that
|
|
105
|
+
// quietly loses rows is exactly what makes a repair hard to audit
|
|
106
|
+
// afterwards, so each one is named.
|
|
107
|
+
for (const filename of repaired.droppedFilenames) {
|
|
108
|
+
warn(`Dropped the manifest entry for ${filename}: no such patch file on disk. ` +
|
|
109
|
+
'Restore the .patch file and re-run the repair if the entry should have survived.');
|
|
110
|
+
}
|
|
111
|
+
if (repaired.written) {
|
|
112
|
+
ctx.mutations.push('patches/patches.json — rebuilt from the on-disk patch files (--repair-patches-manifest)');
|
|
113
|
+
}
|
|
114
|
+
const patchCount = repaired.manifest.patches.length;
|
|
115
|
+
const recovered = repaired.recoveredFilenames.length > 0
|
|
116
|
+
? ` (${repaired.recoveredFilenames.length} with reconstructed metadata — see warnings above)`
|
|
117
|
+
: '';
|
|
118
|
+
return warning(CHECK_NAME, dryRun
|
|
119
|
+
? `Dry run — would rebuild patches.json from ${describeCount(patchCount)}${recovered}. Nothing was written.`
|
|
120
|
+
: `Rebuilt patches.json from ${describeCount(patchCount)}${recovered}. Review recovered metadata before release.`);
|
|
121
|
+
}
|
|
122
|
+
/** Patch manifest consistency check, with its opt-in repair paths. */
|
|
123
|
+
export const PATCH_MANIFEST_CONSISTENCY_CHECK = {
|
|
124
|
+
name: CHECK_NAME,
|
|
125
|
+
dependsOn: ['fireforge.json is valid'],
|
|
126
|
+
run: async (ctx) => {
|
|
127
|
+
if (!(await pathExists(ctx.paths.patches))) {
|
|
128
|
+
return [];
|
|
129
|
+
}
|
|
130
|
+
const issues = await validatePatchesManifestConsistency(ctx.paths.patches);
|
|
131
|
+
if (issues.length === 0) {
|
|
132
|
+
return ok(CHECK_NAME);
|
|
133
|
+
}
|
|
134
|
+
const wantsFilesAffected = ctx.options.repairFilesAffected === true;
|
|
135
|
+
const wantsRebuild = ctx.options.repairPatchesManifest === true;
|
|
136
|
+
if (!wantsFilesAffected && !wantsRebuild) {
|
|
137
|
+
return failure(CHECK_NAME, issues.map((issue) => issue.message).join(' '), recommendManifestRepair(issues));
|
|
138
|
+
}
|
|
139
|
+
try {
|
|
140
|
+
return wantsFilesAffected
|
|
141
|
+
? await runFilesAffectedRepair(ctx, issues)
|
|
142
|
+
: await runManifestRebuild(ctx);
|
|
143
|
+
}
|
|
144
|
+
catch (err) {
|
|
145
|
+
const error = toError(err);
|
|
146
|
+
// A refusal from the repair itself already carries the remedy that
|
|
147
|
+
// fits it (which flag, which file to fix). Appending the generic hint
|
|
148
|
+
// under it buries the specific one and reads as a second, vaguer
|
|
149
|
+
// instruction. Only an unexpected throw gets the generic hint.
|
|
150
|
+
return error instanceof FireForgeError
|
|
151
|
+
? failure(CHECK_NAME, error.message)
|
|
152
|
+
: failure(CHECK_NAME, error.message, 'Repair failed. Fix the underlying patch metadata issue and retry the doctor command.');
|
|
153
|
+
}
|
|
154
|
+
},
|
|
155
|
+
};
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
// SPDX-License-Identifier: EUPL-1.2
|
|
2
2
|
import { readdir } from 'node:fs/promises';
|
|
3
3
|
import { join } from 'node:path';
|
|
4
|
-
import { toError } from '
|
|
5
|
-
import { pathExists, readText } from '
|
|
6
|
-
import { ok, warning } from '
|
|
4
|
+
import { toError } from '../utils/errors.js';
|
|
5
|
+
import { pathExists, readText } from '../utils/fs.js';
|
|
6
|
+
import { ok, warning } from './doctor-check-core.js';
|
|
7
7
|
async function readEngineText(engineDir, relativePath) {
|
|
8
8
|
const fullPath = join(engineDir, relativePath);
|
|
9
9
|
if (!(await pathExists(fullPath)))
|
|
@@ -12,18 +12,16 @@
|
|
|
12
12
|
import type { DoctorCheck } from '../types/commands/index.js';
|
|
13
13
|
import type { DoctorCheckContext } from './doctor-check-core.js';
|
|
14
14
|
/**
|
|
15
|
-
* Inspects the engine working tree and returns a single
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
* `fireforge
|
|
15
|
+
* Inspects the engine working tree and returns a single `DoctorCheck`.
|
|
16
|
+
* Ownership-aware: patch-backed / branding / furnace rows are reported as OK
|
|
17
|
+
* with an ownership summary; unmanaged drift warns; cross-patch conflicts
|
|
18
|
+
* warn loudly with a pointer at `fireforge status --ownership` +
|
|
19
|
+
* `fireforge verify`.
|
|
20
20
|
*
|
|
21
|
-
*
|
|
22
|
-
*
|
|
23
|
-
*
|
|
24
|
-
*
|
|
25
|
-
*
|
|
26
|
-
* import). Returns `undefined` when the worktree is clean so the
|
|
27
|
-
* caller can emit its own ok() row.
|
|
21
|
+
* Ownership is what makes the advice safe: warning on every dirty row and
|
|
22
|
+
* telling the operator to export/discard/reset is actively destructive on a
|
|
23
|
+
* patch-backed import, where the suggested fix would drop the entire patch
|
|
24
|
+
* stack. Returns `undefined` when the worktree is clean so the caller can
|
|
25
|
+
* emit its own ok() row.
|
|
28
26
|
*/
|
|
29
27
|
export declare function inspectEngineWorkingTree(ctx: DoctorCheckContext): Promise<DoctorCheck | undefined>;
|
|
@@ -28,19 +28,17 @@ function formatManagedDetail(counts) {
|
|
|
28
28
|
.join(', ');
|
|
29
29
|
}
|
|
30
30
|
/**
|
|
31
|
-
* Inspects the engine working tree and returns a single
|
|
32
|
-
*
|
|
33
|
-
*
|
|
34
|
-
*
|
|
35
|
-
* `fireforge
|
|
31
|
+
* Inspects the engine working tree and returns a single `DoctorCheck`.
|
|
32
|
+
* Ownership-aware: patch-backed / branding / furnace rows are reported as OK
|
|
33
|
+
* with an ownership summary; unmanaged drift warns; cross-patch conflicts
|
|
34
|
+
* warn loudly with a pointer at `fireforge status --ownership` +
|
|
35
|
+
* `fireforge verify`.
|
|
36
36
|
*
|
|
37
|
-
*
|
|
38
|
-
*
|
|
39
|
-
*
|
|
40
|
-
*
|
|
41
|
-
*
|
|
42
|
-
* import). Returns `undefined` when the worktree is clean so the
|
|
43
|
-
* caller can emit its own ok() row.
|
|
37
|
+
* Ownership is what makes the advice safe: warning on every dirty row and
|
|
38
|
+
* telling the operator to export/discard/reset is actively destructive on a
|
|
39
|
+
* patch-backed import, where the suggested fix would drop the entire patch
|
|
40
|
+
* stack. Returns `undefined` when the worktree is clean so the caller can
|
|
41
|
+
* emit its own ok() row.
|
|
44
42
|
*/
|
|
45
43
|
export async function inspectEngineWorkingTree(ctx) {
|
|
46
44
|
const { paths } = ctx;
|
|
@@ -82,12 +80,7 @@ export async function inspectEngineWorkingTree(ctx) {
|
|
|
82
80
|
const managedTotal = counts.branding + counts.furnace + counts.patchBacked + counts.patchOwnedDrift;
|
|
83
81
|
if (counts.unmanaged === 0) {
|
|
84
82
|
const managedDetail = formatManagedDetail(counts);
|
|
85
|
-
return {
|
|
86
|
-
name: 'Engine working tree',
|
|
87
|
-
passed: true,
|
|
88
|
-
severity: 'ok',
|
|
89
|
-
message: `${managedTotal} tool-managed change${managedTotal === 1 ? '' : 's'} (${managedDetail}), 0 unmanaged. Use "fireforge status --ownership" for details.`,
|
|
90
|
-
};
|
|
83
|
+
return ok('Engine working tree', `${managedTotal} tool-managed change${managedTotal === 1 ? '' : 's'} (${managedDetail}), 0 unmanaged. Use "fireforge status --ownership" for details.`);
|
|
91
84
|
}
|
|
92
85
|
const managedTail = managedTotal > 0
|
|
93
86
|
? ` (${managedTotal} other change${managedTotal === 1 ? '' : 's'} are tool-managed: ${formatManagedDetail(counts)}).`
|
|
@@ -29,7 +29,7 @@ export declare const DOCTOR_CHECK_ORDER: readonly string[];
|
|
|
29
29
|
* @param checks - The check results to display
|
|
30
30
|
* @returns The exit code reflecting the overall result
|
|
31
31
|
*/
|
|
32
|
-
export declare function reportDoctorResults(checks: DoctorCheck[]): ExitCode;
|
|
32
|
+
export declare function reportDoctorResults(checks: DoctorCheck[], mutations?: readonly string[]): ExitCode;
|
|
33
33
|
/**
|
|
34
34
|
* Result of the doctor command, carrying the exit code so the caller
|
|
35
35
|
* (or test) can inspect it without relying on process.exitCode.
|