@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,399 @@
|
|
|
1
|
+
// SPDX-License-Identifier: EUPL-1.2
|
|
2
|
+
/**
|
|
3
|
+
* `fireforge test --negative-control <diff>`: apply a reviewed mutation to
|
|
4
|
+
* engine sources for exactly one harness dispatch, then put every byte back.
|
|
5
|
+
*
|
|
6
|
+
* Safety model (also stated in docs/testing.md):
|
|
7
|
+
*
|
|
8
|
+
* - The control is applied and restored only while the caller holds the
|
|
9
|
+
* engine-session lock, after the pre-test build has packaged and before
|
|
10
|
+
* the harness spawns, so no peer build or test can observe it and a
|
|
11
|
+
* Furnace deploy cannot overwrite it.
|
|
12
|
+
* - Before the first mutated byte is written, the original bytes of every
|
|
13
|
+
* target go to `.fireforge/negative-control/` together with a journal
|
|
14
|
+
* recording each file's original and mutated SHA-256, mode and
|
|
15
|
+
* timestamps. A killed FireForge therefore leaves enough on disk to undo
|
|
16
|
+
* the control, and the next `fireforge test` does so before anything else.
|
|
17
|
+
* - Restore writes the original bytes back atomically, re-applies the
|
|
18
|
+
* original mode and timestamps, and reads the file back to prove the
|
|
19
|
+
* bytes match. It only overwrites a file that still holds exactly the
|
|
20
|
+
* bytes the control wrote: anything else means someone edited the file
|
|
21
|
+
* while the control ran, and that edit is kept, never clobbered, with the
|
|
22
|
+
* original left in the journal directory and the conflict reported.
|
|
23
|
+
* - A SIGINT or SIGTERM restores through {@link restoreActiveNegativeControlsForSignal},
|
|
24
|
+
* which the entry point runs after the harness has shut down and before
|
|
25
|
+
* it releases the held locks.
|
|
26
|
+
*/
|
|
27
|
+
import { lstat, mkdir, readFile, rm, utimes } from 'node:fs/promises';
|
|
28
|
+
import { isAbsolute, join, posix, relative, resolve } from 'node:path';
|
|
29
|
+
import { GeneralError, PreflightRefusalError } from '../errors/base.js';
|
|
30
|
+
import { getNodeErrorCode, toError } from '../utils/errors.js';
|
|
31
|
+
import { writeFileAtomic } from '../utils/fs.js';
|
|
32
|
+
import { sha256Hex } from '../utils/hash.js';
|
|
33
|
+
import { notice } from '../utils/logger.js';
|
|
34
|
+
import { isContainedRelativePath, isPathInsideRoot, normalizePathSlashes, stripEnginePrefix, } from '../utils/paths.js';
|
|
35
|
+
import { loadFurnaceConfig } from './furnace-config.js';
|
|
36
|
+
import { findCompiledControlTargets } from './negative-control-compiled.js';
|
|
37
|
+
import { applyControlHunks, parseControlDiff, } from './negative-control-diff.js';
|
|
38
|
+
import { runInSignalCriticalSection } from './signal-critical.js';
|
|
39
|
+
/** Journal directory, relative to `.fireforge/`. */
|
|
40
|
+
const JOURNAL_DIR = 'negative-control';
|
|
41
|
+
const JOURNAL_FILE = 'journal.json';
|
|
42
|
+
/** Stable refusal class for every control preflight refusal. */
|
|
43
|
+
const NEGATIVE_CONTROL_NOTE = 'negative-control';
|
|
44
|
+
const active = new Set();
|
|
45
|
+
function refuse(message) {
|
|
46
|
+
throw new PreflightRefusalError(message, NEGATIVE_CONTROL_NOTE);
|
|
47
|
+
}
|
|
48
|
+
function journalDir(paths) {
|
|
49
|
+
return join(paths.fireforgeDir, JOURNAL_DIR);
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Maps a `components/custom/<name>/<file>` or
|
|
53
|
+
* `components/overrides/<name>/<file>` path onto the engine file Furnace
|
|
54
|
+
* deploys it to. The run reads the deployed copy, so that is what the
|
|
55
|
+
* control has to mutate.
|
|
56
|
+
*/
|
|
57
|
+
function mapComponentPath(diffPath, config) {
|
|
58
|
+
const [, kind, name, ...rest] = diffPath.split('/');
|
|
59
|
+
const file = rest.join('/');
|
|
60
|
+
if (kind === 'custom' && name !== undefined && rest.length === 1) {
|
|
61
|
+
const component = config.custom[name];
|
|
62
|
+
if (component && (file.endsWith('.mjs') || file.endsWith('.css'))) {
|
|
63
|
+
return posix.join(normalizePathSlashes(component.targetPath), file);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
if (kind === 'overrides' && name !== undefined && rest.length === 1) {
|
|
67
|
+
const override = config.overrides[name];
|
|
68
|
+
if (override && !file.endsWith('.ftl')) {
|
|
69
|
+
return posix.join(normalizePathSlashes(override.basePath), file);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
return refuse(`${diffPath} does not map to one deployed engine file (supported: a custom component's ` +
|
|
73
|
+
'.mjs/.css, or an override file other than .ftl, of a component furnace.json declares). ' +
|
|
74
|
+
'Write the control against the deployed engine file instead.');
|
|
75
|
+
}
|
|
76
|
+
async function resolveTargets(projectRoot, files) {
|
|
77
|
+
let furnaceConfig;
|
|
78
|
+
const targets = [];
|
|
79
|
+
const seen = new Set();
|
|
80
|
+
for (const file of files) {
|
|
81
|
+
const fromComponents = file.path.startsWith('components/');
|
|
82
|
+
let enginePath;
|
|
83
|
+
if (fromComponents) {
|
|
84
|
+
furnaceConfig ??= await loadFurnaceConfig(projectRoot);
|
|
85
|
+
enginePath = mapComponentPath(file.path, furnaceConfig);
|
|
86
|
+
}
|
|
87
|
+
else {
|
|
88
|
+
enginePath = stripEnginePrefix(file.path);
|
|
89
|
+
}
|
|
90
|
+
if (seen.has(enginePath))
|
|
91
|
+
refuse(`two diff sections resolve to engine/${enginePath}.`);
|
|
92
|
+
seen.add(enginePath);
|
|
93
|
+
targets.push({ diffPath: file.path, enginePath, hunks: file.hunks, fromComponents });
|
|
94
|
+
}
|
|
95
|
+
return targets;
|
|
96
|
+
}
|
|
97
|
+
async function prepareTarget(engineDir, target) {
|
|
98
|
+
const absolutePath = join(engineDir, target.enginePath);
|
|
99
|
+
const label = `engine/${target.enginePath}`;
|
|
100
|
+
let stats;
|
|
101
|
+
try {
|
|
102
|
+
stats = await lstat(absolutePath);
|
|
103
|
+
}
|
|
104
|
+
catch (error) {
|
|
105
|
+
if (getNodeErrorCode(error) === 'ENOENT')
|
|
106
|
+
refuse(`${label} does not exist.`);
|
|
107
|
+
throw error;
|
|
108
|
+
}
|
|
109
|
+
if (!stats.isFile()) {
|
|
110
|
+
refuse(`${label} is not a regular file (a symlink or directory cannot be restored byte-exact).`);
|
|
111
|
+
}
|
|
112
|
+
const original = await readFile(absolutePath);
|
|
113
|
+
const text = original.toString('utf8');
|
|
114
|
+
if (!Buffer.from(text, 'utf8').equals(original))
|
|
115
|
+
refuse(`${label} is not valid UTF-8 text.`);
|
|
116
|
+
let mutatedText;
|
|
117
|
+
try {
|
|
118
|
+
mutatedText = applyControlHunks(text, target.hunks, label);
|
|
119
|
+
}
|
|
120
|
+
catch (error) {
|
|
121
|
+
refuse(toError(error).message);
|
|
122
|
+
}
|
|
123
|
+
if (mutatedText === text)
|
|
124
|
+
refuse(`the diff leaves ${label} unchanged.`);
|
|
125
|
+
return {
|
|
126
|
+
target,
|
|
127
|
+
absolutePath,
|
|
128
|
+
original,
|
|
129
|
+
mutated: Buffer.from(mutatedText, 'utf8'),
|
|
130
|
+
mode: stats.mode,
|
|
131
|
+
atimeMs: stats.atimeMs,
|
|
132
|
+
mtimeMs: stats.mtimeMs,
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* Reads, parses and resolves a control diff, and (unless `deferApplyCheck`)
|
|
137
|
+
* proves every hunk applies to the current engine file, so a broken control
|
|
138
|
+
* is refused before any build time is spent.
|
|
139
|
+
*
|
|
140
|
+
* `deferApplyCheck` is for a run that builds first: Furnace redeploys a
|
|
141
|
+
* component's engine copy during the build, so a `components/` control can
|
|
142
|
+
* only be checked against what the build left behind.
|
|
143
|
+
*
|
|
144
|
+
* @param projectRoot - Project root; the diff path resolves against it
|
|
145
|
+
* @param engineDir - Absolute engine directory
|
|
146
|
+
* @param diffFile - The `--negative-control` argument
|
|
147
|
+
* @param options - `deferApplyCheck` skips the up-front apply check for
|
|
148
|
+
* `components/` targets
|
|
149
|
+
*/
|
|
150
|
+
export async function planNegativeControl(projectRoot, engineDir, diffFile, options = {}) {
|
|
151
|
+
let content;
|
|
152
|
+
try {
|
|
153
|
+
content = await readFile(resolve(projectRoot, diffFile), 'utf8');
|
|
154
|
+
}
|
|
155
|
+
catch (error) {
|
|
156
|
+
if (getNodeErrorCode(error) === 'ENOENT') {
|
|
157
|
+
refuse(`Negative control diff not found: ${diffFile} (resolved against the project root).`);
|
|
158
|
+
}
|
|
159
|
+
throw error;
|
|
160
|
+
}
|
|
161
|
+
let files;
|
|
162
|
+
try {
|
|
163
|
+
files = parseControlDiff(content, {
|
|
164
|
+
resolveRename: (source, target) => resolveEditedCopyRename(projectRoot, source, target),
|
|
165
|
+
});
|
|
166
|
+
}
|
|
167
|
+
catch (error) {
|
|
168
|
+
refuse(toError(error).message);
|
|
169
|
+
}
|
|
170
|
+
const targets = await resolveTargets(projectRoot, files);
|
|
171
|
+
for (const target of targets) {
|
|
172
|
+
if (options.deferApplyCheck === true && target.fromComponents)
|
|
173
|
+
continue;
|
|
174
|
+
await prepareTarget(engineDir, target);
|
|
175
|
+
}
|
|
176
|
+
const compiled = await findCompiledControlTargets(engineDir, targets.filter((target) => !target.fromComponents).map((target) => target.enginePath));
|
|
177
|
+
return { diffFile, targets, ...(compiled.length > 0 ? { compiled } : {}) };
|
|
178
|
+
}
|
|
179
|
+
/**
|
|
180
|
+
* A diff path as a project-relative path: a contained relative path as
|
|
181
|
+
* is, and an absolute one (git strips the leading `/` into `a/Users/…`)
|
|
182
|
+
* when it lies inside the project. Undefined otherwise.
|
|
183
|
+
*/
|
|
184
|
+
function projectRelative(projectRoot, path) {
|
|
185
|
+
const normalized = normalizePathSlashes(path);
|
|
186
|
+
for (const candidate of [`/${normalized}`, normalized]) {
|
|
187
|
+
if (!isAbsolute(candidate))
|
|
188
|
+
continue;
|
|
189
|
+
if (isPathInsideRoot(projectRoot, candidate)) {
|
|
190
|
+
return normalizePathSlashes(relative(projectRoot, candidate));
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
return isContainedRelativePath(normalized) ? normalized : undefined;
|
|
194
|
+
}
|
|
195
|
+
/**
|
|
196
|
+
* The control target of a `git diff --no-index <engine file> <edited copy>`
|
|
197
|
+
* section: its old side, when that names a project file and the new side
|
|
198
|
+
* names a copy outside `engine/` and `components/`. A section whose sides
|
|
199
|
+
* both live in those trees is a real rename and stays refused.
|
|
200
|
+
*/
|
|
201
|
+
function resolveEditedCopyRename(projectRoot, source, target) {
|
|
202
|
+
const old = projectRelative(projectRoot, source);
|
|
203
|
+
if (old === undefined)
|
|
204
|
+
return undefined;
|
|
205
|
+
const edited = projectRelative(projectRoot, target);
|
|
206
|
+
const tracked = (path) => path.startsWith('engine/') || path.startsWith('components/');
|
|
207
|
+
if (edited !== undefined && tracked(edited))
|
|
208
|
+
return undefined;
|
|
209
|
+
return old;
|
|
210
|
+
}
|
|
211
|
+
async function writeJournal(paths, journal) {
|
|
212
|
+
await writeFileAtomic(join(journalDir(paths), JOURNAL_FILE), `${JSON.stringify(journal, null, 2)}\n`);
|
|
213
|
+
}
|
|
214
|
+
/**
|
|
215
|
+
* Applies the control: every target is computed first (a hunk that does
|
|
216
|
+
* not apply refuses with nothing written), the originals and the journal
|
|
217
|
+
* are persisted, then the mutated bytes are written. Runs as a signal
|
|
218
|
+
* critical section, so a Ctrl+C mid-apply waits for the apply to finish
|
|
219
|
+
* and the signal path then restores a complete journal.
|
|
220
|
+
*
|
|
221
|
+
* @returns The handle {@link restoreNegativeControl} takes
|
|
222
|
+
*/
|
|
223
|
+
export async function applyNegativeControl(paths, plan) {
|
|
224
|
+
const prepared = [];
|
|
225
|
+
for (const target of plan.targets)
|
|
226
|
+
prepared.push(await prepareTarget(paths.engineDir, target));
|
|
227
|
+
return runInSignalCriticalSection('negative-control-apply', async () => {
|
|
228
|
+
const dir = journalDir(paths);
|
|
229
|
+
await mkdir(dir, { recursive: true });
|
|
230
|
+
const entries = [];
|
|
231
|
+
for (const [index, item] of prepared.entries()) {
|
|
232
|
+
const backup = `${index}.orig`;
|
|
233
|
+
await writeFileAtomic(join(dir, backup), item.original);
|
|
234
|
+
entries.push({
|
|
235
|
+
enginePath: item.target.enginePath,
|
|
236
|
+
backup,
|
|
237
|
+
originalSha256: sha256Hex(item.original),
|
|
238
|
+
mutatedSha256: sha256Hex(item.mutated),
|
|
239
|
+
mode: item.mode,
|
|
240
|
+
atimeMs: item.atimeMs,
|
|
241
|
+
mtimeMs: item.mtimeMs,
|
|
242
|
+
...(plan.compiled?.includes(item.target.enginePath) === true ? { freshMtime: true } : {}),
|
|
243
|
+
});
|
|
244
|
+
}
|
|
245
|
+
const journal = {
|
|
246
|
+
version: 1,
|
|
247
|
+
diffFile: plan.diffFile,
|
|
248
|
+
appliedAt: new Date().toISOString(),
|
|
249
|
+
entries,
|
|
250
|
+
};
|
|
251
|
+
await writeJournal(paths, journal);
|
|
252
|
+
const control = { paths, journal };
|
|
253
|
+
active.add(control);
|
|
254
|
+
try {
|
|
255
|
+
for (const item of prepared)
|
|
256
|
+
await writeFileAtomic(item.absolutePath, item.mutated);
|
|
257
|
+
}
|
|
258
|
+
catch (error) {
|
|
259
|
+
// A half-applied control never reaches a harness: put back whatever
|
|
260
|
+
// was written (untouched files read as already restored), then fail.
|
|
261
|
+
await restoreNegativeControl(control);
|
|
262
|
+
throw error;
|
|
263
|
+
}
|
|
264
|
+
return control;
|
|
265
|
+
});
|
|
266
|
+
}
|
|
267
|
+
async function restoreEntry(paths, entry) {
|
|
268
|
+
const absolutePath = join(paths.engineDir, entry.enginePath);
|
|
269
|
+
let current;
|
|
270
|
+
try {
|
|
271
|
+
current = await readFile(absolutePath);
|
|
272
|
+
}
|
|
273
|
+
catch (error) {
|
|
274
|
+
if (getNodeErrorCode(error) !== 'ENOENT')
|
|
275
|
+
throw error;
|
|
276
|
+
}
|
|
277
|
+
const currentSha = current === undefined ? undefined : sha256Hex(current);
|
|
278
|
+
if (currentSha === entry.originalSha256)
|
|
279
|
+
return 'restored';
|
|
280
|
+
if (currentSha !== entry.mutatedSha256)
|
|
281
|
+
return 'conflict';
|
|
282
|
+
const original = await readFile(join(journalDir(paths), entry.backup));
|
|
283
|
+
if (sha256Hex(original) !== entry.originalSha256) {
|
|
284
|
+
throw new GeneralError(`Negative control backup for engine/${entry.enginePath} does not match its journal; ` +
|
|
285
|
+
`left the file as is. Inspect ${journalDir(paths)}.`);
|
|
286
|
+
}
|
|
287
|
+
await writeFileAtomic(absolutePath, original);
|
|
288
|
+
if (entry.freshMtime === true) {
|
|
289
|
+
const now = Date.now() / 1000;
|
|
290
|
+
await utimes(absolutePath, now, now);
|
|
291
|
+
}
|
|
292
|
+
else {
|
|
293
|
+
await utimes(absolutePath, entry.atimeMs / 1000, entry.mtimeMs / 1000);
|
|
294
|
+
}
|
|
295
|
+
const readBack = await readFile(absolutePath);
|
|
296
|
+
const stats = await lstat(absolutePath);
|
|
297
|
+
if (!readBack.equals(original) || (stats.mode & 0o7777) !== (entry.mode & 0o7777)) {
|
|
298
|
+
throw new GeneralError(`Restoring engine/${entry.enginePath} did not read back byte-exact; ` +
|
|
299
|
+
`the original is kept in ${journalDir(paths)}.`);
|
|
300
|
+
}
|
|
301
|
+
return 'restored';
|
|
302
|
+
}
|
|
303
|
+
async function restoreJournal(paths, journal) {
|
|
304
|
+
const result = { restored: [], conflicts: [] };
|
|
305
|
+
for (const entry of journal.entries) {
|
|
306
|
+
const outcome = await restoreEntry(paths, entry);
|
|
307
|
+
(outcome === 'restored' ? result.restored : result.conflicts).push(entry.enginePath);
|
|
308
|
+
}
|
|
309
|
+
if (result.conflicts.length === 0) {
|
|
310
|
+
await rm(journalDir(paths), { recursive: true, force: true });
|
|
311
|
+
}
|
|
312
|
+
return result;
|
|
313
|
+
}
|
|
314
|
+
function conflictMessage(paths, conflicts) {
|
|
315
|
+
return (`Negative control restore left ${conflicts.length} file(s) alone because they changed while ` +
|
|
316
|
+
`the control was applied: ${conflicts.map((path) => `engine/${path}`).join(', ')}. ` +
|
|
317
|
+
`Their pre-control bytes are kept in ${journalDir(paths)} (see journal.json for which ` +
|
|
318
|
+
'backup belongs to which file). Reconcile by hand, then delete that directory.');
|
|
319
|
+
}
|
|
320
|
+
/**
|
|
321
|
+
* Restores a control applied by {@link applyNegativeControl}. Idempotent:
|
|
322
|
+
* a second caller (the signal handler racing the run's own `finally`)
|
|
323
|
+
* receives the restore already in flight.
|
|
324
|
+
*
|
|
325
|
+
* @throws GeneralError when a file changed under the control (the edit is
|
|
326
|
+
* kept and the original stays in the journal directory) or did not read
|
|
327
|
+
* back byte-exact
|
|
328
|
+
*/
|
|
329
|
+
export function restoreNegativeControl(control) {
|
|
330
|
+
control.restoring ??= (async () => {
|
|
331
|
+
try {
|
|
332
|
+
return await runInSignalCriticalSection('negative-control-restore', async () => {
|
|
333
|
+
const result = await restoreJournal(control.paths, control.journal);
|
|
334
|
+
if (result.conflicts.length > 0) {
|
|
335
|
+
throw new GeneralError(conflictMessage(control.paths, result.conflicts));
|
|
336
|
+
}
|
|
337
|
+
return result;
|
|
338
|
+
});
|
|
339
|
+
}
|
|
340
|
+
finally {
|
|
341
|
+
active.delete(control);
|
|
342
|
+
}
|
|
343
|
+
})();
|
|
344
|
+
return control.restoring;
|
|
345
|
+
}
|
|
346
|
+
/**
|
|
347
|
+
* Restores every applied control on the way out of a SIGINT/SIGTERM. Called
|
|
348
|
+
* by the entry point after child shutdown and before the held locks are
|
|
349
|
+
* force-released. Never throws: a failure is reported on stderr and the
|
|
350
|
+
* journal stays for the next run's recovery.
|
|
351
|
+
*/
|
|
352
|
+
export async function restoreActiveNegativeControlsForSignal() {
|
|
353
|
+
for (const control of [...active]) {
|
|
354
|
+
try {
|
|
355
|
+
await restoreNegativeControl(control);
|
|
356
|
+
}
|
|
357
|
+
catch (error) {
|
|
358
|
+
console.error(`Negative control restore after signal failed: ${toError(error).message}`);
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
/**
|
|
363
|
+
* Undoes a control a killed FireForge left applied. Called at the start of
|
|
364
|
+
* every `fireforge test`, under the engine-session lock. A file that still
|
|
365
|
+
* holds the control's bytes is restored; a file somebody changed since is
|
|
366
|
+
* refused rather than overwritten.
|
|
367
|
+
*
|
|
368
|
+
* @throws PreflightRefusalError (`note=negative-control-pending`) when a
|
|
369
|
+
* journal entry cannot be restored safely
|
|
370
|
+
*/
|
|
371
|
+
export async function recoverPendingNegativeControl(paths) {
|
|
372
|
+
let raw;
|
|
373
|
+
try {
|
|
374
|
+
raw = await readFile(join(journalDir(paths), JOURNAL_FILE), 'utf8');
|
|
375
|
+
}
|
|
376
|
+
catch (error) {
|
|
377
|
+
if (getNodeErrorCode(error) === 'ENOENT')
|
|
378
|
+
return;
|
|
379
|
+
throw error;
|
|
380
|
+
}
|
|
381
|
+
let journal;
|
|
382
|
+
try {
|
|
383
|
+
const parsed = JSON.parse(raw);
|
|
384
|
+
if (parsed?.version !== 1 || !Array.isArray(parsed.entries))
|
|
385
|
+
throw new Error('bad shape');
|
|
386
|
+
journal = parsed;
|
|
387
|
+
}
|
|
388
|
+
catch {
|
|
389
|
+
throw new PreflightRefusalError(`The negative control journal ${join(journalDir(paths), JOURNAL_FILE)} is unreadable. ` +
|
|
390
|
+
'Restore its backups by hand, then delete that directory.', 'negative-control-pending');
|
|
391
|
+
}
|
|
392
|
+
const result = await restoreJournal(paths, journal);
|
|
393
|
+
if (result.conflicts.length > 0) {
|
|
394
|
+
throw new PreflightRefusalError(`A negative control (${journal.diffFile}, applied ${journal.appliedAt}) was left applied by an interrupted run. ` +
|
|
395
|
+
conflictMessage(paths, result.conflicts), 'negative-control-pending');
|
|
396
|
+
}
|
|
397
|
+
notice(`Restored ${result.restored.length} file(s) a negative control (${journal.diffFile}) left applied ` +
|
|
398
|
+
'when its run was killed.');
|
|
399
|
+
}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Reads the objdir's mozpack install manifests to tell how an engine source
|
|
3
|
+
* reaches the runtime a test runs against.
|
|
4
|
+
*
|
|
5
|
+
* mozbuild installs packaged files from manifests under
|
|
6
|
+
* `obj-*\/_build_manifests/install/` and `obj-*\/faster/install_*`. Each
|
|
7
|
+
* line after the version is a `\x1f`-separated entry: type 1 installs a
|
|
8
|
+
* symlink to an absolute source, 2 copies it, 7 preprocesses it, and 5/6
|
|
9
|
+
* are the pattern forms of 1/2 (`base`, `pattern`, `dest dir`). In a
|
|
10
|
+
* non-Windows dev build most chrome and test files are type-1 symlinks back
|
|
11
|
+
* into `engine/`, so an edit to such a file is already what the runtime
|
|
12
|
+
* reads. `_test_files` is rewritten and installed by `mach test` itself on
|
|
13
|
+
* every dispatch, so test files are restaged when a run starts.
|
|
14
|
+
*
|
|
15
|
+
* Every classification is conservative: an entry whose install base is
|
|
16
|
+
* unknown, a symlink that does not resolve to the edited source, or an
|
|
17
|
+
* unreadable manifest leaves the path classified as packaged.
|
|
18
|
+
*/
|
|
19
|
+
interface InstallEntry {
|
|
20
|
+
symlink: boolean;
|
|
21
|
+
/** Absolute installed path, or undefined when the install base is unknown. */
|
|
22
|
+
dest: string | undefined;
|
|
23
|
+
/** Installed by `mach test` at dispatch rather than by the build. */
|
|
24
|
+
atDispatch: boolean;
|
|
25
|
+
}
|
|
26
|
+
interface PatternEntry {
|
|
27
|
+
symlink: boolean;
|
|
28
|
+
/** Engine-relative directory the pattern matches beneath. */
|
|
29
|
+
base: string;
|
|
30
|
+
pattern: RegExp;
|
|
31
|
+
/** Absolute install directory, or undefined when the install base is unknown. */
|
|
32
|
+
destDir: string | undefined;
|
|
33
|
+
atDispatch: boolean;
|
|
34
|
+
}
|
|
35
|
+
/** Parsed install manifests of one objdir. */
|
|
36
|
+
export interface InstallManifestIndex {
|
|
37
|
+
explicit: Map<string, InstallEntry[]>;
|
|
38
|
+
patterns: PatternEntry[];
|
|
39
|
+
engineRoots: string[];
|
|
40
|
+
}
|
|
41
|
+
/** How an engine source reaches the runtime. */
|
|
42
|
+
export type RuntimeDelivery =
|
|
43
|
+
/** Every installed copy is a symlink to the source: edits are already live. */
|
|
44
|
+
'live'
|
|
45
|
+
/** Installed only by `mach test` at dispatch, which restages it. */
|
|
46
|
+
| 'at-dispatch'
|
|
47
|
+
/** At least one installed copy is a real copy (or unverifiable). */
|
|
48
|
+
| 'packaged'
|
|
49
|
+
/** No install manifest names it. */
|
|
50
|
+
| 'unlisted';
|
|
51
|
+
/**
|
|
52
|
+
* Loads every install manifest of `objDir`. Undefined when neither manifest
|
|
53
|
+
* directory is readable, i.e. nothing can be classified.
|
|
54
|
+
*
|
|
55
|
+
* @param engineDir - Absolute engine directory
|
|
56
|
+
* @param objDir - Objdir name under the engine directory
|
|
57
|
+
*/
|
|
58
|
+
export declare function loadInstallManifestIndex(engineDir: string, objDir: string): Promise<InstallManifestIndex | undefined>;
|
|
59
|
+
/**
|
|
60
|
+
* Classifies how `relPath` reaches the runtime. See {@link RuntimeDelivery}.
|
|
61
|
+
*
|
|
62
|
+
* @param index - Index from {@link loadInstallManifestIndex}
|
|
63
|
+
* @param engineDir - Absolute engine directory
|
|
64
|
+
* @param relPath - Engine-relative POSIX path
|
|
65
|
+
*/
|
|
66
|
+
export declare function classifyRuntimeDelivery(index: InstallManifestIndex, engineDir: string, relPath: string): Promise<RuntimeDelivery>;
|
|
67
|
+
/**
|
|
68
|
+
* True when any install-manifest entry installs something from at or
|
|
69
|
+
* beneath the engine-relative directory `dir`, or a pattern entry's base
|
|
70
|
+
* contains it.
|
|
71
|
+
*/
|
|
72
|
+
export declare function installsFromDirectory(index: InstallManifestIndex, dir: string): boolean;
|
|
73
|
+
export {};
|