@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
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `fireforge test --build --furnace-apply reached`: deploy only the Furnace
|
|
3
|
+
* components a requested test reaches.
|
|
4
|
+
*
|
|
5
|
+
* The pre-test build's Furnace apply runs over the whole `components/`
|
|
6
|
+
* tree, so on a shared engine a peer's `test --build` deployed every
|
|
7
|
+
* session's undeployed component edits into the shared objdir, including
|
|
8
|
+
* edits another session was holding back for a before-capture. `reached`
|
|
9
|
+
* keeps the apply to the components the run can observe and names the rest.
|
|
10
|
+
*
|
|
11
|
+
* "Reaches" is textual, and errs towards applying: a component is reached
|
|
12
|
+
* when a requested test file, a `head*.js` beside it, or any test file
|
|
13
|
+
* under a requested directory names the component's tag, or when the test
|
|
14
|
+
* path itself names it. A component no test names cannot change what the
|
|
15
|
+
* run observes through its own code, so leaving its undeployed edit out
|
|
16
|
+
* keeps the run honest about what it packaged.
|
|
17
|
+
*/
|
|
18
|
+
import type { TestOptions } from '../types/commands/index.js';
|
|
19
|
+
import type { FireForgeConfig } from '../types/config.js';
|
|
20
|
+
/** The effective Furnace apply mode for a pre-test build. */
|
|
21
|
+
export type FurnaceApplyMode = 'all' | 'reached' | 'none';
|
|
22
|
+
/**
|
|
23
|
+
* Resolves the mode from the flag and `test.furnaceApply`. `false`
|
|
24
|
+
* (`--no-furnace-apply`) is `none`.
|
|
25
|
+
*/
|
|
26
|
+
export declare function resolveFurnaceApplyMode(options: TestOptions, config: FireForgeConfig): FurnaceApplyMode;
|
|
27
|
+
/**
|
|
28
|
+
* The stale components a request reaches, and the stale ones it does not.
|
|
29
|
+
*
|
|
30
|
+
* @param projectRoot - Project root
|
|
31
|
+
* @param engineDir - Absolute engine directory
|
|
32
|
+
* @param testPaths - Engine-relative requested paths
|
|
33
|
+
*/
|
|
34
|
+
export declare function partitionReachedComponents(projectRoot: string, engineDir: string, testPaths: readonly string[]): Promise<{
|
|
35
|
+
reached: string[];
|
|
36
|
+
skipped: string[];
|
|
37
|
+
}>;
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
// SPDX-License-Identifier: EUPL-1.2
|
|
2
|
+
/**
|
|
3
|
+
* `fireforge test --build --furnace-apply reached`: deploy only the Furnace
|
|
4
|
+
* components a requested test reaches.
|
|
5
|
+
*
|
|
6
|
+
* The pre-test build's Furnace apply runs over the whole `components/`
|
|
7
|
+
* tree, so on a shared engine a peer's `test --build` deployed every
|
|
8
|
+
* session's undeployed component edits into the shared objdir, including
|
|
9
|
+
* edits another session was holding back for a before-capture. `reached`
|
|
10
|
+
* keeps the apply to the components the run can observe and names the rest.
|
|
11
|
+
*
|
|
12
|
+
* "Reaches" is textual, and errs towards applying: a component is reached
|
|
13
|
+
* when a requested test file, a `head*.js` beside it, or any test file
|
|
14
|
+
* under a requested directory names the component's tag, or when the test
|
|
15
|
+
* path itself names it. A component no test names cannot change what the
|
|
16
|
+
* run observes through its own code, so leaving its undeployed edit out
|
|
17
|
+
* keeps the run honest about what it packaged.
|
|
18
|
+
*/
|
|
19
|
+
import { readdir, readFile, stat } from 'node:fs/promises';
|
|
20
|
+
import { basename, dirname, join } from 'node:path';
|
|
21
|
+
import { listStaleFurnaceComponents } from '../core/furnace-staleness.js';
|
|
22
|
+
import { toError } from '../utils/errors.js';
|
|
23
|
+
import { verbose } from '../utils/logger.js';
|
|
24
|
+
/** Files read per run, so a huge directory request cannot stall the build. */
|
|
25
|
+
const MAX_SCANNED_FILES = 4000;
|
|
26
|
+
const SCANNED_EXTENSIONS = /\.(?:m?js|html|xhtml|toml|ini)$/;
|
|
27
|
+
/**
|
|
28
|
+
* Resolves the mode from the flag and `test.furnaceApply`. `false`
|
|
29
|
+
* (`--no-furnace-apply`) is `none`.
|
|
30
|
+
*/
|
|
31
|
+
export function resolveFurnaceApplyMode(options, config) {
|
|
32
|
+
if (options.furnaceApply === false)
|
|
33
|
+
return 'none';
|
|
34
|
+
if (typeof options.furnaceApply === 'string')
|
|
35
|
+
return options.furnaceApply;
|
|
36
|
+
return config.test?.furnaceApply ?? 'all';
|
|
37
|
+
}
|
|
38
|
+
async function collectFiles(path, out) {
|
|
39
|
+
if (out.length >= MAX_SCANNED_FILES)
|
|
40
|
+
return;
|
|
41
|
+
let info;
|
|
42
|
+
try {
|
|
43
|
+
info = await stat(path);
|
|
44
|
+
}
|
|
45
|
+
catch {
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
if (info.isFile()) {
|
|
49
|
+
if (SCANNED_EXTENSIONS.test(path))
|
|
50
|
+
out.push(path);
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
if (!info.isDirectory())
|
|
54
|
+
return;
|
|
55
|
+
let entries;
|
|
56
|
+
try {
|
|
57
|
+
entries = await readdir(path);
|
|
58
|
+
}
|
|
59
|
+
catch {
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
for (const entry of entries.sort()) {
|
|
63
|
+
if (out.length >= MAX_SCANNED_FILES)
|
|
64
|
+
return;
|
|
65
|
+
await collectFiles(join(path, entry), out);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
/** The files whose text decides reach: the request plus `head*.js` beside each file. */
|
|
69
|
+
async function reachFiles(engineDir, testPaths) {
|
|
70
|
+
const files = [];
|
|
71
|
+
for (const path of testPaths) {
|
|
72
|
+
const absolute = join(engineDir, path);
|
|
73
|
+
await collectFiles(absolute, files);
|
|
74
|
+
try {
|
|
75
|
+
if ((await stat(absolute)).isFile()) {
|
|
76
|
+
const dir = dirname(absolute);
|
|
77
|
+
for (const entry of await readdir(dir)) {
|
|
78
|
+
if (/^head.*\.js$/.test(entry))
|
|
79
|
+
files.push(join(dir, entry));
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
catch {
|
|
84
|
+
// A missing path is refused later by the path-existence check.
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
return [...new Set(files)];
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* The stale components a request reaches, and the stale ones it does not.
|
|
91
|
+
*
|
|
92
|
+
* @param projectRoot - Project root
|
|
93
|
+
* @param engineDir - Absolute engine directory
|
|
94
|
+
* @param testPaths - Engine-relative requested paths
|
|
95
|
+
*/
|
|
96
|
+
export async function partitionReachedComponents(projectRoot, engineDir, testPaths) {
|
|
97
|
+
let stale;
|
|
98
|
+
try {
|
|
99
|
+
stale = await listStaleFurnaceComponents(projectRoot);
|
|
100
|
+
}
|
|
101
|
+
catch (error) {
|
|
102
|
+
verbose(`Furnace pending-edit probe failed: ${toError(error).message}`);
|
|
103
|
+
return { reached: [], skipped: [] };
|
|
104
|
+
}
|
|
105
|
+
if (stale.length === 0)
|
|
106
|
+
return { reached: [], skipped: [] };
|
|
107
|
+
const names = new Set();
|
|
108
|
+
for (const path of testPaths) {
|
|
109
|
+
for (const name of stale)
|
|
110
|
+
if (path.includes(name))
|
|
111
|
+
names.add(name);
|
|
112
|
+
}
|
|
113
|
+
for (const file of await reachFiles(engineDir, testPaths)) {
|
|
114
|
+
if (names.size === stale.length)
|
|
115
|
+
break;
|
|
116
|
+
let text;
|
|
117
|
+
try {
|
|
118
|
+
text = await readFile(file, 'utf8');
|
|
119
|
+
}
|
|
120
|
+
catch {
|
|
121
|
+
continue;
|
|
122
|
+
}
|
|
123
|
+
for (const name of stale) {
|
|
124
|
+
if (text.includes(name) || basename(file).includes(name))
|
|
125
|
+
names.add(name);
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
return {
|
|
129
|
+
reached: stale.filter((name) => names.has(name)),
|
|
130
|
+
skipped: stale.filter((name) => !names.has(name)),
|
|
131
|
+
};
|
|
132
|
+
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { TestOptions } from '../types/commands/index.js';
|
|
2
2
|
import type { FireForgeConfig } from '../types/config.js';
|
|
3
|
-
import type { TestRunOutcome } from './test-run.js';
|
|
3
|
+
import type { TestRunOutcome, TestSuite } from './test-run.js';
|
|
4
4
|
/** Rejects pathless `fireforge test` unless the operator selected a pathless mode. */
|
|
5
5
|
export declare function assertPathlessTestMode(testPaths: readonly string[], options: TestOptions): void;
|
|
6
6
|
/** Rejects invalid combinations for mode-like `fireforge test` options. */
|
|
@@ -16,6 +16,8 @@ export interface HarnessClassification {
|
|
|
16
16
|
xpcshell: string[];
|
|
17
17
|
nonXpcshell: string[];
|
|
18
18
|
}
|
|
19
|
+
/** Buckets normalized request paths by the harness their nearest manifest selects. */
|
|
20
|
+
export declare function classifyTestHarnesses(engineDir: string, normalizedPaths: readonly string[]): Promise<HarnessClassification>;
|
|
19
21
|
/**
|
|
20
22
|
* Harness classification is a pure path→manifest lookup and must precede
|
|
21
23
|
* the build dispatch: a mixed xpcshell+mochitest request can never
|
|
@@ -40,3 +42,16 @@ export declare function classifyBeforeDispatch(engineDir: string, normalizedPath
|
|
|
40
42
|
* run build-less without tripping the stale/coverage gate.
|
|
41
43
|
*/
|
|
42
44
|
export declare function reportBuildOnlyCompletion(classification: HarnessClassification, normalizedPaths: readonly string[]): void;
|
|
45
|
+
/**
|
|
46
|
+
* The mach args `--restart-between-tests` forwards: mochitest's own flag,
|
|
47
|
+
* which restarts the browser between test files (the run shape a
|
|
48
|
+
* `standalone` manifest key asks for). Mochitest-only, refused otherwise
|
|
49
|
+
* for the reason `--shuffle` is: xpcshell has no such flag and generic
|
|
50
|
+
* `mach test` would hand it to every suite. Not duplicated when
|
|
51
|
+
* `--mach-arg` already forwards it.
|
|
52
|
+
*
|
|
53
|
+
* @param options - Parsed test options
|
|
54
|
+
* @param suite - The resolved dispatch target
|
|
55
|
+
* @param forwardedMachArgs - `--mach-arg` values after filtering
|
|
56
|
+
*/
|
|
57
|
+
export declare function restartBetweenTestsArgs(options: TestOptions, suite: TestSuite, forwardedMachArgs: readonly string[]): string[];
|
|
@@ -72,7 +72,8 @@ function buildPathlessTestMessage() {
|
|
|
72
72
|
' - `fireforge test --doctor` to run the Marionette preflight only\n' +
|
|
73
73
|
' - `fireforge test --canary` to run the configured short harness canary');
|
|
74
74
|
}
|
|
75
|
-
|
|
75
|
+
/** Buckets normalized request paths by the harness their nearest manifest selects. */
|
|
76
|
+
export async function classifyTestHarnesses(engineDir, normalizedPaths) {
|
|
76
77
|
const result = { xpcshell: [], nonXpcshell: [] };
|
|
77
78
|
for (const testPath of normalizedPaths) {
|
|
78
79
|
const manifest = await findNearestXpcshellManifest(engineDir, testPath);
|
|
@@ -133,3 +134,25 @@ export function reportBuildOnlyCompletion(classification, normalizedPaths) {
|
|
|
133
134
|
info(`Run: fireforge test ${normalizedPaths.join(' ')}`);
|
|
134
135
|
}
|
|
135
136
|
}
|
|
137
|
+
/**
|
|
138
|
+
* The mach args `--restart-between-tests` forwards: mochitest's own flag,
|
|
139
|
+
* which restarts the browser between test files (the run shape a
|
|
140
|
+
* `standalone` manifest key asks for). Mochitest-only, refused otherwise
|
|
141
|
+
* for the reason `--shuffle` is: xpcshell has no such flag and generic
|
|
142
|
+
* `mach test` would hand it to every suite. Not duplicated when
|
|
143
|
+
* `--mach-arg` already forwards it.
|
|
144
|
+
*
|
|
145
|
+
* @param options - Parsed test options
|
|
146
|
+
* @param suite - The resolved dispatch target
|
|
147
|
+
* @param forwardedMachArgs - `--mach-arg` values after filtering
|
|
148
|
+
*/
|
|
149
|
+
export function restartBetweenTestsArgs(options, suite, forwardedMachArgs) {
|
|
150
|
+
if (options.restartBetweenTests !== true)
|
|
151
|
+
return [];
|
|
152
|
+
if (suite !== 'mochitest') {
|
|
153
|
+
throw new GeneralError("--restart-between-tests forwards the mochitest harness's per-file browser restart; the " +
|
|
154
|
+
'xpcshell harness has none, and generic `mach test` dispatch would hand it to every ' +
|
|
155
|
+
'suite. Narrow the paths to browser-chrome/mochitest files (and drop --generic-mach-test).');
|
|
156
|
+
}
|
|
157
|
+
return forwardedMachArgs.includes('--restart-between-tests') ? [] : ['--restart-between-tests'];
|
|
158
|
+
}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Per-run lines and the aggregate verdict of a multi-run `fireforge test`
|
|
3
|
+
* (`--repeat`, mixed harnesses, `--negative-control`). Pure: the
|
|
4
|
+
* orchestration in `test-orchestrate.ts` feeds it the verdict line each
|
|
5
|
+
* sub-run would have printed, captured instead of written.
|
|
6
|
+
*/
|
|
7
|
+
/** One finished sub-run. */
|
|
8
|
+
export interface SubRunResult {
|
|
9
|
+
/** 1-based repetition this run belongs to. */
|
|
10
|
+
repetition: number;
|
|
11
|
+
/** The harness half of a mixed invocation. */
|
|
12
|
+
harness?: 'xpcshell' | 'mochitest';
|
|
13
|
+
/** The captured verdict, without the `FIREFORGE-VERDICT: ` prefix. */
|
|
14
|
+
body: string;
|
|
15
|
+
passed: boolean;
|
|
16
|
+
/** `reason=` of a failed run. */
|
|
17
|
+
reason?: string;
|
|
18
|
+
/** `note=` of a failed run, when it carried one. */
|
|
19
|
+
note?: string;
|
|
20
|
+
/** What the sub-run threw, if anything. */
|
|
21
|
+
error?: unknown;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* How a negative control came out: `caught` when every repetition went red
|
|
25
|
+
* on test failures, `missed` when a repetition stayed green (the tests did
|
|
26
|
+
* not detect the mutation), `inconclusive` when any run failed for another
|
|
27
|
+
* reason or the invocation stopped early.
|
|
28
|
+
*/
|
|
29
|
+
export type ControlOutcome = 'caught' | 'missed' | 'inconclusive';
|
|
30
|
+
/**
|
|
31
|
+
* Parses a captured verdict line into a sub-run result.
|
|
32
|
+
*
|
|
33
|
+
* @param line - The captured line, or undefined when the sub-run wrote none
|
|
34
|
+
*/
|
|
35
|
+
export declare function parseCapturedVerdict(line: string | undefined): Pick<SubRunResult, 'body' | 'passed' | 'reason' | 'note'>;
|
|
36
|
+
/**
|
|
37
|
+
* The `FIREFORGE-RUN:` line for one sub-run: the verdict it would have
|
|
38
|
+
* printed alone, plus `run=<i>/<n>` and, for a mixed invocation,
|
|
39
|
+
* `harness=`. Never `FIREFORGE-VERDICT:`, so the invocation keeps exactly
|
|
40
|
+
* one verdict line.
|
|
41
|
+
*/
|
|
42
|
+
export declare function formatRunLine(result: SubRunResult, index: number, total: number): string;
|
|
43
|
+
/** The failed run with the most structural reason, or undefined when all passed. */
|
|
44
|
+
export declare function worstRun(results: readonly SubRunResult[]): SubRunResult | undefined;
|
|
45
|
+
/**
|
|
46
|
+
* Derives a negative control's outcome.
|
|
47
|
+
*
|
|
48
|
+
* @param results - Every finished sub-run
|
|
49
|
+
* @param repetitions - How many repetitions were planned
|
|
50
|
+
* @param complete - False when the invocation stopped before its last run
|
|
51
|
+
*/
|
|
52
|
+
export declare function deriveControlOutcome(results: readonly SubRunResult[], repetitions: number, complete: boolean): ControlOutcome;
|
|
53
|
+
/**
|
|
54
|
+
* The aggregate verdict body. A single planned run (a lone control) keeps
|
|
55
|
+
* its own line, counts included; several aggregate to `PASS runs=<n>/<n>`
|
|
56
|
+
* or `FAIL reason=<most structural> [note=] runs=<passed>/<planned>`.
|
|
57
|
+
* A control appends `control=<outcome>`.
|
|
58
|
+
*/
|
|
59
|
+
export declare function formatAggregateBody(results: readonly SubRunResult[], plannedTotal: number, control?: ControlOutcome): string;
|
|
60
|
+
/** One-line human summary of a control's outcome. */
|
|
61
|
+
export declare function describeControlOutcome(outcome: ControlOutcome): string;
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
// SPDX-License-Identifier: EUPL-1.2
|
|
2
|
+
/**
|
|
3
|
+
* Per-run lines and the aggregate verdict of a multi-run `fireforge test`
|
|
4
|
+
* (`--repeat`, mixed harnesses, `--negative-control`). Pure: the
|
|
5
|
+
* orchestration in `test-orchestrate.ts` feeds it the verdict line each
|
|
6
|
+
* sub-run would have printed, captured instead of written.
|
|
7
|
+
*/
|
|
8
|
+
/** The prefix every verdict line starts with. */
|
|
9
|
+
const VERDICT_PREFIX = 'FIREFORGE-VERDICT: ';
|
|
10
|
+
/**
|
|
11
|
+
* Parses a captured verdict line into a sub-run result.
|
|
12
|
+
*
|
|
13
|
+
* @param line - The captured line, or undefined when the sub-run wrote none
|
|
14
|
+
*/
|
|
15
|
+
export function parseCapturedVerdict(line) {
|
|
16
|
+
const body = (line ?? `${VERDICT_PREFIX}FAIL reason=preflight`).slice(VERDICT_PREFIX.length);
|
|
17
|
+
const passed = body.startsWith('PASS');
|
|
18
|
+
const reason = /(?:^| )reason=(\S+)/.exec(body)?.[1];
|
|
19
|
+
const note = /(?:^| )note=(\S+)/.exec(body)?.[1];
|
|
20
|
+
return {
|
|
21
|
+
body,
|
|
22
|
+
passed,
|
|
23
|
+
...(reason === undefined ? {} : { reason }),
|
|
24
|
+
...(note === undefined ? {} : { note }),
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* The `FIREFORGE-RUN:` line for one sub-run: the verdict it would have
|
|
29
|
+
* printed alone, plus `run=<i>/<n>` and, for a mixed invocation,
|
|
30
|
+
* `harness=`. Never `FIREFORGE-VERDICT:`, so the invocation keeps exactly
|
|
31
|
+
* one verdict line.
|
|
32
|
+
*/
|
|
33
|
+
export function formatRunLine(result, index, total) {
|
|
34
|
+
const harness = result.harness === undefined ? '' : ` harness=${result.harness}`;
|
|
35
|
+
return `FIREFORGE-RUN: ${result.body} run=${index + 1}/${total}${harness}`;
|
|
36
|
+
}
|
|
37
|
+
/** Most structural first: the reason an aggregate failure reports. */
|
|
38
|
+
const REASON_RANK = [
|
|
39
|
+
'inconclusive',
|
|
40
|
+
'preflight',
|
|
41
|
+
'crash',
|
|
42
|
+
'harness-arguments',
|
|
43
|
+
'no-tests',
|
|
44
|
+
'test-failures',
|
|
45
|
+
];
|
|
46
|
+
function rankOf(reason) {
|
|
47
|
+
const rank = REASON_RANK.indexOf(reason ?? '');
|
|
48
|
+
return rank === -1 ? REASON_RANK.length : rank;
|
|
49
|
+
}
|
|
50
|
+
/** The failed run with the most structural reason, or undefined when all passed. */
|
|
51
|
+
export function worstRun(results) {
|
|
52
|
+
let worst;
|
|
53
|
+
for (const result of results) {
|
|
54
|
+
if (result.passed)
|
|
55
|
+
continue;
|
|
56
|
+
if (worst === undefined || rankOf(result.reason) < rankOf(worst.reason))
|
|
57
|
+
worst = result;
|
|
58
|
+
}
|
|
59
|
+
return worst;
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Derives a negative control's outcome.
|
|
63
|
+
*
|
|
64
|
+
* @param results - Every finished sub-run
|
|
65
|
+
* @param repetitions - How many repetitions were planned
|
|
66
|
+
* @param complete - False when the invocation stopped before its last run
|
|
67
|
+
*/
|
|
68
|
+
export function deriveControlOutcome(results, repetitions, complete) {
|
|
69
|
+
if (!complete)
|
|
70
|
+
return 'inconclusive';
|
|
71
|
+
if (results.some((result) => !result.passed && result.reason !== 'test-failures')) {
|
|
72
|
+
return 'inconclusive';
|
|
73
|
+
}
|
|
74
|
+
for (let repetition = 1; repetition <= repetitions; repetition += 1) {
|
|
75
|
+
const red = results.some((result) => result.repetition === repetition && result.reason === 'test-failures');
|
|
76
|
+
if (!red)
|
|
77
|
+
return 'missed';
|
|
78
|
+
}
|
|
79
|
+
return 'caught';
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* The aggregate verdict body. A single planned run (a lone control) keeps
|
|
83
|
+
* its own line, counts included; several aggregate to `PASS runs=<n>/<n>`
|
|
84
|
+
* or `FAIL reason=<most structural> [note=] runs=<passed>/<planned>`.
|
|
85
|
+
* A control appends `control=<outcome>`.
|
|
86
|
+
*/
|
|
87
|
+
export function formatAggregateBody(results, plannedTotal, control) {
|
|
88
|
+
const controlKey = control === undefined ? '' : ` control=${control}`;
|
|
89
|
+
const only = results[0];
|
|
90
|
+
if (plannedTotal === 1 && only !== undefined)
|
|
91
|
+
return `${only.body}${controlKey}`;
|
|
92
|
+
const passed = results.filter((result) => result.passed).length;
|
|
93
|
+
const runs = ` runs=${passed}/${plannedTotal}`;
|
|
94
|
+
const worst = worstRun(results);
|
|
95
|
+
if (worst === undefined && results.length === plannedTotal)
|
|
96
|
+
return `PASS${runs}${controlKey}`;
|
|
97
|
+
const reason = worst?.reason ?? 'preflight';
|
|
98
|
+
const note = worst?.note === undefined ? '' : ` note=${worst.note}`;
|
|
99
|
+
return `FAIL reason=${reason}${note}${runs}${controlKey}`;
|
|
100
|
+
}
|
|
101
|
+
/** One-line human summary of a control's outcome. */
|
|
102
|
+
export function describeControlOutcome(outcome) {
|
|
103
|
+
switch (outcome) {
|
|
104
|
+
case 'caught':
|
|
105
|
+
return 'Negative control: the tests went red on the mutation, as a control should (control=caught).';
|
|
106
|
+
case 'missed':
|
|
107
|
+
return 'Negative control: the tests STAYED GREEN with the mutation applied, so they do not detect it (control=missed).';
|
|
108
|
+
case 'inconclusive':
|
|
109
|
+
return 'Negative control: inconclusive, a run failed for a reason other than test failures or did not run (control=inconclusive).';
|
|
110
|
+
}
|
|
111
|
+
}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Multi-run orchestration for `fireforge test`, all under the one
|
|
3
|
+
* engine-session lock hold the command already has:
|
|
4
|
+
*
|
|
5
|
+
* - mixed harness paths run as two consecutive mach invocations, xpcshell
|
|
6
|
+
* first, with one pre-test build (when `--build`) packaging both halves;
|
|
7
|
+
* - `--repeat <n>` runs the same selection n times, building once;
|
|
8
|
+
* - `--negative-control <diff>` applies a reviewed mutation after the
|
|
9
|
+
* build and right before each dispatch, and restores it after the run.
|
|
10
|
+
*
|
|
11
|
+
* Each sub-run is the ordinary single-run body. Its verdict line is
|
|
12
|
+
* captured rather than printed (see `setVerdictCapture`) and echoed as a
|
|
13
|
+
* `FIREFORGE-RUN:` line, and the invocation ends with one aggregate
|
|
14
|
+
* `FIREFORGE-VERDICT:` line. A request that needs none of this runs the
|
|
15
|
+
* body exactly as before.
|
|
16
|
+
*/
|
|
17
|
+
import type { TestOptions } from '../types/commands/index.js';
|
|
18
|
+
/** What the orchestrator asks of one sub-run beyond its paths and options. */
|
|
19
|
+
export interface TestRunHooks {
|
|
20
|
+
/**
|
|
21
|
+
* Paths the pre-test build packages and records as coverage when they
|
|
22
|
+
* are wider than this run's own: the union of a mixed invocation's
|
|
23
|
+
* halves, so the second half runs build-less against the same build.
|
|
24
|
+
*/
|
|
25
|
+
coveragePaths?: string[];
|
|
26
|
+
/** Runs after every preflight gate and the pre-test build, right before dispatch. */
|
|
27
|
+
beforeDispatch?: () => Promise<void>;
|
|
28
|
+
/**
|
|
29
|
+
* Runs right before the pre-test build: a negative control on compiled
|
|
30
|
+
* source, which only reaches the binary when the build compiles it.
|
|
31
|
+
*/
|
|
32
|
+
beforeBuild?: () => Promise<void>;
|
|
33
|
+
/** `--repeat` run this sub-run is (1-based), for `--results`. */
|
|
34
|
+
repetition?: number;
|
|
35
|
+
/** Where dispatches write their mozlog raw logs (`--results`, `--shard-size`). */
|
|
36
|
+
rawLogDir?: string;
|
|
37
|
+
}
|
|
38
|
+
/** The single-run body (`runTestCommandBody`), injected to avoid an import cycle. */
|
|
39
|
+
export type TestRunBody = (paths: string[], options: TestOptions, hooks: TestRunHooks) => Promise<void>;
|
|
40
|
+
/**
|
|
41
|
+
* Runs `fireforge test` as one or several sub-runs. Always recovers a
|
|
42
|
+
* negative control a killed earlier run left applied, first.
|
|
43
|
+
*
|
|
44
|
+
* @param projectRoot - Project root
|
|
45
|
+
* @param testPaths - The positional test paths
|
|
46
|
+
* @param options - Parsed test options
|
|
47
|
+
* @param body - The single-run body
|
|
48
|
+
* @param onRefusal - Renders a sub-run's preflight refusal and emits its
|
|
49
|
+
* `FAIL reason=preflight` verdict (captured), as `testCommand` does for a
|
|
50
|
+
* single run
|
|
51
|
+
*/
|
|
52
|
+
export declare function orchestrateTestRuns(projectRoot: string, testPaths: string[], options: TestOptions, body: TestRunBody, onRefusal: (error: unknown) => void): Promise<void>;
|