@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
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
/**
|
|
3
3
|
* `fireforge patch <verb>` parent command. Groups single-patch mutations and
|
|
4
4
|
* planners (`compact`, `delete`, `lint-ignore`, `move-files`, `rename`,
|
|
5
|
-
* `reorder`, `
|
|
6
|
-
* top-level command list. Queue-level
|
|
7
|
-
* and `status` stay flat.
|
|
5
|
+
* `reorder`, `reserve`, `retire`, `split`, `stage`, `staged-dependency`,
|
|
6
|
+
* `tier`) so they do not clutter the top-level command list. Queue-level
|
|
7
|
+
* verbs like `lint`, `export`, `verify`, and `status` stay flat.
|
|
8
8
|
*/
|
|
9
9
|
import { Command } from 'commander';
|
|
10
10
|
import { registerPatchCompact } from './compact.js';
|
|
@@ -13,7 +13,10 @@ import { registerPatchLintIgnore } from './lint-ignore.js';
|
|
|
13
13
|
import { registerPatchMoveFiles } from './move-files.js';
|
|
14
14
|
import { registerPatchRename } from './rename.js';
|
|
15
15
|
import { registerPatchReorder } from './reorder.js';
|
|
16
|
+
import { registerPatchReserve } from './reserve.js';
|
|
17
|
+
import { registerPatchRetire } from './retire.js';
|
|
16
18
|
import { registerPatchSplit } from './split.js';
|
|
19
|
+
import { registerPatchStage } from './stage.js';
|
|
17
20
|
import { registerPatchStagedDependency } from './staged-dependency.js';
|
|
18
21
|
import { registerPatchTier } from './tier.js';
|
|
19
22
|
/**
|
|
@@ -25,7 +28,7 @@ import { registerPatchTier } from './tier.js';
|
|
|
25
28
|
export function registerPatch(program, context) {
|
|
26
29
|
const patch = program
|
|
27
30
|
.command('patch')
|
|
28
|
-
.description('Manage individual patches in the queue (compact, delete, lint-ignore, move-files, rename, reorder, staged-dependency, tier)')
|
|
31
|
+
.description('Manage individual patches in the queue (compact, delete, lint-ignore, move-files, rename, reorder, reserve, retire, split, stage, staged-dependency, tier)')
|
|
29
32
|
// Match `fireforge furnace`'s no-args contract: print the group's help
|
|
30
33
|
// and exit 0. Without this default action, commander routes
|
|
31
34
|
// `fireforge patch` (no subcommand) through its own help-then-exit-1
|
|
@@ -40,7 +43,10 @@ export function registerPatch(program, context) {
|
|
|
40
43
|
registerPatchMoveFiles(patch, context);
|
|
41
44
|
registerPatchRename(patch, context);
|
|
42
45
|
registerPatchReorder(patch, context);
|
|
46
|
+
registerPatchReserve(patch, context);
|
|
47
|
+
registerPatchRetire(patch, context);
|
|
43
48
|
registerPatchSplit(patch, context);
|
|
49
|
+
registerPatchStage(patch, context);
|
|
44
50
|
registerPatchStagedDependency(patch, context);
|
|
45
51
|
registerPatchTier(patch, context);
|
|
46
52
|
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Batch and per-entry input for `patch lint-ignore --add`. Split out of
|
|
3
|
+
* `lint-ignore.ts` for the per-file line budget.
|
|
4
|
+
*
|
|
5
|
+
* A rebaseline that sets a ceiling per rule used to take one call per rule,
|
|
6
|
+
* each taking the patch lock and rewriting `patches.json` (138 calls on one
|
|
7
|
+
* consumer's queue), because `--max` applied to every `--add` of a call.
|
|
8
|
+
* Two forms lift that:
|
|
9
|
+
*
|
|
10
|
+
* - `--add <rule>=<max>` gives each entry its own ceiling in one call.
|
|
11
|
+
* - `--from <json-file>` reads every entry from a file, under one lock hold
|
|
12
|
+
* and one write. The file is a JSON array of entries (a check ID string,
|
|
13
|
+
* or `{ rule, max, reason?, share?, meta?, patch? }`), or a
|
|
14
|
+
* `lint --per-patch --report` document, whose `lintIgnoreCeilings` rows
|
|
15
|
+
* for the target patch are rebaselined to their current measurement.
|
|
16
|
+
*/
|
|
17
|
+
import type { LintIgnoreEntry, PatchLintIgnoreOptions, PatchSizeShare } from '../../types/commands/index.js';
|
|
18
|
+
/**
|
|
19
|
+
* Turns `--add` values into entries: `<rule>=<max>` is a ceiling at `max`,
|
|
20
|
+
* a bare ID is a ceiling at `--max` when that is given and a bare waiver
|
|
21
|
+
* otherwise. Every ceiling takes `--reason` (required) and `--share`.
|
|
22
|
+
*
|
|
23
|
+
* @param ids - The `--add` values
|
|
24
|
+
* @param options - Command options (`max`, `reason`, `share`)
|
|
25
|
+
* @returns The entries to upsert
|
|
26
|
+
*/
|
|
27
|
+
export declare function resolveAddEntries(ids: readonly string[], options: Pick<PatchLintIgnoreOptions, 'max' | 'reason' | 'share'>): LintIgnoreEntry[];
|
|
28
|
+
/** Entries read from a `--from` file for one target patch. */
|
|
29
|
+
export interface LintIgnoreBatch {
|
|
30
|
+
entries: LintIgnoreEntry[];
|
|
31
|
+
/** Entries naming a different patch, left out. */
|
|
32
|
+
skippedForOtherPatches: number;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Reads a `--from` file into entries for `targetFilename`.
|
|
36
|
+
*
|
|
37
|
+
* @param path - JSON file path
|
|
38
|
+
* @param targetFilename - The patch the command edits
|
|
39
|
+
* @param defaultReason - `--reason`, used for object entries without one
|
|
40
|
+
* @returns The validated entries and the count left out for other patches
|
|
41
|
+
*/
|
|
42
|
+
export declare function readLintIgnoreBatch(path: string, targetFilename: string, defaultReason: string | undefined): Promise<LintIgnoreBatch>;
|
|
43
|
+
/** Parses `--share`. */
|
|
44
|
+
export declare function parseShare(value: string): PatchSizeShare;
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
// SPDX-License-Identifier: EUPL-1.2
|
|
2
|
+
/**
|
|
3
|
+
* Batch and per-entry input for `patch lint-ignore --add`. Split out of
|
|
4
|
+
* `lint-ignore.ts` for the per-file line budget.
|
|
5
|
+
*
|
|
6
|
+
* A rebaseline that sets a ceiling per rule used to take one call per rule,
|
|
7
|
+
* each taking the patch lock and rewriting `patches.json` (138 calls on one
|
|
8
|
+
* consumer's queue), because `--max` applied to every `--add` of a call.
|
|
9
|
+
* Two forms lift that:
|
|
10
|
+
*
|
|
11
|
+
* - `--add <rule>=<max>` gives each entry its own ceiling in one call.
|
|
12
|
+
* - `--from <json-file>` reads every entry from a file, under one lock hold
|
|
13
|
+
* and one write. The file is a JSON array of entries (a check ID string,
|
|
14
|
+
* or `{ rule, max, reason?, share?, meta?, patch? }`), or a
|
|
15
|
+
* `lint --per-patch --report` document, whose `lintIgnoreCeilings` rows
|
|
16
|
+
* for the target patch are rebaselined to their current measurement.
|
|
17
|
+
*/
|
|
18
|
+
import { LINT_IGNORE_CEILING_RULES, parseLintIgnoreEntries } from '../../core/patch-lint-ignore.js';
|
|
19
|
+
import { InvalidArgumentError } from '../../errors/base.js';
|
|
20
|
+
import { toError } from '../../utils/errors.js';
|
|
21
|
+
import { readJson } from '../../utils/fs.js';
|
|
22
|
+
import { isArray, isObject } from '../../utils/validation.js';
|
|
23
|
+
const RULE_MAX_PATTERN = /^(?<rule>[^=\s]+)=(?<max>[1-9]\d*)$/;
|
|
24
|
+
/**
|
|
25
|
+
* Turns `--add` values into entries: `<rule>=<max>` is a ceiling at `max`,
|
|
26
|
+
* a bare ID is a ceiling at `--max` when that is given and a bare waiver
|
|
27
|
+
* otherwise. Every ceiling takes `--reason` (required) and `--share`.
|
|
28
|
+
*
|
|
29
|
+
* @param ids - The `--add` values
|
|
30
|
+
* @param options - Command options (`max`, `reason`, `share`)
|
|
31
|
+
* @returns The entries to upsert
|
|
32
|
+
*/
|
|
33
|
+
export function resolveAddEntries(ids, options) {
|
|
34
|
+
const parsed = ids.map((id) => {
|
|
35
|
+
if (id.includes('=')) {
|
|
36
|
+
const match = RULE_MAX_PATTERN.exec(id);
|
|
37
|
+
if (match?.groups === undefined) {
|
|
38
|
+
throw new InvalidArgumentError(`--add ${id}: expected <rule>=<max> with a positive integer max.`, '--add');
|
|
39
|
+
}
|
|
40
|
+
return { rule: match.groups['rule'], max: Number(match.groups['max']) };
|
|
41
|
+
}
|
|
42
|
+
return { rule: id, max: options.max };
|
|
43
|
+
});
|
|
44
|
+
const ceilings = parsed.filter((entry) => entry.max !== undefined);
|
|
45
|
+
if (ceilings.length === 0) {
|
|
46
|
+
if (options.reason !== undefined || options.share !== undefined) {
|
|
47
|
+
throw new InvalidArgumentError('--reason and --share apply to ceilings: pass --max <n> or --add <rule>=<max>.', options.reason !== undefined ? '--reason' : '--share');
|
|
48
|
+
}
|
|
49
|
+
return parsed.map((entry) => entry.rule);
|
|
50
|
+
}
|
|
51
|
+
if (options.reason === undefined || options.reason.trim() === '') {
|
|
52
|
+
throw new InvalidArgumentError('A lintIgnore ceiling needs --reason <text> (with --max <n> or --add <rule>=<max>).', '--reason');
|
|
53
|
+
}
|
|
54
|
+
const unmeasured = ceilings.filter((entry) => !LINT_IGNORE_CEILING_RULES.includes(entry.rule));
|
|
55
|
+
if (unmeasured.length > 0) {
|
|
56
|
+
throw new InvalidArgumentError(`A ceiling only applies to the measured size rules (${LINT_IGNORE_CEILING_RULES.join(', ')}); ` +
|
|
57
|
+
`got ${unmeasured.map((entry) => entry.rule).join(', ')}.`, '--max');
|
|
58
|
+
}
|
|
59
|
+
const { reason, share } = options;
|
|
60
|
+
return validated(parsed.map((entry) => entry.max === undefined
|
|
61
|
+
? entry.rule
|
|
62
|
+
: { rule: entry.rule, max: entry.max, reason, ...(share !== undefined ? { share } : {}) }), '--add');
|
|
63
|
+
}
|
|
64
|
+
/** Runs the manifest validator over CLI-built entries, as an argument error. */
|
|
65
|
+
function validated(entries, flag) {
|
|
66
|
+
try {
|
|
67
|
+
return parseLintIgnoreEntries(entries, flag);
|
|
68
|
+
}
|
|
69
|
+
catch (error) {
|
|
70
|
+
throw new InvalidArgumentError(toError(error).message, flag);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
/** The target patch's ceiling rows of a lint report, rebaselined to their measurement. */
|
|
74
|
+
function rebaselineFromReport(data, targetFilename) {
|
|
75
|
+
const patches = isArray(data['patches']) ? data['patches'] : [];
|
|
76
|
+
const row = patches.find((patch) => isObject(patch) && patch['filename'] === targetFilename);
|
|
77
|
+
const ceilings = isObject(row) && isArray(row['lintIgnoreCeilings']) ? row['lintIgnoreCeilings'] : [];
|
|
78
|
+
const raw = [];
|
|
79
|
+
for (const ceiling of ceilings) {
|
|
80
|
+
if (!isObject(ceiling) || typeof ceiling['measurement'] !== 'number')
|
|
81
|
+
continue;
|
|
82
|
+
if (ceiling['measurement'] <= 0)
|
|
83
|
+
continue;
|
|
84
|
+
const { measurement, rule, reason, share, meta } = ceiling;
|
|
85
|
+
raw.push({
|
|
86
|
+
rule,
|
|
87
|
+
max: measurement,
|
|
88
|
+
reason,
|
|
89
|
+
...(share !== undefined ? { share } : {}),
|
|
90
|
+
...(meta !== undefined ? { meta } : {}),
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
return { raw, skipped: patches.length - (row === undefined ? 0 : 1) };
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Reads a `--from` file into entries for `targetFilename`.
|
|
97
|
+
*
|
|
98
|
+
* @param path - JSON file path
|
|
99
|
+
* @param targetFilename - The patch the command edits
|
|
100
|
+
* @param defaultReason - `--reason`, used for object entries without one
|
|
101
|
+
* @returns The validated entries and the count left out for other patches
|
|
102
|
+
*/
|
|
103
|
+
export async function readLintIgnoreBatch(path, targetFilename, defaultReason) {
|
|
104
|
+
let data;
|
|
105
|
+
try {
|
|
106
|
+
data = await readJson(path);
|
|
107
|
+
}
|
|
108
|
+
catch (error) {
|
|
109
|
+
throw new InvalidArgumentError(`Cannot read --from ${path}: ${toError(error).message}`, '--from');
|
|
110
|
+
}
|
|
111
|
+
if (isObject(data)) {
|
|
112
|
+
const { raw, skipped } = rebaselineFromReport(data, targetFilename);
|
|
113
|
+
return { entries: validated(raw, '--from'), skippedForOtherPatches: skipped };
|
|
114
|
+
}
|
|
115
|
+
if (!isArray(data)) {
|
|
116
|
+
throw new InvalidArgumentError('--from must hold a JSON array of lintIgnore entries or a "lint --per-patch --report" document.', '--from');
|
|
117
|
+
}
|
|
118
|
+
const raw = [];
|
|
119
|
+
let skipped = 0;
|
|
120
|
+
for (const entry of data) {
|
|
121
|
+
if (!isObject(entry)) {
|
|
122
|
+
raw.push(entry);
|
|
123
|
+
continue;
|
|
124
|
+
}
|
|
125
|
+
const { patch, ...rest } = entry;
|
|
126
|
+
if (patch !== undefined && patch !== targetFilename) {
|
|
127
|
+
skipped++;
|
|
128
|
+
continue;
|
|
129
|
+
}
|
|
130
|
+
raw.push(rest['reason'] === undefined && defaultReason !== undefined
|
|
131
|
+
? { ...rest, reason: defaultReason }
|
|
132
|
+
: rest);
|
|
133
|
+
}
|
|
134
|
+
return { entries: validated(raw, '--from'), skippedForOtherPatches: skipped };
|
|
135
|
+
}
|
|
136
|
+
/** Parses `--share`. */
|
|
137
|
+
export function parseShare(value) {
|
|
138
|
+
if (value !== 'test' && value !== 'product') {
|
|
139
|
+
throw new InvalidArgumentError(`--share must be "test" or "product" (got "${value}").`, '--share');
|
|
140
|
+
}
|
|
141
|
+
return value;
|
|
142
|
+
}
|
|
@@ -11,7 +11,11 @@
|
|
|
11
11
|
* re-export's engine read + diff regeneration roundtrip is wasted.
|
|
12
12
|
*
|
|
13
13
|
* Modes are mutually exclusive: exactly one of `--add`, `--remove`, or
|
|
14
|
-
* `--clear` must be supplied per invocation.
|
|
14
|
+
* `--clear` must be supplied per invocation. `--add <rule> --max <n>
|
|
15
|
+
* --reason <text>` writes a size waiver with a ceiling (see
|
|
16
|
+
* `core/patch-lint-ignore.ts`) instead of a bare check ID; an `--add` for a
|
|
17
|
+
* rule that already has an entry replaces it, so the same command moves a
|
|
18
|
+
* ceiling or widens it back to a bare waiver. The read-modify-write
|
|
15
19
|
* happens inside the patch directory lock via {@link mutatePatchMetadata}
|
|
16
20
|
* so a concurrent writer cannot interleave between the read and the
|
|
17
21
|
* write, which matters when an operator scripts repeated invocations or
|
|
@@ -12,20 +12,27 @@
|
|
|
12
12
|
* re-export's engine read + diff regeneration roundtrip is wasted.
|
|
13
13
|
*
|
|
14
14
|
* Modes are mutually exclusive: exactly one of `--add`, `--remove`, or
|
|
15
|
-
* `--clear` must be supplied per invocation.
|
|
15
|
+
* `--clear` must be supplied per invocation. `--add <rule> --max <n>
|
|
16
|
+
* --reason <text>` writes a size waiver with a ceiling (see
|
|
17
|
+
* `core/patch-lint-ignore.ts`) instead of a bare check ID; an `--add` for a
|
|
18
|
+
* rule that already has an entry replaces it, so the same command moves a
|
|
19
|
+
* ceiling or widens it back to a bare waiver. The read-modify-write
|
|
16
20
|
* happens inside the patch directory lock via {@link mutatePatchMetadata}
|
|
17
21
|
* so a concurrent writer cannot interleave between the read and the
|
|
18
22
|
* write, which matters when an operator scripts repeated invocations or
|
|
19
23
|
* runs `--add` and `--remove` back-to-back.
|
|
20
24
|
*/
|
|
21
|
-
import { Command } from 'commander';
|
|
25
|
+
import { Command, Option } from 'commander';
|
|
22
26
|
import { confirmDestructive } from '../../core/destructive.js';
|
|
23
27
|
import { appendHistoryBestEffort } from '../../core/history-log.js';
|
|
24
28
|
import { mutatePatchMetadata } from '../../core/patch-export.js';
|
|
29
|
+
import { addedLintIgnoreEntries, formatLintIgnoreEntry, formatLintIgnoreList, lintIgnoreRule, removeLintIgnoreRules, upsertLintIgnoreEntries, } from '../../core/patch-lint-ignore.js';
|
|
25
30
|
import { GeneralError, InvalidArgumentError } from '../../errors/base.js';
|
|
26
31
|
import { info, intro, outro, warn } from '../../utils/logger.js';
|
|
27
|
-
import { addWaitLockOption, resolveWaitLockSeconds, stringListOption, } from '../../utils/options.js';
|
|
32
|
+
import { addWaitLockOption, commanderArgParser, resolveWaitLockSeconds, stringListOption, } from '../../utils/options.js';
|
|
33
|
+
import { parsePositiveIntegerFlag } from '../../utils/validation.js';
|
|
28
34
|
import { proceedAfterDecision } from '../destructive-decision.js';
|
|
35
|
+
import { parseShare, readLintIgnoreBatch, resolveAddEntries } from './lint-ignore-from.js';
|
|
29
36
|
import { requirePatchQueue, requirePatchTarget } from './patch-context.js';
|
|
30
37
|
/**
|
|
31
38
|
* Printed whenever `--add` lands a new check id. The waiver this command
|
|
@@ -44,19 +51,10 @@ const LINT_IGNORE_REVIEW_WARNING = "This lint waiver is subject to the project's
|
|
|
44
51
|
* present" contract).
|
|
45
52
|
*/
|
|
46
53
|
function applyMode(existing, mode, values) {
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
const merged = [...existingSet];
|
|
52
|
-
return merged.length > 0 ? merged : undefined;
|
|
53
|
-
}
|
|
54
|
-
if (mode === 'remove') {
|
|
55
|
-
for (const v of values)
|
|
56
|
-
existingSet.delete(v);
|
|
57
|
-
const remaining = [...existingSet];
|
|
58
|
-
return remaining.length > 0 ? remaining : undefined;
|
|
59
|
-
}
|
|
54
|
+
if (mode === 'add')
|
|
55
|
+
return upsertLintIgnoreEntries(existing, values);
|
|
56
|
+
if (mode === 'remove')
|
|
57
|
+
return removeLintIgnoreRules(existing, values.map(lintIgnoreRule));
|
|
60
58
|
// mode === 'clear'
|
|
61
59
|
return undefined;
|
|
62
60
|
}
|
|
@@ -66,29 +64,53 @@ function applyMode(existing, mode, values) {
|
|
|
66
64
|
* message format directly without mocking the logger transport.
|
|
67
65
|
*/
|
|
68
66
|
function describeChange(before, after, mode, values) {
|
|
69
|
-
const beforeSet = new Set(before);
|
|
70
|
-
const afterSet = new Set(after);
|
|
71
67
|
if (mode === 'clear') {
|
|
72
68
|
return before.length === 0
|
|
73
69
|
? 'lintIgnore was already empty — no change'
|
|
74
|
-
: `lintIgnore cleared (was ${before
|
|
70
|
+
: `lintIgnore cleared (was ${formatLintIgnoreList(before)})`;
|
|
75
71
|
}
|
|
76
|
-
const currentLabel = before.length > 0 ? `[${before
|
|
72
|
+
const currentLabel = before.length > 0 ? `[${formatLintIgnoreList(before)}]` : '(empty)';
|
|
77
73
|
if (mode === 'add') {
|
|
78
|
-
const added =
|
|
74
|
+
const added = addedLintIgnoreEntries(before, after);
|
|
79
75
|
if (added.length === 0) {
|
|
80
76
|
// Surface the existing list so a no-op `--add` does not require a
|
|
81
77
|
// follow-up `patches.json` read to confirm what was already present.
|
|
82
78
|
return `lintIgnore unchanged (current: ${currentLabel}; all requested IDs already present)`;
|
|
83
79
|
}
|
|
84
|
-
return `lintIgnore += ${added
|
|
80
|
+
return `lintIgnore += ${formatLintIgnoreList(added)} → ${formatLintIgnoreList(after)}`;
|
|
85
81
|
}
|
|
86
82
|
// mode === 'remove'
|
|
87
|
-
const
|
|
83
|
+
const requested = new Set(values.map(lintIgnoreRule));
|
|
84
|
+
const removed = before.filter((entry) => requested.has(lintIgnoreRule(entry)));
|
|
88
85
|
if (removed.length === 0) {
|
|
89
86
|
return `lintIgnore unchanged (current: ${currentLabel}; none of the requested IDs were present)`;
|
|
90
87
|
}
|
|
91
|
-
return `lintIgnore −= ${removed
|
|
88
|
+
return `lintIgnore −= ${formatLintIgnoreList(removed)} → ${formatLintIgnoreList(after)}`;
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Turns the mode's IDs into manifest entries, applying `--max`/`--reason`
|
|
92
|
+
* and `<rule>=<max>` to `--add` (see `lint-ignore-from.ts`). Refuses a
|
|
93
|
+
* ceiling flag without `--add`, a ceiling without a `--reason`, and a
|
|
94
|
+
* ceiling on a rule that carries no measurement, so a waiver that could
|
|
95
|
+
* never suppress anything is not written. A `--from` add resolves later,
|
|
96
|
+
* once the target patch is known.
|
|
97
|
+
*/
|
|
98
|
+
function resolveRequestedEntries(mode, options) {
|
|
99
|
+
const ceilingFlag = options.max !== undefined ? '--max' : options.share !== undefined ? '--share' : undefined;
|
|
100
|
+
if ((ceilingFlag !== undefined || options.reason !== undefined) && mode !== 'add') {
|
|
101
|
+
throw new InvalidArgumentError('--max, --reason and --share only apply to --add.', ceilingFlag ?? '--reason');
|
|
102
|
+
}
|
|
103
|
+
if (mode === 'remove')
|
|
104
|
+
return [...(options.remove ?? [])];
|
|
105
|
+
if (mode !== 'add')
|
|
106
|
+
return [];
|
|
107
|
+
if (options.from !== undefined) {
|
|
108
|
+
if ((options.add?.length ?? 0) > 0 || ceilingFlag !== undefined) {
|
|
109
|
+
throw new InvalidArgumentError('--from takes its entries from the file; it combines only with --reason (the default reason).', (options.add?.length ?? 0) > 0 ? '--add' : ceilingFlag);
|
|
110
|
+
}
|
|
111
|
+
return [];
|
|
112
|
+
}
|
|
113
|
+
return resolveAddEntries(options.add ?? [], options);
|
|
92
114
|
}
|
|
93
115
|
/**
|
|
94
116
|
* Runs the `patch lint-ignore` command: reads the patch's existing
|
|
@@ -105,7 +127,7 @@ export async function patchLintIgnoreCommand(projectRoot, identifier, options =
|
|
|
105
127
|
// `--add foo --remove bar` are rejected: an operator who needs both
|
|
106
128
|
// runs the command twice (clearer audit trail), and `--clear` plus a
|
|
107
129
|
// mode is contradictory.
|
|
108
|
-
const adding = (options.add?.length ?? 0) > 0;
|
|
130
|
+
const adding = (options.add?.length ?? 0) > 0 || options.from !== undefined;
|
|
109
131
|
const removing = (options.remove?.length ?? 0) > 0;
|
|
110
132
|
const clearing = options.clear === true;
|
|
111
133
|
const modeCount = [adding, removing, clearing].filter(Boolean).length;
|
|
@@ -113,12 +135,22 @@ export async function patchLintIgnoreCommand(projectRoot, identifier, options =
|
|
|
113
135
|
throw new InvalidArgumentError('--add, --remove, and --clear are mutually exclusive. Pick one mode per invocation.', 'patch lint-ignore');
|
|
114
136
|
}
|
|
115
137
|
if (modeCount === 0) {
|
|
116
|
-
throw new InvalidArgumentError('Specify --add <id>, --remove <id>, or --clear.', 'patch lint-ignore');
|
|
138
|
+
throw new InvalidArgumentError('Specify --add <id>, --from <json-file>, --remove <id>, or --clear.', 'patch lint-ignore');
|
|
117
139
|
}
|
|
118
140
|
const mode = adding ? 'add' : removing ? 'remove' : 'clear';
|
|
119
|
-
|
|
141
|
+
let values = resolveRequestedEntries(mode, options);
|
|
120
142
|
const { paths, manifest } = await requirePatchQueue(projectRoot);
|
|
121
143
|
const target = requirePatchTarget(identifier, manifest.patches);
|
|
144
|
+
if (options.from !== undefined) {
|
|
145
|
+
const batch = await readLintIgnoreBatch(options.from, target.filename, options.reason);
|
|
146
|
+
if (batch.skippedForOtherPatches > 0) {
|
|
147
|
+
info(`--from: ${batch.skippedForOtherPatches} entry/entries for other patches left out.`);
|
|
148
|
+
}
|
|
149
|
+
if (batch.entries.length === 0) {
|
|
150
|
+
throw new InvalidArgumentError(`--from ${options.from} holds no lintIgnore entry for ${target.filename}.`, '--from');
|
|
151
|
+
}
|
|
152
|
+
values = batch.entries;
|
|
153
|
+
}
|
|
122
154
|
// Destructive-operation contract (docs/lifecycle-invariants.md): manifest
|
|
123
155
|
// metadata mutations get summary + dry-run + confirmation/--yes + history
|
|
124
156
|
// uniformly. Accepting --yes without ever prompting makes the flag appear
|
|
@@ -126,7 +158,7 @@ export async function patchLintIgnoreCommand(projectRoot, identifier, options =
|
|
|
126
158
|
// of mutation an operator should approve consciously.
|
|
127
159
|
const currentList = target.lintIgnore ?? [];
|
|
128
160
|
const projectedList = applyMode(currentList, mode, values) ?? [];
|
|
129
|
-
const addsNewIds = mode === 'add' && projectedList.length >
|
|
161
|
+
const addsNewIds = mode === 'add' && addedLintIgnoreEntries(currentList, projectedList).length > 0;
|
|
130
162
|
const projectedSummary = describeChange(currentList, projectedList, mode, values);
|
|
131
163
|
const decision = await confirmDestructive({
|
|
132
164
|
operation: 'patch-lint-ignore',
|
|
@@ -158,7 +190,7 @@ export async function patchLintIgnoreCommand(projectRoot, identifier, options =
|
|
|
158
190
|
const existing = result.before.lintIgnore ?? [];
|
|
159
191
|
const projected = result.after.lintIgnore ?? [];
|
|
160
192
|
info(`${target.filename}: ${describeChange(existing, projected, mode, values)}.`);
|
|
161
|
-
if (mode === 'add' && projected.length >
|
|
193
|
+
if (mode === 'add' && addedLintIgnoreEntries(existing, projected).length > 0) {
|
|
162
194
|
warn(LINT_IGNORE_REVIEW_WARNING);
|
|
163
195
|
}
|
|
164
196
|
await appendHistoryBestEffort(paths.patches, {
|
|
@@ -166,7 +198,7 @@ export async function patchLintIgnoreCommand(projectRoot, identifier, options =
|
|
|
166
198
|
args: {
|
|
167
199
|
filename: target.filename,
|
|
168
200
|
mode,
|
|
169
|
-
values:
|
|
201
|
+
values: values.map(formatLintIgnoreEntry),
|
|
170
202
|
before: existing,
|
|
171
203
|
after: projected,
|
|
172
204
|
},
|
|
@@ -186,9 +218,16 @@ export function registerPatchLintIgnore(parent, context) {
|
|
|
186
218
|
const command = parent
|
|
187
219
|
.command('lint-ignore <name>')
|
|
188
220
|
.description('Edit PatchMetadata.lintIgnore on a single patch (no .patch body rewrite). One mode per invocation.')
|
|
189
|
-
.option('--add <check-id>', 'Lint check ID to add to the patch lintIgnore list (repeatable)', ...stringListOption())
|
|
221
|
+
.option('--add <check-id>', 'Lint check ID to add to the patch lintIgnore list (repeatable); <rule>=<max> adds a ceiling at <max>', ...stringListOption())
|
|
190
222
|
.option('--remove <check-id>', 'Lint check ID to remove from the patch lintIgnore list (repeatable)', ...stringListOption())
|
|
191
223
|
.option('--clear', 'Drop the lintIgnore field entirely')
|
|
224
|
+
.addOption(new Option('--max <n>', 'With --add: write a size waiver with a ceiling, suppressing the rule only while its ' +
|
|
225
|
+
'measurement is at most <n> (file-too-large, large-patch-lines, large-patch-files)').argParser(commanderArgParser((v) => parsePositiveIntegerFlag('--max', v))))
|
|
226
|
+
.option('--reason <text>', 'Why the ceiling exists (required with --max or <rule>=<max>; with --from: the default for entries without one)')
|
|
227
|
+
.addOption(new Option('--share <share>', 'With a large-patch-lines ceiling: bound only the "product" or "test" share of the measurement').argParser(commanderArgParser(parseShare)))
|
|
228
|
+
.option('--from <json-file>', 'Add every entry in a JSON file under one lock hold: an array of check IDs or ' +
|
|
229
|
+
'{ rule, max, reason?, share?, meta?, patch? } objects, or a "lint --per-patch --report" ' +
|
|
230
|
+
'document, whose ceilings for this patch are rebaselined to their current measurement')
|
|
192
231
|
.option('--dry-run', 'Show what would change without writing')
|
|
193
232
|
.option('-y, --yes', 'Skip confirmation prompt (required for non-TTY)');
|
|
194
233
|
addWaitLockOption(command).action(withErrorHandling(async (name, options) => {
|
|
@@ -203,6 +242,14 @@ export function registerPatchLintIgnore(parent, context) {
|
|
|
203
242
|
normalized.remove = options.remove;
|
|
204
243
|
if (options.clear === true)
|
|
205
244
|
normalized.clear = true;
|
|
245
|
+
if (options.max !== undefined)
|
|
246
|
+
normalized.max = options.max;
|
|
247
|
+
if (options.reason !== undefined)
|
|
248
|
+
normalized.reason = options.reason;
|
|
249
|
+
if (options.share !== undefined)
|
|
250
|
+
normalized.share = options.share;
|
|
251
|
+
if (options.from !== undefined)
|
|
252
|
+
normalized.from = options.from;
|
|
206
253
|
if (options.dryRun === true)
|
|
207
254
|
normalized.dryRun = true;
|
|
208
255
|
if (options.yes === true)
|
|
@@ -14,17 +14,20 @@ import { getProjectPaths, loadConfig } from '../../core/config.js';
|
|
|
14
14
|
import { assertConfirmationAvailable, confirmDestructive } from '../../core/destructive.js';
|
|
15
15
|
import { formatPatchNotFoundError } from '../../core/patch-identifier-suggest.js';
|
|
16
16
|
import { buildPatchQueueContext } from '../../core/patch-lint.js';
|
|
17
|
+
import { buildLintIgnoreChecks } from '../../core/patch-lint-ignore.js';
|
|
17
18
|
import { loadPatchesManifest, resolvePatchIdentifier } from '../../core/patch-manifest.js';
|
|
18
19
|
import { formatPatchOrder } from '../../core/patch-parse.js';
|
|
19
20
|
import { enforcePatchPolicy } from '../../core/patch-policy.js';
|
|
20
21
|
import { GeneralError, InvalidArgumentError } from '../../errors/base.js';
|
|
21
22
|
import { info, intro, outro, success } from '../../utils/logger.js';
|
|
22
23
|
import { normalizePatchDisplayName } from '../../utils/validation.js';
|
|
24
|
+
import { withDeclarationsReport } from '../declarations-report.js';
|
|
23
25
|
import { proceedAfterDecision } from '../destructive-decision.js';
|
|
24
26
|
import { resolvePlacementPlan } from '../export-flow.js';
|
|
25
27
|
import { runPatchLint } from '../export-shared.js';
|
|
26
|
-
import { commitPatchSplit } from './split.js';
|
|
27
|
-
import { assertSourceOwnsFiles, buildNewPatchMetadata, buildSplitDiff, buildSplitSummary,
|
|
28
|
+
import { commitPatchSplit, reportSplitStagedChanges } from './split.js';
|
|
29
|
+
import { assertSourceOwnsFiles, buildNewPatchMetadata, buildSplitDiff, buildSplitSummary, projectSplitManifest, runProjectedSplitLint, splitDeclarationRenamer, } from './split-plan.js';
|
|
30
|
+
import { emptyStagedMaintenance, findOwnerRewriteHolders } from './split-staged.js';
|
|
28
31
|
/**
|
|
29
32
|
* Runs `patch move-files --create --order <n>`: plans the create+move as a
|
|
30
33
|
* split, lints the projection, confirms, and commits transactionally.
|
|
@@ -85,9 +88,26 @@ export async function patchMoveFilesCreateCommand(projectRoot, fromIdentifier, n
|
|
|
85
88
|
name: displayName,
|
|
86
89
|
description: options.description ?? '',
|
|
87
90
|
ownerRewrites: findOwnerRewriteHolders(manifest.patches, source.filename, movedSet),
|
|
88
|
-
// Populated by runProjectedSplitLint below (forward edges into the new
|
|
91
|
+
// Populated by runProjectedSplitLint below (forward edges into the new
|
|
92
|
+
// patch, and the declarations the move re-homes or makes unused).
|
|
89
93
|
stagedDependencyAdditions: new Map(),
|
|
94
|
+
stagedMaintenance: emptyStagedMaintenance(),
|
|
90
95
|
};
|
|
96
|
+
// Policy first: the projected manifest (orders, ranges, the gap rule)
|
|
97
|
+
// does not depend on the lint below, so a refused --order fails before
|
|
98
|
+
// the per-patch and projected lint passes instead of after them.
|
|
99
|
+
enforcePatchPolicy({
|
|
100
|
+
config,
|
|
101
|
+
manifest: projectSplitManifest(manifest, plan, buildNewPatchMetadata(plan, config)),
|
|
102
|
+
command: 'patch move-files --create',
|
|
103
|
+
forceUnsafe: options.forceUnsafe === true,
|
|
104
|
+
hints: {
|
|
105
|
+
'description-required': 'Pass --description "<text>" (or -d) on this command to set the created patch\'s description.',
|
|
106
|
+
'numeric-gap': 'With patchPolicy.allowGaps: false, orders are contiguous within a range: --order must ' +
|
|
107
|
+
"fill an existing gap or a retired slot, or take the number right after the range's last " +
|
|
108
|
+
'patch. A number reserved past a gap cannot be used until the numbers before it exist.',
|
|
109
|
+
},
|
|
110
|
+
});
|
|
91
111
|
// Per-patch lint both projected bodies, threading the source patch's
|
|
92
112
|
// tier/lintIgnore so an intentional-advisory patch can still move files.
|
|
93
113
|
// The whole-queue context (built once, with the config so it carries the
|
|
@@ -96,7 +116,7 @@ export async function patchMoveFilesCreateCommand(projectRoot, fromIdentifier, n
|
|
|
96
116
|
// resolve exactly as they will after the move lands. Without it the
|
|
97
117
|
// projection lint is blind.
|
|
98
118
|
const patchQueueCtx = await buildPatchQueueContext(paths.patches, config);
|
|
99
|
-
const ignoreChecks =
|
|
119
|
+
const ignoreChecks = buildLintIgnoreChecks(source.lintIgnore);
|
|
100
120
|
await runPatchLint({
|
|
101
121
|
engineDir: paths.engine,
|
|
102
122
|
filesAffected: remainingFiles,
|
|
@@ -117,18 +137,16 @@ export async function patchMoveFilesCreateCommand(projectRoot, fromIdentifier, n
|
|
|
117
137
|
ignoreChecks,
|
|
118
138
|
patchTier: source.tier,
|
|
119
139
|
});
|
|
120
|
-
const
|
|
121
|
-
plan.stagedDependencyAdditions = stagedDependencyAdditions;
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
hints: {
|
|
129
|
-
'description-required': 'Pass --description "<text>" (or -d) on this command to set the created patch\'s description.',
|
|
130
|
-
},
|
|
140
|
+
const projected = runProjectedSplitLint(plan, patchQueueCtx);
|
|
141
|
+
plan.stagedDependencyAdditions = projected.stagedDependencyAdditions;
|
|
142
|
+
plan.stagedMaintenance = projected.stagedMaintenance;
|
|
143
|
+
const conflicts = await withDeclarationsReport(projected.conflicts, {
|
|
144
|
+
projectRoot,
|
|
145
|
+
regressions: projected.regressions,
|
|
146
|
+
out: options.declarationsOut,
|
|
147
|
+
rename: splitDeclarationRenamer(plan),
|
|
131
148
|
});
|
|
149
|
+
const newMetadata = buildNewPatchMetadata(plan, config);
|
|
132
150
|
const decision = await confirmDestructive({
|
|
133
151
|
operation: 'patch-move-files-create',
|
|
134
152
|
title: `Create ${placement.newFilename} (order ${placement.insertionOrder}) and move ${movedFiles.length} file(s) out of ${source.filename}`,
|
|
@@ -143,8 +161,6 @@ export async function patchMoveFilesCreateCommand(projectRoot, fromIdentifier, n
|
|
|
143
161
|
await commitPatchSplit(paths.patches, plan, newMetadata, options, config);
|
|
144
162
|
success(`Created ${placement.newFilename} (order ${formatPatchOrder(placement.insertionOrder)}) ` +
|
|
145
163
|
`and moved ${plan.movedFiles.length} file(s) out of ${source.filename}`);
|
|
146
|
-
|
|
147
|
-
info(`Re-pointed staged-dependency owners in: ${plan.ownerRewrites.join(', ')}`);
|
|
148
|
-
}
|
|
164
|
+
reportSplitStagedChanges(plan);
|
|
149
165
|
outro('Move complete');
|
|
150
166
|
}
|
|
@@ -14,10 +14,11 @@
|
|
|
14
14
|
* reflect both patches' content, because both bodies are regenerated from
|
|
15
15
|
* the worktree.
|
|
16
16
|
*/
|
|
17
|
-
import { join } from 'node:path';
|
|
17
|
+
import { dirname, join, resolve } from 'node:path';
|
|
18
18
|
import { assertConfirmationAvailable, confirmDestructive, } from '../../core/destructive.js';
|
|
19
19
|
import { appendHistoryBestEffort } from '../../core/history-log.js';
|
|
20
20
|
import { buildPatchQueueContext, collectForwardImportEdges, formatPatchLintIssue, lintPatchQueue, } from '../../core/patch-lint.js';
|
|
21
|
+
import { buildLintIgnoreChecks } from '../../core/patch-lint-ignore.js';
|
|
21
22
|
import { computeProjectedLintRegressions } from '../../core/patch-lint-projection.js';
|
|
22
23
|
import { withPatchDirectoryLock } from '../../core/patch-lock.js';
|
|
23
24
|
import { loadPatchesManifest, savePatchesManifest, validatePatchesManifest, } from '../../core/patch-manifest.js';
|
|
@@ -26,10 +27,12 @@ import { toError } from '../../utils/errors.js';
|
|
|
26
27
|
import { readText, writeText } from '../../utils/fs.js';
|
|
27
28
|
import { info, outro, success, warn } from '../../utils/logger.js';
|
|
28
29
|
import { resolveWaitLockSeconds } from '../../utils/options.js';
|
|
30
|
+
import { withDeclarationsReport } from '../declarations-report.js';
|
|
29
31
|
import { proceedAfterDecision } from '../destructive-decision.js';
|
|
30
32
|
import { runPatchLint } from '../export-shared.js';
|
|
31
33
|
import { projectEntryBody } from './entry-projection.js';
|
|
32
|
-
import { buildSplitDiff,
|
|
34
|
+
import { buildSplitDiff, mergeStagedForwardImports } from './split-plan.js';
|
|
35
|
+
import { findOwnerRewriteHolders, rewriteSplitOwners } from './split-staged.js';
|
|
33
36
|
/**
|
|
34
37
|
* Projects the post-move queue through cross-patch lint, auto-declaring the
|
|
35
38
|
* forward edges the move introduces into the target (an importer that used
|
|
@@ -89,7 +92,7 @@ function runProjectedMoveLint(plan, baseCtx) {
|
|
|
89
92
|
reason: `move would introduce ${regressions.length} cross-patch lint error(s)`,
|
|
90
93
|
details: regressions.map(formatPatchLintIssue),
|
|
91
94
|
};
|
|
92
|
-
return { conflicts, stagedDependencyAdditions };
|
|
95
|
+
return { conflicts, regressions, stagedDependencyAdditions };
|
|
93
96
|
}
|
|
94
97
|
/**
|
|
95
98
|
* Commits a confirmed move under the patch-directory lock: write both
|
|
@@ -198,7 +201,7 @@ export async function runMoveFilesInto(args) {
|
|
|
198
201
|
config: args.config,
|
|
199
202
|
skipLint: options.skipLint,
|
|
200
203
|
patchQueueCtx,
|
|
201
|
-
ignoreChecks:
|
|
204
|
+
ignoreChecks: buildLintIgnoreChecks(source.lintIgnore),
|
|
202
205
|
patchTier: source.tier,
|
|
203
206
|
});
|
|
204
207
|
await runPatchLint({
|
|
@@ -208,7 +211,7 @@ export async function runMoveFilesInto(args) {
|
|
|
208
211
|
config: args.config,
|
|
209
212
|
skipLint: options.skipLint,
|
|
210
213
|
patchQueueCtx,
|
|
211
|
-
ignoreChecks:
|
|
214
|
+
ignoreChecks: buildLintIgnoreChecks(target.lintIgnore),
|
|
212
215
|
patchTier: target.tier,
|
|
213
216
|
});
|
|
214
217
|
const manifest = await loadPatchesManifest(patchesDir);
|
|
@@ -223,8 +226,13 @@ export async function runMoveFilesInto(args) {
|
|
|
223
226
|
ownerRewrites: findOwnerRewriteHolders(manifest?.patches ?? [], source.filename, new Set(files)),
|
|
224
227
|
stagedDependencyAdditions: new Map(),
|
|
225
228
|
};
|
|
226
|
-
const
|
|
227
|
-
plan.stagedDependencyAdditions = stagedDependencyAdditions;
|
|
229
|
+
const projected = runProjectedMoveLint(plan, patchQueueCtx);
|
|
230
|
+
plan.stagedDependencyAdditions = projected.stagedDependencyAdditions;
|
|
231
|
+
const conflicts = await withDeclarationsReport(projected.conflicts, {
|
|
232
|
+
projectRoot: dirname(resolve(patchesDir)),
|
|
233
|
+
regressions: projected.regressions,
|
|
234
|
+
out: options.declarationsOut,
|
|
235
|
+
});
|
|
228
236
|
const decision = await confirmDestructive({
|
|
229
237
|
operation: 'patch-move-files',
|
|
230
238
|
title: `Move ${files.length} file(s) from ${source.filename} to ${target.filename}`,
|
|
@@ -164,13 +164,16 @@ export function registerPatchMoveFiles(parent, context) {
|
|
|
164
164
|
'or create the target patch and move the files in one transaction with --create --order <n>.')
|
|
165
165
|
.option('--file <path>', 'File path relative to engine/ to move (repeatable)', ...stringListOption())
|
|
166
166
|
.option('--create', 'Create <to> as a new patch and move the files into it (requires --order)')
|
|
167
|
-
.option('--order <n>', 'Exact sparse order for the created patch (only valid with --create)
|
|
167
|
+
.option('--order <n>', 'Exact sparse order for the created patch (only valid with --create). With ' +
|
|
168
|
+
'patchPolicy.allowGaps: false, orders are contiguous within a range: pick a gap, a ' +
|
|
169
|
+
"retired slot, or the number after the range's last patch; checked before any lint runs", commanderArgParser((raw) => parsePositiveIntegerFlag('--order', raw)))
|
|
168
170
|
.option('--category <category>', "Category for the created patch (default: the source patch's)")
|
|
169
171
|
.option('-d, --description <desc>', 'Description for the created patch')
|
|
170
172
|
.option('--dry-run', 'Show what would happen without writing')
|
|
171
173
|
.option('-y, --yes', 'Skip confirmation prompt (required for non-TTY)')
|
|
172
174
|
.option('--force-unsafe', 'Bypass projected-lint refusals')
|
|
173
|
-
.option('--skip-lint', 'Skip per-patch lint of the projected bodies')
|
|
175
|
+
.option('--skip-lint', 'Skip per-patch lint of the projected bodies')
|
|
176
|
+
.option('--declarations-out <path>', 'Where a refusal writes its one --from-ready staged-declaration report (default: .fireforge/declarations/<timestamp>.json)');
|
|
174
177
|
addWaitLockOption(command).action(withErrorHandling(async (from, to, options) => {
|
|
175
178
|
await patchMoveFilesCommand(getProjectRoot(), from, to, {
|
|
176
179
|
...pickDefined({
|
|
@@ -183,6 +186,7 @@ export function registerPatchMoveFiles(parent, context) {
|
|
|
183
186
|
yes: options.yes,
|
|
184
187
|
forceUnsafe: options.forceUnsafe,
|
|
185
188
|
skipLint: options.skipLint,
|
|
189
|
+
declarationsOut: options.declarationsOut,
|
|
186
190
|
waitLock: options.waitLock,
|
|
187
191
|
}),
|
|
188
192
|
});
|