@hominis/fireforge 0.45.0 → 0.46.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +409 -446
- package/dist/bin/fireforge.d.ts +1 -1
- package/dist/bin/fireforge.js +21 -15
- package/dist/build-info.json +4 -4
- package/dist/src/cli-usage-error.d.ts +46 -0
- package/dist/src/cli-usage-error.js +81 -0
- package/dist/src/cli.d.ts +7 -2
- package/dist/src/cli.js +47 -47
- package/dist/src/commands/bootstrap-checks.js +2 -1
- package/dist/src/commands/bootstrap.js +3 -4
- package/dist/src/commands/build.js +27 -17
- package/dist/src/commands/config.js +9 -9
- package/dist/src/commands/destructive-decision.d.ts +19 -0
- package/dist/src/commands/destructive-decision.js +31 -0
- package/dist/src/commands/discard.js +5 -5
- package/dist/src/commands/doctor-check-core.d.ts +4 -10
- package/dist/src/commands/doctor-check-core.js +0 -8
- package/dist/src/commands/doctor-external-toolchains.js +2 -2
- package/dist/src/commands/doctor-furnace-config-sync.d.ts +2 -2
- package/dist/src/commands/doctor-furnace-config-sync.js +20 -20
- package/dist/src/commands/doctor-furnace-jar.d.ts +1 -1
- package/dist/src/commands/doctor-furnace-jar.js +1 -1
- package/dist/src/commands/doctor-furnace.js +22 -22
- package/dist/src/commands/doctor-orphaned-harness.d.ts +10 -17
- package/dist/src/commands/doctor-orphaned-harness.js +14 -23
- package/dist/src/commands/doctor-patch-manifest.d.ts +2 -1
- package/dist/src/commands/doctor-patch-manifest.js +7 -6
- package/dist/src/commands/doctor-post-rebase-audit.js +3 -3
- package/dist/src/commands/doctor-source-pin.d.ts +12 -12
- package/dist/src/commands/doctor-source-pin.js +14 -14
- package/dist/src/commands/doctor-working-tree.d.ts +3 -3
- package/dist/src/commands/doctor-working-tree.js +3 -3
- package/dist/src/commands/doctor.d.ts +3 -1
- package/dist/src/commands/doctor.js +15 -16
- package/dist/src/commands/download.js +50 -37
- package/dist/src/commands/export-all.js +29 -12
- package/dist/src/commands/export-flow.d.ts +5 -5
- package/dist/src/commands/export-flow.js +29 -59
- package/dist/src/commands/export-placement-conflicts.d.ts +3 -3
- package/dist/src/commands/export-placement-conflicts.js +12 -12
- package/dist/src/commands/export-placement-gate.d.ts +2 -2
- package/dist/src/commands/export-placement-gate.js +7 -13
- package/dist/src/commands/export-placement-policy.d.ts +1 -1
- package/dist/src/commands/export-placement-policy.js +4 -6
- package/dist/src/commands/export-shared.d.ts +51 -32
- package/dist/src/commands/export-shared.js +17 -32
- package/dist/src/commands/export.js +14 -5
- package/dist/src/commands/furnace/apply.js +16 -16
- package/dist/src/commands/furnace/authoring-config.d.ts +13 -0
- package/dist/src/commands/furnace/authoring-config.js +19 -0
- package/dist/src/commands/furnace/chrome-doc-remove.d.ts +1 -1
- package/dist/src/commands/furnace/chrome-doc-remove.js +2 -2
- package/dist/src/commands/furnace/chrome-doc-templates.d.ts +14 -14
- package/dist/src/commands/furnace/chrome-doc-templates.js +17 -17
- package/dist/src/commands/furnace/chrome-doc-tests.d.ts +2 -2
- package/dist/src/commands/furnace/chrome-doc-tests.js +4 -4
- package/dist/src/commands/furnace/chrome-doc.d.ts +8 -8
- package/dist/src/commands/furnace/chrome-doc.js +18 -18
- package/dist/src/commands/furnace/create-browser-test.d.ts +1 -1
- package/dist/src/commands/furnace/create-browser-test.js +7 -12
- package/dist/src/commands/furnace/create-dry-run.d.ts +4 -4
- package/dist/src/commands/furnace/create-dry-run.js +6 -9
- package/dist/src/commands/furnace/create-features.d.ts +2 -2
- package/dist/src/commands/furnace/create-features.js +2 -2
- package/dist/src/commands/furnace/create-mochikit.d.ts +4 -4
- package/dist/src/commands/furnace/create-mochikit.js +7 -7
- package/dist/src/commands/furnace/create-templates.d.ts +31 -15
- package/dist/src/commands/furnace/create-templates.js +20 -19
- package/dist/src/commands/furnace/create-xpcshell.d.ts +5 -5
- package/dist/src/commands/furnace/create-xpcshell.js +8 -8
- package/dist/src/commands/furnace/create.d.ts +1 -1
- package/dist/src/commands/furnace/create.js +35 -29
- package/dist/src/commands/furnace/deploy.js +15 -6
- package/dist/src/commands/furnace/diff.js +7 -7
- package/dist/src/commands/furnace/index.js +1 -1
- package/dist/src/commands/furnace/init.js +17 -16
- package/dist/src/commands/furnace/list.js +2 -2
- package/dist/src/commands/furnace/override.d.ts +1 -1
- package/dist/src/commands/furnace/override.js +43 -34
- package/dist/src/commands/furnace/preview.js +17 -17
- package/dist/src/commands/furnace/refresh.js +15 -7
- package/dist/src/commands/furnace/remove-mutations.d.ts +9 -10
- package/dist/src/commands/furnace/remove-mutations.js +19 -19
- package/dist/src/commands/furnace/remove-state.d.ts +1 -1
- package/dist/src/commands/furnace/remove-state.js +1 -1
- package/dist/src/commands/furnace/remove.js +4 -8
- package/dist/src/commands/furnace/rename-browser-test.js +10 -15
- package/dist/src/commands/furnace/rename-xpcshell.d.ts +2 -2
- package/dist/src/commands/furnace/rename-xpcshell.js +3 -3
- package/dist/src/commands/furnace/rename.js +36 -36
- package/dist/src/commands/furnace/scan.js +3 -3
- package/dist/src/commands/furnace/status.js +19 -16
- package/dist/src/commands/furnace/sync.js +6 -6
- package/dist/src/commands/furnace/test-file-name.d.ts +28 -0
- package/dist/src/commands/furnace/test-file-name.js +39 -0
- package/dist/src/commands/furnace/validate.js +11 -12
- package/dist/src/commands/furnace/validation-output.d.ts +21 -9
- package/dist/src/commands/furnace/validation-output.js +3 -8
- package/dist/src/commands/import.js +22 -29
- package/dist/src/commands/lint-per-patch.d.ts +2 -2
- package/dist/src/commands/lint-per-patch.js +27 -12
- package/dist/src/commands/lint-per-run-checkjs.d.ts +14 -15
- package/dist/src/commands/lint-per-run-checkjs.js +14 -15
- package/dist/src/commands/lint-report.d.ts +3 -3
- package/dist/src/commands/lint-report.js +4 -4
- package/dist/src/commands/lint.d.ts +5 -4
- package/dist/src/commands/lint.js +36 -36
- package/dist/src/commands/manifest.d.ts +4 -4
- package/dist/src/commands/manifest.js +1 -1
- package/dist/src/commands/package.js +4 -6
- package/dist/src/commands/patch/compact.d.ts +2 -2
- package/dist/src/commands/patch/compact.js +19 -20
- package/dist/src/commands/patch/delete.d.ts +1 -1
- package/dist/src/commands/patch/delete.js +23 -33
- package/dist/src/commands/patch/entry-projection.d.ts +13 -0
- package/dist/src/commands/patch/entry-projection.js +24 -0
- package/dist/src/commands/patch/lint-ignore.d.ts +3 -12
- package/dist/src/commands/patch/lint-ignore.js +33 -44
- package/dist/src/commands/patch/move-files-create.d.ts +2 -2
- package/dist/src/commands/patch/move-files-create.js +29 -15
- package/dist/src/commands/patch/move-files-into.d.ts +2 -2
- package/dist/src/commands/patch/move-files-into.js +41 -37
- package/dist/src/commands/patch/move-files.js +5 -14
- package/dist/src/commands/patch/patch-context.d.ts +1 -1
- package/dist/src/commands/patch/rename.d.ts +4 -4
- package/dist/src/commands/patch/rename.js +35 -49
- package/dist/src/commands/patch/reorder.js +35 -48
- package/dist/src/commands/patch/split-plan.d.ts +7 -8
- package/dist/src/commands/patch/split-plan.js +10 -13
- package/dist/src/commands/patch/split.d.ts +2 -2
- package/dist/src/commands/patch/split.js +50 -48
- package/dist/src/commands/patch/staged-dependency-validate.d.ts +1 -1
- package/dist/src/commands/patch/staged-dependency-validate.js +3 -3
- package/dist/src/commands/patch/staged-dependency.d.ts +1 -1
- package/dist/src/commands/patch/staged-dependency.js +22 -28
- package/dist/src/commands/patch/tier.d.ts +2 -2
- package/dist/src/commands/patch/tier.js +20 -30
- package/dist/src/commands/patch-rename-map.d.ts +19 -0
- package/dist/src/commands/patch-rename-map.js +36 -0
- package/dist/src/commands/pending-resolution.d.ts +15 -0
- package/dist/src/commands/pending-resolution.js +25 -0
- package/dist/src/commands/re-export-adjacent.d.ts +25 -3
- package/dist/src/commands/re-export-adjacent.js +40 -24
- package/dist/src/commands/re-export-bulk-scan.d.ts +3 -3
- package/dist/src/commands/re-export-bulk-scan.js +23 -27
- package/dist/src/commands/re-export-drift.d.ts +10 -10
- package/dist/src/commands/re-export-drift.js +33 -33
- package/dist/src/commands/re-export-files.d.ts +2 -3
- package/dist/src/commands/re-export-files.js +52 -44
- package/dist/src/commands/re-export-lint.d.ts +29 -30
- package/dist/src/commands/re-export-lint.js +36 -29
- package/dist/src/commands/re-export-options.d.ts +1 -1
- package/dist/src/commands/re-export-options.js +1 -1
- package/dist/src/commands/re-export-register.d.ts +1 -1
- package/dist/src/commands/re-export-register.js +1 -1
- package/dist/src/commands/re-export-scan.d.ts +1 -1
- package/dist/src/commands/re-export-scan.js +12 -9
- package/dist/src/commands/re-export-single.d.ts +23 -4
- package/dist/src/commands/re-export-single.js +39 -31
- package/dist/src/commands/re-export.js +35 -17
- package/dist/src/commands/rebase/abort.js +9 -14
- package/dist/src/commands/rebase/continue.js +20 -19
- package/dist/src/commands/rebase/index.d.ts +1 -1
- package/dist/src/commands/rebase/index.js +5 -5
- package/dist/src/commands/rebase/patch-loop.d.ts +2 -2
- package/dist/src/commands/rebase/patch-loop.js +20 -24
- package/dist/src/commands/register.js +5 -5
- package/dist/src/commands/reset.js +1 -1
- package/dist/src/commands/resolve.d.ts +2 -2
- package/dist/src/commands/resolve.js +21 -13
- package/dist/src/commands/run.d.ts +0 -13
- package/dist/src/commands/run.js +38 -51
- package/dist/src/commands/setup-support.d.ts +16 -4
- package/dist/src/commands/setup-support.js +20 -20
- package/dist/src/commands/setup.js +4 -10
- package/dist/src/commands/source.js +9 -2
- package/dist/src/commands/status-check.d.ts +3 -3
- package/dist/src/commands/status-check.js +6 -6
- package/dist/src/commands/status-json.d.ts +14 -13
- package/dist/src/commands/status-json.js +9 -8
- package/dist/src/commands/status-output.d.ts +3 -3
- package/dist/src/commands/status-output.js +5 -5
- package/dist/src/commands/status-ownership.d.ts +3 -3
- package/dist/src/commands/status-ownership.js +3 -3
- package/dist/src/commands/status.js +25 -26
- package/dist/src/commands/test-build-phase.d.ts +3 -3
- package/dist/src/commands/test-build-phase.js +48 -24
- package/dist/src/commands/test-diagnose.d.ts +1 -1
- package/dist/src/commands/test-diagnose.js +20 -20
- package/dist/src/commands/test-modes.d.ts +4 -4
- package/dist/src/commands/test-modes.js +4 -5
- package/dist/src/commands/test-register.js +5 -3
- package/dist/src/commands/test-run.d.ts +11 -11
- package/dist/src/commands/test-run.js +40 -33
- package/dist/src/commands/test-stale-gate.d.ts +12 -12
- package/dist/src/commands/test-stale-gate.js +17 -17
- package/dist/src/commands/test-verdict.d.ts +19 -5
- package/dist/src/commands/test-verdict.js +26 -11
- package/dist/src/commands/test.d.ts +3 -3
- package/dist/src/commands/test.js +73 -36
- package/dist/src/commands/token-coverage.js +3 -3
- package/dist/src/commands/token-list.d.ts +26 -0
- package/dist/src/commands/token-list.js +153 -0
- package/dist/src/commands/token.js +26 -10
- package/dist/src/commands/tree.js +26 -21
- package/dist/src/commands/typecheck.d.ts +6 -6
- package/dist/src/commands/typecheck.js +16 -16
- package/dist/src/commands/verify.d.ts +3 -3
- package/dist/src/commands/verify.js +10 -10
- package/dist/src/commands/watch.js +11 -11
- package/dist/src/commands/wire.js +17 -16
- package/dist/src/core/ast-utils.d.ts +7 -7
- package/dist/src/core/ast-utils.js +8 -8
- package/dist/src/core/branding.d.ts +5 -12
- package/dist/src/core/branding.js +6 -5
- package/dist/src/core/browser-wire.d.ts +1 -1
- package/dist/src/core/browser-wire.js +10 -7
- package/dist/src/core/build-audit-platform.d.ts +32 -3
- package/dist/src/core/build-audit-platform.js +153 -13
- package/dist/src/core/build-audit-registration.d.ts +5 -5
- package/dist/src/core/build-audit-registration.js +10 -9
- package/dist/src/core/build-audit-resolve.d.ts +5 -5
- package/dist/src/core/build-audit-resolve.js +6 -6
- package/dist/src/core/build-audit-skip.d.ts +57 -0
- package/dist/src/core/build-audit-skip.js +112 -0
- package/dist/src/core/build-audit-transforms.d.ts +2 -2
- package/dist/src/core/build-audit-transforms.js +3 -3
- package/dist/src/core/build-audit.d.ts +21 -8
- package/dist/src/core/build-audit.js +142 -40
- package/dist/src/core/build-baseline-types.d.ts +19 -18
- package/dist/src/core/build-baseline-types.js +1 -1
- package/dist/src/core/build-baseline.d.ts +48 -31
- package/dist/src/core/build-baseline.js +20 -43
- package/dist/src/core/build-jar-escalation.d.ts +8 -8
- package/dist/src/core/build-jar-escalation.js +18 -17
- package/dist/src/core/build-overwrite-guard.d.ts +4 -4
- package/dist/src/core/build-overwrite-guard.js +14 -14
- package/dist/src/core/build-prepare.d.ts +4 -12
- package/dist/src/core/build-prepare.js +22 -26
- package/dist/src/core/config-mutate.js +4 -4
- package/dist/src/core/config-paths.d.ts +2 -6
- package/dist/src/core/config-paths.js +4 -2
- package/dist/src/core/config-state.d.ts +0 -6
- package/dist/src/core/config-state.js +3 -21
- package/dist/src/core/config-validate-build-audit.d.ts +8 -0
- package/dist/src/core/config-validate-build-audit.js +80 -0
- package/dist/src/core/config-validate-file-size.d.ts +1 -1
- package/dist/src/core/config-validate-file-size.js +3 -3
- package/dist/src/core/config-validate-patch-policy.d.ts +2 -2
- package/dist/src/core/config-validate-patch-policy.js +3 -3
- package/dist/src/core/config-validate-test-toolchains.d.ts +2 -2
- package/dist/src/core/config-validate-test-toolchains.js +4 -5
- package/dist/src/core/config-validate.js +22 -12
- package/dist/src/core/config.d.ts +12 -12
- package/dist/src/core/config.js +21 -25
- package/dist/src/core/coverage-extend.d.ts +16 -16
- package/dist/src/core/coverage-extend.js +20 -20
- package/dist/src/core/destructive.d.ts +14 -14
- package/dist/src/core/destructive.js +9 -9
- package/dist/src/core/diff-hunks.d.ts +2 -2
- package/dist/src/core/diff-hunks.js +7 -7
- package/dist/src/core/discard-baseline.d.ts +10 -10
- package/dist/src/core/discard-baseline.js +22 -23
- package/dist/src/core/display-state.d.ts +11 -11
- package/dist/src/core/display-state.js +12 -12
- package/dist/src/core/engine-changes.d.ts +2 -2
- package/dist/src/core/engine-changes.js +2 -2
- package/dist/src/core/engine-precondition.d.ts +5 -13
- package/dist/src/core/engine-precondition.js +5 -10
- package/dist/src/core/engine-session-lock.d.ts +18 -18
- package/dist/src/core/engine-session-lock.js +50 -54
- package/dist/src/core/export-moved-code-shape.d.ts +7 -7
- package/dist/src/core/export-moved-code-shape.js +10 -10
- package/dist/src/core/file-lock-owner.d.ts +103 -0
- package/dist/src/core/file-lock-owner.js +259 -0
- package/dist/src/core/file-lock.d.ts +14 -19
- package/dist/src/core/file-lock.js +90 -128
- package/dist/src/core/firefox-cache.d.ts +13 -1
- package/dist/src/core/firefox-cache.js +61 -36
- package/dist/src/core/firefox-download.d.ts +15 -0
- package/dist/src/core/firefox-download.js +38 -22
- package/dist/src/core/firefox-extract.d.ts +8 -7
- package/dist/src/core/firefox-extract.js +45 -27
- package/dist/src/core/firefox.d.ts +34 -36
- package/dist/src/core/firefox.js +13 -44
- package/dist/src/core/furnace-apply-dry-run.d.ts +1 -6
- package/dist/src/core/furnace-apply-dry-run.js +2 -8
- package/dist/src/core/furnace-apply-ftl.d.ts +5 -5
- package/dist/src/core/furnace-apply-ftl.js +8 -8
- package/dist/src/core/furnace-apply-helpers.d.ts +9 -20
- package/dist/src/core/furnace-apply-helpers.js +28 -39
- package/dist/src/core/furnace-apply-output.js +1 -1
- package/dist/src/core/furnace-apply-overwrite-warn.d.ts +9 -9
- package/dist/src/core/furnace-apply-overwrite-warn.js +13 -11
- package/dist/src/core/furnace-apply-undeploy-actions.d.ts +1 -1
- package/dist/src/core/furnace-apply-undeploy-actions.js +1 -1
- package/dist/src/core/furnace-apply.d.ts +4 -4
- package/dist/src/core/furnace-apply.js +50 -29
- package/dist/src/core/furnace-checksum-utils.d.ts +5 -5
- package/dist/src/core/furnace-checksum-utils.js +5 -5
- package/dist/src/core/furnace-config-custom.d.ts +1 -1
- package/dist/src/core/furnace-config-custom.js +2 -2
- package/dist/src/core/furnace-config-order.js +1 -1
- package/dist/src/core/furnace-config-tokens.d.ts +3 -3
- package/dist/src/core/furnace-config-tokens.js +3 -3
- package/dist/src/core/furnace-config-validate.js +2 -2
- package/dist/src/core/furnace-config.d.ts +5 -5
- package/dist/src/core/furnace-config.js +40 -53
- package/dist/src/core/furnace-constants.d.ts +6 -6
- package/dist/src/core/furnace-constants.js +9 -8
- package/dist/src/core/furnace-css-fragments.d.ts +6 -6
- package/dist/src/core/furnace-css-fragments.js +11 -11
- package/dist/src/core/furnace-dir-entry.d.ts +20 -0
- package/dist/src/core/furnace-dir-entry.js +21 -0
- package/dist/src/core/furnace-jsconfig.d.ts +7 -7
- package/dist/src/core/furnace-jsconfig.js +22 -20
- package/dist/src/core/furnace-operation.d.ts +22 -19
- package/dist/src/core/furnace-operation.js +38 -34
- package/dist/src/core/furnace-precondition.d.ts +10 -10
- package/dist/src/core/furnace-precondition.js +8 -8
- package/dist/src/core/furnace-refresh.d.ts +18 -6
- package/dist/src/core/furnace-refresh.js +5 -8
- package/dist/src/core/furnace-registration-ast.d.ts +2 -3
- package/dist/src/core/furnace-registration-ast.js +9 -12
- package/dist/src/core/furnace-registration-remove.d.ts +4 -4
- package/dist/src/core/furnace-registration-remove.js +6 -6
- package/dist/src/core/furnace-registration-validate.d.ts +2 -2
- package/dist/src/core/furnace-registration-validate.js +2 -2
- package/dist/src/core/furnace-registration.d.ts +7 -6
- package/dist/src/core/furnace-registration.js +29 -36
- package/dist/src/core/furnace-rollback.d.ts +1 -1
- package/dist/src/core/furnace-rollback.js +5 -5
- package/dist/src/core/furnace-scanner.js +3 -6
- package/dist/src/core/furnace-stale-export.d.ts +17 -16
- package/dist/src/core/furnace-stale-export.js +16 -15
- package/dist/src/core/furnace-staleness.d.ts +2 -2
- package/dist/src/core/furnace-staleness.js +2 -2
- package/dist/src/core/furnace-state-persist.d.ts +12 -12
- package/dist/src/core/furnace-state-persist.js +10 -10
- package/dist/src/core/furnace-step-errors.d.ts +6 -6
- package/dist/src/core/furnace-step-errors.js +6 -6
- package/dist/src/core/furnace-validate-accessibility.js +14 -14
- package/dist/src/core/furnace-validate-compatibility.js +9 -9
- package/dist/src/core/furnace-validate-registration.d.ts +2 -2
- package/dist/src/core/furnace-validate-registration.js +18 -20
- package/dist/src/core/furnace-validate-structure.d.ts +1 -1
- package/dist/src/core/furnace-validate-structure.js +4 -4
- package/dist/src/core/furnace-validate.js +9 -9
- package/dist/src/core/furnace-version-drift.d.ts +5 -5
- package/dist/src/core/furnace-version-drift.js +5 -5
- package/dist/src/core/git-base.d.ts +6 -4
- package/dist/src/core/git-base.js +29 -7
- package/dist/src/core/git-diff-new-file.d.ts +40 -0
- package/dist/src/core/git-diff-new-file.js +119 -0
- package/dist/src/core/git-diff.d.ts +13 -13
- package/dist/src/core/git-diff.js +121 -189
- package/dist/src/core/git-file-ops.d.ts +6 -13
- package/dist/src/core/git-file-ops.js +11 -35
- package/dist/src/core/git-readonly-index.d.ts +12 -14
- package/dist/src/core/git-readonly-index.js +12 -16
- package/dist/src/core/git-status.d.ts +9 -2
- package/dist/src/core/git-status.js +23 -11
- package/dist/src/core/git.d.ts +3 -9
- package/dist/src/core/git.js +28 -57
- package/dist/src/core/harness-orphans.d.ts +17 -17
- package/dist/src/core/harness-orphans.js +28 -27
- package/dist/src/core/history-log.d.ts +19 -0
- package/dist/src/core/history-log.js +29 -0
- package/dist/src/core/license-headers.d.ts +19 -18
- package/dist/src/core/license-headers.js +29 -28
- package/dist/src/core/mach-build-artifacts.d.ts +21 -21
- package/dist/src/core/mach-build-artifacts.js +23 -23
- package/dist/src/core/mach-error-hints.d.ts +5 -10
- package/dist/src/core/mach-error-hints.js +14 -14
- package/dist/src/core/mach-known-noise-filter.d.ts +42 -38
- package/dist/src/core/mach-known-noise-filter.js +57 -56
- package/dist/src/core/mach-mozconfig.d.ts +6 -6
- package/dist/src/core/mach-mozconfig.js +17 -16
- package/dist/src/core/mach-python.d.ts +3 -0
- package/dist/src/core/mach-python.js +13 -7
- package/dist/src/core/mach-resource-shim.d.ts +24 -12
- package/dist/src/core/mach-resource-shim.js +124 -21
- package/dist/src/core/mach.d.ts +59 -73
- package/dist/src/core/mach.js +47 -115
- package/dist/src/core/marionette-port.d.ts +15 -30
- package/dist/src/core/marionette-port.js +46 -89
- package/dist/src/core/marionette-preflight.d.ts +6 -6
- package/dist/src/core/marionette-preflight.js +32 -50
- package/dist/src/core/markdown-table.d.ts +9 -9
- package/dist/src/core/markdown-table.js +14 -14
- package/dist/src/core/mochitest-server-port.d.ts +8 -8
- package/dist/src/core/mochitest-server-port.js +17 -17
- package/dist/src/core/module-resolution-preflight.d.ts +8 -8
- package/dist/src/core/module-resolution-preflight.js +11 -11
- package/dist/src/core/moz-manifest-helpers.d.ts +7 -7
- package/dist/src/core/moz-manifest-helpers.js +7 -7
- package/dist/src/core/moz-manifest-register.d.ts +1 -1
- package/dist/src/core/moz-manifest-register.js +2 -2
- package/dist/src/core/moz-manifest-rules.js +46 -42
- package/dist/src/core/moz-manifest-tokenizers.js +1 -1
- package/dist/src/core/ownership-table.d.ts +5 -5
- package/dist/src/core/ownership-table.js +7 -7
- package/dist/src/core/parser-fallback.d.ts +3 -3
- package/dist/src/core/parser-fallback.js +3 -3
- package/dist/src/core/patch-apply-fuzz.d.ts +5 -5
- package/dist/src/core/patch-apply-fuzz.js +13 -13
- package/dist/src/core/patch-apply.d.ts +13 -14
- package/dist/src/core/patch-apply.js +36 -42
- package/dist/src/core/patch-export-coverage.d.ts +0 -9
- package/dist/src/core/patch-export-coverage.js +1 -30
- package/dist/src/core/patch-export-update.d.ts +21 -4
- package/dist/src/core/patch-export-update.js +7 -6
- package/dist/src/core/patch-export.d.ts +20 -30
- package/dist/src/core/patch-export.js +55 -77
- package/dist/src/core/patch-files.d.ts +0 -4
- package/dist/src/core/patch-files.js +0 -11
- package/dist/src/core/patch-identifier-suggest.d.ts +1 -1
- package/dist/src/core/patch-identifier-suggest.js +4 -4
- package/dist/src/core/patch-lint-binary.d.ts +12 -18
- package/dist/src/core/patch-lint-cache.d.ts +18 -2
- package/dist/src/core/patch-lint-cache.js +16 -19
- package/dist/src/core/patch-lint-checkjs.d.ts +55 -38
- package/dist/src/core/patch-lint-checkjs.js +78 -64
- package/dist/src/core/patch-lint-chrome-jsdoc.d.ts +8 -9
- package/dist/src/core/patch-lint-chrome-jsdoc.js +10 -11
- package/dist/src/core/patch-lint-creators.d.ts +5 -9
- package/dist/src/core/patch-lint-creators.js +3 -3
- package/dist/src/core/patch-lint-cross.d.ts +27 -19
- package/dist/src/core/patch-lint-cross.js +67 -110
- package/dist/src/core/patch-lint-css.d.ts +1 -1
- package/dist/src/core/patch-lint-css.js +15 -11
- package/dist/src/core/patch-lint-diff-tag.d.ts +5 -5
- package/dist/src/core/patch-lint-diff-tag.js +5 -5
- package/dist/src/core/patch-lint-diff.d.ts +4 -4
- package/dist/src/core/patch-lint-diff.js +4 -4
- package/dist/src/core/patch-lint-file-size.d.ts +3 -3
- package/dist/src/core/patch-lint-file-size.js +6 -6
- package/dist/src/core/patch-lint-forward-registration.d.ts +58 -0
- package/dist/src/core/patch-lint-forward-registration.js +210 -0
- package/dist/src/core/patch-lint-jsdoc.d.ts +2 -2
- package/dist/src/core/patch-lint-jsdoc.js +46 -46
- package/dist/src/core/patch-lint-module-registration.d.ts +3 -9
- package/dist/src/core/patch-lint-module-registration.js +1 -1
- package/dist/src/core/patch-lint-mozbuild.d.ts +1 -1
- package/dist/src/core/patch-lint-mozbuild.js +10 -10
- package/dist/src/core/patch-lint-observer.d.ts +3 -3
- package/dist/src/core/patch-lint-observer.js +7 -7
- package/dist/src/core/patch-lint-ownership.d.ts +6 -6
- package/dist/src/core/patch-lint-ownership.js +6 -6
- package/dist/src/core/patch-lint-prettier.d.ts +6 -6
- package/dist/src/core/patch-lint-prettier.js +7 -7
- package/dist/src/core/patch-lint-queue-types.d.ts +60 -0
- package/dist/src/core/patch-lint-queue-types.js +12 -0
- package/dist/src/core/patch-lint-staged-registration.d.ts +61 -0
- package/dist/src/core/patch-lint-staged-registration.js +90 -0
- package/dist/src/core/patch-lint-unmanaged-companion.d.ts +23 -23
- package/dist/src/core/patch-lint-unmanaged-companion.js +26 -26
- package/dist/src/core/patch-lint.d.ts +41 -35
- package/dist/src/core/patch-lint.js +52 -49
- package/dist/src/core/patch-lock.d.ts +1 -1
- package/dist/src/core/patch-lock.js +11 -11
- package/dist/src/core/patch-manifest-consistency.d.ts +7 -7
- package/dist/src/core/patch-manifest-consistency.js +16 -17
- package/dist/src/core/patch-manifest-files-affected.d.ts +1 -1
- package/dist/src/core/patch-manifest-files-affected.js +3 -3
- package/dist/src/core/patch-manifest-io.d.ts +14 -14
- package/dist/src/core/patch-manifest-io.js +35 -34
- package/dist/src/core/patch-manifest-query.d.ts +1 -1
- package/dist/src/core/patch-manifest-query.js +4 -4
- package/dist/src/core/patch-manifest-resolve.d.ts +5 -5
- package/dist/src/core/patch-manifest-resolve.js +7 -7
- package/dist/src/core/patch-manifest-validate.js +3 -3
- package/dist/src/core/patch-manifest.d.ts +2 -2
- package/dist/src/core/patch-manifest.js +2 -2
- package/dist/src/core/patch-parse.d.ts +32 -21
- package/dist/src/core/patch-parse.js +40 -15
- package/dist/src/core/patch-policy.js +15 -27
- package/dist/src/core/patch-registration-refs.d.ts +4 -4
- package/dist/src/core/patch-registration-refs.js +7 -7
- package/dist/src/core/patch-source-metadata.d.ts +1 -3
- package/dist/src/core/patch-source-metadata.js +0 -4
- package/dist/src/core/patch-transform.d.ts +8 -16
- package/dist/src/core/patch-transform.js +13 -23
- package/dist/src/core/process-cpu-time.d.ts +1 -1
- package/dist/src/core/process-cpu-time.js +6 -6
- package/dist/src/core/rebase-session.d.ts +9 -15
- package/dist/src/core/rebase-session.js +13 -25
- package/dist/src/core/register-browser-content.js +3 -2
- package/dist/src/core/register-browser-test.js +2 -1
- package/dist/src/core/register-module.js +2 -1
- package/dist/src/core/register-result.d.ts +1 -1
- package/dist/src/core/register-result.js +1 -1
- package/dist/src/core/register-scaffold.d.ts +2 -2
- package/dist/src/core/register-scaffold.js +8 -7
- package/dist/src/core/register-shared-css.d.ts +3 -3
- package/dist/src/core/register-shared-css.js +6 -5
- package/dist/src/core/register-xpcshell-test.d.ts +2 -2
- package/dist/src/core/register-xpcshell-test.js +2 -2
- package/dist/src/core/run-log-redact.d.ts +38 -0
- package/dist/src/core/run-log-redact.js +69 -0
- package/dist/src/core/run-log.d.ts +21 -10
- package/dist/src/core/run-log.js +76 -27
- package/dist/src/core/shared-ftl.d.ts +2 -2
- package/dist/src/core/shared-ftl.js +6 -6
- package/dist/src/core/signal-critical.d.ts +2 -2
- package/dist/src/core/signal-critical.js +4 -6
- package/dist/src/core/smoke-patterns.d.ts +5 -6
- package/dist/src/core/smoke-patterns.js +15 -20
- package/dist/src/core/state-file.d.ts +15 -4
- package/dist/src/core/state-file.js +14 -1
- package/dist/src/core/status-binary.d.ts +8 -8
- package/dist/src/core/status-binary.js +12 -12
- package/dist/src/core/status-classify.d.ts +17 -17
- package/dist/src/core/status-classify.js +13 -12
- package/dist/src/core/test-changed-prefs.d.ts +12 -12
- package/dist/src/core/test-changed-prefs.js +40 -25
- package/dist/src/core/test-harness-crash.d.ts +39 -39
- package/dist/src/core/test-harness-crash.js +69 -69
- package/dist/src/core/test-harness-output.d.ts +7 -7
- package/dist/src/core/test-harness-output.js +7 -7
- package/dist/src/core/test-harness-verdict-notes.d.ts +13 -14
- package/dist/src/core/test-harness-verdict-notes.js +4 -4
- package/dist/src/core/test-path-scope.d.ts +8 -8
- package/dist/src/core/test-path-scope.js +11 -11
- package/dist/src/core/test-stale-check.d.ts +22 -23
- package/dist/src/core/test-stale-check.js +31 -30
- package/dist/src/core/test-stale-symlink.d.ts +1 -1
- package/dist/src/core/test-stale-symlink.js +1 -1
- package/dist/src/core/test-stall-triage.d.ts +9 -9
- package/dist/src/core/test-stall-triage.js +22 -22
- package/dist/src/core/test-xpcshell-retry.d.ts +26 -7
- package/dist/src/core/test-xpcshell-retry.js +14 -11
- package/dist/src/core/token-category.d.ts +35 -2
- package/dist/src/core/token-category.js +67 -58
- package/dist/src/core/token-coverage.js +4 -5
- package/dist/src/core/token-dark-mode.d.ts +9 -9
- package/dist/src/core/token-dark-mode.js +13 -25
- package/dist/src/core/token-docs.d.ts +1 -1
- package/dist/src/core/token-inventory.d.ts +56 -0
- package/dist/src/core/token-inventory.js +109 -0
- package/dist/src/core/token-manager.d.ts +4 -4
- package/dist/src/core/token-manager.js +22 -22
- package/dist/src/core/token-scaffold.d.ts +4 -4
- package/dist/src/core/token-scaffold.js +4 -4
- package/dist/src/core/token-variant.d.ts +14 -14
- package/dist/src/core/token-variant.js +52 -53
- package/dist/src/core/toolchain-preflight.d.ts +15 -15
- package/dist/src/core/toolchain-preflight.js +23 -23
- package/dist/src/core/tree-cow.d.ts +3 -5
- package/dist/src/core/tree-cow.js +8 -8
- package/dist/src/core/tree-guard.d.ts +3 -3
- package/dist/src/core/tree-guard.js +23 -23
- package/dist/src/core/tree-store.d.ts +15 -15
- package/dist/src/core/tree-store.js +39 -38
- package/dist/src/core/typecheck-shim.d.ts +16 -15
- package/dist/src/core/typecheck-shim.js +26 -25
- package/dist/src/core/typecheck.d.ts +12 -12
- package/dist/src/core/typecheck.js +33 -33
- package/dist/src/core/wire-destroy.d.ts +2 -2
- package/dist/src/core/wire-destroy.js +5 -5
- package/dist/src/core/wire-dom-fragment.d.ts +3 -3
- package/dist/src/core/wire-dom-fragment.js +12 -23
- package/dist/src/core/wire-init.d.ts +2 -2
- package/dist/src/core/wire-init.js +7 -7
- package/dist/src/core/wire-subscript.d.ts +1 -1
- package/dist/src/core/wire-subscript.js +3 -3
- package/dist/src/core/wire-utils.d.ts +9 -9
- package/dist/src/core/wire-utils.js +16 -28
- package/dist/src/core/xpcshell-appdir.d.ts +20 -20
- package/dist/src/core/xpcshell-appdir.js +28 -30
- package/dist/src/core/xpcshell-profile-dir.d.ts +3 -3
- package/dist/src/core/xpcshell-profile-dir.js +7 -7
- package/dist/src/errors/base.d.ts +69 -16
- package/dist/src/errors/base.js +95 -26
- package/dist/src/errors/build.d.ts +6 -6
- package/dist/src/errors/build.js +26 -34
- package/dist/src/errors/codes.d.ts +10 -10
- package/dist/src/errors/codes.js +10 -10
- package/dist/src/errors/config.d.ts +0 -14
- package/dist/src/errors/config.js +13 -34
- package/dist/src/errors/download.d.ts +13 -0
- package/dist/src/errors/download.js +53 -24
- package/dist/src/errors/furnace.d.ts +2 -2
- package/dist/src/errors/furnace.js +8 -9
- package/dist/src/errors/git.d.ts +9 -9
- package/dist/src/errors/git.js +21 -31
- package/dist/src/errors/patch.d.ts +3 -3
- package/dist/src/errors/patch.js +11 -13
- package/dist/src/errors/rebase.d.ts +1 -1
- package/dist/src/errors/rebase.js +8 -8
- package/dist/src/errors/run.d.ts +1 -1
- package/dist/src/errors/run.js +1 -1
- package/dist/src/index.d.ts +4 -4
- package/dist/src/index.js +4 -4
- package/dist/src/types/commands/options.d.ts +155 -200
- package/dist/src/types/commands/patches.d.ts +19 -19
- package/dist/src/types/commands/project.d.ts +3 -3
- package/dist/src/types/config.d.ts +52 -19
- package/dist/src/types/furnace.d.ts +17 -17
- package/dist/src/types/index.d.ts +0 -1
- package/dist/src/types/json.d.ts +3 -3
- package/dist/src/types/json.js +2 -2
- package/dist/src/types/typecheck.d.ts +3 -3
- package/dist/src/utils/assert.d.ts +4 -16
- package/dist/src/utils/assert.js +7 -24
- package/dist/src/utils/build-info.d.ts +6 -6
- package/dist/src/utils/build-info.js +6 -6
- package/dist/src/utils/child-env.d.ts +7 -6
- package/dist/src/utils/child-env.js +5 -5
- package/dist/src/utils/concurrency.d.ts +2 -2
- package/dist/src/utils/concurrency.js +2 -2
- package/dist/src/utils/elapsed.js +10 -1
- package/dist/src/utils/errors.d.ts +8 -8
- package/dist/src/utils/errors.js +8 -8
- package/dist/src/utils/fs.d.ts +1 -1
- package/dist/src/utils/fs.js +15 -20
- package/dist/src/utils/hash.d.ts +12 -0
- package/dist/src/utils/hash.js +16 -0
- package/dist/src/utils/line-dispatch.d.ts +15 -0
- package/dist/src/utils/line-dispatch.js +48 -0
- package/dist/src/utils/logger.d.ts +4 -4
- package/dist/src/utils/logger.js +11 -11
- package/dist/src/utils/machine-output.js +2 -2
- package/dist/src/utils/options.d.ts +14 -20
- package/dist/src/utils/options.js +26 -27
- package/dist/src/utils/package-root.js +5 -14
- package/dist/src/utils/paths.d.ts +4 -4
- package/dist/src/utils/paths.js +4 -4
- package/dist/src/utils/platform.d.ts +0 -4
- package/dist/src/utils/process-group.d.ts +10 -9
- package/dist/src/utils/process-group.js +37 -36
- package/dist/src/utils/process.d.ts +70 -55
- package/dist/src/utils/process.js +129 -179
- package/dist/src/utils/ps-duration.d.ts +4 -4
- package/dist/src/utils/ps-duration.js +9 -9
- package/dist/src/utils/regex.d.ts +4 -4
- package/dist/src/utils/regex.js +7 -7
- package/dist/src/utils/sleep.d.ts +26 -0
- package/dist/src/utils/sleep.js +31 -0
- package/dist/src/utils/stdio-drain.d.ts +7 -7
- package/dist/src/utils/stdio-drain.js +8 -8
- package/dist/src/utils/validation.d.ts +12 -49
- package/dist/src/utils/validation.js +26 -36
- package/docs/README.md +2 -2
- package/docs/configuration.md +163 -69
- package/docs/exit-codes.md +66 -49
- package/docs/furnace.md +20 -19
- package/docs/lifecycle-invariants.md +414 -247
- package/docs/machine-output.md +58 -34
- package/docs/patch-workflow.md +48 -44
- package/docs/run-logs.md +72 -28
- package/docs/testing.md +105 -98
- package/docs/verification-trees.md +23 -22
- package/package.json +7 -6
- package/dist/src/commands/rebase.d.ts +0 -4
- package/dist/src/commands/rebase.js +0 -5
- package/dist/src/core/patch-artifact-normalize.d.ts +0 -21
- package/dist/src/core/patch-artifact-normalize.js +0 -24
- package/dist/src/core/patch-lint-reexports.d.ts +0 -7
- package/dist/src/core/patch-lint-reexports.js +0 -8
- package/dist/src/core/wire-targets.d.ts +0 -7
- package/dist/src/core/wire-targets.js +0 -8
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
// SPDX-License-Identifier: EUPL-1.2
|
|
2
|
+
/**
|
|
3
|
+
* Conservative secret redaction for the run-log FILE tee.
|
|
4
|
+
*
|
|
5
|
+
* A run log is a complete copy of mach's output, and mach echoes its
|
|
6
|
+
* environment in places (configure summaries, `mach env`, harness
|
|
7
|
+
* diagnostics that print the command line). The terminal already showed
|
|
8
|
+
* every byte to the operator who ran it. The file, by contrast, is retained
|
|
9
|
+
* twenty deep and gets attached to bug reports. So the file gets a narrow
|
|
10
|
+
* masking pass and the terminal does not.
|
|
11
|
+
*
|
|
12
|
+
* Minimal and pattern-based. See {@link redactRunLogText} for the exact
|
|
13
|
+
* contract. It is a seatbelt against the common accidental leak, not a
|
|
14
|
+
* guarantee that a log is free of secrets.
|
|
15
|
+
*/
|
|
16
|
+
/** Env-style keys whose assigned value is masked. */
|
|
17
|
+
const SECRET_KEY_PATTERN = /(TOKEN|SECRET|PASSWORD|PASSWD|API_KEY|AUTH)/i;
|
|
18
|
+
/**
|
|
19
|
+
* `KEY=value` where KEY is an identifier and the value runs to the next
|
|
20
|
+
* whitespace, or is a single/double-quoted string. The leading group keeps
|
|
21
|
+
* the assignment anchored at a token boundary so `x.y=z` is not split
|
|
22
|
+
* mid-token. A hyphen IS a boundary: mach and configure echo their argv, so
|
|
23
|
+
* `--token=…`, `--password=…` and `-DAUTH_TOKEN=…` are exactly the forms a
|
|
24
|
+
* retained log would otherwise carry verbatim (the lead keeps the dash, and
|
|
25
|
+
* the key is what follows it). Empty values are left alone (nothing to hide).
|
|
26
|
+
*/
|
|
27
|
+
const ENV_ASSIGNMENT_PATTERN = /(^|[\s"'([{,;-])([A-Za-z_][A-Za-z0-9_]*)=("(?:[^"\\]|\\.)*"|'[^']*'|[^\s"',;)\]}]+)/g;
|
|
28
|
+
/** `Authorization: <scheme> <credential>` (scheme optional) in HTTP dumps. */
|
|
29
|
+
const AUTHORIZATION_HEADER_PATTERN = /(authorization\s*:\s*)(?:(bearer|basic|token)\s+)?(\S+)/gi;
|
|
30
|
+
/** Marker written in place of a masked value. */
|
|
31
|
+
const REDACTED = '<redacted>';
|
|
32
|
+
function redactLine(line) {
|
|
33
|
+
return line
|
|
34
|
+
.replace(ENV_ASSIGNMENT_PATTERN, (whole, lead, key) => SECRET_KEY_PATTERN.test(key) ? `${lead}${key}=${REDACTED}` : whole)
|
|
35
|
+
.replace(AUTHORIZATION_HEADER_PATTERN, (_whole, lead, scheme) => scheme === undefined ? `${lead}${REDACTED}` : `${lead}${scheme} ${REDACTED}`);
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Masks the obvious secret shapes in run-log text, line by line.
|
|
39
|
+
*
|
|
40
|
+
* Redacted:
|
|
41
|
+
* - the value of an env-style assignment `KEY=value` whose KEY matches
|
|
42
|
+
* `/(TOKEN|SECRET|PASSWORD|PASSWD|API_KEY|AUTH)/i`. The value up to the
|
|
43
|
+
* next whitespace, or a whole quoted string, becomes `KEY=<redacted>`.
|
|
44
|
+
* The `--flag=value` and `-DNAME=value` spellings of the same shape are
|
|
45
|
+
* covered (`--password=x` → `--password=<redacted>`).
|
|
46
|
+
* - the credential of an `Authorization:` header (`Bearer`, `Basic` and
|
|
47
|
+
* `Token` schemes keep the scheme word, and anything else masks the
|
|
48
|
+
* whole value).
|
|
49
|
+
*
|
|
50
|
+
* Not redacted: secrets that appear without one of those key names or
|
|
51
|
+
* headers (a bare token in a URL query string, a space-separated
|
|
52
|
+
* `--password foo` CLI argument, JSON `"token": "..."` fields, cookies).
|
|
53
|
+
* Line structure and every other byte pass through unchanged. `\n`, `\r\n`
|
|
54
|
+
* and lone `\r` all delimit lines, so carriage-return-repainted progress
|
|
55
|
+
* output is masked per repaint.
|
|
56
|
+
*
|
|
57
|
+
* @param text - One or more complete lines
|
|
58
|
+
* @returns The same text with masked values
|
|
59
|
+
*/
|
|
60
|
+
export function redactRunLogText(text) {
|
|
61
|
+
if (text.length === 0)
|
|
62
|
+
return text;
|
|
63
|
+
// Split with a capturing group so the terminators survive the round trip.
|
|
64
|
+
// Odd indices are the terminators themselves.
|
|
65
|
+
return text
|
|
66
|
+
.split(/(\r\n|\n|\r)/)
|
|
67
|
+
.map((part, index) => (index % 2 === 0 ? redactLine(part) : part))
|
|
68
|
+
.join('');
|
|
69
|
+
}
|
|
@@ -2,19 +2,19 @@
|
|
|
2
2
|
* Per-run output logs under `.fireforge/logs/`.
|
|
3
3
|
*
|
|
4
4
|
* A run's diagnosis used to exist in exactly one place: the terminal. Piping
|
|
5
|
-
* through `tail`/`grep
|
|
6
|
-
* the summary and discards the `TEST-UNEXPECTED-FAIL` lines that say
|
|
5
|
+
* through `tail`/`grep`, the ergonomic default when output is long, keeps
|
|
6
|
+
* the summary and discards the `TEST-UNEXPECTED-FAIL` lines that say what
|
|
7
7
|
* broke, and it launders the exit code besides. The operator rule ("never
|
|
8
8
|
* pipe a run") was written down three times downstream and broken after each
|
|
9
|
-
* writing,
|
|
10
|
-
*
|
|
9
|
+
* writing, so this is not an operator problem: the tool is the only party
|
|
10
|
+
* that can make the log survive the mistake.
|
|
11
11
|
*
|
|
12
12
|
* So `test` and `build` write their own complete copy as they stream, and the
|
|
13
13
|
* `FIREFORGE-VERDICT:` line names the path. A piped, truncated, or
|
|
14
14
|
* backgrounded run then still leaves a re-readable artifact.
|
|
15
15
|
*
|
|
16
|
-
* Everything here is
|
|
17
|
-
*
|
|
16
|
+
* Everything here is best-effort. A log is a diagnostic aid, and a run must
|
|
17
|
+
* never fail because one could not be opened, written, or pruned.
|
|
18
18
|
* Every entry point swallows its errors and degrades to "no log", which is
|
|
19
19
|
* exactly the behaviour that existed before this module.
|
|
20
20
|
*/
|
|
@@ -22,7 +22,11 @@
|
|
|
22
22
|
export interface RunLog {
|
|
23
23
|
/** Absolute path to the log file. */
|
|
24
24
|
path: string;
|
|
25
|
-
/**
|
|
25
|
+
/**
|
|
26
|
+
* Appends output. Complete lines pass through {@link redactRunLogText}
|
|
27
|
+
* before hitting disk. A trailing partial line is held until its newline
|
|
28
|
+
* arrives (or until `close`). Silently drops on any stream error.
|
|
29
|
+
*/
|
|
26
30
|
write: (chunk: string) => void;
|
|
27
31
|
/** Flushes and closes. Resolves even when the stream already failed. */
|
|
28
32
|
close: () => Promise<void>;
|
|
@@ -45,13 +49,20 @@ export declare function setActiveRunLog(log: RunLog | undefined): void;
|
|
|
45
49
|
export declare function getActiveRunLogPath(): string | undefined;
|
|
46
50
|
/** Appends to the active run log. A no-op when none is open. */
|
|
47
51
|
export declare function writeToActiveRunLog(chunk: string): void;
|
|
48
|
-
/**
|
|
52
|
+
/**
|
|
53
|
+
* Closes and clears the active run log. Resolves even when none is open.
|
|
54
|
+
*
|
|
55
|
+
* Also called from the entry point's SIGINT/SIGTERM path: the held partial
|
|
56
|
+
* line and anything queued in the stream would otherwise be lost across
|
|
57
|
+
* `process.exit`, and a killed run's last line is usually the one that
|
|
58
|
+
* says what it was doing.
|
|
59
|
+
*/
|
|
49
60
|
export declare function closeActiveRunLog(): Promise<void>;
|
|
50
61
|
/**
|
|
51
|
-
* A writable that forwards to `base`
|
|
62
|
+
* A writable that forwards to `base` and to the active run log.
|
|
52
63
|
*
|
|
53
64
|
* Used by the stdio-inheriting capture path, whose collectors take a mirror
|
|
54
|
-
* stream rather than per-chunk callbacks
|
|
65
|
+
* stream rather than per-chunk callbacks, so the tee reuses the mirror the
|
|
55
66
|
* exec layer already supports instead of growing a second hook.
|
|
56
67
|
*
|
|
57
68
|
* @param base - The stream to forward to (normally `process.stdout`)
|
package/dist/src/core/run-log.js
CHANGED
|
@@ -3,19 +3,19 @@
|
|
|
3
3
|
* Per-run output logs under `.fireforge/logs/`.
|
|
4
4
|
*
|
|
5
5
|
* A run's diagnosis used to exist in exactly one place: the terminal. Piping
|
|
6
|
-
* through `tail`/`grep
|
|
7
|
-
* the summary and discards the `TEST-UNEXPECTED-FAIL` lines that say
|
|
6
|
+
* through `tail`/`grep`, the ergonomic default when output is long, keeps
|
|
7
|
+
* the summary and discards the `TEST-UNEXPECTED-FAIL` lines that say what
|
|
8
8
|
* broke, and it launders the exit code besides. The operator rule ("never
|
|
9
9
|
* pipe a run") was written down three times downstream and broken after each
|
|
10
|
-
* writing,
|
|
11
|
-
*
|
|
10
|
+
* writing, so this is not an operator problem: the tool is the only party
|
|
11
|
+
* that can make the log survive the mistake.
|
|
12
12
|
*
|
|
13
13
|
* So `test` and `build` write their own complete copy as they stream, and the
|
|
14
14
|
* `FIREFORGE-VERDICT:` line names the path. A piped, truncated, or
|
|
15
15
|
* backgrounded run then still leaves a re-readable artifact.
|
|
16
16
|
*
|
|
17
|
-
* Everything here is
|
|
18
|
-
*
|
|
17
|
+
* Everything here is best-effort. A log is a diagnostic aid, and a run must
|
|
18
|
+
* never fail because one could not be opened, written, or pruned.
|
|
19
19
|
* Every entry point swallows its errors and degrades to "no log", which is
|
|
20
20
|
* exactly the behaviour that existed before this module.
|
|
21
21
|
*/
|
|
@@ -23,8 +23,11 @@ import { createWriteStream } from 'node:fs';
|
|
|
23
23
|
import { mkdir, readdir, unlink } from 'node:fs/promises';
|
|
24
24
|
import { join } from 'node:path';
|
|
25
25
|
import { Writable } from 'node:stream';
|
|
26
|
+
import { toError } from '../utils/errors.js';
|
|
26
27
|
import { verbose } from '../utils/logger.js';
|
|
27
28
|
import { FIREFORGE_DIR } from './config-paths.js';
|
|
29
|
+
import { redactRunLogText } from './run-log-redact.js';
|
|
30
|
+
import { fileSafeTimestamp } from './state-file.js';
|
|
28
31
|
/** Directory under `.fireforge/` holding run logs. */
|
|
29
32
|
const LOGS_DIRNAME = 'logs';
|
|
30
33
|
/**
|
|
@@ -33,24 +36,38 @@ const LOGS_DIRNAME = 'logs';
|
|
|
33
36
|
* most often needs to read together.
|
|
34
37
|
*/
|
|
35
38
|
const RETAINED_LOGS_PER_COMMAND = 20;
|
|
39
|
+
/**
|
|
40
|
+
* Cap on the partial line held back between writes. A child emitting one
|
|
41
|
+
* enormous unterminated line (a minified dump on stderr) would otherwise
|
|
42
|
+
* grow the buffer without bound (and, because each write rebuilds
|
|
43
|
+
* `pending + chunk`, quadratically), with nothing reaching disk until
|
|
44
|
+
* close. Past the cap the tail is redacted and written as-is. A `KEY=value`
|
|
45
|
+
* split exactly at the cap boundary is the accepted cost. Same figure as
|
|
46
|
+
* `line-dispatch.ts` uses for the stream matchers.
|
|
47
|
+
*/
|
|
48
|
+
const MAX_PENDING_LINE_SIZE = 1024 * 1024;
|
|
49
|
+
/**
|
|
50
|
+
* Index just past the last line terminator in `text`, or -1 when there is
|
|
51
|
+
* none. `\n` and lone `\r` both terminate: progress-bar output (mach,
|
|
52
|
+
* cargo) repaints a line with carriage returns and may never send a
|
|
53
|
+
* newline, which would otherwise pin the whole run in `pending`. A single
|
|
54
|
+
* trailing `\r` is not a terminator yet: it may be the first half of a
|
|
55
|
+
* `\r\n` split across chunks.
|
|
56
|
+
*/
|
|
57
|
+
function lastLineEnd(text) {
|
|
58
|
+
const lastNewline = text.lastIndexOf('\n');
|
|
59
|
+
const lastReturn = text.lastIndexOf('\r');
|
|
60
|
+
const cut = lastReturn > lastNewline && lastReturn < text.length - 1 ? lastReturn : lastNewline;
|
|
61
|
+
return cut === -1 ? -1 : cut + 1;
|
|
62
|
+
}
|
|
36
63
|
/** `.fireforge/logs` under `projectRoot`. */
|
|
37
64
|
export function getRunLogDir(projectRoot) {
|
|
38
65
|
return join(projectRoot, FIREFORGE_DIR, LOGS_DIRNAME);
|
|
39
66
|
}
|
|
40
|
-
/**
|
|
41
|
-
* A filesystem-safe, sortable timestamp: `2026-08-28T14-32-05-123Z`.
|
|
42
|
-
*
|
|
43
|
-
* Colons are not portable in filenames (Windows rejects them outright), so
|
|
44
|
-
* the ISO form is punctuated with dashes only. Lexical order still equals
|
|
45
|
-
* chronological order, which is what the pruning below relies on.
|
|
46
|
-
*/
|
|
47
|
-
function logTimestamp(now) {
|
|
48
|
-
return now.toISOString().replace(/[:.]/g, '-');
|
|
49
|
-
}
|
|
50
67
|
/**
|
|
51
68
|
* Makes room for one new log by deleting the oldest, so that at most
|
|
52
69
|
* {@link RETAINED_LOGS_PER_COMMAND} logs for `command` exist once the new
|
|
53
|
-
* one is created. Pruning runs
|
|
70
|
+
* one is created. Pruning runs before the file is opened, hence the
|
|
54
71
|
* `- 1`, without which the directory settles at N + 1.
|
|
55
72
|
*
|
|
56
73
|
* Best-effort: a failure here must not stop the run that is about to be
|
|
@@ -76,7 +93,7 @@ async function pruneRunLogs(dir, command) {
|
|
|
76
93
|
}));
|
|
77
94
|
}
|
|
78
95
|
catch (error) {
|
|
79
|
-
verbose(`Run-log pruning skipped: ${
|
|
96
|
+
verbose(`Run-log pruning skipped: ${toError(error).message}`);
|
|
80
97
|
}
|
|
81
98
|
}
|
|
82
99
|
/**
|
|
@@ -91,14 +108,14 @@ async function pruneRunLogs(dir, command) {
|
|
|
91
108
|
export async function openRunLog(projectRoot, command, now = new Date()) {
|
|
92
109
|
const dir = getRunLogDir(projectRoot);
|
|
93
110
|
let stream;
|
|
94
|
-
const path = join(dir, `${command}-${
|
|
111
|
+
const path = join(dir, `${command}-${fileSafeTimestamp(now)}.log`);
|
|
95
112
|
try {
|
|
96
113
|
await mkdir(dir, { recursive: true });
|
|
97
114
|
await pruneRunLogs(dir, command);
|
|
98
115
|
stream = createWriteStream(path, { flags: 'a' });
|
|
99
116
|
}
|
|
100
117
|
catch (error) {
|
|
101
|
-
verbose(`Run log unavailable (${path}): ${
|
|
118
|
+
verbose(`Run log unavailable (${path}): ${toError(error).message}`);
|
|
102
119
|
return undefined;
|
|
103
120
|
}
|
|
104
121
|
// A stream error after open (disk full, a removed directory) must not
|
|
@@ -109,19 +126,44 @@ export async function openRunLog(projectRoot, command, now = new Date()) {
|
|
|
109
126
|
broken = true;
|
|
110
127
|
verbose(`Run log write failed (${path}): ${error.message}`);
|
|
111
128
|
});
|
|
129
|
+
// Redaction is per LINE, and chunks arrive at arbitrary byte boundaries,
|
|
130
|
+
// so a `KEY=value` split across two chunks would slip past a per-chunk
|
|
131
|
+
// pass. Hold the trailing partial line until its terminator arrives (or
|
|
132
|
+
// it outgrows MAX_PENDING_LINE_SIZE, or the log is closed).
|
|
133
|
+
let pending = '';
|
|
134
|
+
const emit = (text) => {
|
|
135
|
+
if (broken || text.length === 0)
|
|
136
|
+
return;
|
|
137
|
+
try {
|
|
138
|
+
stream.write(redactRunLogText(text));
|
|
139
|
+
}
|
|
140
|
+
catch {
|
|
141
|
+
broken = true;
|
|
142
|
+
}
|
|
143
|
+
};
|
|
112
144
|
return {
|
|
113
145
|
path,
|
|
114
146
|
write: (chunk) => {
|
|
115
147
|
if (broken)
|
|
116
148
|
return;
|
|
117
|
-
|
|
118
|
-
|
|
149
|
+
const buffered = pending + chunk;
|
|
150
|
+
const lineEnd = lastLineEnd(buffered);
|
|
151
|
+
if (lineEnd === -1) {
|
|
152
|
+
pending = buffered;
|
|
119
153
|
}
|
|
120
|
-
|
|
121
|
-
|
|
154
|
+
else {
|
|
155
|
+
pending = buffered.slice(lineEnd);
|
|
156
|
+
emit(buffered.slice(0, lineEnd));
|
|
157
|
+
}
|
|
158
|
+
if (pending.length > MAX_PENDING_LINE_SIZE) {
|
|
159
|
+
emit(pending);
|
|
160
|
+
pending = '';
|
|
122
161
|
}
|
|
123
162
|
},
|
|
124
163
|
close: async () => {
|
|
164
|
+
const tail = pending;
|
|
165
|
+
pending = '';
|
|
166
|
+
emit(tail);
|
|
125
167
|
await new Promise((resolve) => {
|
|
126
168
|
stream.end(() => {
|
|
127
169
|
resolve();
|
|
@@ -155,17 +197,24 @@ export function getActiveRunLogPath() {
|
|
|
155
197
|
export function writeToActiveRunLog(chunk) {
|
|
156
198
|
activeRunLog?.write(chunk);
|
|
157
199
|
}
|
|
158
|
-
/**
|
|
200
|
+
/**
|
|
201
|
+
* Closes and clears the active run log. Resolves even when none is open.
|
|
202
|
+
*
|
|
203
|
+
* Also called from the entry point's SIGINT/SIGTERM path: the held partial
|
|
204
|
+
* line and anything queued in the stream would otherwise be lost across
|
|
205
|
+
* `process.exit`, and a killed run's last line is usually the one that
|
|
206
|
+
* says what it was doing.
|
|
207
|
+
*/
|
|
159
208
|
export async function closeActiveRunLog() {
|
|
160
209
|
const log = activeRunLog;
|
|
161
210
|
activeRunLog = undefined;
|
|
162
211
|
await log?.close();
|
|
163
212
|
}
|
|
164
213
|
/**
|
|
165
|
-
* A writable that forwards to `base`
|
|
214
|
+
* A writable that forwards to `base` and to the active run log.
|
|
166
215
|
*
|
|
167
216
|
* Used by the stdio-inheriting capture path, whose collectors take a mirror
|
|
168
|
-
* stream rather than per-chunk callbacks
|
|
217
|
+
* stream rather than per-chunk callbacks, so the tee reuses the mirror the
|
|
169
218
|
* exec layer already supports instead of growing a second hook.
|
|
170
219
|
*
|
|
171
220
|
* @param base - The stream to forward to (normally `process.stdout`)
|
|
@@ -2,13 +2,13 @@
|
|
|
2
2
|
* Structural rules for the `sharedFtl` field on a custom component.
|
|
3
3
|
*
|
|
4
4
|
* Both the `--shared-ftl` CLI flag path (`furnace create`) and the
|
|
5
|
-
* furnace.json parser apply the same rules
|
|
5
|
+
* furnace.json parser apply the same rules. Extracting them here
|
|
6
6
|
* avoids drift between the two entry points and lets the `.mjs`
|
|
7
7
|
* template generator assume the value is safe to interpolate verbatim.
|
|
8
8
|
*/
|
|
9
9
|
/**
|
|
10
10
|
* Outcome of {@link validateSharedFtl}. `ok: true` carries the trimmed
|
|
11
|
-
* (operator-safe) value
|
|
11
|
+
* (operator-safe) value. `ok: false` carries a human-readable message
|
|
12
12
|
* suitable for throwing as a `FurnaceError` or `InvalidArgumentError`.
|
|
13
13
|
*/
|
|
14
14
|
export type SharedFtlValidation = {
|
|
@@ -3,18 +3,18 @@
|
|
|
3
3
|
* Structural rules for the `sharedFtl` field on a custom component.
|
|
4
4
|
*
|
|
5
5
|
* Both the `--shared-ftl` CLI flag path (`furnace create`) and the
|
|
6
|
-
* furnace.json parser apply the same rules
|
|
6
|
+
* furnace.json parser apply the same rules. Extracting them here
|
|
7
7
|
* avoids drift between the two entry points and lets the `.mjs`
|
|
8
8
|
* template generator assume the value is safe to interpolate verbatim.
|
|
9
9
|
*/
|
|
10
10
|
/**
|
|
11
11
|
* Characters that must not appear in `sharedFtl`.
|
|
12
12
|
*
|
|
13
|
-
*
|
|
14
|
-
* boundary for the generated `.mjs
|
|
15
|
-
* sink with `JSON.stringify` (`commands/furnace/create-templates.ts`),
|
|
16
|
-
* is what actually makes interpolation safe and what covers the two
|
|
17
|
-
* this rule never catches
|
|
13
|
+
* This is a policy rule about what a sensible FTL path looks like, not the
|
|
14
|
+
* safety boundary for the generated `.mjs`. The scaffold escapes the value at
|
|
15
|
+
* its sink with `JSON.stringify` (`commands/furnace/create-templates.ts`),
|
|
16
|
+
* which is what actually makes interpolation safe, and what covers the two
|
|
17
|
+
* inputs this rule never catches: a `"` and a raw newline.
|
|
18
18
|
*
|
|
19
19
|
* Kept because each remains a real sign of a malformed path:
|
|
20
20
|
* - `\` is a path-escape we do not want to interpret.
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
* for the slot to clear before calling `process.exit`, so a signal that
|
|
14
14
|
* lands mid-body is held until the body's state write finishes.
|
|
15
15
|
*
|
|
16
|
-
* This module is a pure runtime registry
|
|
16
|
+
* This module is a pure runtime registry. It installs no signal handlers
|
|
17
17
|
* itself. The bin entry point is responsible for awaiting
|
|
18
18
|
* `waitForActiveCriticalSections` before terminating.
|
|
19
19
|
*/
|
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
* SIGTERM that arrives during `fn` will hold exit until `fn` returns (or
|
|
24
24
|
* rejects).
|
|
25
25
|
*
|
|
26
|
-
* `fn` should be short
|
|
26
|
+
* `fn` should be short. Anything that takes longer than the bounded wait in
|
|
27
27
|
* the bin handler (`SIGNAL_CRITICAL_SECTION_TIMEOUT_MS`) will time out and
|
|
28
28
|
* the handler will exit anyway. The intent is "guard the apply + state
|
|
29
29
|
* persist pair," not "postpone exit indefinitely."
|
|
@@ -14,10 +14,11 @@
|
|
|
14
14
|
* for the slot to clear before calling `process.exit`, so a signal that
|
|
15
15
|
* lands mid-body is held until the body's state write finishes.
|
|
16
16
|
*
|
|
17
|
-
* This module is a pure runtime registry
|
|
17
|
+
* This module is a pure runtime registry. It installs no signal handlers
|
|
18
18
|
* itself. The bin entry point is responsible for awaiting
|
|
19
19
|
* `waitForActiveCriticalSections` before terminating.
|
|
20
20
|
*/
|
|
21
|
+
import { sleep } from '../utils/sleep.js';
|
|
21
22
|
const activeSections = new Set();
|
|
22
23
|
/**
|
|
23
24
|
* Runs `fn` inside a signal-deferred critical section. The CLI entry point's
|
|
@@ -25,7 +26,7 @@ const activeSections = new Set();
|
|
|
25
26
|
* SIGTERM that arrives during `fn` will hold exit until `fn` returns (or
|
|
26
27
|
* rejects).
|
|
27
28
|
*
|
|
28
|
-
* `fn` should be short
|
|
29
|
+
* `fn` should be short. Anything that takes longer than the bounded wait in
|
|
29
30
|
* the bin handler (`SIGNAL_CRITICAL_SECTION_TIMEOUT_MS`) will time out and
|
|
30
31
|
* the handler will exit anyway. The intent is "guard the apply + state
|
|
31
32
|
* persist pair," not "postpone exit indefinitely."
|
|
@@ -57,8 +58,5 @@ export async function waitForActiveCriticalSections(timeoutMs) {
|
|
|
57
58
|
if (activeSections.size === 0)
|
|
58
59
|
return;
|
|
59
60
|
const snapshot = [...activeSections].map((s) => s.promise);
|
|
60
|
-
await Promise.race([
|
|
61
|
-
Promise.allSettled(snapshot).then(() => undefined),
|
|
62
|
-
new Promise((resolve) => setTimeout(resolve, timeoutMs)),
|
|
63
|
-
]);
|
|
61
|
+
await Promise.race([Promise.allSettled(snapshot).then(() => undefined), sleep(timeoutMs)]);
|
|
64
62
|
}
|
|
@@ -10,17 +10,16 @@
|
|
|
10
10
|
* warning (e.g. `"pending JavaScript error cleanup"`) do not start with
|
|
11
11
|
* the prefix and should not trip the scanner.
|
|
12
12
|
*/
|
|
13
|
-
export declare const SMOKE_ERROR_PATTERNS: readonly RegExp[];
|
|
14
13
|
/**
|
|
15
14
|
* Returns `true` when `line` matches any pattern in
|
|
16
|
-
* {@link SMOKE_ERROR_PATTERNS}. Does not consult the allowlist
|
|
15
|
+
* {@link SMOKE_ERROR_PATTERNS}. Does not consult the allowlist. That step
|
|
17
16
|
* lives in {@link matchAllowlist}, so the smoke runner can count
|
|
18
17
|
* allowlisted hits separately from raw error matches for its summary.
|
|
19
18
|
*/
|
|
20
19
|
export declare function matchesSmokeError(line: string): boolean;
|
|
21
20
|
/**
|
|
22
21
|
* One compiled allowlist entry with its provenance retained so the smoke
|
|
23
|
-
* summary can attribute hits per entry
|
|
22
|
+
* summary can attribute hits per entry. An entry that silently
|
|
24
23
|
* stops matching (its suppressed shape changed upstream) is only
|
|
25
24
|
* detectable when zero-hit entries are visible.
|
|
26
25
|
*/
|
|
@@ -33,16 +32,16 @@ export interface CompiledAllowlistEntry {
|
|
|
33
32
|
}
|
|
34
33
|
/**
|
|
35
34
|
* Returns the index of the FIRST entry in `allow` matching `line`, or -1.
|
|
36
|
-
* First-match attribution is deterministic and cheap
|
|
35
|
+
* First-match attribution is deterministic and cheap. A line matching
|
|
37
36
|
* several entries credits the earliest one. Safe to call with an empty
|
|
38
37
|
* allowlist (always returns -1).
|
|
39
38
|
*/
|
|
40
39
|
export declare function matchAllowlist(line: string, allow: readonly CompiledAllowlistEntry[]): number;
|
|
41
40
|
/**
|
|
42
|
-
* Parses a newline-delimited allowlist file body. Lines are trimmed
|
|
41
|
+
* Parses a newline-delimited allowlist file body. Lines are trimmed. Blank
|
|
43
42
|
* lines and `#`-prefixed comments are skipped. Each remaining line is
|
|
44
43
|
* compiled as a RegExp with its `<file>:<line>` origin retained. A bad
|
|
45
|
-
* pattern throws immediately
|
|
44
|
+
* pattern throws immediately: better to fail fast at CLI parse time than
|
|
46
45
|
* to silently let a typo match nothing.
|
|
47
46
|
*/
|
|
48
47
|
export declare function compileAllowlistFromFile(body: string, sourcePath: string): CompiledAllowlistEntry[];
|
|
@@ -16,25 +16,25 @@
|
|
|
16
16
|
* process. A hit on any of these patterns is a smoke failure unless the
|
|
17
17
|
* line also matches the caller-supplied allowlist.
|
|
18
18
|
*
|
|
19
|
-
* Additions here should be conservative
|
|
19
|
+
* Additions here should be conservative. False positives turn every
|
|
20
20
|
* smoke run into noise for operators and every CI run into flake.
|
|
21
21
|
*/
|
|
22
22
|
import { toError } from '../utils/errors.js';
|
|
23
|
-
|
|
24
|
-
// Firefox chrome error lines
|
|
23
|
+
const SMOKE_ERROR_PATTERNS = [
|
|
24
|
+
// Firefox chrome error lines: `JavaScript error: chrome://…, line N: TypeError: …`.
|
|
25
25
|
/^\s*JavaScript error:/i,
|
|
26
26
|
// Some log paths prefix browser-console `console.error(...)` with the literal label below.
|
|
27
27
|
/^\s*console\.error:/i,
|
|
28
28
|
// Older bracketed-prefix variant still seen in some chrome logs / test runs.
|
|
29
29
|
/^\s*\[JavaScript (Error|Warning)\]/i,
|
|
30
|
-
// IPC-layer fatal assertions
|
|
30
|
+
// IPC-layer fatal assertions. Firefox prints `###!!! [Parent] Error: …` on content-process crashes.
|
|
31
31
|
/^\s*###!!! \[Parent\]/,
|
|
32
32
|
// A chrome:// or resource:// URL that resolves to nothing. Outside
|
|
33
33
|
// automation Gecko only PRINTS this (printf_stderr in
|
|
34
|
-
// `CheckForBrokenChromeURL`, netwerk/base/nsNetUtil.cpp)
|
|
34
|
+
// `CheckForBrokenChromeURL`, netwerk/base/nsNetUtil.cpp). Under
|
|
35
35
|
// `xpc::IsInAutomation()` the same condition is a
|
|
36
36
|
// `MOZ_CRASH_UNSAFE_PRINTF` in whichever process opened the channel. So
|
|
37
|
-
// the smoke probe
|
|
37
|
+
// the smoke probe, which runs outside automation, sees the printed
|
|
38
38
|
// line for the same defect that hard-crashes every harness run, and a
|
|
39
39
|
// probe that exits 0 on it reports "startup is healthy" for a build that
|
|
40
40
|
// hangs at "Waiting for browser…". Both spellings are matched: the
|
|
@@ -44,7 +44,7 @@ export const SMOKE_ERROR_PATTERNS = [
|
|
|
44
44
|
];
|
|
45
45
|
/**
|
|
46
46
|
* Returns `true` when `line` matches any pattern in
|
|
47
|
-
* {@link SMOKE_ERROR_PATTERNS}. Does not consult the allowlist
|
|
47
|
+
* {@link SMOKE_ERROR_PATTERNS}. Does not consult the allowlist. That step
|
|
48
48
|
* lives in {@link matchAllowlist}, so the smoke runner can count
|
|
49
49
|
* allowlisted hits separately from raw error matches for its summary.
|
|
50
50
|
*/
|
|
@@ -58,23 +58,18 @@ export function matchesSmokeError(line) {
|
|
|
58
58
|
}
|
|
59
59
|
/**
|
|
60
60
|
* Returns the index of the FIRST entry in `allow` matching `line`, or -1.
|
|
61
|
-
* First-match attribution is deterministic and cheap
|
|
61
|
+
* First-match attribution is deterministic and cheap. A line matching
|
|
62
62
|
* several entries credits the earliest one. Safe to call with an empty
|
|
63
63
|
* allowlist (always returns -1).
|
|
64
64
|
*/
|
|
65
65
|
export function matchAllowlist(line, allow) {
|
|
66
|
-
|
|
67
|
-
if (allow[i]?.pattern.test(line)) {
|
|
68
|
-
return i;
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
|
-
return -1;
|
|
66
|
+
return allow.findIndex((entry) => entry.pattern.test(line));
|
|
72
67
|
}
|
|
73
68
|
/**
|
|
74
|
-
* Parses a newline-delimited allowlist file body. Lines are trimmed
|
|
69
|
+
* Parses a newline-delimited allowlist file body. Lines are trimmed. Blank
|
|
75
70
|
* lines and `#`-prefixed comments are skipped. Each remaining line is
|
|
76
71
|
* compiled as a RegExp with its `<file>:<line>` origin retained. A bad
|
|
77
|
-
* pattern throws immediately
|
|
72
|
+
* pattern throws immediately: better to fail fast at CLI parse time than
|
|
78
73
|
* to silently let a typo match nothing.
|
|
79
74
|
*/
|
|
80
75
|
export function compileAllowlistFromFile(body, sourcePath) {
|
|
@@ -88,12 +83,12 @@ export function compileAllowlistFromFile(body, sourcePath) {
|
|
|
88
83
|
compiled.push({
|
|
89
84
|
pattern: new RegExp(line),
|
|
90
85
|
source: line,
|
|
91
|
-
origin: `${sourcePath}:${
|
|
86
|
+
origin: `${sourcePath}:${index + 1}`,
|
|
92
87
|
});
|
|
93
88
|
}
|
|
94
89
|
catch (error) {
|
|
95
90
|
const message = toError(error).message;
|
|
96
|
-
throw new Error(`Invalid allowlist regex at ${sourcePath}:${
|
|
91
|
+
throw new Error(`Invalid allowlist regex at ${sourcePath}:${index + 1}: ${message}`, {
|
|
97
92
|
cause: error,
|
|
98
93
|
});
|
|
99
94
|
}
|
|
@@ -111,12 +106,12 @@ export function compileAllowlistFromStrings(sources) {
|
|
|
111
106
|
compiled.push({
|
|
112
107
|
pattern: new RegExp(source),
|
|
113
108
|
source,
|
|
114
|
-
origin: `--console-allow #${
|
|
109
|
+
origin: `--console-allow #${index + 1}`,
|
|
115
110
|
});
|
|
116
111
|
}
|
|
117
112
|
catch (error) {
|
|
118
113
|
const message = toError(error).message;
|
|
119
|
-
throw new Error(`Invalid --console-allow regex at position ${
|
|
114
|
+
throw new Error(`Invalid --console-allow regex at position ${index + 1} ("${source}"): ${message}`, { cause: error });
|
|
120
115
|
}
|
|
121
116
|
});
|
|
122
117
|
return compiled;
|
|
@@ -1,21 +1,32 @@
|
|
|
1
1
|
/** Runs an operation while holding the sidecar lock for a FireForge state file. */
|
|
2
2
|
export declare function withStateFileLock<T>(statePath: string, operation: () => Promise<T>): Promise<T>;
|
|
3
|
+
/**
|
|
4
|
+
* A filesystem-safe, sortable timestamp: `2026-08-28T14-32-05-123Z`.
|
|
5
|
+
*
|
|
6
|
+
* Colons are not portable in filenames (Windows rejects them outright), so
|
|
7
|
+
* the ISO form is punctuated with dashes only. Lexical order still equals
|
|
8
|
+
* chronological order, which is what run-log pruning relies on.
|
|
9
|
+
*
|
|
10
|
+
* @param now - Instant to render
|
|
11
|
+
* @returns The ISO-8601 form with `:` and `.` replaced by `-`
|
|
12
|
+
*/
|
|
13
|
+
export declare function fileSafeTimestamp(now: Date): string;
|
|
3
14
|
/** Renames a state file out of the way while preserving it for later inspection. */
|
|
4
15
|
export declare function quarantineStateFile(statePath: string, reason?: string): Promise<string | undefined>;
|
|
5
16
|
/**
|
|
6
17
|
* Outcome of a version check on a persisted FireForge document.
|
|
7
18
|
*
|
|
8
19
|
* The distinction that matters is `newer` vs `corrupt`. A document written
|
|
9
|
-
* by a
|
|
10
|
-
*
|
|
20
|
+
* by a newer FireForge is not damaged. The operator simply needs to upgrade.
|
|
21
|
+
* A check that collapses the two offers destructive remedies. The
|
|
11
22
|
* sharpest case is the tree marker, whose `schemaVersion` check inside a
|
|
12
23
|
* boolean type guard makes a `schemaVersion: 2` marker read as "missing or
|
|
13
|
-
* mistypes a required field"
|
|
24
|
+
* mistypes a required field". `tree-guard.ts` is default-deny on corrupt, so
|
|
14
25
|
* a newer FireForge would lock the operator out of every mutating command
|
|
15
26
|
* inside that tree.
|
|
16
27
|
*
|
|
17
28
|
* `furnace.json` is the pattern the rest should follow: it refuses a newer
|
|
18
|
-
* version by name and tells the operator to upgrade (`
|
|
29
|
+
* version by name and tells the operator to upgrade (`validateConfigVersion`
|
|
19
30
|
* in `furnace-config.ts`).
|
|
20
31
|
*/
|
|
21
32
|
export type DocumentVersionCheck = {
|
|
@@ -12,12 +12,25 @@ export async function withStateFileLock(statePath, operation) {
|
|
|
12
12
|
`(age: ${Math.round(ageMs / 1000)}s). A previous fireforge process may have crashed.`,
|
|
13
13
|
});
|
|
14
14
|
}
|
|
15
|
+
/**
|
|
16
|
+
* A filesystem-safe, sortable timestamp: `2026-08-28T14-32-05-123Z`.
|
|
17
|
+
*
|
|
18
|
+
* Colons are not portable in filenames (Windows rejects them outright), so
|
|
19
|
+
* the ISO form is punctuated with dashes only. Lexical order still equals
|
|
20
|
+
* chronological order, which is what run-log pruning relies on.
|
|
21
|
+
*
|
|
22
|
+
* @param now - Instant to render
|
|
23
|
+
* @returns The ISO-8601 form with `:` and `.` replaced by `-`
|
|
24
|
+
*/
|
|
25
|
+
export function fileSafeTimestamp(now) {
|
|
26
|
+
return now.toISOString().replace(/[:.]/g, '-');
|
|
27
|
+
}
|
|
15
28
|
/** Renames a state file out of the way while preserving it for later inspection. */
|
|
16
29
|
export async function quarantineStateFile(statePath, reason = 'corrupt') {
|
|
17
30
|
if (!(await pathExists(statePath))) {
|
|
18
31
|
return undefined;
|
|
19
32
|
}
|
|
20
|
-
const timestamp = new Date()
|
|
33
|
+
const timestamp = fileSafeTimestamp(new Date());
|
|
21
34
|
const quarantinedPath = `${statePath}.${reason}-${timestamp}`;
|
|
22
35
|
await rename(statePath, quarantinedPath);
|
|
23
36
|
return basename(quarantinedPath);
|