@hominis/fireforge 0.49.1 → 0.50.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 +41 -0
- 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 +28 -0
- package/dist/src/commands/check-report.js +78 -0
- package/dist/src/commands/check-run.d.ts +28 -0
- package/dist/src/commands/check-run.js +104 -0
- package/dist/src/commands/check-steps.d.ts +67 -0
- package/dist/src/commands/check-steps.js +175 -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/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-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-templates.d.ts +8 -3
- package/dist/src/commands/furnace/create-templates.js +8 -23
- 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 +93 -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 +127 -114
- package/dist/src/commands/furnace/validation-output.js +14 -3
- package/dist/src/commands/lint-per-patch.js +31 -60
- package/dist/src/commands/lint-report.d.ts +8 -4
- package/dist/src/commands/lint-report.js +15 -5
- package/dist/src/commands/lint.js +15 -34
- package/dist/src/commands/manifest.js +2 -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 +13 -98
- package/dist/src/commands/patch/index.d.ts +1 -1
- package/dist/src/commands/patch/index.js +4 -2
- package/dist/src/commands/patch/lint-ignore.d.ts +5 -1
- package/dist/src/commands/patch/lint-ignore.js +65 -28
- package/dist/src/commands/patch/move-files-create.js +26 -17
- package/dist/src/commands/patch/move-files-into.js +5 -3
- package/dist/src/commands/patch/move-files.js +3 -1
- 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 +7 -0
- package/dist/src/commands/patch/retire.d.ts +34 -0
- package/dist/src/commands/patch/retire.js +128 -0
- package/dist/src/commands/patch/split-plan.d.ts +7 -7
- package/dist/src/commands/patch/split-plan.js +45 -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 +51 -15
- 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.js +14 -41
- 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 +45 -2
- package/dist/src/commands/re-export-adjacent.js +156 -37
- 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-lint.d.ts +2 -1
- package/dist/src/commands/re-export-lint.js +23 -10
- package/dist/src/commands/re-export-options.js +45 -4
- 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-register.js +42 -17
- package/dist/src/commands/re-export-removed.d.ts +12 -1
- package/dist/src/commands/re-export-removed.js +41 -11
- 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 +17 -9
- package/dist/src/commands/re-export-scan.js +56 -23
- package/dist/src/commands/re-export-single.js +22 -6
- 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 +37 -24
- 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 +21 -0
- package/dist/src/commands/test-build-furnace.js +48 -0
- package/dist/src/commands/test-build-phase.js +47 -41
- package/dist/src/commands/test-checkjs.js +7 -0
- package/dist/src/commands/test-diagnose.js +7 -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 +43 -0
- package/dist/src/commands/test-orchestrate.js +222 -0
- package/dist/src/commands/test-perf-scope.d.ts +29 -0
- package/dist/src/commands/test-perf-scope.js +83 -0
- package/dist/src/commands/test-prelock.d.ts +51 -0
- package/dist/src/commands/test-prelock.js +177 -0
- package/dist/src/commands/test-register.js +54 -10
- package/dist/src/commands/test-run.js +4 -1
- package/dist/src/commands/test-stale-gate.js +57 -27
- package/dist/src/commands/test-verdict.d.ts +10 -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 +66 -60
- package/dist/src/commands/token-lint.d.ts +14 -0
- package/dist/src/commands/token-lint.js +111 -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 +59 -35
- 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 +7 -0
- package/dist/src/core/build-prepare.js +14 -8
- 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 +8 -0
- package/dist/src/core/config-validate-check.d.ts +8 -0
- package/dist/src/core/config-validate-check.js +143 -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 +7 -0
- package/dist/src/core/config-validate-token-scales.d.ts +6 -0
- package/dist/src/core/config-validate-token-scales.js +50 -0
- package/dist/src/core/config-validate.js +14 -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 +97 -0
- package/dist/src/core/coverage-records.js +350 -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 +10 -1
- package/dist/src/core/engine-session-lock.js +28 -8
- 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.d.ts +4 -25
- package/dist/src/core/file-lock.js +105 -138
- 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 +12 -2
- 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 +9 -0
- package/dist/src/core/furnace-config-validate-exceptions.js +71 -0
- package/dist/src/core/furnace-config-validate.js +8 -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-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 +4 -2
- package/dist/src/core/furnace-validate-accessibility.js +10 -1
- package/dist/src/core/furnace-validate-exceptions.d.ts +40 -0
- package/dist/src/core/furnace-validate-exceptions.js +43 -0
- package/dist/src/core/furnace-validate-icon-button.d.ts +7 -0
- package/dist/src/core/furnace-validate-icon-button.js +49 -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 +157 -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/mach.js +8 -1
- package/dist/src/core/negative-control-diff.d.ts +39 -0
- package/dist/src/core/negative-control-diff.js +136 -0
- package/dist/src/core/negative-control.d.ts +138 -0
- package/dist/src/core/negative-control.js +356 -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/patch-export-update.d.ts +2 -0
- package/dist/src/core/patch-export-update.js +1 -0
- package/dist/src/core/patch-export.js +3 -4
- package/dist/src/core/patch-lint-checkjs-any-import.d.ts +37 -0
- package/dist/src/core/patch-lint-checkjs-any-import.js +61 -0
- package/dist/src/core/patch-lint-checkjs.js +8 -11
- 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.js +12 -4
- package/dist/src/core/patch-lint-css.d.ts +8 -2
- package/dist/src/core/patch-lint-css.js +10 -4
- 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 +18 -0
- package/dist/src/core/patch-lint-forward-registration-extended.js +35 -10
- package/dist/src/core/patch-lint-forward-registration.js +10 -0
- package/dist/src/core/patch-lint-ignore.d.ts +152 -0
- package/dist/src/core/patch-lint-ignore.js +299 -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 +323 -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 +39 -0
- package/dist/src/core/patch-lint-token-scale.js +109 -0
- package/dist/src/core/patch-lint.d.ts +11 -83
- package/dist/src/core/patch-lint.js +64 -286
- 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 +19 -8
- package/dist/src/core/patch-manifest-validate.js +34 -2
- package/dist/src/core/patch-order-legal.d.ts +25 -0
- package/dist/src/core/patch-order-legal.js +83 -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 +16 -3
- package/dist/src/core/patch-policy.js +16 -9
- package/dist/src/core/patch-retired.d.ts +35 -0
- package/dist/src/core/patch-retired.js +54 -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 +20 -0
- package/dist/src/core/run-log.js +89 -3
- 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 +18 -1
- package/dist/src/core/test-harness-crash.js +6 -4
- package/dist/src/core/test-harness-signature.d.ts +17 -0
- package/dist/src/core/test-harness-signature.js +4 -0
- package/dist/src/core/test-run-completeness.d.ts +57 -0
- package/dist/src/core/test-run-completeness.js +144 -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/token-lint.d.ts +50 -0
- package/dist/src/core/token-lint.js +126 -0
- package/dist/src/core/tree-guard.js +3 -0
- package/dist/src/core/typecheck-shim.d.ts +1 -1
- package/dist/src/core/typecheck-shim.js +90 -2
- package/dist/src/index.d.ts +8 -3
- package/dist/src/index.js +3 -1
- package/dist/src/types/commands/index.d.ts +2 -2
- package/dist/src/types/commands/options.d.ts +148 -21
- package/dist/src/types/commands/patches.d.ts +75 -1
- package/dist/src/types/config.d.ts +192 -0
- package/dist/src/types/config.js +9 -0
- package/dist/src/types/furnace.d.ts +43 -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 +34 -6
- package/dist/src/utils/options.js +86 -5
- 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 +282 -9
- package/docs/exit-codes.md +18 -1
- package/docs/furnace.md +97 -3
- package/docs/lifecycle-invariants.md +52 -19
- package/docs/machine-output.md +74 -12
- package/docs/patch-workflow.md +297 -22
- package/docs/run-logs.md +20 -1
- package/docs/testing.md +276 -20
- package/package.json +2 -2
|
@@ -3,46 +3,85 @@
|
|
|
3
3
|
* a CI-enforceable non-zero exit: the default policy fails on any
|
|
4
4
|
* classification outside {patch-backed, branding, furnace}, and
|
|
5
5
|
* `--fail-on <class,...>` replaces that set for finer control.
|
|
6
|
+
* `--allow <class,...>` names classes that never fail, and
|
|
7
|
+
* `--fail-on-unknown` fails every present class that neither list names,
|
|
8
|
+
* so a gate keeps failing closed when FireForge adds a classification.
|
|
9
|
+
* `ownership-conflict` is a check class beside the file classifications:
|
|
10
|
+
* a path claimed by more than one patch, judged from the same rows as
|
|
11
|
+
* `--include-ownership`.
|
|
6
12
|
*
|
|
7
13
|
* Helper module consumed by status.ts, which sits at the max-lines budget.
|
|
8
14
|
* No top-level registrar is exported and none is wanted.
|
|
9
15
|
*/
|
|
10
16
|
import type { ClassifiedFile, FileClassification } from '../core/status-classify.js';
|
|
17
|
+
/**
|
|
18
|
+
* A class `--fail-on`/`--allow` can name: every file classification, plus
|
|
19
|
+
* `ownership-conflict`, which is judged from the ownership rows rather
|
|
20
|
+
* than from a file's classification.
|
|
21
|
+
*/
|
|
22
|
+
export type StatusCheckClass = FileClassification | 'ownership-conflict';
|
|
11
23
|
/** Resolved `--check`/`--fail-on` policy for one status invocation. */
|
|
12
24
|
export interface StatusCheckPolicy {
|
|
13
25
|
checkEnabled: boolean;
|
|
14
|
-
|
|
26
|
+
/** Classes that fail: `--fail-on` (or the default set) minus `--allow`. */
|
|
27
|
+
failOn: readonly StatusCheckClass[];
|
|
28
|
+
/** `--allow`: classes that never fail. Set only when the flag was given. */
|
|
29
|
+
allow?: readonly StatusCheckClass[];
|
|
30
|
+
/** `--fail-on-unknown`: a present class named by neither list fails. */
|
|
31
|
+
failOnUnknown?: boolean;
|
|
15
32
|
}
|
|
16
33
|
/**
|
|
17
|
-
* Resolves the enforcement policy from the raw flags
|
|
18
|
-
* `--
|
|
19
|
-
*
|
|
34
|
+
* Resolves the enforcement policy from the raw flags. `--fail-on`,
|
|
35
|
+
* `--allow` and `--fail-on-unknown` each imply `--check`. `--fail-on`
|
|
36
|
+
* replaces the default set and `--allow` subtracts from it (naming one
|
|
37
|
+
* class in both is refused). `--fail-on-unknown` needs `--allow`: without
|
|
38
|
+
* an allow list every class the caller did not name, `patch-backed`
|
|
39
|
+
* included, would fail. All of them are refused alongside the modes that
|
|
40
|
+
* skip (or elide) classification.
|
|
20
41
|
*/
|
|
21
42
|
export declare function resolveStatusCheckPolicy(options: {
|
|
22
43
|
check?: boolean;
|
|
23
44
|
failOn?: string;
|
|
45
|
+
allow?: string;
|
|
46
|
+
failOnUnknown?: boolean;
|
|
24
47
|
raw?: boolean;
|
|
25
48
|
unmanaged?: boolean;
|
|
26
49
|
ownership?: boolean;
|
|
27
50
|
testCoverage?: boolean;
|
|
28
51
|
}): StatusCheckPolicy;
|
|
29
|
-
/**
|
|
52
|
+
/**
|
|
53
|
+
* True when the policy can fail on `ownership-conflict`, so the caller has
|
|
54
|
+
* to build the ownership rows even without `--include-ownership`.
|
|
55
|
+
*/
|
|
56
|
+
export declare function policyNeedsOwnership(policy: StatusCheckPolicy): boolean;
|
|
57
|
+
/** One failing class with a non-empty file list. */
|
|
30
58
|
export interface StatusCheckOffender {
|
|
31
|
-
classification:
|
|
59
|
+
classification: StatusCheckClass;
|
|
32
60
|
count: number;
|
|
33
61
|
files: string[];
|
|
62
|
+
/**
|
|
63
|
+
* Set when the class failed only through `--fail-on-unknown`: neither
|
|
64
|
+
* `--fail-on` nor `--allow` named it.
|
|
65
|
+
*/
|
|
66
|
+
unnamed?: true;
|
|
34
67
|
}
|
|
35
68
|
/**
|
|
36
|
-
* Collects the
|
|
37
|
-
*
|
|
38
|
-
*
|
|
39
|
-
*
|
|
69
|
+
* Collects the failing classes that have offending files, with full file
|
|
70
|
+
* lists: the fail set in policy order, then (under `--fail-on-unknown`)
|
|
71
|
+
* every other present class neither list names, in first-seen order.
|
|
72
|
+
* Shared by the human `--check` verdict and the JSON `check` block so the
|
|
73
|
+
* two views can never disagree about what failed.
|
|
74
|
+
*
|
|
75
|
+
* @param classified - Classified worktree entries
|
|
76
|
+
* @param policy - Resolved policy
|
|
77
|
+
* @param ownershipConflicts - Paths claimed by more than one patch. Only
|
|
78
|
+
* read for the `ownership-conflict` class
|
|
40
79
|
*/
|
|
41
|
-
export declare function collectStatusCheckOffenders(classified: readonly ClassifiedFile[], policy: StatusCheckPolicy): StatusCheckOffender[];
|
|
80
|
+
export declare function collectStatusCheckOffenders(classified: readonly ClassifiedFile[], policy: StatusCheckPolicy, ownershipConflicts?: readonly string[]): StatusCheckOffender[];
|
|
42
81
|
/**
|
|
43
|
-
* Throws a GeneralError (exit 1) when the policy is enabled and any
|
|
44
|
-
*
|
|
45
|
-
*
|
|
46
|
-
*
|
|
82
|
+
* Throws a GeneralError (exit 1) when the policy is enabled and any
|
|
83
|
+
* failing class is non-empty, naming each offending class with its first
|
|
84
|
+
* few files. A disabled policy or a fully tool-covered tree passes
|
|
85
|
+
* silently.
|
|
47
86
|
*/
|
|
48
|
-
export declare function runStatusCheck(classified: readonly ClassifiedFile[], policy: StatusCheckPolicy): void;
|
|
87
|
+
export declare function runStatusCheck(classified: readonly ClassifiedFile[], policy: StatusCheckPolicy, ownershipConflicts?: readonly string[]): void;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { GeneralError, InvalidArgumentError } from '../errors/base.js';
|
|
2
|
-
const
|
|
2
|
+
const ALL_CHECK_CLASSES = [
|
|
3
3
|
'patch-backed',
|
|
4
4
|
'patch-owned-drift',
|
|
5
5
|
'unmanaged',
|
|
@@ -7,12 +7,15 @@ const ALL_CLASSIFICATIONS = [
|
|
|
7
7
|
'furnace',
|
|
8
8
|
'conflict',
|
|
9
9
|
'binary-unsupported',
|
|
10
|
+
'ownership-conflict',
|
|
10
11
|
];
|
|
11
12
|
/**
|
|
12
13
|
* Default `--check` policy: everything outside {patch-backed, branding,
|
|
13
14
|
* furnace, binary-unsupported} fails. `binary-unsupported` is excluded so
|
|
14
15
|
* an honest "cannot compare" does not keep the gate permanently red.
|
|
15
16
|
* Strict CI can opt in via `--fail-on binary-unsupported`.
|
|
17
|
+
* `ownership-conflict` is opt-in too: the human `--ownership` mode already
|
|
18
|
+
* fails on it, and adding it here would change the default gate.
|
|
16
19
|
*/
|
|
17
20
|
const DEFAULT_FAIL_CLASSIFICATIONS = [
|
|
18
21
|
'unmanaged',
|
|
@@ -20,13 +23,19 @@ const DEFAULT_FAIL_CLASSIFICATIONS = [
|
|
|
20
23
|
'conflict',
|
|
21
24
|
];
|
|
22
25
|
/**
|
|
23
|
-
* Resolves the enforcement policy from the raw flags
|
|
24
|
-
* `--
|
|
25
|
-
*
|
|
26
|
+
* Resolves the enforcement policy from the raw flags. `--fail-on`,
|
|
27
|
+
* `--allow` and `--fail-on-unknown` each imply `--check`. `--fail-on`
|
|
28
|
+
* replaces the default set and `--allow` subtracts from it (naming one
|
|
29
|
+
* class in both is refused). `--fail-on-unknown` needs `--allow`: without
|
|
30
|
+
* an allow list every class the caller did not name, `patch-backed`
|
|
31
|
+
* included, would fail. All of them are refused alongside the modes that
|
|
32
|
+
* skip (or elide) classification.
|
|
26
33
|
*/
|
|
27
34
|
export function resolveStatusCheckPolicy(options) {
|
|
28
|
-
const failOnList =
|
|
29
|
-
const
|
|
35
|
+
const failOnList = parseCheckClassList(options.failOn, '--fail-on');
|
|
36
|
+
const allowList = parseCheckClassList(options.allow, '--allow');
|
|
37
|
+
const failOnUnknown = options.failOnUnknown === true;
|
|
38
|
+
const checkEnabled = options.check === true || failOnList !== undefined || allowList !== undefined || failOnUnknown;
|
|
30
39
|
if (checkEnabled &&
|
|
31
40
|
(options.raw === true ||
|
|
32
41
|
options.unmanaged === true ||
|
|
@@ -34,17 +43,32 @@ export function resolveStatusCheckPolicy(options) {
|
|
|
34
43
|
options.testCoverage === true)) {
|
|
35
44
|
throw new InvalidArgumentError('--check cannot be combined with --raw, --unmanaged, --ownership, or --test-coverage. Use the default view or --json.', '--check');
|
|
36
45
|
}
|
|
37
|
-
|
|
46
|
+
if (failOnUnknown && allowList === undefined) {
|
|
47
|
+
throw new InvalidArgumentError('--fail-on-unknown requires --allow naming the classes that may pass. Without it every class you did not name, patch-backed included, would fail.', '--fail-on-unknown');
|
|
48
|
+
}
|
|
49
|
+
const overlap = (failOnList ?? []).filter((entry) => allowList?.includes(entry) === true);
|
|
50
|
+
if (overlap.length > 0) {
|
|
51
|
+
throw new InvalidArgumentError(`--fail-on and --allow both name ${overlap.join(', ')}. A class either fails or is allowed.`, '--allow');
|
|
52
|
+
}
|
|
53
|
+
const base = failOnList ?? DEFAULT_FAIL_CLASSIFICATIONS;
|
|
54
|
+
const policy = {
|
|
55
|
+
checkEnabled,
|
|
56
|
+
failOn: allowList ? base.filter((entry) => !allowList.includes(entry)) : base,
|
|
57
|
+
};
|
|
58
|
+
if (allowList !== undefined)
|
|
59
|
+
policy.allow = allowList;
|
|
60
|
+
if (failOnUnknown)
|
|
61
|
+
policy.failOnUnknown = true;
|
|
62
|
+
return policy;
|
|
38
63
|
}
|
|
39
|
-
function
|
|
40
|
-
return
|
|
64
|
+
function isCheckClass(value) {
|
|
65
|
+
return ALL_CHECK_CLASSES.includes(value);
|
|
41
66
|
}
|
|
42
67
|
/**
|
|
43
|
-
* Parses a comma-separated `--fail-on` value into a
|
|
44
|
-
* Returns undefined when the flag was not given
|
|
45
|
-
* the default policy only under `--check`).
|
|
68
|
+
* Parses a comma-separated `--fail-on`/`--allow` value into a class list.
|
|
69
|
+
* Returns undefined when the flag was not given.
|
|
46
70
|
*/
|
|
47
|
-
function
|
|
71
|
+
function parseCheckClassList(raw, flag) {
|
|
48
72
|
if (raw === undefined)
|
|
49
73
|
return undefined;
|
|
50
74
|
const parts = raw
|
|
@@ -52,52 +76,83 @@ function parseFailOnClassifications(raw) {
|
|
|
52
76
|
.map((part) => part.trim())
|
|
53
77
|
.filter((part) => part.length > 0);
|
|
54
78
|
if (parts.length === 0) {
|
|
55
|
-
throw new InvalidArgumentError(
|
|
79
|
+
throw new InvalidArgumentError(`${flag} requires at least one classification. Valid: ${ALL_CHECK_CLASSES.join(', ')}.`, flag);
|
|
56
80
|
}
|
|
57
|
-
const
|
|
81
|
+
const classes = [];
|
|
58
82
|
for (const part of parts) {
|
|
59
|
-
if (!
|
|
60
|
-
throw new InvalidArgumentError(`Unknown
|
|
83
|
+
if (!isCheckClass(part)) {
|
|
84
|
+
throw new InvalidArgumentError(`Unknown ${flag} classification "${part}". Valid: ${ALL_CHECK_CLASSES.join(', ')}.`, flag);
|
|
61
85
|
}
|
|
62
|
-
if (!
|
|
63
|
-
|
|
86
|
+
if (!classes.includes(part))
|
|
87
|
+
classes.push(part);
|
|
64
88
|
}
|
|
65
|
-
return
|
|
89
|
+
return classes;
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* True when the policy can fail on `ownership-conflict`, so the caller has
|
|
93
|
+
* to build the ownership rows even without `--include-ownership`.
|
|
94
|
+
*/
|
|
95
|
+
export function policyNeedsOwnership(policy) {
|
|
96
|
+
if (!policy.checkEnabled)
|
|
97
|
+
return false;
|
|
98
|
+
if (policy.failOn.includes('ownership-conflict'))
|
|
99
|
+
return true;
|
|
100
|
+
return policy.failOnUnknown === true && policy.allow?.includes('ownership-conflict') !== true;
|
|
66
101
|
}
|
|
67
102
|
const CHECK_FILE_PREVIEW_MAX = 3;
|
|
68
103
|
/**
|
|
69
|
-
* Collects the
|
|
70
|
-
*
|
|
71
|
-
*
|
|
72
|
-
*
|
|
104
|
+
* Collects the failing classes that have offending files, with full file
|
|
105
|
+
* lists: the fail set in policy order, then (under `--fail-on-unknown`)
|
|
106
|
+
* every other present class neither list names, in first-seen order.
|
|
107
|
+
* Shared by the human `--check` verdict and the JSON `check` block so the
|
|
108
|
+
* two views can never disagree about what failed.
|
|
109
|
+
*
|
|
110
|
+
* @param classified - Classified worktree entries
|
|
111
|
+
* @param policy - Resolved policy
|
|
112
|
+
* @param ownershipConflicts - Paths claimed by more than one patch. Only
|
|
113
|
+
* read for the `ownership-conflict` class
|
|
73
114
|
*/
|
|
74
|
-
export function collectStatusCheckOffenders(classified, policy) {
|
|
115
|
+
export function collectStatusCheckOffenders(classified, policy, ownershipConflicts = []) {
|
|
116
|
+
const filesOf = (checkClass) => checkClass === 'ownership-conflict'
|
|
117
|
+
? [...ownershipConflicts]
|
|
118
|
+
: classified.filter((entry) => entry.classification === checkClass).map((e) => e.file);
|
|
75
119
|
const offenders = [];
|
|
76
|
-
for (const
|
|
77
|
-
const files =
|
|
78
|
-
.filter((entry) => entry.classification === classification)
|
|
79
|
-
.map((entry) => entry.file);
|
|
120
|
+
for (const checkClass of policy.failOn) {
|
|
121
|
+
const files = filesOf(checkClass);
|
|
80
122
|
if (files.length === 0)
|
|
81
123
|
continue;
|
|
82
|
-
offenders.push({ classification, count: files.length, files });
|
|
124
|
+
offenders.push({ classification: checkClass, count: files.length, files });
|
|
125
|
+
}
|
|
126
|
+
if (policy.failOnUnknown !== true)
|
|
127
|
+
return offenders;
|
|
128
|
+
const named = new Set([...policy.failOn, ...(policy.allow ?? [])]);
|
|
129
|
+
const present = [...new Set(classified.map((e) => e.classification))];
|
|
130
|
+
if (ownershipConflicts.length > 0)
|
|
131
|
+
present.push('ownership-conflict');
|
|
132
|
+
for (const checkClass of present) {
|
|
133
|
+
if (named.has(checkClass))
|
|
134
|
+
continue;
|
|
135
|
+
const files = filesOf(checkClass);
|
|
136
|
+
offenders.push({ classification: checkClass, count: files.length, files, unnamed: true });
|
|
83
137
|
}
|
|
84
138
|
return offenders;
|
|
85
139
|
}
|
|
86
140
|
/**
|
|
87
|
-
* Throws a GeneralError (exit 1) when the policy is enabled and any
|
|
88
|
-
*
|
|
89
|
-
*
|
|
90
|
-
*
|
|
141
|
+
* Throws a GeneralError (exit 1) when the policy is enabled and any
|
|
142
|
+
* failing class is non-empty, naming each offending class with its first
|
|
143
|
+
* few files. A disabled policy or a fully tool-covered tree passes
|
|
144
|
+
* silently.
|
|
91
145
|
*/
|
|
92
|
-
export function runStatusCheck(classified, policy) {
|
|
146
|
+
export function runStatusCheck(classified, policy, ownershipConflicts = []) {
|
|
93
147
|
if (!policy.checkEnabled)
|
|
94
148
|
return;
|
|
95
|
-
const offending = collectStatusCheckOffenders(classified, policy).map((offender) => {
|
|
149
|
+
const offending = collectStatusCheckOffenders(classified, policy, ownershipConflicts).map((offender) => {
|
|
96
150
|
const preview = offender.files.slice(0, CHECK_FILE_PREVIEW_MAX).join(', ');
|
|
97
151
|
const more = offender.count > CHECK_FILE_PREVIEW_MAX
|
|
98
152
|
? `, +${offender.count - CHECK_FILE_PREVIEW_MAX} more`
|
|
99
153
|
: '';
|
|
100
|
-
|
|
154
|
+
const unnamed = offender.unnamed === true ? ' [named by neither --fail-on nor --allow]' : '';
|
|
155
|
+
return `${offender.count} ${offender.classification}${unnamed} (${preview}${more})`;
|
|
101
156
|
});
|
|
102
157
|
if (offending.length === 0)
|
|
103
158
|
return;
|
|
@@ -9,24 +9,37 @@
|
|
|
9
9
|
* `files[]` entirely, because engine-clean gates need the verdict,
|
|
10
10
|
* per-class counts, and offender names, not a payload that grows with
|
|
11
11
|
* the queue (175 KB+ on a large one).
|
|
12
|
+
*
|
|
13
|
+
* Both carry the `check` block when the `--check` policy is active, and the
|
|
14
|
+
* `scope` block under `--patches`.
|
|
12
15
|
*/
|
|
13
16
|
import type { ClassifiedFile } from '../core/status-classify.js';
|
|
14
17
|
import { type StatusCheckPolicy } from './status-check.js';
|
|
15
18
|
import type { OwnershipJsonBlock } from './status-ownership.js';
|
|
19
|
+
import type { StatusScope } from './status-scope.js';
|
|
20
|
+
/** What a JSON payload adds beside the classification counts. */
|
|
21
|
+
export interface StatusJsonContext {
|
|
22
|
+
policy: StatusCheckPolicy;
|
|
23
|
+
/** Paths claimed by more than one patch, for the `ownership-conflict` class. */
|
|
24
|
+
ownershipConflicts: readonly string[];
|
|
25
|
+
/** The `--include-ownership` block, when asked for. */
|
|
26
|
+
ownership?: OwnershipJsonBlock | undefined;
|
|
27
|
+
/** The `--patches` scope, when given. */
|
|
28
|
+
scope?: StatusScope | undefined;
|
|
29
|
+
}
|
|
16
30
|
/**
|
|
17
|
-
* Full `--json` payload: summary plus the per-file `files[]` list, and
|
|
18
|
-
*
|
|
19
|
-
* Additive within schemaVersion 1: a consumer that does not ask for
|
|
31
|
+
* Full `--json` payload: summary plus the per-file `files[]` list, and the
|
|
32
|
+
* additive `check`, `scope` and `ownership` blocks when their flags are
|
|
33
|
+
* set. Additive within schemaVersion 1: a consumer that does not ask for a
|
|
20
34
|
* block never sees the key.
|
|
21
35
|
*/
|
|
22
|
-
export declare function renderJsonStatus(classified: readonly ClassifiedFile[],
|
|
36
|
+
export declare function renderJsonStatus(classified: readonly ClassifiedFile[], context: StatusJsonContext): void;
|
|
23
37
|
/**
|
|
24
38
|
* Summary-only `--json --summary` payload. Counts are always present. When
|
|
25
39
|
* the `--check`/`--fail-on` policy is active, the payload adds a `check`
|
|
26
40
|
* block with the active fail set, the verdict, and the offending files per
|
|
27
|
-
*
|
|
28
|
-
*
|
|
29
|
-
*
|
|
30
|
-
* the flag.
|
|
41
|
+
* failing class (sourced from the same collector as the human `--check`
|
|
42
|
+
* message, so the two views can never disagree). The absent `files[]` is
|
|
43
|
+
* the mode signal within schemaVersion 1. Consumers opt in via the flag.
|
|
31
44
|
*/
|
|
32
|
-
export declare function renderJsonSummaryStatus(classified: readonly ClassifiedFile[],
|
|
45
|
+
export declare function renderJsonSummaryStatus(classified: readonly ClassifiedFile[], context: StatusJsonContext): void;
|
|
@@ -16,12 +16,45 @@ function countByClassification(classified) {
|
|
|
16
16
|
return byClassification;
|
|
17
17
|
}
|
|
18
18
|
/**
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
*
|
|
19
|
+
* Builds the `check` block, or undefined when no policy is active.
|
|
20
|
+
* `allow` and `failOnUnknown` appear only when the caller set them, so a
|
|
21
|
+
* consumer that never passes those flags sees the block it always did.
|
|
22
|
+
*/
|
|
23
|
+
function buildCheckBlock(classified, context) {
|
|
24
|
+
const { policy } = context;
|
|
25
|
+
if (!policy.checkEnabled)
|
|
26
|
+
return undefined;
|
|
27
|
+
const offenders = collectStatusCheckOffenders(classified, policy, context.ownershipConflicts);
|
|
28
|
+
return {
|
|
29
|
+
enabled: true,
|
|
30
|
+
failOn: policy.failOn,
|
|
31
|
+
...(policy.allow !== undefined ? { allow: policy.allow } : {}),
|
|
32
|
+
...(policy.failOnUnknown === true ? { failOnUnknown: true } : {}),
|
|
33
|
+
failed: offenders.length > 0,
|
|
34
|
+
offenders,
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
/** The additive tail both payloads share: check, scope, ownership. */
|
|
38
|
+
function buildTrailingBlocks(classified, context) {
|
|
39
|
+
const check = buildCheckBlock(classified, context);
|
|
40
|
+
return {
|
|
41
|
+
...(check !== undefined ? { check } : {}),
|
|
42
|
+
...(context.scope !== undefined ? { scope: context.scope } : {}),
|
|
43
|
+
...(context.ownership !== undefined ? { ownership: context.ownership } : {}),
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
function writePayload(output) {
|
|
47
|
+
process.stdout.write(JSON.stringify(output, null, 2) + '\n');
|
|
48
|
+
// Payload written: stdout is now spoken for. See docs/machine-output.md.
|
|
49
|
+
setStdoutSealed(true);
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Full `--json` payload: summary plus the per-file `files[]` list, and the
|
|
53
|
+
* additive `check`, `scope` and `ownership` blocks when their flags are
|
|
54
|
+
* set. Additive within schemaVersion 1: a consumer that does not ask for a
|
|
22
55
|
* block never sees the key.
|
|
23
56
|
*/
|
|
24
|
-
export function renderJsonStatus(classified,
|
|
57
|
+
export function renderJsonStatus(classified, context) {
|
|
25
58
|
const outputFiles = classified.map((f) => {
|
|
26
59
|
const entry = {
|
|
27
60
|
file: f.file,
|
|
@@ -34,49 +67,31 @@ export function renderJsonStatus(classified, ownership) {
|
|
|
34
67
|
}
|
|
35
68
|
return entry;
|
|
36
69
|
});
|
|
37
|
-
|
|
70
|
+
writePayload({
|
|
38
71
|
schemaVersion: 1,
|
|
39
72
|
summary: {
|
|
40
73
|
total: outputFiles.length,
|
|
41
74
|
byClassification: countByClassification(classified),
|
|
42
75
|
},
|
|
43
76
|
files: outputFiles,
|
|
44
|
-
...(
|
|
45
|
-
};
|
|
46
|
-
process.stdout.write(JSON.stringify(output, null, 2) + '\n');
|
|
47
|
-
// Payload written: stdout is now spoken for. See docs/machine-output.md.
|
|
48
|
-
setStdoutSealed(true);
|
|
77
|
+
...buildTrailingBlocks(classified, context),
|
|
78
|
+
});
|
|
49
79
|
}
|
|
50
80
|
/**
|
|
51
81
|
* Summary-only `--json --summary` payload. Counts are always present. When
|
|
52
82
|
* the `--check`/`--fail-on` policy is active, the payload adds a `check`
|
|
53
83
|
* block with the active fail set, the verdict, and the offending files per
|
|
54
|
-
*
|
|
55
|
-
*
|
|
56
|
-
*
|
|
57
|
-
* the flag.
|
|
84
|
+
* failing class (sourced from the same collector as the human `--check`
|
|
85
|
+
* message, so the two views can never disagree). The absent `files[]` is
|
|
86
|
+
* the mode signal within schemaVersion 1. Consumers opt in via the flag.
|
|
58
87
|
*/
|
|
59
|
-
export function renderJsonSummaryStatus(classified,
|
|
60
|
-
|
|
88
|
+
export function renderJsonSummaryStatus(classified, context) {
|
|
89
|
+
writePayload({
|
|
61
90
|
schemaVersion: 1,
|
|
62
91
|
summary: {
|
|
63
92
|
total: classified.length,
|
|
64
93
|
byClassification: countByClassification(classified),
|
|
65
94
|
},
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
const offenders = collectStatusCheckOffenders(classified, policy);
|
|
69
|
-
output.check = {
|
|
70
|
-
enabled: true,
|
|
71
|
-
failOn: policy.failOn,
|
|
72
|
-
failed: offenders.length > 0,
|
|
73
|
-
offenders,
|
|
74
|
-
};
|
|
75
|
-
}
|
|
76
|
-
if (ownership !== undefined) {
|
|
77
|
-
output.ownership = ownership;
|
|
78
|
-
}
|
|
79
|
-
process.stdout.write(JSON.stringify(output, null, 2) + '\n');
|
|
80
|
-
// Payload written: stdout is now spoken for. See docs/machine-output.md.
|
|
81
|
-
setStdoutSealed(true);
|
|
95
|
+
...buildTrailingBlocks(classified, context),
|
|
96
|
+
});
|
|
82
97
|
}
|
|
@@ -220,6 +220,8 @@ export function renderTestCoverageStatus(baseline) {
|
|
|
220
220
|
}
|
|
221
221
|
const list = coverage.map((path) => ` - ${path}`).join('\n');
|
|
222
222
|
info(`Test packaging coverage: scoped to ${coverage.length} path(s):\n${list}\n` +
|
|
223
|
-
|
|
223
|
+
(baseline.fullCoverageAnchor === undefined
|
|
224
|
+
? 'A "fireforge test" over paths outside this list will be refused as uncovered.'
|
|
225
|
+
: 'A "fireforge test" over paths outside this list stays covered by the earlier full build while their own staging inputs are unchanged, and is refused otherwise.'));
|
|
224
226
|
outro(`Coverage: scoped (${coverage.length} paths)`);
|
|
225
227
|
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `status --patches <list>`: judges only the named patches' files. Split
|
|
3
|
+
* out of status.ts, which sits at the max-lines budget.
|
|
4
|
+
*
|
|
5
|
+
* On a shared engine a peer's unexported work keeps a tree-wide gate red
|
|
6
|
+
* for everyone. The scope keeps a file when the patch that owns it (or,
|
|
7
|
+
* for a conflict, any patch that claims it) is named, and an ownership
|
|
8
|
+
* row when any of its owners is named. An unmanaged file has no owning
|
|
9
|
+
* patch, so no scope covers it: scoped runs never judge unexported files.
|
|
10
|
+
* That is the point of the scope, and also its limit, which the docs say.
|
|
11
|
+
*/
|
|
12
|
+
import type { OwnershipRow } from '../core/ownership-table.js';
|
|
13
|
+
import type { ClassifiedFile, StatusFile } from '../core/status-classify.js';
|
|
14
|
+
/** The resolved `--patches` scope: manifest filenames, in request order. */
|
|
15
|
+
export interface StatusScope {
|
|
16
|
+
patches: string[];
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Resolves raw `--patches` values against the manifest. Returns undefined
|
|
20
|
+
* when the flag was not given, and refuses a name that matches no patch
|
|
21
|
+
* (so a typo fails loud instead of judging nothing).
|
|
22
|
+
*
|
|
23
|
+
* @param patchesDir - Absolute path to the patches directory
|
|
24
|
+
* @param requested - Raw `--patches` values (each may be a comma list)
|
|
25
|
+
*/
|
|
26
|
+
export declare function resolveStatusScope(patchesDir: string, requested: readonly string[] | undefined): Promise<StatusScope | undefined>;
|
|
27
|
+
/** Keeps only the classified entries the scope covers. No scope keeps all. */
|
|
28
|
+
export declare function scopeClassified(classified: ClassifiedFile[], scope: StatusScope | undefined): ClassifiedFile[];
|
|
29
|
+
/** Keeps only the ownership rows with an owner in scope. No scope keeps all. */
|
|
30
|
+
export declare function scopeOwnershipRows(rows: OwnershipRow[], scope: StatusScope | undefined): OwnershipRow[];
|
|
31
|
+
/**
|
|
32
|
+
* Builds the ownership rows from the full scan (classification needs every
|
|
33
|
+
* file to find claims), then narrows them to the scope.
|
|
34
|
+
*/
|
|
35
|
+
export declare function collectScopedOwnershipRows(patchesDir: string, files: StatusFile[], classified: readonly ClassifiedFile[], scope: StatusScope | undefined): Promise<OwnershipRow[]>;
|
|
36
|
+
/** The paths the `ownership-conflict` check class judges. */
|
|
37
|
+
export declare function ownershipConflictPaths(rows: readonly OwnershipRow[]): string[];
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { loadPatchesManifest } from '../core/patch-manifest.js';
|
|
2
|
+
import { selectPatchSubset } from '../core/patch-subset.js';
|
|
3
|
+
import { GeneralError } from '../errors/base.js';
|
|
4
|
+
import { collectOwnershipRows } from './status-ownership.js';
|
|
5
|
+
/**
|
|
6
|
+
* Resolves raw `--patches` values against the manifest. Returns undefined
|
|
7
|
+
* when the flag was not given, and refuses a name that matches no patch
|
|
8
|
+
* (so a typo fails loud instead of judging nothing).
|
|
9
|
+
*
|
|
10
|
+
* @param patchesDir - Absolute path to the patches directory
|
|
11
|
+
* @param requested - Raw `--patches` values (each may be a comma list)
|
|
12
|
+
*/
|
|
13
|
+
export async function resolveStatusScope(patchesDir, requested) {
|
|
14
|
+
if (requested === undefined || requested.length === 0)
|
|
15
|
+
return undefined;
|
|
16
|
+
const manifest = await loadPatchesManifest(patchesDir);
|
|
17
|
+
if (!manifest || manifest.patches.length === 0) {
|
|
18
|
+
throw new GeneralError('--patches needs a patch queue, but patches.json lists no patches.');
|
|
19
|
+
}
|
|
20
|
+
const subset = selectPatchSubset(manifest, requested, '--patches selects patches (filename, stem, order number, manifest name, or slug), not engine files.');
|
|
21
|
+
return { patches: subset.map((patch) => patch.filename) };
|
|
22
|
+
}
|
|
23
|
+
/** True when the entry's owner, or any patch claiming it, is in scope. */
|
|
24
|
+
function isInScope(entry, names) {
|
|
25
|
+
if (entry.owner !== undefined && names.has(entry.owner))
|
|
26
|
+
return true;
|
|
27
|
+
return entry.claimedBy?.some((patch) => names.has(patch)) === true;
|
|
28
|
+
}
|
|
29
|
+
/** Keeps only the classified entries the scope covers. No scope keeps all. */
|
|
30
|
+
export function scopeClassified(classified, scope) {
|
|
31
|
+
if (scope === undefined)
|
|
32
|
+
return classified;
|
|
33
|
+
const names = new Set(scope.patches);
|
|
34
|
+
return classified.filter((entry) => isInScope(entry, names));
|
|
35
|
+
}
|
|
36
|
+
/** Keeps only the ownership rows with an owner in scope. No scope keeps all. */
|
|
37
|
+
export function scopeOwnershipRows(rows, scope) {
|
|
38
|
+
if (scope === undefined)
|
|
39
|
+
return rows;
|
|
40
|
+
const names = new Set(scope.patches);
|
|
41
|
+
return rows.filter((row) => row.owners.some((owner) => names.has(owner)));
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Builds the ownership rows from the full scan (classification needs every
|
|
45
|
+
* file to find claims), then narrows them to the scope.
|
|
46
|
+
*/
|
|
47
|
+
export async function collectScopedOwnershipRows(patchesDir, files, classified, scope) {
|
|
48
|
+
const rows = await collectOwnershipRows(patchesDir, (await loadPatchesManifest(patchesDir))?.patches ?? [], files, classified);
|
|
49
|
+
return scopeOwnershipRows(rows, scope);
|
|
50
|
+
}
|
|
51
|
+
/** The paths the `ownership-conflict` check class judges. */
|
|
52
|
+
export function ownershipConflictPaths(rows) {
|
|
53
|
+
return rows.filter((row) => row.conflict).map((row) => row.path);
|
|
54
|
+
}
|