@hominis/fireforge 0.49.2 → 0.51.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +87 -1
- package/README.md +1 -1
- package/dist/bin/fireforge.js +6 -0
- package/dist/build-info.json +4 -4
- package/dist/src/commands/build-prelock.d.ts +20 -0
- package/dist/src/commands/build-prelock.js +50 -0
- package/dist/src/commands/build.d.ts +3 -1
- package/dist/src/commands/build.js +13 -6
- package/dist/src/commands/check-report.d.ts +41 -0
- package/dist/src/commands/check-report.js +91 -0
- package/dist/src/commands/check-run.d.ts +33 -0
- package/dist/src/commands/check-run.js +112 -0
- package/dist/src/commands/check-steps.d.ts +75 -0
- package/dist/src/commands/check-steps.js +200 -0
- package/dist/src/commands/check.d.ts +32 -0
- package/dist/src/commands/check.js +160 -0
- package/dist/src/commands/config.js +5 -6
- package/dist/src/commands/declarations-report.d.ts +43 -0
- package/dist/src/commands/declarations-report.js +76 -0
- package/dist/src/commands/doctor-engine-eslint.js +6 -1
- package/dist/src/commands/doctor-source-pin.js +4 -1
- package/dist/src/commands/export-adopt-check.d.ts +38 -0
- package/dist/src/commands/export-adopt-check.js +98 -0
- package/dist/src/commands/export-flow.js +29 -14
- package/dist/src/commands/export-placement-gate.d.ts +6 -2
- package/dist/src/commands/export-placement-gate.js +8 -0
- package/dist/src/commands/export-shared.d.ts +2 -1
- package/dist/src/commands/export-staged-registration.d.ts +46 -0
- package/dist/src/commands/export-staged-registration.js +91 -0
- package/dist/src/commands/forward-import-remedy.d.ts +32 -0
- package/dist/src/commands/forward-import-remedy.js +63 -0
- package/dist/src/commands/furnace/apply.js +3 -3
- package/dist/src/commands/furnace/chrome-doc-remove.d.ts +2 -1
- package/dist/src/commands/furnace/chrome-doc-remove.js +2 -2
- package/dist/src/commands/furnace/chrome-doc.d.ts +2 -1
- package/dist/src/commands/furnace/chrome-doc.js +2 -2
- package/dist/src/commands/furnace/create.js +2 -2
- package/dist/src/commands/furnace/deploy-named.d.ts +48 -0
- package/dist/src/commands/furnace/deploy-named.js +107 -0
- package/dist/src/commands/furnace/deploy.d.ts +3 -2
- package/dist/src/commands/furnace/deploy.js +50 -86
- package/dist/src/commands/furnace/diff.js +26 -3
- package/dist/src/commands/furnace/index.js +66 -41
- package/dist/src/commands/furnace/init.js +13 -6
- package/dist/src/commands/furnace/override.js +4 -2
- package/dist/src/commands/furnace/preview.js +4 -3
- package/dist/src/commands/furnace/refresh.js +2 -2
- package/dist/src/commands/furnace/remove.js +4 -3
- package/dist/src/commands/furnace/rename-dry-run.d.ts +29 -0
- package/dist/src/commands/furnace/rename-dry-run.js +127 -0
- package/dist/src/commands/furnace/rename-helpers.d.ts +7 -0
- package/dist/src/commands/furnace/rename-helpers.js +15 -1
- package/dist/src/commands/furnace/rename-registrations.d.ts +41 -0
- package/dist/src/commands/furnace/rename-registrations.js +98 -0
- package/dist/src/commands/furnace/rename.d.ts +2 -1
- package/dist/src/commands/furnace/rename.js +28 -66
- package/dist/src/commands/furnace/scan.d.ts +9 -4
- package/dist/src/commands/furnace/scan.js +11 -9
- package/dist/src/commands/furnace/sync.js +3 -2
- package/dist/src/commands/furnace/validate-report.d.ts +45 -0
- package/dist/src/commands/furnace/validate-report.js +91 -0
- package/dist/src/commands/furnace/validate.d.ts +1 -1
- package/dist/src/commands/furnace/validate.js +151 -113
- package/dist/src/commands/furnace/validation-output.js +14 -3
- package/dist/src/commands/lint-per-patch.js +36 -61
- package/dist/src/commands/lint-per-run-checkjs.js +2 -2
- package/dist/src/commands/lint-report.d.ts +8 -4
- package/dist/src/commands/lint-report.js +20 -5
- package/dist/src/commands/lint.js +15 -34
- package/dist/src/commands/manifest.js +4 -0
- package/dist/src/commands/park.d.ts +22 -0
- package/dist/src/commands/park.js +232 -0
- package/dist/src/commands/patch/delete-gap-notice.js +3 -1
- package/dist/src/commands/patch/delete.d.ts +1 -1
- package/dist/src/commands/patch/delete.js +24 -104
- package/dist/src/commands/patch/index.d.ts +3 -3
- package/dist/src/commands/patch/index.js +10 -4
- package/dist/src/commands/patch/lint-ignore-from.d.ts +44 -0
- package/dist/src/commands/patch/lint-ignore-from.js +142 -0
- package/dist/src/commands/patch/lint-ignore.d.ts +5 -1
- package/dist/src/commands/patch/lint-ignore.js +78 -31
- package/dist/src/commands/patch/move-files-create.js +34 -18
- package/dist/src/commands/patch/move-files-into.js +15 -7
- package/dist/src/commands/patch/move-files.js +6 -2
- package/dist/src/commands/patch/removal-created-files.d.ts +48 -0
- package/dist/src/commands/patch/removal-created-files.js +83 -0
- package/dist/src/commands/patch/removal-dependents.d.ts +63 -0
- package/dist/src/commands/patch/removal-dependents.js +133 -0
- package/dist/src/commands/patch/rename.js +20 -1
- package/dist/src/commands/patch/reserve.d.ts +33 -0
- package/dist/src/commands/patch/reserve.js +152 -0
- package/dist/src/commands/patch/retire.d.ts +34 -0
- package/dist/src/commands/patch/retire.js +133 -0
- package/dist/src/commands/patch/split-plan.d.ts +17 -8
- package/dist/src/commands/patch/split-plan.js +60 -28
- package/dist/src/commands/patch/split-staged.d.ts +108 -0
- package/dist/src/commands/patch/split-staged.js +202 -0
- package/dist/src/commands/patch/split.d.ts +5 -0
- package/dist/src/commands/patch/split.js +62 -17
- package/dist/src/commands/patch/stage.d.ts +34 -0
- package/dist/src/commands/patch/stage.js +153 -0
- package/dist/src/commands/patch/staged-dependency-batch.d.ts +48 -0
- package/dist/src/commands/patch/staged-dependency-batch.js +176 -0
- package/dist/src/commands/patch/staged-dependency-entries.d.ts +36 -0
- package/dist/src/commands/patch/staged-dependency-entries.js +52 -0
- package/dist/src/commands/patch/staged-dependency-from.d.ts +14 -0
- package/dist/src/commands/patch/staged-dependency-from.js +108 -0
- package/dist/src/commands/patch/staged-dependency-remove.d.ts +31 -0
- package/dist/src/commands/patch/staged-dependency-remove.js +80 -0
- package/dist/src/commands/patch/staged-dependency.js +54 -139
- package/dist/src/commands/re-export-adjacent-registrations.d.ts +20 -0
- package/dist/src/commands/re-export-adjacent-registrations.js +75 -0
- package/dist/src/commands/re-export-adjacent.d.ts +50 -2
- package/dist/src/commands/re-export-adjacent.js +160 -40
- package/dist/src/commands/re-export-bulk-scan.d.ts +2 -1
- package/dist/src/commands/re-export-bulk-scan.js +22 -7
- package/dist/src/commands/re-export-drift.d.ts +36 -8
- package/dist/src/commands/re-export-drift.js +73 -49
- package/dist/src/commands/re-export-files.js +11 -8
- package/dist/src/commands/re-export-hunks.d.ts +35 -0
- package/dist/src/commands/re-export-hunks.js +220 -0
- package/dist/src/commands/re-export-lint.d.ts +2 -1
- package/dist/src/commands/re-export-lint.js +23 -10
- package/dist/src/commands/re-export-options.js +74 -6
- package/dist/src/commands/re-export-preflight.d.ts +23 -0
- package/dist/src/commands/re-export-preflight.js +160 -0
- package/dist/src/commands/re-export-purity-scope.d.ts +18 -0
- package/dist/src/commands/re-export-purity-scope.js +131 -0
- package/dist/src/commands/re-export-register.js +56 -17
- package/dist/src/commands/re-export-removed.d.ts +13 -2
- package/dist/src/commands/re-export-removed.js +57 -12
- package/dist/src/commands/re-export-scan-owner.d.ts +44 -0
- package/dist/src/commands/re-export-scan-owner.js +116 -0
- package/dist/src/commands/re-export-scan.d.ts +19 -9
- package/dist/src/commands/re-export-scan.js +60 -24
- package/dist/src/commands/re-export-single.js +122 -46
- package/dist/src/commands/re-export-stale-registrations.d.ts +18 -0
- package/dist/src/commands/re-export-stale-registrations.js +62 -0
- package/dist/src/commands/re-export-summary.d.ts +28 -0
- package/dist/src/commands/re-export-summary.js +36 -0
- package/dist/src/commands/re-export.js +71 -57
- package/dist/src/commands/rebase/index.js +17 -17
- package/dist/src/commands/run.js +16 -2
- package/dist/src/commands/status-check.d.ts +55 -16
- package/dist/src/commands/status-check.js +92 -37
- package/dist/src/commands/status-json.d.ts +22 -9
- package/dist/src/commands/status-json.js +47 -32
- package/dist/src/commands/status-output.js +3 -1
- package/dist/src/commands/status-scope.d.ts +37 -0
- package/dist/src/commands/status-scope.js +54 -0
- package/dist/src/commands/status.js +66 -23
- package/dist/src/commands/test-browser-preflight.js +19 -3
- package/dist/src/commands/test-build-furnace.d.ts +22 -0
- package/dist/src/commands/test-build-furnace.js +54 -0
- package/dist/src/commands/test-build-phase.js +64 -41
- package/dist/src/commands/test-checkjs.js +10 -2
- package/dist/src/commands/test-diagnose.js +7 -0
- package/dist/src/commands/test-dispatch.d.ts +39 -0
- package/dist/src/commands/test-dispatch.js +211 -0
- package/dist/src/commands/test-furnace-reach.d.ts +37 -0
- package/dist/src/commands/test-furnace-reach.js +132 -0
- package/dist/src/commands/test-modes.d.ts +16 -1
- package/dist/src/commands/test-modes.js +24 -1
- package/dist/src/commands/test-multi-verdict.d.ts +61 -0
- package/dist/src/commands/test-multi-verdict.js +111 -0
- package/dist/src/commands/test-orchestrate.d.ts +52 -0
- package/dist/src/commands/test-orchestrate.js +240 -0
- package/dist/src/commands/test-perf-scope.d.ts +50 -0
- package/dist/src/commands/test-perf-scope.js +138 -0
- package/dist/src/commands/test-prelock.d.ts +51 -0
- package/dist/src/commands/test-prelock.js +273 -0
- package/dist/src/commands/test-register.js +69 -10
- package/dist/src/commands/test-results.d.ts +62 -0
- package/dist/src/commands/test-results.js +62 -0
- package/dist/src/commands/test-run.d.ts +13 -55
- package/dist/src/commands/test-run.js +74 -99
- package/dist/src/commands/test-shards.d.ts +110 -0
- package/dist/src/commands/test-shards.js +255 -0
- package/dist/src/commands/test-stale-gate.d.ts +5 -1
- package/dist/src/commands/test-stale-gate.js +60 -28
- package/dist/src/commands/test-verdict.d.ts +11 -1
- package/dist/src/commands/test-verdict.js +28 -1
- package/dist/src/commands/test.d.ts +6 -1
- package/dist/src/commands/test.js +120 -124
- package/dist/src/commands/token-lint.d.ts +14 -0
- package/dist/src/commands/token-lint.js +151 -0
- package/dist/src/commands/token.js +10 -0
- package/dist/src/commands/verify-scope.d.ts +28 -0
- package/dist/src/commands/verify-scope.js +67 -0
- package/dist/src/commands/verify.d.ts +10 -2
- package/dist/src/commands/verify.js +67 -36
- package/dist/src/core/build-baseline-types.d.ts +46 -0
- package/dist/src/core/build-baseline-validate.js +19 -0
- package/dist/src/core/build-baseline.d.ts +5 -1
- package/dist/src/core/build-baseline.js +3 -1
- package/dist/src/core/build-overwrite-guard.d.ts +50 -0
- package/dist/src/core/build-overwrite-guard.js +84 -4
- package/dist/src/core/build-prepare.d.ts +13 -0
- package/dist/src/core/build-prepare.js +42 -10
- package/dist/src/core/build-run-record.d.ts +74 -0
- package/dist/src/core/build-run-record.js +136 -0
- package/dist/src/core/checkjs-support-heads.d.ts +41 -0
- package/dist/src/core/checkjs-support-heads.js +104 -0
- package/dist/src/core/config-paths.d.ts +2 -2
- package/dist/src/core/config-paths.js +10 -0
- package/dist/src/core/config-validate-check.d.ts +8 -0
- package/dist/src/core/config-validate-check.js +219 -0
- package/dist/src/core/config-validate-file-size.d.ts +9 -6
- package/dist/src/core/config-validate-file-size.js +91 -2
- package/dist/src/core/config-validate-history.d.ts +11 -0
- package/dist/src/core/config-validate-history.js +38 -0
- package/dist/src/core/config-validate-patch-policy.js +100 -0
- package/dist/src/core/config-validate-test-toolchains.js +21 -0
- package/dist/src/core/config-validate-token-scales.d.ts +9 -0
- package/dist/src/core/config-validate-token-scales.js +92 -0
- package/dist/src/core/config-validate.js +20 -5
- package/dist/src/core/config.d.ts +5 -0
- package/dist/src/core/config.js +16 -0
- package/dist/src/core/coverage-dispatch.d.ts +24 -0
- package/dist/src/core/coverage-dispatch.js +44 -0
- package/dist/src/core/coverage-extend.d.ts +70 -45
- package/dist/src/core/coverage-extend.js +199 -144
- package/dist/src/core/coverage-records.d.ts +108 -0
- package/dist/src/core/coverage-records.js +384 -0
- package/dist/src/core/destructive.d.ts +7 -4
- package/dist/src/core/destructive.js +10 -10
- package/dist/src/core/engine-session-lock.d.ts +16 -1
- package/dist/src/core/engine-session-lock.js +38 -10
- package/dist/src/core/export-moved-code-shape.d.ts +49 -11
- package/dist/src/core/export-moved-code-shape.js +135 -44
- package/dist/src/core/file-lock-queue.d.ts +67 -0
- package/dist/src/core/file-lock-queue.js +221 -0
- package/dist/src/core/file-lock-shared.d.ts +57 -0
- package/dist/src/core/file-lock-shared.js +117 -0
- package/dist/src/core/file-lock.d.ts +13 -25
- package/dist/src/core/file-lock.js +163 -140
- package/dist/src/core/furnace-apply-output.d.ts +10 -0
- package/dist/src/core/furnace-apply-output.js +31 -1
- package/dist/src/core/furnace-apply.js +22 -12
- package/dist/src/core/furnace-composed-source.d.ts +76 -0
- package/dist/src/core/furnace-composed-source.js +167 -0
- package/dist/src/core/furnace-config-validate-exceptions.d.ts +16 -0
- package/dist/src/core/furnace-config-validate-exceptions.js +102 -0
- package/dist/src/core/furnace-config-validate.js +14 -0
- package/dist/src/core/furnace-css-fragments.d.ts +10 -0
- package/dist/src/core/furnace-css-fragments.js +26 -0
- package/dist/src/core/furnace-operation.d.ts +3 -3
- package/dist/src/core/furnace-registration-jar-inplace.d.ts +12 -0
- package/dist/src/core/furnace-registration-jar-inplace.js +80 -0
- package/dist/src/core/furnace-registration-remove.d.ts +22 -1
- package/dist/src/core/furnace-registration-remove.js +53 -17
- package/dist/src/core/furnace-registration-rename.d.ts +26 -0
- package/dist/src/core/furnace-registration-rename.js +77 -0
- package/dist/src/core/furnace-registration.d.ts +14 -4
- package/dist/src/core/furnace-registration.js +44 -10
- package/dist/src/core/furnace-staleness.d.ts +7 -0
- package/dist/src/core/furnace-staleness.js +34 -24
- package/dist/src/core/furnace-validate-accessibility.d.ts +8 -4
- package/dist/src/core/furnace-validate-accessibility.js +71 -28
- package/dist/src/core/furnace-validate-exceptions.d.ts +48 -0
- package/dist/src/core/furnace-validate-exceptions.js +80 -0
- package/dist/src/core/furnace-validate-icon-button.d.ts +7 -0
- package/dist/src/core/furnace-validate-icon-button.js +78 -0
- package/dist/src/core/furnace-validate.js +1 -1
- package/dist/src/core/harness-port-fallback.d.ts +60 -0
- package/dist/src/core/harness-port-fallback.js +96 -0
- package/dist/src/core/history-log-file.d.ts +61 -0
- package/dist/src/core/history-log-file.js +164 -0
- package/dist/src/core/history-log.d.ts +2 -1
- package/dist/src/core/history-log.js +2 -1
- package/dist/src/core/json-preserving-edit.d.ts +22 -0
- package/dist/src/core/json-preserving-edit.js +199 -0
- package/dist/src/core/line-prefixer.d.ts +18 -0
- package/dist/src/core/line-prefixer.js +34 -0
- package/dist/src/core/mach.d.ts +7 -0
- package/dist/src/core/mach.js +32 -10
- package/dist/src/core/module-resolution-preflight.d.ts +19 -3
- package/dist/src/core/module-resolution-preflight.js +24 -6
- package/dist/src/core/negative-control-compiled.d.ts +27 -0
- package/dist/src/core/negative-control-compiled.js +73 -0
- package/dist/src/core/negative-control-diff.d.ts +51 -0
- package/dist/src/core/negative-control-diff.js +179 -0
- package/dist/src/core/negative-control.d.ts +150 -0
- package/dist/src/core/negative-control.js +399 -0
- package/dist/src/core/objdir-install-manifests.d.ts +73 -0
- package/dist/src/core/objdir-install-manifests.js +226 -0
- package/dist/src/core/park-store.d.ts +63 -0
- package/dist/src/core/park-store.js +216 -0
- package/dist/src/core/patch-export-update.d.ts +6 -0
- package/dist/src/core/patch-export-update.js +13 -3
- package/dist/src/core/patch-export.d.ts +3 -2
- package/dist/src/core/patch-export.js +22 -16
- package/dist/src/core/patch-files.js +26 -8
- package/dist/src/core/patch-lint-checkjs-any-import.d.ts +39 -0
- package/dist/src/core/patch-lint-checkjs-any-import.js +63 -0
- package/dist/src/core/patch-lint-checkjs-diagnostics.d.ts +17 -0
- package/dist/src/core/patch-lint-checkjs-diagnostics.js +32 -0
- package/dist/src/core/patch-lint-checkjs.d.ts +10 -1
- package/dist/src/core/patch-lint-checkjs.js +20 -13
- package/dist/src/core/patch-lint-code-lines.d.ts +59 -0
- package/dist/src/core/patch-lint-code-lines.js +105 -0
- package/dist/src/core/patch-lint-cross.d.ts +3 -1
- package/dist/src/core/patch-lint-cross.js +17 -4
- package/dist/src/core/patch-lint-css.d.ts +8 -2
- package/dist/src/core/patch-lint-css.js +24 -14
- package/dist/src/core/patch-lint-file-size.d.ts +12 -5
- package/dist/src/core/patch-lint-file-size.js +22 -11
- package/dist/src/core/patch-lint-forward-registration-extended.d.ts +23 -0
- package/dist/src/core/patch-lint-forward-registration-extended.js +36 -11
- package/dist/src/core/patch-lint-forward-registration.js +10 -0
- package/dist/src/core/patch-lint-ignore.d.ts +196 -0
- package/dist/src/core/patch-lint-ignore.js +429 -0
- package/dist/src/core/patch-lint-ownership.d.ts +10 -0
- package/dist/src/core/patch-lint-ownership.js +26 -0
- package/dist/src/core/patch-lint-size-thresholds.d.ts +52 -0
- package/dist/src/core/patch-lint-size-thresholds.js +110 -0
- package/dist/src/core/patch-lint-size.d.ts +117 -0
- package/dist/src/core/patch-lint-size.js +331 -0
- package/dist/src/core/patch-lint-staged-registration.d.ts +18 -1
- package/dist/src/core/patch-lint-staged-registration.js +20 -0
- package/dist/src/core/patch-lint-token-scale.d.ts +57 -0
- package/dist/src/core/patch-lint-token-scale.js +286 -0
- package/dist/src/core/patch-lint.d.ts +11 -83
- package/dist/src/core/patch-lint.js +66 -288
- package/dist/src/core/patch-lock.js +7 -6
- package/dist/src/core/patch-manifest-consistency.js +7 -6
- package/dist/src/core/patch-manifest-io.d.ts +6 -3
- package/dist/src/core/patch-manifest-io.js +27 -9
- package/dist/src/core/patch-manifest-key-order.d.ts +24 -0
- package/dist/src/core/patch-manifest-key-order.js +61 -0
- package/dist/src/core/patch-manifest-stage.d.ts +46 -0
- package/dist/src/core/patch-manifest-stage.js +96 -0
- package/dist/src/core/patch-manifest-validate.js +61 -3
- package/dist/src/core/patch-order-legal.d.ts +26 -0
- package/dist/src/core/patch-order-legal.js +88 -0
- package/dist/src/core/patch-policy-content.d.ts +40 -0
- package/dist/src/core/patch-policy-content.js +216 -0
- package/dist/src/core/patch-policy.d.ts +22 -5
- package/dist/src/core/patch-policy.js +26 -12
- package/dist/src/core/patch-retired.d.ts +57 -0
- package/dist/src/core/patch-retired.js +92 -0
- package/dist/src/core/patch-subset.d.ts +16 -0
- package/dist/src/core/patch-subset.js +66 -0
- package/dist/src/core/preflight-wait.d.ts +20 -0
- package/dist/src/core/preflight-wait.js +38 -0
- package/dist/src/core/rebase-from-version.d.ts +46 -0
- package/dist/src/core/rebase-from-version.js +71 -0
- package/dist/src/core/run-log.d.ts +26 -0
- package/dist/src/core/run-log.js +106 -4
- package/dist/src/core/run-profile.d.ts +7 -0
- package/dist/src/core/run-profile.js +7 -1
- package/dist/src/core/smoke-patterns.d.ts +5 -0
- package/dist/src/core/smoke-patterns.js +13 -0
- package/dist/src/core/test-harness-crash.d.ts +19 -1
- package/dist/src/core/test-harness-crash.js +8 -9
- package/dist/src/core/test-harness-signature.d.ts +33 -0
- package/dist/src/core/test-harness-signature.js +23 -1
- package/dist/src/core/test-raw-log.d.ts +66 -0
- package/dist/src/core/test-raw-log.js +122 -0
- package/dist/src/core/test-run-completeness.d.ts +90 -0
- package/dist/src/core/test-run-completeness.js +184 -0
- package/dist/src/core/test-stale-check.d.ts +27 -1
- package/dist/src/core/test-stale-check.js +39 -49
- package/dist/src/core/test-stale-exempt.d.ts +40 -0
- package/dist/src/core/test-stale-exempt.js +70 -0
- package/dist/src/core/test-xpcshell-retry.d.ts +2 -0
- package/dist/src/core/test-xpcshell-retry.js +2 -1
- package/dist/src/core/token-lint.d.ts +53 -0
- package/dist/src/core/token-lint.js +131 -0
- package/dist/src/core/token-sibling-sheets.d.ts +46 -0
- package/dist/src/core/token-sibling-sheets.js +119 -0
- package/dist/src/core/tree-guard.js +5 -0
- package/dist/src/core/typecheck-shim.d.ts +6 -2
- package/dist/src/core/typecheck-shim.js +205 -4
- package/dist/src/core/typecheck.js +3 -1
- package/dist/src/index.d.ts +14 -3
- package/dist/src/index.js +6 -1
- package/dist/src/types/commands/index.d.ts +2 -2
- package/dist/src/types/commands/options.d.ts +212 -24
- package/dist/src/types/commands/patches.d.ts +118 -1
- package/dist/src/types/config.d.ts +264 -0
- package/dist/src/types/config.js +9 -0
- package/dist/src/types/furnace.d.ts +63 -1
- package/dist/src/types/furnace.js +7 -0
- package/dist/src/types/index.d.ts +1 -1
- package/dist/src/utils/options.d.ts +36 -7
- package/dist/src/utils/options.js +94 -8
- package/dist/src/utils/path-glob.d.ts +15 -0
- package/dist/src/utils/path-glob.js +47 -0
- package/dist/src/utils/regex.d.ts +15 -3
- package/dist/src/utils/regex.js +37 -16
- package/docs/configuration.md +369 -11
- package/docs/exit-codes.md +18 -1
- package/docs/furnace.md +139 -3
- package/docs/lifecycle-invariants.md +65 -30
- package/docs/machine-output.md +120 -12
- package/docs/patch-workflow.md +458 -22
- package/docs/run-logs.md +20 -1
- package/docs/testing.md +346 -21
- package/package.json +3 -3
|
@@ -10,6 +10,7 @@ import { GeneralError, InvalidArgumentError } from '../errors/base.js';
|
|
|
10
10
|
import { elapsedSince } from '../utils/elapsed.js';
|
|
11
11
|
import { toError } from '../utils/errors.js';
|
|
12
12
|
import { cancel, info, intro, isCancel, outro, spinner, success, warn, } from '../utils/logger.js';
|
|
13
|
+
import { ADJACENT_MEANS, buildAdjacentUnmanagedContext, reportAdjacentCarveOutUsage, } from './re-export-adjacent.js';
|
|
13
14
|
import { loadScanFilesAssignments, withDryRunPurityGuard, withDryRunReExportLock, } from './re-export-bulk-scan.js';
|
|
14
15
|
import { warnUnseenExpectedDrift } from './re-export-drift.js';
|
|
15
16
|
import { reExportFilesInPlace } from './re-export-files.js';
|
|
@@ -17,7 +18,9 @@ import { buildReExportLintContext, finishReExportLint } from './re-export-lint.j
|
|
|
17
18
|
import { applyReExportFilesPositionalFolding, validateReExportOptionCombinations, } from './re-export-options.js';
|
|
18
19
|
import { validateExpectedRemovals } from './re-export-removed.js';
|
|
19
20
|
import { normalizeEngineRelativeInput, normalizeScanFiles } from './re-export-scan.js';
|
|
20
|
-
import {
|
|
21
|
+
import { assignScanFileOwners, scanOptionsForPatch } from './re-export-scan-owner.js';
|
|
22
|
+
import { reExportSinglePatchWithIndexLockRetry, } from './re-export-single.js';
|
|
23
|
+
import { formatReExportRunSummary } from './re-export-summary.js';
|
|
21
24
|
async function resolveSelectedPatches(patches, options, manifest) {
|
|
22
25
|
if (options.all) {
|
|
23
26
|
return [...manifest.patches];
|
|
@@ -56,6 +59,27 @@ async function resolveSelectedPatches(patches, options, manifest) {
|
|
|
56
59
|
const selectedFilenames = selected;
|
|
57
60
|
return manifest.patches.filter((p) => selectedFilenames.includes(p.filename));
|
|
58
61
|
}
|
|
62
|
+
/** Refreshes each selected patch in turn, collecting which wrote and which failed. */
|
|
63
|
+
async function reExportEach(args) {
|
|
64
|
+
const { selectedPatches, options, scanAssignments, progress, startedAt, shared } = args;
|
|
65
|
+
const written = [];
|
|
66
|
+
const failed = [];
|
|
67
|
+
for (const [index, patch] of selectedPatches.entries()) {
|
|
68
|
+
const patchOptions = scanOptionsForPatch(options, patch.filename, scanAssignments);
|
|
69
|
+
progress.message(`Re-exporting ${index + 1}/${selectedPatches.length}: ${patch.filename} (${patch.filesAffected.length} file(s), ${elapsedSince(startedAt)} elapsed)...`);
|
|
70
|
+
try {
|
|
71
|
+
if (await reExportSinglePatchWithIndexLockRetry({ ...shared, patch, options: patchOptions })) {
|
|
72
|
+
written.push(patch.filename);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
catch (error) {
|
|
76
|
+
failed.push(patch.filename);
|
|
77
|
+
warn(`Failed to re-export ${patch.filename}`);
|
|
78
|
+
warn(toError(error).message);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
return { written, failed };
|
|
82
|
+
}
|
|
59
83
|
/**
|
|
60
84
|
* Runs the re-export command to regenerate existing patches from current engine state.
|
|
61
85
|
* @param projectRoot - Root directory of the project
|
|
@@ -73,7 +97,9 @@ export async function reExportCommand(projectRoot, patches, options) {
|
|
|
73
97
|
options = cleanedOptions;
|
|
74
98
|
}
|
|
75
99
|
const isDryRun = options.dryRun === true;
|
|
76
|
-
|
|
100
|
+
// The banner says which mode is in force: a path flag that swallowed
|
|
101
|
+
// `--dry-run` as its value once turned a preview into a write unnoticed.
|
|
102
|
+
intro(isDryRun ? 'FireForge Re-export (DRY RUN)' : 'FireForge Re-export (WRITING)');
|
|
77
103
|
// Accept export-style space-separated paths after --files by folding
|
|
78
104
|
// path-shaped extra positionals into the file list.
|
|
79
105
|
({ patches, options } = applyReExportFilesPositionalFolding(patches, options));
|
|
@@ -94,12 +120,13 @@ export async function reExportCommand(projectRoot, patches, options) {
|
|
|
94
120
|
: await resolveSelectedPatches(patches, options, manifest);
|
|
95
121
|
if (!selectedPatches)
|
|
96
122
|
return;
|
|
123
|
+
const scanAssignments = scanFilesByPatch ?? assignScanFileOwners(options.scanFiles, selectedPatches, manifest);
|
|
97
124
|
if (selectedPatches.length === 0) {
|
|
98
125
|
warn('No patches selected');
|
|
99
126
|
outro('Nothing to re-export');
|
|
100
127
|
return;
|
|
101
128
|
}
|
|
102
|
-
const expectedRemovals = await validateExpectedRemovals(paths, selectedPatches, options);
|
|
129
|
+
const expectedRemovals = await validateExpectedRemovals(paths, selectedPatches, options, manifest.patches);
|
|
103
130
|
if (expectedRemovals.length > 0)
|
|
104
131
|
options = { ...options, expectRemoved: expectedRemovals };
|
|
105
132
|
if (scanFilesByPatch !== undefined) {
|
|
@@ -119,20 +146,13 @@ export async function reExportCommand(projectRoot, patches, options) {
|
|
|
119
146
|
// we write anything.
|
|
120
147
|
if (options.files !== undefined) {
|
|
121
148
|
const filesConfig = await loadConfig(projectRoot);
|
|
122
|
-
await withDryRunReExportLock(paths.fireforgeDir, isDryRun, () => withDryRunPurityGuard(paths.engine, paths.patches, isDryRun, () => reExportFilesInPlace(paths, selectedPatches, options, filesConfig)));
|
|
149
|
+
await withDryRunReExportLock(paths.fireforgeDir, isDryRun, () => withDryRunPurityGuard(paths.engine, paths.patches, isDryRun, () => reExportFilesInPlace(paths, selectedPatches, options, filesConfig), { patches: selectedPatches }));
|
|
123
150
|
return;
|
|
124
151
|
}
|
|
125
152
|
const config = await loadConfig(projectRoot);
|
|
126
153
|
// Classification inputs for the scan-less adjacency advisory, computed
|
|
127
154
|
// once for the whole run.
|
|
128
|
-
const adjacentCtx =
|
|
129
|
-
binaryName: config.binaryName,
|
|
130
|
-
furnacePrefixes: await collectFurnaceManagedPrefixes(paths.root),
|
|
131
|
-
refuseAdjacentUnmanaged: options.refuseAdjacentUnmanaged === true,
|
|
132
|
-
approvedUnmanaged: new Set((options.expectUnmanaged ?? []).map((file) => normalizeEngineRelativeInput(file, '--expect-unmanaged'))),
|
|
133
|
-
approvedSeen: new Set(),
|
|
134
|
-
refusals: [],
|
|
135
|
-
};
|
|
155
|
+
const adjacentCtx = buildAdjacentUnmanagedContext(options, config.binaryName, await collectFurnaceManagedPrefixes(paths.root));
|
|
136
156
|
const driftCtx = buildForeignDriftContext(options);
|
|
137
157
|
// Hoisted lint context, one per run: queue context + checkJs
|
|
138
158
|
// program + per-patch result cache, shared across every loop iteration.
|
|
@@ -140,42 +160,31 @@ export async function reExportCommand(projectRoot, patches, options) {
|
|
|
140
160
|
// reports includes it.
|
|
141
161
|
const startedAt = Date.now();
|
|
142
162
|
const lintCtx = await buildReExportLintContext(projectRoot, paths, config, options.noCache === true, new Set(selectedPatches.map((patch) => patch.filename)));
|
|
143
|
-
let reExported = 0;
|
|
144
|
-
const reExportedFilenames = [];
|
|
145
|
-
const failedFilenames = [];
|
|
146
163
|
const progress = spinner('Preparing re-export...');
|
|
147
|
-
await withDryRunReExportLock(paths.fireforgeDir, isDryRun,
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
isDryRun,
|
|
159
|
-
config,
|
|
160
|
-
adjacentCtx,
|
|
161
|
-
driftCtx,
|
|
162
|
-
lintCtx,
|
|
163
|
-
});
|
|
164
|
-
if (exported) {
|
|
165
|
-
reExported++;
|
|
166
|
-
reExportedFilenames.push(patch.filename);
|
|
167
|
-
}
|
|
168
|
-
}
|
|
169
|
-
catch (error) {
|
|
170
|
-
failedFilenames.push(patch.filename);
|
|
171
|
-
warn(`Failed to re-export ${patch.filename}`);
|
|
172
|
-
warn(toError(error).message);
|
|
173
|
-
}
|
|
174
|
-
}
|
|
175
|
-
}));
|
|
164
|
+
const outcome = await withDryRunReExportLock(paths.fireforgeDir, isDryRun, () => withDryRunPurityGuard(paths.engine, paths.patches, isDryRun, () => reExportEach({
|
|
165
|
+
selectedPatches,
|
|
166
|
+
options,
|
|
167
|
+
scanAssignments,
|
|
168
|
+
progress,
|
|
169
|
+
startedAt,
|
|
170
|
+
shared: { paths, manifest, isDryRun, config, adjacentCtx, driftCtx, lintCtx },
|
|
171
|
+
}), { patches: selectedPatches }));
|
|
172
|
+
const reExportedFilenames = outcome.written;
|
|
173
|
+
const failedFilenames = outcome.failed;
|
|
174
|
+
const reExported = reExportedFilenames.length;
|
|
176
175
|
await finishReExportLint(lintCtx);
|
|
177
176
|
warnUnseenExpectedDrift(driftCtx);
|
|
178
177
|
warnUnseenApprovedUnmanaged(adjacentCtx);
|
|
178
|
+
const summary = formatReExportRunSummary({
|
|
179
|
+
selected: selectedPatches.map((patch) => patch.filename),
|
|
180
|
+
written: reExportedFilenames,
|
|
181
|
+
failed: failedFilenames,
|
|
182
|
+
refusedAdjacent: adjacentCtx.refusals.map((r) => r.patchFilename),
|
|
183
|
+
refusedDrift: driftCtx.refusals.map((r) => r.patchFilename),
|
|
184
|
+
isDryRun,
|
|
185
|
+
});
|
|
186
|
+
if (summary !== undefined)
|
|
187
|
+
info(summary);
|
|
179
188
|
throwRunLevelRefusals(adjacentCtx, driftCtx, progress);
|
|
180
189
|
if (reExported === 0 && selectedPatches.length > 0) {
|
|
181
190
|
progress.error('Re-export failed');
|
|
@@ -198,6 +207,7 @@ export async function reExportCommand(projectRoot, patches, options) {
|
|
|
198
207
|
selectedCount: selectedPatches.length,
|
|
199
208
|
reExportedFilenames,
|
|
200
209
|
failedFilenames,
|
|
210
|
+
selectedFilenames: selectedPatches.map((patch) => patch.filename),
|
|
201
211
|
shouldStamp,
|
|
202
212
|
stampRequested: options.stamp === true,
|
|
203
213
|
config,
|
|
@@ -224,9 +234,11 @@ function buildForeignDriftContext(options) {
|
|
|
224
234
|
* admit, and reads as an approval that is in force when it is not.
|
|
225
235
|
* A warning rather than a refusal: an approved path legitimately goes unmet
|
|
226
236
|
* when the reviewed file has since been adopted into a patch, which is the
|
|
227
|
-
* outcome the carve-out exists to be retired by.
|
|
237
|
+
* outcome the carve-out exists to be retired by. The `--expect-new` and
|
|
238
|
+
* `--adjacent-ignore` accounting is reported first, alongside.
|
|
228
239
|
*/
|
|
229
240
|
function warnUnseenApprovedUnmanaged(adjacentCtx) {
|
|
241
|
+
reportAdjacentCarveOutUsage(adjacentCtx);
|
|
230
242
|
const unseen = [...adjacentCtx.approvedUnmanaged].filter((file) => !adjacentCtx.approvedSeen.has(file));
|
|
231
243
|
if (unseen.length === 0)
|
|
232
244
|
return;
|
|
@@ -244,17 +256,18 @@ function warnUnseenApprovedUnmanaged(adjacentCtx) {
|
|
|
244
256
|
function throwRunLevelRefusals(adjacentCtx, driftCtx, progress) {
|
|
245
257
|
if (adjacentCtx.refusals.length > 0) {
|
|
246
258
|
progress.error('Re-export refused');
|
|
247
|
-
// Each offender is named with the owned directory
|
|
248
|
-
// adjacent: an unattended run reads only this
|
|
249
|
-
// anchor it cannot tell which of a
|
|
250
|
-
// the file
|
|
259
|
+
// Each offender is named with the owned directory (or registering
|
|
260
|
+
// carrier) that made it adjacent: an unattended run reads only this
|
|
261
|
+
// line, and without the anchor it cannot tell which of a
|
|
262
|
+
// multi-directory patch's locations the file belongs to.
|
|
251
263
|
const offenders = adjacentCtx.refusals
|
|
252
264
|
.map((r) => `${r.patchFilename} (${r.anchored.join(', ')})`)
|
|
253
265
|
.join('; ');
|
|
254
266
|
throw new GeneralError(`Refused ${adjacentCtx.refusals.length} patch(es) with adjacent unmanaged files ` +
|
|
255
|
-
`(--refuse-adjacent-unmanaged): ${offenders}.
|
|
256
|
-
`
|
|
257
|
-
|
|
267
|
+
`(--refuse-adjacent-unmanaged): ${offenders}. ${ADJACENT_MEANS} ` +
|
|
268
|
+
`Adopt reviewed files with --scan --scan-file, or export them as a new patch ` +
|
|
269
|
+
`(name a file your next export adopts with --expect-new, and a reviewed, deliberately ` +
|
|
270
|
+
`unmanaged file with --expect-unmanaged or --adjacent-ignore).`);
|
|
258
271
|
}
|
|
259
272
|
if (driftCtx.refusals.length > 0) {
|
|
260
273
|
progress.error('Re-export refused');
|
|
@@ -263,11 +276,11 @@ function throwRunLevelRefusals(adjacentCtx, driftCtx, progress) {
|
|
|
263
276
|
const unreadablePart = unreadable.length > 0
|
|
264
277
|
? ` ${unreadable.length} of these refused because the old patch body was missing or unreadable, so the drift comparison could not run (fail-closed).`
|
|
265
278
|
: '';
|
|
266
|
-
throw new GeneralError(`Refused ${driftCtx.refusals.length} patch(es) whose refreshed body would
|
|
267
|
-
`
|
|
279
|
+
throw new GeneralError(`Refused ${driftCtx.refusals.length} patch(es) whose refreshed body would add or drop ` +
|
|
280
|
+
`lines relative to the old patch body (--refuse-foreign-drift): ${names}.${unreadablePart}\n\n` +
|
|
268
281
|
'The flag cannot tell WHO wrote those lines, and the two populations have opposite ' +
|
|
269
282
|
'remedies:\n' +
|
|
270
|
-
' - Lines you
|
|
283
|
+
' - Lines you changed yourself since the last export (the per-file report tags these ' +
|
|
271
284
|
'"edited since your last export"): name them with --expect <path> so this run captures ' +
|
|
272
285
|
'them, or re-run without the flag to capture every drifting file.\n' +
|
|
273
286
|
" - Lines another session owns: do NOT proceed — commit or stash that session's work " +
|
|
@@ -305,9 +318,10 @@ function reportReExportOutcome(args) {
|
|
|
305
318
|
outro('Re-export complete');
|
|
306
319
|
}
|
|
307
320
|
if (reExported < selectedCount) {
|
|
308
|
-
const skippedCount = selectedCount - reExported - args.failedFilenames.length;
|
|
309
321
|
const failedPart = args.failedFilenames.length > 0 ? ` Failed: ${args.failedFilenames.join(', ')}.` : '';
|
|
310
|
-
const
|
|
322
|
+
const accounted = new Set([...args.reExportedFilenames, ...args.failedFilenames]);
|
|
323
|
+
const skipped = args.selectedFilenames.filter((name) => !accounted.has(name));
|
|
324
|
+
const skippedPart = skipped.length > 0 ? ` Skipped: ${skipped.join(', ')} (see warnings above).` : '';
|
|
311
325
|
throw new GeneralError(`${isDryRun ? '[dry-run] Would re-export' : 'Re-exported'} only ${reExported} of ` +
|
|
312
326
|
`${selectedCount} selected patch(es).${failedPart}${skippedPart} ` +
|
|
313
327
|
'Partial re-export exits non-zero so it cannot pass as success in scripts; ' +
|
|
@@ -19,12 +19,13 @@ import { discoverPatches } from '../../core/patch-files.js';
|
|
|
19
19
|
import { loadPatchesManifest } from '../../core/patch-manifest.js';
|
|
20
20
|
import { getPatchSourceVersion } from '../../core/patch-source-metadata.js';
|
|
21
21
|
import { replayQueueIndexOnly } from '../../core/rebase-dry-run.js';
|
|
22
|
+
import { formatPatchStampSpread, readCommittedFirefoxPin, resolveRebaseFromVersion, tallyPatchStamps, } from '../../core/rebase-from-version.js';
|
|
22
23
|
import { getRebaseSessionPath, readRebaseSession, saveRebaseSession, } from '../../core/rebase-session.js';
|
|
23
24
|
import { GeneralError } from '../../errors/base.js';
|
|
24
25
|
import { CorruptRebaseSessionError, RebaseDryRunRejectError, RebaseSessionExistsError, } from '../../errors/rebase.js';
|
|
25
26
|
import { info, intro, outro, spinner, warn } from '../../utils/logger.js';
|
|
26
27
|
import { addWaitLockOption, commanderArgParser, pickDefined, resolveWaitLockSeconds, } from '../../utils/options.js';
|
|
27
|
-
import {
|
|
28
|
+
import { parsePositiveIntegerFlag } from '../../utils/validation.js';
|
|
28
29
|
import { handleAbort } from './abort.js';
|
|
29
30
|
import { confirmDirtyEngineReset } from './confirm.js';
|
|
30
31
|
import { handleContinue } from './continue.js';
|
|
@@ -58,27 +59,26 @@ async function handleFreshStart(projectRoot, options) {
|
|
|
58
59
|
if (!manifest || manifest.patches.length === 0) {
|
|
59
60
|
throw new GeneralError('No patches found in manifest. Nothing to rebase.');
|
|
60
61
|
}
|
|
61
|
-
//
|
|
62
|
-
//
|
|
63
|
-
//
|
|
64
|
-
//
|
|
65
|
-
const
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
const fromVersion = sortedVersions[0] ?? currentVersion;
|
|
72
|
-
const fromProduct = manifest.patches.find((p) => getPatchSourceVersion(p) === fromVersion)?.sourceProduct ??
|
|
73
|
-
config.firefox.product;
|
|
74
|
-
if (versionCounts.size === 1 && fromVersion === currentVersion) {
|
|
62
|
+
// The queue can carry several stamps: patches re-exported since the last
|
|
63
|
+
// hop are stamped newer than untouched ones. "Nothing to rebase" is a fact
|
|
64
|
+
// about the stamps; the "from" label is the previous pin (the committed
|
|
65
|
+
// `firefox.version`), with the oldest stamp only as the fallback.
|
|
66
|
+
const spread = tallyPatchStamps(manifest.patches.map((p) => getPatchSourceVersion(p)));
|
|
67
|
+
const oldestStamp = spread.versions[0] ?? currentVersion;
|
|
68
|
+
const from = resolveRebaseFromVersion(currentVersion, await readCommittedFirefoxPin(projectRoot), spread, manifest.patches.find((p) => getPatchSourceVersion(p) === oldestStamp)?.sourceProduct);
|
|
69
|
+
const fromVersion = from.version;
|
|
70
|
+
const fromProduct = from.product ?? config.firefox.product;
|
|
71
|
+
if (spread.versions.length === 1 && oldestStamp === currentVersion) {
|
|
75
72
|
info('All patches already match the current Firefox version. Nothing to rebase.');
|
|
76
73
|
outro('Rebase not needed');
|
|
77
74
|
return;
|
|
78
75
|
}
|
|
79
76
|
info(`Rebasing patches: ${fromVersion} → ${currentVersion}`);
|
|
80
|
-
if (
|
|
81
|
-
info(
|
|
77
|
+
if (from.origin === 'patch-stamps') {
|
|
78
|
+
info('From-version is the oldest patch stamp: no committed fireforge.json pin precedes the target.');
|
|
79
|
+
}
|
|
80
|
+
if (from.origin === 'committed-pin' || spread.versions.length > 1) {
|
|
81
|
+
info(`Patch stamps: ${formatPatchStampSpread(spread)}`);
|
|
82
82
|
}
|
|
83
83
|
// The rebase replays onto whatever engine/ holds. The pin is the target,
|
|
84
84
|
// so an engine still on another version means the download step has not
|
package/dist/src/commands/run.js
CHANGED
|
@@ -9,7 +9,7 @@ import { warnIfFurnaceStale } from '../core/furnace-staleness.js';
|
|
|
9
9
|
import { hasBuildArtifacts, hasRunnableBundle, run, runMachSmoke } from '../core/mach.js';
|
|
10
10
|
import { assertBuildArtifacts } from '../core/mach-build-artifacts.js';
|
|
11
11
|
import { resolveRunProfile, sweepAbandonedRunProfiles, } from '../core/run-profile.js';
|
|
12
|
-
import { compileAllowlistFromFile, compileAllowlistFromStrings, findOverCapAllowlistEntries, matchAllowlist, matchesSmokeError, } from '../core/smoke-patterns.js';
|
|
12
|
+
import { compileAllowlistFromFile, compileAllowlistFromStrings, findOverCapAllowlistEntries, isBrowserConsoleLine, matchAllowlist, matchesSmokeError, } from '../core/smoke-patterns.js';
|
|
13
13
|
import { GeneralError, InvalidArgumentError } from '../errors/base.js';
|
|
14
14
|
import { BuildError } from '../errors/build.js';
|
|
15
15
|
import { ExitCode } from '../errors/codes.js';
|
|
@@ -105,6 +105,7 @@ export async function runCommand(projectRoot, options = {}) {
|
|
|
105
105
|
const profile = await resolveRunProfile({
|
|
106
106
|
profile: options.profile,
|
|
107
107
|
tempProfile: options.tempProfile,
|
|
108
|
+
purgeCaches: options.purgeCaches,
|
|
108
109
|
smoke: options.smokeExit !== undefined,
|
|
109
110
|
});
|
|
110
111
|
try {
|
|
@@ -188,6 +189,7 @@ async function runSmokeExit(engineDir, options, profile) {
|
|
|
188
189
|
warn(`--capture-console stream error: ${err.message}`);
|
|
189
190
|
});
|
|
190
191
|
const findings = [];
|
|
192
|
+
let browserConsoleLines = 0;
|
|
191
193
|
let allowlistedErrorHits = 0;
|
|
192
194
|
let allowlistedTotalHits = 0;
|
|
193
195
|
const allowlistHits = new Array(allowlist.length).fill(0);
|
|
@@ -197,6 +199,8 @@ async function runSmokeExit(engineDir, options, profile) {
|
|
|
197
199
|
// mirror preserves stdout/stderr separation for downstream piping.
|
|
198
200
|
const sink = stream === 'stdout' ? process.stdout : process.stderr;
|
|
199
201
|
sink.write(`${line}\n`);
|
|
202
|
+
if (isBrowserConsoleLine(line))
|
|
203
|
+
browserConsoleLines += 1;
|
|
200
204
|
// Count allowlist hits up-front, regardless of error-pattern match.
|
|
201
205
|
// Incrementing only when the line also matches an error pattern makes an
|
|
202
206
|
// allowlist regex that visibly matches `console.warn: RSLoader:` report 0
|
|
@@ -269,6 +273,15 @@ async function runSmokeExit(engineDir, options, profile) {
|
|
|
269
273
|
return;
|
|
270
274
|
}
|
|
271
275
|
if (result.exitCode === 0 || result.exitCode === 130 || result.exitCode === 143) {
|
|
276
|
+
// A clean status before the window with no browser output at all is a
|
|
277
|
+
// launch that never reached a window (a profile lock, a startup-crash
|
|
278
|
+
// streak's silent exit, a self-restart), not a clean run.
|
|
279
|
+
if (browserConsoleLines === 0) {
|
|
280
|
+
throw new SmokeRunError(`Browser exited with code ${result.exitCode} after ${(elapsedMs / 1000).toFixed(1)}s, ` +
|
|
281
|
+
'before the smoke-exit window elapsed, without any console output. A silent early ' +
|
|
282
|
+
'exit means the launch never reached a window: check the profile for a stale ' +
|
|
283
|
+
'.parentlock or a startup-crash streak (toolkit.startup.recent_crashes).', ExitCode.SMOKE_LAUNCH_FAILURE);
|
|
284
|
+
}
|
|
272
285
|
return;
|
|
273
286
|
}
|
|
274
287
|
throw new SmokeRunError(`Browser exited with code ${result.exitCode} before smoke-exit window elapsed.`, ExitCode.SMOKE_LAUNCH_FAILURE);
|
|
@@ -392,7 +405,8 @@ export function registerRun(program, { getProjectRoot, withErrorHandling }) {
|
|
|
392
405
|
.option('--console-allow-file <path>', 'Newline-delimited allowlist regex file. Blank lines and # comments are ignored. A "# max-hits: N" comment directly above an entry caps how many lines it may match in one run; more than that fails the run with exit 12.')
|
|
393
406
|
.option('--capture-console <file>', 'Mirror captured console output to <file> for post-exit inspection.')
|
|
394
407
|
.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.')
|
|
395
|
-
.option('--profile <path>', 'Launch with this profile directory (passed to Firefox as -profile). Left in place after the run. With --smoke-exit it replaces the default fresh profile.')
|
|
408
|
+
.option('--profile <path>', 'Launch with this profile directory (passed to Firefox as -profile). Left in place after the run. With --smoke-exit it replaces the default fresh profile. Firefox gets -purgecaches too, so the profile does not run chrome scripts an earlier build cached.')
|
|
409
|
+
.option('--no-purge-caches', 'With --profile, keep the profile startup cache (do not pass -purgecaches).')
|
|
396
410
|
.option('--temp-profile', 'Launch with a fresh temporary profile that is removed when the run ends. The default for --smoke-exit.')
|
|
397
411
|
.action(withErrorHandling(
|
|
398
412
|
// `args` is the variadic positional, not a Commander flag, so it
|
|
@@ -3,46 +3,85 @@
|
|
|
3
3
|
* a CI-enforceable non-zero exit: the default policy fails on any
|
|
4
4
|
* classification outside {patch-backed, branding, furnace}, and
|
|
5
5
|
* `--fail-on <class,...>` replaces that set for finer control.
|
|
6
|
+
* `--allow <class,...>` names classes that never fail, and
|
|
7
|
+
* `--fail-on-unknown` fails every present class that neither list names,
|
|
8
|
+
* so a gate keeps failing closed when FireForge adds a classification.
|
|
9
|
+
* `ownership-conflict` is a check class beside the file classifications:
|
|
10
|
+
* a path claimed by more than one patch, judged from the same rows as
|
|
11
|
+
* `--include-ownership`.
|
|
6
12
|
*
|
|
7
13
|
* Helper module consumed by status.ts, which sits at the max-lines budget.
|
|
8
14
|
* No top-level registrar is exported and none is wanted.
|
|
9
15
|
*/
|
|
10
16
|
import type { ClassifiedFile, FileClassification } from '../core/status-classify.js';
|
|
17
|
+
/**
|
|
18
|
+
* A class `--fail-on`/`--allow` can name: every file classification, plus
|
|
19
|
+
* `ownership-conflict`, which is judged from the ownership rows rather
|
|
20
|
+
* than from a file's classification.
|
|
21
|
+
*/
|
|
22
|
+
export type StatusCheckClass = FileClassification | 'ownership-conflict';
|
|
11
23
|
/** Resolved `--check`/`--fail-on` policy for one status invocation. */
|
|
12
24
|
export interface StatusCheckPolicy {
|
|
13
25
|
checkEnabled: boolean;
|
|
14
|
-
|
|
26
|
+
/** Classes that fail: `--fail-on` (or the default set) minus `--allow`. */
|
|
27
|
+
failOn: readonly StatusCheckClass[];
|
|
28
|
+
/** `--allow`: classes that never fail. Set only when the flag was given. */
|
|
29
|
+
allow?: readonly StatusCheckClass[];
|
|
30
|
+
/** `--fail-on-unknown`: a present class named by neither list fails. */
|
|
31
|
+
failOnUnknown?: boolean;
|
|
15
32
|
}
|
|
16
33
|
/**
|
|
17
|
-
* Resolves the enforcement policy from the raw flags
|
|
18
|
-
* `--
|
|
19
|
-
*
|
|
34
|
+
* Resolves the enforcement policy from the raw flags. `--fail-on`,
|
|
35
|
+
* `--allow` and `--fail-on-unknown` each imply `--check`. `--fail-on`
|
|
36
|
+
* replaces the default set and `--allow` subtracts from it (naming one
|
|
37
|
+
* class in both is refused). `--fail-on-unknown` needs `--allow`: without
|
|
38
|
+
* an allow list every class the caller did not name, `patch-backed`
|
|
39
|
+
* included, would fail. All of them are refused alongside the modes that
|
|
40
|
+
* skip (or elide) classification.
|
|
20
41
|
*/
|
|
21
42
|
export declare function resolveStatusCheckPolicy(options: {
|
|
22
43
|
check?: boolean;
|
|
23
44
|
failOn?: string;
|
|
45
|
+
allow?: string;
|
|
46
|
+
failOnUnknown?: boolean;
|
|
24
47
|
raw?: boolean;
|
|
25
48
|
unmanaged?: boolean;
|
|
26
49
|
ownership?: boolean;
|
|
27
50
|
testCoverage?: boolean;
|
|
28
51
|
}): StatusCheckPolicy;
|
|
29
|
-
/**
|
|
52
|
+
/**
|
|
53
|
+
* True when the policy can fail on `ownership-conflict`, so the caller has
|
|
54
|
+
* to build the ownership rows even without `--include-ownership`.
|
|
55
|
+
*/
|
|
56
|
+
export declare function policyNeedsOwnership(policy: StatusCheckPolicy): boolean;
|
|
57
|
+
/** One failing class with a non-empty file list. */
|
|
30
58
|
export interface StatusCheckOffender {
|
|
31
|
-
classification:
|
|
59
|
+
classification: StatusCheckClass;
|
|
32
60
|
count: number;
|
|
33
61
|
files: string[];
|
|
62
|
+
/**
|
|
63
|
+
* Set when the class failed only through `--fail-on-unknown`: neither
|
|
64
|
+
* `--fail-on` nor `--allow` named it.
|
|
65
|
+
*/
|
|
66
|
+
unnamed?: true;
|
|
34
67
|
}
|
|
35
68
|
/**
|
|
36
|
-
* Collects the
|
|
37
|
-
*
|
|
38
|
-
*
|
|
39
|
-
*
|
|
69
|
+
* Collects the failing classes that have offending files, with full file
|
|
70
|
+
* lists: the fail set in policy order, then (under `--fail-on-unknown`)
|
|
71
|
+
* every other present class neither list names, in first-seen order.
|
|
72
|
+
* Shared by the human `--check` verdict and the JSON `check` block so the
|
|
73
|
+
* two views can never disagree about what failed.
|
|
74
|
+
*
|
|
75
|
+
* @param classified - Classified worktree entries
|
|
76
|
+
* @param policy - Resolved policy
|
|
77
|
+
* @param ownershipConflicts - Paths claimed by more than one patch. Only
|
|
78
|
+
* read for the `ownership-conflict` class
|
|
40
79
|
*/
|
|
41
|
-
export declare function collectStatusCheckOffenders(classified: readonly ClassifiedFile[], policy: StatusCheckPolicy): StatusCheckOffender[];
|
|
80
|
+
export declare function collectStatusCheckOffenders(classified: readonly ClassifiedFile[], policy: StatusCheckPolicy, ownershipConflicts?: readonly string[]): StatusCheckOffender[];
|
|
42
81
|
/**
|
|
43
|
-
* Throws a GeneralError (exit 1) when the policy is enabled and any
|
|
44
|
-
*
|
|
45
|
-
*
|
|
46
|
-
*
|
|
82
|
+
* Throws a GeneralError (exit 1) when the policy is enabled and any
|
|
83
|
+
* failing class is non-empty, naming each offending class with its first
|
|
84
|
+
* few files. A disabled policy or a fully tool-covered tree passes
|
|
85
|
+
* silently.
|
|
47
86
|
*/
|
|
48
|
-
export declare function runStatusCheck(classified: readonly ClassifiedFile[], policy: StatusCheckPolicy): void;
|
|
87
|
+
export declare function runStatusCheck(classified: readonly ClassifiedFile[], policy: StatusCheckPolicy, ownershipConflicts?: readonly string[]): void;
|