fallow 3.33.1 → 3.34.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.
@@ -24,7 +24,7 @@
24
24
 
25
25
 
26
26
  /**
27
- * Schemas for the JSON output of fallow commands. Object-shaped envelopes covered by the `FallowOutput` contract carry a top-level `kind` discriminator. Current kind values: `audit`, `explain`, `inspect_target`, `trace`, `trace-error`, `review-envelope`, `review-reconcile`, `coverage-setup`, `coverage-analyze`, `list-boundaries`, `list-workspaces`, `health`, `dupes`, `dead-code-grouped`, `architecture-grouped`, `impact`, `impact-cross-repo`, `security`, `security-survivors`, `security-blind-spots`, `dead-code`, `architecture`, `combined`, `feature-flags`, `audit-brief`, `decision-surface`, `review-walkthrough-guide`, `review-walkthrough-validation`, `suppression-inventory`, `doctor`, `type-aware-status`, `similar-code`, `similar-code-inspect`, `similar-code-review`, `similar-code-status`, `similar-code-cache-clear`. Consumers should branch on `kind` instead of probing for unique field presence. `CodeClimateOutput` is a bare JSON array (per the Code Climate / GitLab Code Quality spec) and stays a sibling root branch discriminated by checking whether the document root is an array. `ErrorOutput` is the `--format json` failure document, emitted on stdout with a non-zero exit; it carries no `kind` and is discriminated by the `error: true` field.
27
+ * Schemas for the JSON output of fallow commands. Object-shaped envelopes covered by the `FallowOutput` contract carry a top-level `kind` discriminator. Current kind values: `audit`, `explain`, `inspect_target`, `trace`, `trace-error`, `review-envelope`, `review-reconcile`, `coverage-setup`, `coverage-analyze`, `list-boundaries`, `list-workspaces`, `health`, `dupes`, `dead-code-grouped`, `architecture-grouped`, `impact`, `impact-cross-repo`, `security`, `security-survivors`, `security-blind-spots`, `dead-code`, `architecture`, `combined`, `feature-flags`, `audit-brief`, `decision-surface`, `review-walkthrough-guide`, `review-walkthrough-validation`, `suppression-inventory`, `doctor`, `type-aware-status`, `similar-code`, `similar-code-inspect`, `similar-code-review`, `similar-code-status`, `similar-code-cache-clear`, `mutation`, `mutation-plan`, `mutation-inspect`. Consumers should branch on `kind` instead of probing for unique field presence. `CodeClimateOutput` is a bare JSON array (per the Code Climate / GitLab Code Quality spec) and stays a sibling root branch discriminated by checking whether the document root is an array. `ErrorOutput` is the `--format json` failure document, emitted on stdout with a non-zero exit; it carries no `kind` and is discriminated by the `error: true` field.
28
28
  */
29
29
  export type FallowJsonOutput = (FallowOutput | CodeClimateOutput | ErrorOutput)
30
30
  /**
@@ -116,11 +116,17 @@ kind: "similar-code-review"
116
116
  kind: "similar-code-status"
117
117
  }) | (SimilarCodeCacheClearOutput & {
118
118
  kind: "similar-code-cache-clear"
119
+ }) | (MutationReport & {
120
+ kind: "mutation"
121
+ }) | (MutationPlanOutput & {
122
+ kind: "mutation-plan"
123
+ }) | (MutationInspectOutput & {
124
+ kind: "mutation-inspect"
119
125
  }))
120
126
  /**
121
127
  * Schema projection for the audit envelope's exact version.
122
128
  */
123
- export type AuditSchemaVersion = 12
129
+ export type AuditSchemaVersion = 13
124
130
  /**
125
131
  * Fallow CLI version that produced this envelope. Renders to the JSON wire as
126
132
  * a bare string (e.g. `"2.74.0"`).
@@ -269,7 +275,7 @@ export type IssueAction = (FixAction | SuppressLineAction | SuppressFileAction |
269
275
  * Discriminant string for [`FixAction`]. Kebab-case per the JSON output
270
276
  * contract.
271
277
  */
272
- export type FixActionType = ("remove-export" | "delete-file" | "remove-dependency" | "move-dependency" | "remove-enum-member" | "remove-class-member" | "resolve-import" | "install-dependency" | "remove-duplicate" | "move-to-dev" | "move-to-prod" | "refactor-cycle" | "refactor-re-export-cycle" | "refactor-boundary" | "export-type" | "migrate-deprecated-export" | "remove-catalog-entry" | "remove-empty-catalog-group" | "update-catalog-reference" | "add-catalog-entry" | "remove-catalog-reference" | "remove-dependency-override" | "fix-dependency-override" | "resolve-policy-violation" | "move-to-server-module" | "split-mixed-barrel" | "hoist-directive" | "wire-server-action" | "provide-inject" | "use-load-data" | "render-component" | "use-component-prop" | "review-component-prop" | "emit-component-event" | "wire-svelte-event" | "resolve-route-collision" | "resolve-dynamic-segment-name-conflict" | "add-suppression-reason" | "remove-stale-suppression")
278
+ export type FixActionType = ("remove-export" | "delete-file" | "remove-dependency" | "move-dependency" | "remove-enum-member" | "remove-class-member" | "resolve-import" | "install-dependency" | "remove-duplicate" | "move-to-dev" | "move-to-prod" | "refactor-cycle" | "refactor-re-export-cycle" | "refactor-boundary" | "export-type" | "migrate-deprecated-export" | "remove-catalog-entry" | "remove-empty-catalog-group" | "update-catalog-reference" | "add-catalog-entry" | "remove-catalog-reference" | "remove-dependency-override" | "fix-dependency-override" | "resolve-policy-violation" | "move-to-server-module" | "split-mixed-barrel" | "hoist-directive" | "wire-server-action" | "provide-inject" | "use-load-data" | "render-component" | "use-component-prop" | "review-component-prop" | "emit-component-event" | "wire-svelte-event" | "compose-effect-layer" | "fail-tagged-error" | "remove-catch-tag-handler" | "resolve-route-collision" | "resolve-dynamic-segment-name-conflict" | "add-suppression-reason" | "remove-stale-suppression")
273
279
  /**
274
280
  * Singleton discriminant for [`SuppressLineAction`].
275
281
  */
@@ -445,6 +451,10 @@ export type DependencyOverrideSource = ("pnpm-workspace.yaml" | "package.json")
445
451
  * surfacing them statically catches the issue first.
446
452
  */
447
453
  export type DependencyOverrideMisconfigReason = ("unparsable-key" | "empty-value")
454
+ /**
455
+ * Kind of an Effect layer definition.
456
+ */
457
+ export type EffectLayerKind = ("top_level" | "static_member")
448
458
  /**
449
459
  * Which advisory a loaded baseline earned on this run.
450
460
  *
@@ -679,6 +689,14 @@ kind: "file-scores-unavailable"
679
689
  cause: string
680
690
  kind: "hotspots-skipped"
681
691
  } | {
692
+ /**
693
+ * Kebab-case token: `shallow-clone` (the fetched history is
694
+ * incomplete) or `too-few-commits` (fewer analyzed commits than the
695
+ * minimum revisions of one file). The set is open.
696
+ */
697
+ cause: string
698
+ kind: "change-coupling-skipped"
699
+ } | {
682
700
  /**
683
701
  * `true` when the run also asked for ownership attribution, which a
684
702
  * shallow clone skews further by inflating single-author dominance.
@@ -821,6 +839,14 @@ export type ExceededThreshold = ("cyclomatic" | "cognitive" | "both" | "crap" |
821
839
  * scores. Default thresholds: cognitive 25/40, cyclomatic 30/50.
822
840
  */
823
841
  export type FindingSeverity = ("moderate" | "high" | "critical")
842
+ /**
843
+ * Whether the mutation evidence still describes the current source file.
844
+ */
845
+ export type HealthMutationState = ("fresh" | "stale")
846
+ /**
847
+ * Why mutation evidence is stale.
848
+ */
849
+ export type HealthMutationStaleReason = ("file-missing" | "no-digest" | "source-changed")
824
850
  /**
825
851
  * Coverage tier classification for CRAP findings.
826
852
  */
@@ -874,7 +900,7 @@ export type CoverageSourceConsistency = ("uniform" | "mixed")
874
900
  * set is OPEN: a later release can add a section, so a consumer must accept
875
901
  * a token that it does not know.
876
902
  */
877
- export type HealthSection = ("complexity" | "vital-signs" | "score" | "file-scores" | "coverage-gaps" | "hotspots" | "targets" | "trend" | "runtime-coverage" | "css")
903
+ export type HealthSection = ("complexity" | "vital-signs" | "score" | "file-scores" | "coverage-gaps" | "hotspots" | "change-coupling" | "targets" | "trend" | "runtime-coverage" | "mutation" | "css")
878
904
  /**
879
905
  * Lifecycle state for a configured threshold override.
880
906
  */
@@ -985,6 +1011,10 @@ export type RuntimeCoverageRiskBand = ("low" | "medium" | "high")
985
1011
  * License or trial watermark applied to runtime coverage output.
986
1012
  */
987
1013
  export type RuntimeCoverageWatermark = ("trial-expired" | "license-expired-grace" | "unknown")
1014
+ /**
1015
+ * Whether the result is conclusive.
1016
+ */
1017
+ export type MutationCompletionStatus = ("complete" | "partial")
988
1018
  /**
989
1019
  * Coverage-intelligence JSON contract version. Scoped to the
990
1020
  * `coverage_intelligence` block and independent of the top-level fallow
@@ -1014,7 +1044,7 @@ export type CoverageIntelligenceMatchConfidence = ("path-function-line" | "path-
1014
1044
  /**
1015
1045
  * Category of refactoring recommendation.
1016
1046
  */
1017
- export type RecommendationCategory = ("urgent_churn_complexity" | "break_circular_dependency" | "split_high_impact" | "remove_dead_code" | "extract_complex_functions" | "extract_dependencies" | "add_test_coverage")
1047
+ export type RecommendationCategory = ("urgent_churn_complexity" | "break_circular_dependency" | "split_high_impact" | "remove_dead_code" | "extract_complex_functions" | "extract_dependencies" | "add_test_coverage" | "resolve_hidden_coupling")
1018
1048
  /**
1019
1049
  * A ranked refactoring recommendation for a file.
1020
1050
  *
@@ -1097,6 +1127,22 @@ export type StylingFindingConfidence = ("high" | "low")
1097
1127
  * Agent handling hint for a [`StylingFinding`].
1098
1128
  */
1099
1129
  export type StylingAgentDisposition = ("fix-confidently" | "verify-first")
1130
+ /**
1131
+ * The rule that owns a diff-risk finding.
1132
+ */
1133
+ export type DiffRiskRule = ("weakened-tests" | "added-suppression" | "test-only-branch" | "diverged-clone-sibling" | "added-dependency")
1134
+ /**
1135
+ * How a `weakened-tests` finding weakened the tests.
1136
+ */
1137
+ export type WeakenedTestsKind = ("skip-only" | "removed-tests" | "assertion-drop" | "coverage-threshold")
1138
+ /**
1139
+ * The severity of a diff-risk finding, from its rule.
1140
+ */
1141
+ export type DiffRiskSeverity = ("error" | "warn")
1142
+ /**
1143
+ * The type of a diff-risk action. Every type is a suppression.
1144
+ */
1145
+ export type DiffRiskActionType = ("suppress-line" | "suppress-file" | "suppress-in-config")
1100
1146
  /**
1101
1147
  * `target` block of [`InspectOutput`], tagged by `type`.
1102
1148
  */
@@ -1129,6 +1175,16 @@ export type InspectSectionStatus = ("ok" | "partial" | "unavailable" | "error")
1129
1175
  * Granularity an [`InspectEvidenceSection`] payload covers.
1130
1176
  */
1131
1177
  export type InspectEvidenceScope = ("symbol" | "file" | "project_filtered_to_file")
1178
+ /**
1179
+ * Whether a whole-word text search for an export name finds a consumer that
1180
+ * the module graph resolves. The levels sort from best to worst.
1181
+ */
1182
+ export type SearchVisibility = ("found" | "renamed" | "missed")
1183
+ /**
1184
+ * Why a text search for an export name does not find the uses in a consumer,
1185
+ * or why a consumer is not a search target (`pass-through`).
1186
+ */
1187
+ export type SearchGapReason = ("import-alias" | "default-import" | "re-export-alias" | "namespace-use" | "dynamic-import" | "pass-through")
1132
1188
  /**
1133
1189
  * Wire-shape version of the [`DependencyUsage`] object.
1134
1190
  *
@@ -1244,7 +1300,7 @@ export type LogicalGroupStatus = ("ok" | "empty" | "invalid_path")
1244
1300
  /**
1245
1301
  * Exact schema version for [`HealthOutput`].
1246
1302
  */
1247
- export type HealthSchemaVersion = 11
1303
+ export type HealthSchemaVersion = 12
1248
1304
  /**
1249
1305
  * Resolver mode label for grouped envelopes (dead-code, dupes, health).
1250
1306
  *
@@ -1304,8 +1360,11 @@ export type SecuritySchemaVersion = ("1" | "2" | "3" | "4" | "5" | "6" | "7" | "
1304
1360
  /**
1305
1361
  * Severity level for rules.
1306
1362
  *
1307
- * Controls whether an issue type causes CI failure (`error`), is reported
1308
- * without failing (`warn`), or is suppressed entirely (`off`).
1363
+ * Controls whether an issue type sets a non-zero exit code (`error`), is
1364
+ * reported without an effect on the exit code (`warn`), or is suppressed
1365
+ * entirely (`off`). `--fail-on-issues` promotes `warn` to `error`. The
1366
+ * dead-code count gate of the GitHub Action counts `warn` findings unless its
1367
+ * `fail-on-issues` input is `false`.
1309
1368
  */
1310
1369
  export type Severity = ("error" | "warn" | "off")
1311
1370
  /**
@@ -1382,7 +1441,7 @@ export type SecurityBlindSpotsSchemaVersion = "1"
1382
1441
  /**
1383
1442
  * Schema projection for the combined envelope's exact version.
1384
1443
  */
1385
- export type CombinedSchemaVersion = 13
1444
+ export type CombinedSchemaVersion = 14
1386
1445
  /**
1387
1446
  * Schema projection for the feature-flags envelope's exact version.
1388
1447
  */
@@ -1427,7 +1486,7 @@ export type VendorFlagState = ("on" | "off" | "rolled_out" | "archived" | "exper
1427
1486
  * Independently-versioned wire-version newtype for the brief envelope.
1428
1487
  * Serializes as the integer `REVIEW_BRIEF_SCHEMA_VERSION`.
1429
1488
  */
1430
- export type ReviewBriefSchemaVersion = 12
1489
+ export type ReviewBriefSchemaVersion = 13
1431
1490
  /**
1432
1491
  * The exactly-three shippable decision categories (the SOLID-3). No cut category
1433
1492
  * (abstraction / deletion / convention / irreversibility) is representable: this
@@ -1467,6 +1526,25 @@ export type WeakeningKind = ("test-weakened" | "threshold-lowered" | "suppressio
1467
1526
  * Where a cognitive-complexity improvement came from.
1468
1527
  */
1469
1528
  export type CognitiveAttribution = ("nesting-reset" | "fewer-branch-points" | "mixed")
1529
+ /**
1530
+ * Whether the project has tests to measure against.
1531
+ */
1532
+ export type TestReachStatus = ("measured" | "no-tests")
1533
+ /**
1534
+ * Why mock detection is or is not active.
1535
+ */
1536
+ export type TestReachMasking = ("active" | "no-mocks" | "capped")
1537
+ /**
1538
+ * How tests reach one changed export.
1539
+ *
1540
+ * Treat this as an open set: a later version can add a class. A consumer
1541
+ * must read an unknown value as "needs attention".
1542
+ */
1543
+ export type TestReachClass = ("mocked-only" | "none" | "none-file" | "transitive" | "direct" | "framework")
1544
+ /**
1545
+ * Whether the export existed before the change.
1546
+ */
1547
+ export type ExportChange = ("modified" | "new")
1470
1548
  /**
1471
1549
  * Independently-versioned wire-version newtype. Serializes as the integer
1472
1550
  * [`DECISION_SURFACE_SCHEMA_VERSION`].
@@ -1600,6 +1678,46 @@ export type SimilarCodeStatusSchemaVersion = "1"
1600
1678
  * Version singleton for vector-cache clear output.
1601
1679
  */
1602
1680
  export type SimilarCodeCacheClearSchemaVersion = "1"
1681
+ /**
1682
+ * Version singleton for a mutation report.
1683
+ */
1684
+ export type MutationSchemaVersion = "1"
1685
+ /**
1686
+ * Why a run is partial.
1687
+ */
1688
+ export type MutationIncompleteReason = ("runtime-error" | "mutant-limit" | "time-budget" | "skipped-files" | "unloaded-files" | "baseline-failure" | "worktree-changed" | "typecheck-failed" | "worktree-unchecked")
1689
+ /**
1690
+ * Which code a run mutates.
1691
+ */
1692
+ export type MutationScopeKind = ("changed" | "all" | "paths")
1693
+ /**
1694
+ * The result of one mutant.
1695
+ */
1696
+ export type MutantStatus = ("killed" | "timeout" | "survived" | "no_coverage" | "runtime_error" | "flaky" | "pruned" | "pending" | "equivalent" | "compile_error")
1697
+ /**
1698
+ * Why the type check did not check a survivor.
1699
+ */
1700
+ export type MutationTypecheckSkipReason = ("no-project" | "not-type-checked" | "source-changed" | "file-missing" | "unsupported-file")
1701
+ /**
1702
+ * Version singleton for a mutation plan.
1703
+ */
1704
+ export type MutationPlanSchemaVersion = "1"
1705
+ /**
1706
+ * The status of a mutant in a plan.
1707
+ */
1708
+ export type MutationPlanDisposition = ("planned" | "pending" | "no_coverage" | "pruned")
1709
+ /**
1710
+ * Version singleton for a mutation inspect packet.
1711
+ */
1712
+ export type MutationInspectSchemaVersion = "1"
1713
+ /**
1714
+ * Whether the saved report still describes the current file.
1715
+ */
1716
+ export type MutationInspectStatus = ("fresh" | "stale")
1717
+ /**
1718
+ * Why an inspect packet is stale.
1719
+ */
1720
+ export type MutationStaleReason = ("file-missing" | "no-digest" | "source-changed" | "mutant-not-reproduced")
1603
1721
  /**
1604
1722
  * Discriminator value for [`CodeClimateIssue::kind`].
1605
1723
  */
@@ -1667,7 +1785,8 @@ gate_outcomes?: (GateOutcomes | null)
1667
1785
  */
1668
1786
  _meta?: (Meta | null)
1669
1787
  /**
1670
- * Dead-code findings scoped to the audit changeset.
1788
+ * Dead-code findings scoped to the audit changeset. Absent when no file
1789
+ * changed, or when `summary.dead_code_skipped` says the pass was skipped.
1671
1790
  */
1672
1791
  dead_code?: (CheckOutput | null)
1673
1792
  /**
@@ -1678,6 +1797,12 @@ duplication?: (DupesReportPayload | null)
1678
1797
  * Complexity findings scoped to the audit changeset.
1679
1798
  */
1680
1799
  complexity?: (HealthReport | null)
1800
+ /**
1801
+ * Diff-risk findings: facts about the change itself, such as weakened
1802
+ * tests or added suppressions. Every finding is introduced. Absent when
1803
+ * the change has no diff-risk finding.
1804
+ */
1805
+ diff_risk?: (DiffRiskReport | null)
1681
1806
  /**
1682
1807
  * Read-only follow-up commands computed from this run's findings. See
1683
1808
  * `CheckOutput::next_steps` for the contract.
@@ -1696,6 +1821,24 @@ dead_code_issues: number
1696
1821
  * Whether any reported dead-code issue has error severity.
1697
1822
  */
1698
1823
  dead_code_has_errors: boolean
1824
+ /**
1825
+ * True when `--only`, `--skip` or `audit.deadCode = false` skipped the
1826
+ * dead-code sub-analysis. The dead-code counts are then 0 and do not mean
1827
+ * a clean result. Omitted when the sub-analysis ran.
1828
+ */
1829
+ dead_code_skipped?: boolean
1830
+ /**
1831
+ * True when `--only`, `--skip` or `audit.health = false` skipped the
1832
+ * health sub-analysis. The complexity and styling counts are then 0 and
1833
+ * do not mean a clean result. Omitted when the sub-analysis ran.
1834
+ */
1835
+ complexity_skipped?: boolean
1836
+ /**
1837
+ * True when `--only`, `--skip` or `audit.dupes = false` skipped the
1838
+ * duplication sub-analysis. The clone-group counts are then 0 and do not
1839
+ * mean a clean result. Omitted when the sub-analysis ran.
1840
+ */
1841
+ duplication_skipped?: boolean
1699
1842
  /**
1700
1843
  * Total complexity findings reported for the changed files.
1701
1844
  */
@@ -1742,6 +1885,7 @@ duplication_inherited: number
1742
1885
  styling_introduced: number
1743
1886
  styling_inherited: number
1744
1887
  duplication_demoted: number
1888
+ diff_risk_introduced: number
1745
1889
  }
1746
1890
  /**
1747
1891
  * The verdict of every gate a run evaluated, keyed by name.
@@ -3086,6 +3230,23 @@ unused_component_outputs?: UnusedComponentOutputFinding[]
3086
3230
  * `warn`.
3087
3231
  */
3088
3232
  unused_svelte_events?: UnusedSvelteEventFinding[]
3233
+ /**
3234
+ * Effect layers composed only into other layers that nothing uses.
3235
+ * Gated on the project declaring `effect`. Default severity is `warn`.
3236
+ */
3237
+ unused_effect_layers?: UnusedEffectLayerFinding[]
3238
+ /**
3239
+ * Effect tagged error classes that only type positions or `catchTag`
3240
+ * handlers reference. Gated on the project declaring `effect`. Default
3241
+ * severity is `warn`.
3242
+ */
3243
+ unused_tagged_errors?: UnusedTaggedErrorFinding[]
3244
+ /**
3245
+ * `catchTag` / `catchTags` handlers for a project tag that no code
3246
+ * produces and that no `unused_tagged_errors` entry covers. Gated on the
3247
+ * project declaring `effect`. Default severity is `warn`.
3248
+ */
3249
+ unproduced_catch_tags?: UnproducedCatchTagFinding[]
3089
3250
  /**
3090
3251
  * Next.js Server Actions (exports of `"use server"` files) that no code in
3091
3252
  * the project references. Reclassified out of `unused_exports` for
@@ -3293,6 +3454,10 @@ export interface CheckSummary {
3293
3454
  * Total number of issues across all categories.
3294
3455
  */
3295
3456
  total_issues: number
3457
+ /**
3458
+ * Prop chains whose saved effective severity explicitly enforces error policy.
3459
+ */
3460
+ prop_drilling_chains?: number
3296
3461
  /**
3297
3462
  * Unused source files.
3298
3463
  */
@@ -3364,6 +3529,18 @@ unused_component_outputs?: number
3364
3529
  * whose name is listened to nowhere in the project.
3365
3530
  */
3366
3531
  unused_svelte_events?: number
3532
+ /**
3533
+ * Effect layers composed only into layers that nothing uses.
3534
+ */
3535
+ unused_effect_layers?: number
3536
+ /**
3537
+ * Effect tagged error classes that no code constructs or fails with.
3538
+ */
3539
+ unused_tagged_errors?: number
3540
+ /**
3541
+ * `catchTag` handlers for a project tag that no code produces.
3542
+ */
3543
+ unproduced_catch_tags?: number
3367
3544
  /**
3368
3545
  * Next.js Server Actions (exports of `"use server"` files) referenced by no
3369
3546
  * code in the project.
@@ -6279,6 +6456,181 @@ introduced?: (AuditIntroduced | null)
6279
6456
  */
6280
6457
  effective_severity?: (EffectiveSeverity | null)
6281
6458
  }
6459
+ /**
6460
+ * Wire-shape envelope for an [`UnusedEffectLayer`] finding. There is no safe auto-fix: a test or a script outside the project graph can still use the layer. Actions are manual
6461
+ * remediation guidance plus a line-level suppress.
6462
+ */
6463
+ export interface UnusedEffectLayerFinding {
6464
+ /**
6465
+ * The module that defines the layer.
6466
+ */
6467
+ path: string
6468
+ /**
6469
+ * `FooLive`, or `FooService.layer` for a static member.
6470
+ */
6471
+ name: string
6472
+ kind: EffectLayerKind
6473
+ /**
6474
+ * 1-based line number of the layer name.
6475
+ */
6476
+ line: number
6477
+ /**
6478
+ * 0-based byte column offset of the layer name.
6479
+ */
6480
+ col: number
6481
+ /**
6482
+ * The unused layers that compose this layer, sorted by name.
6483
+ */
6484
+ dead_consumers: string[]
6485
+ /**
6486
+ * Stable id of this finding: `dc1:<rule>:<16 hex digits>`, with a
6487
+ * `~<k>` suffix when several findings of one type share an identity.
6488
+ * Line and column are not inputs, so the id survives line shifts,
6489
+ * reformats and reorders. A rename of the file or the symbol gives a
6490
+ * new id. Absent in output from older versions.
6491
+ */
6492
+ finding_id?: (string | null)
6493
+ /**
6494
+ * Suggested next steps. Always emitted (possibly empty for
6495
+ * forward-compat).
6496
+ */
6497
+ actions: IssueAction[]
6498
+ /**
6499
+ * Set by the audit pass when this finding is introduced relative to
6500
+ * the merge-base.
6501
+ */
6502
+ introduced?: (AuditIntroduced | null)
6503
+ /**
6504
+ * Gate severity of this finding after `rules` and `overrides[].rules`
6505
+ * resolve for its path. CI formats read it for the annotation, SARIF
6506
+ * and CodeClimate level. Absent in output from older versions. Not
6507
+ * part of the finding identity, baseline keys or fingerprints.
6508
+ */
6509
+ effective_severity?: (EffectiveSeverity | null)
6510
+ }
6511
+ /**
6512
+ * Wire-shape envelope for an [`UnusedTaggedError`] finding. There is no safe auto-fix: the error can be part of a public API contract. Actions are manual
6513
+ * remediation guidance plus a line-level suppress.
6514
+ */
6515
+ export interface UnusedTaggedErrorFinding {
6516
+ /**
6517
+ * The module that declares the class.
6518
+ */
6519
+ path: string
6520
+ /**
6521
+ * The class name.
6522
+ */
6523
+ name: string
6524
+ /**
6525
+ * The `_tag` value of the class.
6526
+ */
6527
+ tag: string
6528
+ /**
6529
+ * 1-based line number of the class name.
6530
+ */
6531
+ line: number
6532
+ /**
6533
+ * 0-based byte column offset of the class name.
6534
+ */
6535
+ col: number
6536
+ /**
6537
+ * The `catchTag` / `catchTags` handlers that name the tag.
6538
+ */
6539
+ catch_sites: EffectCatchSite[]
6540
+ /**
6541
+ * Stable id of this finding: `dc1:<rule>:<16 hex digits>`, with a
6542
+ * `~<k>` suffix when several findings of one type share an identity.
6543
+ * Line and column are not inputs, so the id survives line shifts,
6544
+ * reformats and reorders. A rename of the file or the symbol gives a
6545
+ * new id. Absent in output from older versions.
6546
+ */
6547
+ finding_id?: (string | null)
6548
+ /**
6549
+ * Suggested next steps. Always emitted (possibly empty for
6550
+ * forward-compat).
6551
+ */
6552
+ actions: IssueAction[]
6553
+ /**
6554
+ * Set by the audit pass when this finding is introduced relative to
6555
+ * the merge-base.
6556
+ */
6557
+ introduced?: (AuditIntroduced | null)
6558
+ /**
6559
+ * Gate severity of this finding after `rules` and `overrides[].rules`
6560
+ * resolve for its path. CI formats read it for the annotation, SARIF
6561
+ * and CodeClimate level. Absent in output from older versions. Not
6562
+ * part of the finding identity, baseline keys or fingerprints.
6563
+ */
6564
+ effective_severity?: (EffectiveSeverity | null)
6565
+ }
6566
+ /**
6567
+ * A source location of a `catchTag` or `catchTags` handler.
6568
+ */
6569
+ export interface EffectCatchSite {
6570
+ /**
6571
+ * The module that contains the handler.
6572
+ */
6573
+ path: string
6574
+ /**
6575
+ * 1-based line number of the handled tag.
6576
+ */
6577
+ line: number
6578
+ /**
6579
+ * 0-based byte column offset of the handled tag.
6580
+ */
6581
+ col: number
6582
+ }
6583
+ /**
6584
+ * Wire-shape envelope for an [`UnproducedCatchTag`] finding. There is no safe auto-fix: the handler can guard against a future producer. Actions are manual
6585
+ * remediation guidance plus a line-level suppress.
6586
+ */
6587
+ export interface UnproducedCatchTagFinding {
6588
+ /**
6589
+ * The module that contains the handler.
6590
+ */
6591
+ path: string
6592
+ /**
6593
+ * The handled tag.
6594
+ */
6595
+ tag: string
6596
+ /**
6597
+ * 1-based line number of the handled tag.
6598
+ */
6599
+ line: number
6600
+ /**
6601
+ * 0-based byte column offset of the handled tag.
6602
+ */
6603
+ col: number
6604
+ /**
6605
+ * The project classes that declare the tag, sorted by name.
6606
+ */
6607
+ candidate_classes: string[]
6608
+ /**
6609
+ * Stable id of this finding: `dc1:<rule>:<16 hex digits>`, with a
6610
+ * `~<k>` suffix when several findings of one type share an identity.
6611
+ * Line and column are not inputs, so the id survives line shifts,
6612
+ * reformats and reorders. A rename of the file or the symbol gives a
6613
+ * new id. Absent in output from older versions.
6614
+ */
6615
+ finding_id?: (string | null)
6616
+ /**
6617
+ * Suggested next steps. Always emitted (possibly empty for
6618
+ * forward-compat).
6619
+ */
6620
+ actions: IssueAction[]
6621
+ /**
6622
+ * Set by the audit pass when this finding is introduced relative to
6623
+ * the merge-base.
6624
+ */
6625
+ introduced?: (AuditIntroduced | null)
6626
+ /**
6627
+ * Gate severity of this finding after `rules` and `overrides[].rules`
6628
+ * resolve for its path. CI formats read it for the annotation, SARIF
6629
+ * and CodeClimate level. Absent in output from older versions. Not
6630
+ * part of the finding identity, baseline keys or fingerprints.
6631
+ */
6632
+ effective_severity?: (EffectiveSeverity | null)
6633
+ }
6282
6634
  /**
6283
6635
  * Wire-shape envelope for an [`UnusedServerAction`] finding. There is no safe
6284
6636
  * auto-fix: the fix is binary but judgement-bearing (wire the action up to a
@@ -6425,11 +6777,10 @@ actions: IssueAction[]
6425
6777
  */
6426
6778
  introduced?: (AuditIntroduced | null)
6427
6779
  /**
6428
- * Rule severity of this finding. This type never gates the run, so the
6429
- * value does not change the exit code. `fallow report --from` reads it
6430
- * for the SARIF level, so the level does not depend on the config at
6431
- * render time. Absent in output from older versions. Not part of the
6432
- * finding identity, baseline keys or fingerprints.
6780
+ * Rule severity after resolving overrides for the source hop. An explicit
6781
+ * `error` enforces the chain; `warn` stays advisory under strict flags.
6782
+ * Saved reports use this value for CI levels. Absent in older output.
6783
+ * Not part of finding identity, baseline keys or fingerprints.
6433
6784
  */
6434
6785
  effective_severity?: (EffectiveSeverity | null)
6435
6786
  }
@@ -7481,11 +7832,24 @@ hotspots?: HotspotFinding[]
7481
7832
  * beside it rather than gating this summary.
7482
7833
  */
7483
7834
  hotspot_summary?: (HotspotSummary | null)
7835
+ /**
7836
+ * Hidden change coupling: file pairs that change together in the git
7837
+ * history without an import or re-export chain between them. Present
7838
+ * when the hotspots section ran and the run read the git history.
7839
+ * Advisory: no health score weight.
7840
+ */
7841
+ change_coupling?: (ChangeCouplingReport | null)
7484
7842
  /**
7485
7843
  * Runtime coverage findings from the paid sidecar (only populated with
7486
7844
  * `--runtime-coverage`).
7487
7845
  */
7488
7846
  runtime_coverage?: (RuntimeCoverageReport | null)
7847
+ /**
7848
+ * The join of a saved mutation report with the complexity findings
7849
+ * (only populated with `--mutation-report`). It never changes the CRAP
7850
+ * scores or the health score.
7851
+ */
7852
+ mutation?: (HealthMutationSummary | null)
7489
7853
  /**
7490
7854
  * Combined coverage, runtime, complexity, and change-scope verdicts.
7491
7855
  */
@@ -7621,6 +7985,13 @@ effective_severity?: (EffectiveSeverity | null)
7621
7985
  * CRAP score (change risk anti-pattern), when coverage data exists.
7622
7986
  */
7623
7987
  crap?: (number | null)
7988
+ /**
7989
+ * Mutation evidence of the function from a saved `fallow mutation`
7990
+ * report (`fallow health --mutation-report`). A separate value: it never
7991
+ * changes `crap` or the health score. Absent without the flag, and when
7992
+ * no function result of the report matches the finding.
7993
+ */
7994
+ mutation?: (HealthFindingMutation | null)
7624
7995
  /**
7625
7996
  * Test coverage percentage (0-100) backing the CRAP score.
7626
7997
  */
@@ -7719,52 +8090,125 @@ custom: number
7719
8090
  max_effect_dep_arity?: (number | null)
7720
8091
  }
7721
8092
  /**
7722
- * Component-level aggregate attached to a template complexity finding,
7723
- * pairing the template's scores with the worst class-side function.
8093
+ * The mutation evidence of one complexity finding.
7724
8094
  */
7725
- export interface ComponentRollup {
8095
+ export interface HealthFindingMutation {
8096
+ state: HealthMutationState
7726
8097
  /**
7727
- * Component name.
8098
+ * Why the evidence is stale. Absent when the state is `fresh`.
7728
8099
  */
7729
- component: string
8100
+ stale_reason?: (HealthMutationStaleReason | null)
7730
8101
  /**
7731
- * Name of the worst-scoring function in the component class.
8102
+ * The mutation score of the function, a fraction from 0 to 1:
8103
+ * `(killed + timeout) / (killed + timeout + survived)`. Absent when the
8104
+ * state is `stale`, and when no mutant of the function ran to a tested
8105
+ * result.
7732
8106
  */
7733
- class_worst_function: string
8107
+ score?: (number | null)
7734
8108
  /**
7735
- * Cyclomatic complexity of that worst class function.
8109
+ * The number of mutants of the function for each status. Absent when
8110
+ * the state is `stale`.
7736
8111
  */
7737
- class_cyclomatic: number
8112
+ counts?: (MutationStatusCounts | null)
8113
+ }
7738
8114
  /**
7739
- * Cognitive complexity of that worst class function.
8115
+ * The number of mutants for each status, and the mutation score.
7740
8116
  */
7741
- class_cognitive: number
8117
+ export interface MutationStatusCounts {
7742
8118
  /**
7743
- * Template file path relative to the project root.
8119
+ * Each mutant.
7744
8120
  */
7745
- template_path: string
8121
+ total: number
7746
8122
  /**
7747
- * Cyclomatic complexity of the template.
8123
+ * Killed mutants.
7748
8124
  */
7749
- template_cyclomatic: number
8125
+ killed: number
7750
8126
  /**
7751
- * Cognitive complexity of the template.
8127
+ * Mutants that passed their timeout.
7752
8128
  */
7753
- template_cognitive: number
7754
- }
8129
+ timeout: number
7755
8130
  /**
7756
- * A single complexity increment, located at its source line/column.
7757
- *
7758
- * `weight` is the amount this construct added to `metric`; for nested
7759
- * cognitive increments `weight == 1 + nesting`. Consumers that render inline
7760
- * (the VS Code editor breakdown) group contributions by `line` and sum the
7761
- * weights, deferring the per-kind list to a hover.
8131
+ * Mutants that each covering test let pass.
7762
8132
  */
7763
- export interface ComplexityContribution {
8133
+ survived: number
7764
8134
  /**
7765
- * 1-based line number where the construct begins.
8135
+ * Mutants that no test reaches.
7766
8136
  */
7767
- line: number
8137
+ no_coverage: number
8138
+ /**
8139
+ * Mutants with a runner fault.
8140
+ */
8141
+ runtime_error: number
8142
+ /**
8143
+ * Mutants where the second run in a new companion changed whether the
8144
+ * tests detect the mutant.
8145
+ */
8146
+ flaky: number
8147
+ /**
8148
+ * Mutants that a static rule removed.
8149
+ */
8150
+ pruned: number
8151
+ /**
8152
+ * Mutants that did not run.
8153
+ */
8154
+ pending: number
8155
+ /**
8156
+ * Mutants that a verdict marks as equivalent.
8157
+ */
8158
+ equivalent: number
8159
+ /**
8160
+ * Survived mutants that do not type-check. A report from a version
8161
+ * before `--typecheck` has no such field, so it reads as 0.
8162
+ */
8163
+ compile_error?: number
8164
+ }
8165
+ /**
8166
+ * Component-level aggregate attached to a template complexity finding,
8167
+ * pairing the template's scores with the worst class-side function.
8168
+ */
8169
+ export interface ComponentRollup {
8170
+ /**
8171
+ * Component name.
8172
+ */
8173
+ component: string
8174
+ /**
8175
+ * Name of the worst-scoring function in the component class.
8176
+ */
8177
+ class_worst_function: string
8178
+ /**
8179
+ * Cyclomatic complexity of that worst class function.
8180
+ */
8181
+ class_cyclomatic: number
8182
+ /**
8183
+ * Cognitive complexity of that worst class function.
8184
+ */
8185
+ class_cognitive: number
8186
+ /**
8187
+ * Template file path relative to the project root.
8188
+ */
8189
+ template_path: string
8190
+ /**
8191
+ * Cyclomatic complexity of the template.
8192
+ */
8193
+ template_cyclomatic: number
8194
+ /**
8195
+ * Cognitive complexity of the template.
8196
+ */
8197
+ template_cognitive: number
8198
+ }
8199
+ /**
8200
+ * A single complexity increment, located at its source line/column.
8201
+ *
8202
+ * `weight` is the amount this construct added to `metric`; for nested
8203
+ * cognitive increments `weight == 1 + nesting`. Consumers that render inline
8204
+ * (the VS Code editor breakdown) group contributions by `line` and sum the
8205
+ * weights, deferring the per-kind list to a hover.
8206
+ */
8207
+ export interface ComplexityContribution {
8208
+ /**
8209
+ * 1-based line number where the construct begins.
8210
+ */
8211
+ line: number
7768
8212
  /**
7769
8213
  * 0-based byte column where the construct begins.
7770
8214
  */
@@ -8473,11 +8917,11 @@ function_count: number
8473
8917
  lines: number
8474
8918
  /**
8475
8919
  * Highest CRAP score among the file's functions. Always the raw measured
8476
- * value; threshold overrides never rewrite it.
8920
+ * value; threshold overrides and suppressions never rewrite it.
8477
8921
  */
8478
8922
  crap_max: number
8479
8923
  /**
8480
- * Functions whose rounded CRAP score meets or exceeds their effective
8924
+ * Unsuppressed functions whose rounded CRAP score meets or exceeds their effective
8481
8925
  * ceiling, resolved from `health.thresholdOverrides` over the global
8482
8926
  * `maxCrap` / `--max-crap` value. Zero when CRAP enforcement is disabled
8483
8927
  * (global ceiling `0`).
@@ -8491,6 +8935,26 @@ crap_above_threshold: number
8491
8935
  * function at or above the canonical baseline. Omitted when zero.
8492
8936
  */
8493
8937
  crap_exempted?: number
8938
+ /**
8939
+ * Concrete scored functions accepted by a complexity suppression, including
8940
+ * subthreshold functions and disabled-enforcement runs. Omitted when zero.
8941
+ * May overlap with configured exemptions; the counts are not a partition.
8942
+ */
8943
+ crap_suppressed?: number
8944
+ /**
8945
+ * Highest rounded CRAP among unsuppressed scored functions, including
8946
+ * subthreshold and configured-exempt functions. Present with the paired
8947
+ * unsuppressed threshold whenever a scored suppression exists. Explicitly
8948
+ * zero when every scored function is suppressed; raw crap_max is unchanged.
8949
+ */
8950
+ crap_unsuppressed_max?: (number | null)
8951
+ /**
8952
+ * Lowest effective ceiling among unsuppressed scored functions, or the run
8953
+ * global when none remain. Emitted with crap_unsuppressed_max. Consumers
8954
+ * receiving an absent or partial pair fall back to the complete legacy pair:
8955
+ * crap_max and crap_effective_threshold (or the run global when absent).
8956
+ */
8957
+ crap_unsuppressed_effective_threshold?: (number | null)
8494
8958
  /**
8495
8959
  * Lowest effective CRAP ceiling among the file's functions, present only
8496
8960
  * when it differs from the run global (`summary.max_crap_threshold`).
@@ -8712,6 +9176,19 @@ complexity_density: number
8712
9176
  */
8713
9177
  fan_in: number
8714
9178
  trend: ChurnTrend
9179
+ /**
9180
+ * Change dispersion: the median number of analyzed files in the commits
9181
+ * that changed this file, over the change coupling history window. Bulk
9182
+ * commits above the coupling file cap are not counted. Absent when the
9183
+ * history has no commit ids (for example imported churn without them).
9184
+ */
9185
+ median_files_per_commit?: (number | null)
9186
+ /**
9187
+ * Change dispersion: the median number of changed lines (added plus
9188
+ * deleted, analyzed files only) in the commits that changed this file.
9189
+ * Same window and rules as `median_files_per_commit`.
9190
+ */
9191
+ median_lines_per_commit?: (number | null)
8715
9192
  /**
8716
9193
  * Ownership metrics, when ownership analysis ran.
8717
9194
  */
@@ -8885,6 +9362,105 @@ epoch_secs: number
8885
9362
  */
8886
9363
  reproducible: boolean
8887
9364
  }
9365
+ /**
9366
+ * Hidden change coupling: pairs of files that change together in the git
9367
+ * history while no import or re-export chain connects them.
9368
+ *
9369
+ * An agent that follows the import graph cannot find the second file of a
9370
+ * hidden pair. The section is advisory: it has no health score weight and
9371
+ * never gates.
9372
+ */
9373
+ export interface ChangeCouplingReport {
9374
+ /**
9375
+ * History window that the section reads, for example `"12 months"`.
9376
+ * Without `--since` the window is 12 months, wider than the hotspot
9377
+ * window.
9378
+ */
9379
+ since: string
9380
+ /**
9381
+ * Commits that changed at least one analyzed file and were not skipped.
9382
+ */
9383
+ commits_analyzed: number
9384
+ /**
9385
+ * Commits skipped because they changed more analyzed files than
9386
+ * `thresholds.max_files_per_commit`.
9387
+ */
9388
+ commits_skipped: number
9389
+ /**
9390
+ * Hidden pairs in scope before `--top` cuts `pairs`.
9391
+ */
9392
+ total_pairs: number
9393
+ thresholds: ChangeCouplingThresholds
9394
+ /**
9395
+ * Hidden pairs, sorted by `degree` and then `shared_revisions` (both
9396
+ * descending), then by path. Empty when the history cannot show
9397
+ * coupling; `workspace_diagnostics` then tells why.
9398
+ */
9399
+ pairs: HiddenCouplingPair[]
9400
+ }
9401
+ /**
9402
+ * Thresholds that a hidden pair met.
9403
+ */
9404
+ export interface ChangeCouplingThresholds {
9405
+ /**
9406
+ * Commits with more analyzed files than this are skipped.
9407
+ */
9408
+ max_files_per_commit: number
9409
+ /**
9410
+ * Minimum commits for each file of a pair.
9411
+ */
9412
+ min_revisions: number
9413
+ /**
9414
+ * Minimum commits that change both files of a pair.
9415
+ */
9416
+ min_shared_revisions: number
9417
+ /**
9418
+ * Minimum coupling degree, from 0 to 1.
9419
+ */
9420
+ min_degree: number
9421
+ /**
9422
+ * Degree at or above which a pair is `strong`.
9423
+ */
9424
+ strong_degree: number
9425
+ }
9426
+ /**
9427
+ * Two files that change together without a static edge between them.
9428
+ */
9429
+ export interface HiddenCouplingPair {
9430
+ /**
9431
+ * First file, relative to the project root. Sorts before `path_b`.
9432
+ */
9433
+ path_a: string
9434
+ /**
9435
+ * Second file, relative to the project root.
9436
+ */
9437
+ path_b: string
9438
+ /**
9439
+ * Commits that changed `path_a` in the window.
9440
+ */
9441
+ revisions_a: number
9442
+ /**
9443
+ * Commits that changed `path_b` in the window.
9444
+ */
9445
+ revisions_b: number
9446
+ /**
9447
+ * Commits that changed both files.
9448
+ */
9449
+ shared_revisions: number
9450
+ /**
9451
+ * Coupling degree from 0 to 1: `shared_revisions` divided by the mean of
9452
+ * `revisions_a` and `revisions_b`.
9453
+ */
9454
+ degree: number
9455
+ /**
9456
+ * True when `degree` reaches `thresholds.strong_degree`. The check uses
9457
+ * the rounded `degree` that the report shows, so 0.495 counts as 0.5.
9458
+ * A strong pair gives each file the `hidden_coupling` target factor. A
9459
+ * file that no other target rule claims becomes a
9460
+ * `resolve_hidden_coupling` refactoring target.
9461
+ */
9462
+ strong?: boolean
9463
+ }
8888
9464
  /**
8889
9465
  * Runtime coverage findings merged into the health report or emitted by
8890
9466
  * `fallow coverage analyze`. Present in health output when --runtime-coverage
@@ -9439,6 +10015,50 @@ stale: boolean
9439
10015
  */
9440
10016
  stale_after_days: number
9441
10017
  }
10018
+ /**
10019
+ * The join of a saved mutation report with the complexity findings.
10020
+ */
10021
+ export interface HealthMutationSummary {
10022
+ /**
10023
+ * The completion status of the run that wrote the report. Only
10024
+ * `complete` makes an empty survivor list conclusive. Absent when the
10025
+ * report has no completion.
10026
+ */
10027
+ completion?: (MutationCompletionStatus | null)
10028
+ /**
10029
+ * The number of function results in the report.
10030
+ */
10031
+ functions: number
10032
+ /**
10033
+ * The number of complexity findings with fresh mutation evidence.
10034
+ */
10035
+ findings_fresh: number
10036
+ /**
10037
+ * The number of complexity findings with stale mutation evidence.
10038
+ */
10039
+ findings_stale: number
10040
+ /**
10041
+ * The number of complexity findings that no function result of the
10042
+ * report matches. A finding matches when the path, the first line and
10043
+ * the name are equal.
10044
+ */
10045
+ findings_unmatched: number
10046
+ /**
10047
+ * The report files that do not match the current source, sorted by
10048
+ * path. Their functions have no score.
10049
+ */
10050
+ stale_files?: HealthMutationStaleFile[]
10051
+ }
10052
+ /**
10053
+ * One file of the mutation report that does not match the current source.
10054
+ */
10055
+ export interface HealthMutationStaleFile {
10056
+ /**
10057
+ * The root-relative path, with forward slashes.
10058
+ */
10059
+ path: string
10060
+ reason: HealthMutationStaleReason
10061
+ }
9442
10062
  /**
9443
10063
  * Combined coverage, runtime, complexity, and change-scope verdicts.
9444
10064
  */
@@ -9695,6 +10315,11 @@ direct_callers?: DirectCallerEvidence[]
9695
10315
  * Other duplicate-code instances that share a clone group with this target.
9696
10316
  */
9697
10317
  clone_siblings?: CloneSiblingEvidence[]
10318
+ /**
10319
+ * Files that change together with this target without a static edge
10320
+ * (populated for `ResolveHiddenCoupling` targets), strongest first.
10321
+ */
10322
+ co_change_partners?: CoChangePartnerEvidence[]
9698
10323
  }
9699
10324
  /**
9700
10325
  * A function referenced in target evidence.
@@ -9764,6 +10389,23 @@ end_line: number
9764
10389
  */
9765
10390
  fingerprint: string
9766
10391
  }
10392
+ /**
10393
+ * A hidden change-coupling partner referenced in target evidence.
10394
+ */
10395
+ export interface CoChangePartnerEvidence {
10396
+ /**
10397
+ * File that changes together with the target.
10398
+ */
10399
+ path: string
10400
+ /**
10401
+ * Commits that changed both files.
10402
+ */
10403
+ shared_revisions: number
10404
+ /**
10405
+ * Coupling degree from 0 to 1.
10406
+ */
10407
+ degree: number
10408
+ }
9767
10409
  /**
9768
10410
  * Suggested action attached to a [`RefactoringTarget`].
9769
10411
  *
@@ -11223,6 +11865,88 @@ actions: CssCandidateAction[]
11223
11865
  */
11224
11866
  introduced?: (boolean | null)
11225
11867
  }
11868
+ /**
11869
+ * The diff-risk section of `fallow audit` JSON.
11870
+ */
11871
+ export interface DiffRiskReport {
11872
+ /**
11873
+ * Findings, ordered by path, line, rule and kind.
11874
+ */
11875
+ findings: DiffRiskFinding[]
11876
+ }
11877
+ /**
11878
+ * One diff-risk finding.
11879
+ */
11880
+ export interface DiffRiskFinding {
11881
+ rule: DiffRiskRule
11882
+ /**
11883
+ * How the tests were weakened. Present only on `weakened-tests`.
11884
+ */
11885
+ kind?: (WeakenedTestsKind | null)
11886
+ /**
11887
+ * Root-relative path of the changed file, with forward slashes.
11888
+ */
11889
+ path: string
11890
+ /**
11891
+ * 1-based head line. Absent when the finding is about the whole file,
11892
+ * for example removed tests or a deleted file.
11893
+ */
11894
+ line?: (number | null)
11895
+ /**
11896
+ * One-sentence statement of the fact.
11897
+ */
11898
+ message: string
11899
+ /**
11900
+ * The token, the count change, or the value change that supports the
11901
+ * finding.
11902
+ */
11903
+ evidence: string
11904
+ severity: DiffRiskSeverity
11905
+ /**
11906
+ * Always `true`: the change introduced the finding.
11907
+ */
11908
+ introduced: boolean
11909
+ /**
11910
+ * Related locations, such as the unchanged siblings of a clone group.
11911
+ */
11912
+ related?: DiffRiskLocation[]
11913
+ /**
11914
+ * Suppression actions.
11915
+ */
11916
+ actions: DiffRiskAction[]
11917
+ }
11918
+ /**
11919
+ * A location that relates to a diff-risk finding, such as an unchanged clone
11920
+ * sibling.
11921
+ */
11922
+ export interface DiffRiskLocation {
11923
+ /**
11924
+ * Root-relative path, with forward slashes.
11925
+ */
11926
+ path: string
11927
+ /**
11928
+ * 1-based line.
11929
+ */
11930
+ line: number
11931
+ }
11932
+ /**
11933
+ * One action on a diff-risk finding.
11934
+ */
11935
+ export interface DiffRiskAction {
11936
+ type: DiffRiskActionType
11937
+ /**
11938
+ * Always `false`: Fallow does not apply a suppression for you.
11939
+ */
11940
+ auto_fixable: boolean
11941
+ /**
11942
+ * Human-readable description of the action.
11943
+ */
11944
+ description: string
11945
+ /**
11946
+ * The suppression comment to insert. Absent on `suppress-in-config`.
11947
+ */
11948
+ comment?: (string | null)
11949
+ }
11226
11950
  /**
11227
11951
  * Envelope emitted by `fallow explain <issue-type> --format json`.
11228
11952
  *
@@ -11468,6 +12192,29 @@ from_file: string
11468
12192
  * Reference kind, such as named import, default import, or re-export.
11469
12193
  */
11470
12194
  kind: string
12195
+ /**
12196
+ * 1-based line of the import statement in `from_file`. Absent when the
12197
+ * graph holds no source position for the reference or the file cannot be
12198
+ * read.
12199
+ */
12200
+ line?: (number | null)
12201
+ /**
12202
+ * Whether a whole-word text search for the export name finds this
12203
+ * consumer. Absent when no check applies, for example when the consumer
12204
+ * source cannot be read.
12205
+ */
12206
+ search_visibility?: (SearchVisibility | null)
12207
+ /**
12208
+ * Why a text search does not find the uses in this consumer. With
12209
+ * `search_visibility` `found`, only `pass-through` occurs: the consumer
12210
+ * forwards the export and does not use it.
12211
+ */
12212
+ reason?: (SearchGapReason | null)
12213
+ /**
12214
+ * The name to search for in this consumer instead of the export name.
12215
+ * Absent when the export name finds the uses or no single name does.
12216
+ */
12217
+ search_as?: (string | null)
11471
12218
  }
11472
12219
  /**
11473
12220
  * Direct references that credit one namespace of an export binding.
@@ -11556,7 +12303,8 @@ owner_file_reachable: boolean
11556
12303
  */
11557
12304
  owner_is_entry_point: boolean
11558
12305
  /**
11559
- * Files that reference the owning export directly.
12306
+ * Files that reference the owning export directly. The search visibility
12307
+ * fields on each entry check the owner export name, not the member name.
11560
12308
  */
11561
12309
  owner_direct_references: ExportReference[]
11562
12310
  /**
@@ -12126,6 +12874,28 @@ consumed_symbols: string[]
12126
12874
  * Scope note for the syntactic trace.
12127
12875
  */
12128
12876
  note: string
12877
+ /**
12878
+ * Whether a whole-word text search for the consumed symbol names finds
12879
+ * this consumer. When the consumer uses more than one symbol, the worst
12880
+ * level wins (`missed`, then `renamed`, then `found`). Absent when no
12881
+ * check applies, for example when the consumer source cannot be read.
12882
+ */
12883
+ search_visibility?: (SearchVisibility | null)
12884
+ /**
12885
+ * Why a text search does not find the uses of the worst symbol. With
12886
+ * `search_visibility` `found`, only `pass-through` occurs.
12887
+ */
12888
+ reason?: (SearchGapReason | null)
12889
+ /**
12890
+ * The name to search for in this consumer instead of the symbol name.
12891
+ */
12892
+ search_as?: (string | null)
12893
+ /**
12894
+ * The entry of `consumed_symbols` that `search_visibility`, `reason`
12895
+ * and `search_as` describe: the worst symbol, `default` for a default
12896
+ * export. Present when `search_visibility` is present.
12897
+ */
12898
+ search_symbol?: (string | null)
12129
12899
  }
12130
12900
  /**
12131
12901
  * Result of asking how one module reaches another: the shortest import path.
@@ -13084,11 +13854,24 @@ hotspots?: HotspotFinding[]
13084
13854
  * beside it rather than gating this summary.
13085
13855
  */
13086
13856
  hotspot_summary?: (HotspotSummary | null)
13857
+ /**
13858
+ * Hidden change coupling: file pairs that change together in the git
13859
+ * history without an import or re-export chain between them. Present
13860
+ * when the hotspots section ran and the run read the git history.
13861
+ * Advisory: no health score weight.
13862
+ */
13863
+ change_coupling?: (ChangeCouplingReport | null)
13087
13864
  /**
13088
13865
  * Runtime coverage findings from the paid sidecar (only populated with
13089
13866
  * `--runtime-coverage`).
13090
13867
  */
13091
13868
  runtime_coverage?: (RuntimeCoverageReport | null)
13869
+ /**
13870
+ * The join of a saved mutation report with the complexity findings
13871
+ * (only populated with `--mutation-report`). It never changes the CRAP
13872
+ * scores or the health score.
13873
+ */
13874
+ mutation?: (HealthMutationSummary | null)
13092
13875
  /**
13093
13876
  * Combined coverage, runtime, complexity, and change-scope verdicts.
13094
13877
  */
@@ -13990,6 +14773,23 @@ unused_component_outputs?: UnusedComponentOutputFinding[]
13990
14773
  * `warn`.
13991
14774
  */
13992
14775
  unused_svelte_events?: UnusedSvelteEventFinding[]
14776
+ /**
14777
+ * Effect layers composed only into other layers that nothing uses.
14778
+ * Gated on the project declaring `effect`. Default severity is `warn`.
14779
+ */
14780
+ unused_effect_layers?: UnusedEffectLayerFinding[]
14781
+ /**
14782
+ * Effect tagged error classes that only type positions or `catchTag`
14783
+ * handlers reference. Gated on the project declaring `effect`. Default
14784
+ * severity is `warn`.
14785
+ */
14786
+ unused_tagged_errors?: UnusedTaggedErrorFinding[]
14787
+ /**
14788
+ * `catchTag` / `catchTags` handlers for a project tag that no code
14789
+ * produces and that no `unused_tagged_errors` entry covers. Gated on the
14790
+ * project declaring `effect`. Default severity is `warn`.
14791
+ */
14792
+ unproduced_catch_tags?: UnproducedCatchTagFinding[]
13993
14793
  /**
13994
14794
  * Next.js Server Actions (exports of `"use server"` files) that no code in
13995
14795
  * the project references. Reclassified out of `unused_exports` for
@@ -15701,6 +16501,23 @@ unused_component_outputs?: UnusedComponentOutputFinding[]
15701
16501
  * `warn`.
15702
16502
  */
15703
16503
  unused_svelte_events?: UnusedSvelteEventFinding[]
16504
+ /**
16505
+ * Effect layers composed only into other layers that nothing uses.
16506
+ * Gated on the project declaring `effect`. Default severity is `warn`.
16507
+ */
16508
+ unused_effect_layers?: UnusedEffectLayerFinding[]
16509
+ /**
16510
+ * Effect tagged error classes that only type positions or `catchTag`
16511
+ * handlers reference. Gated on the project declaring `effect`. Default
16512
+ * severity is `warn`.
16513
+ */
16514
+ unused_tagged_errors?: UnusedTaggedErrorFinding[]
16515
+ /**
16516
+ * `catchTag` / `catchTags` handlers for a project tag that no code
16517
+ * produces and that no `unused_tagged_errors` entry covers. Gated on the
16518
+ * project declaring `effect`. Default severity is `warn`.
16519
+ */
16520
+ unproduced_catch_tags?: UnproducedCatchTagFinding[]
15704
16521
  /**
15705
16522
  * Next.js Server Actions (exports of `"use server"` files) that no code in
15706
16523
  * the project references. Reclassified out of `unused_exports` for
@@ -16624,6 +17441,12 @@ complexity?: (HealthReport | null)
16624
17441
  * comparison ran.
16625
17442
  */
16626
17443
  branching?: (BranchingReport | null)
17444
+ /**
17445
+ * How tests reach the value exports that the diff changes. Advisory,
17446
+ * never gates. Absent when the diff changes no value export or no diff
17447
+ * is known.
17448
+ */
17449
+ test_reach?: (TestReachFacts | null)
16627
17450
  }
16628
17451
  /**
16629
17452
  * The ranked, capped decision surface plus the set of signal_ids the
@@ -16877,6 +17700,28 @@ affected_by_dir_omitted: number
16877
17700
  * deliberately skips story and test consumers that the affected set counts.
16878
17701
  */
16879
17702
  coordination_gap: CoordinationGapFact[]
17703
+ /**
17704
+ * Co-change gaps: a changed file has a hidden change-coupling partner
17705
+ * that is absent from the diff. The two files changed together in most
17706
+ * commits of the history window, but no import or re-export chain
17707
+ * connects them, so the graph facts above cannot point at the partner.
17708
+ * Advisory, never gates. Omitted when empty.
17709
+ * At most 10 entries (`CO_CHANGE_GAP_CAP`), strongest degree first.
17710
+ */
17711
+ co_change_gap?: CoChangeGapFact[]
17712
+ /**
17713
+ * All co-change gaps, before the cap cuts `co_change_gap`. Omitted
17714
+ * when zero.
17715
+ */
17716
+ co_change_gap_count?: number
17717
+ /**
17718
+ * Consumers that a whole-word text search for a changed export name does
17719
+ * not find (`missed`), or finds only under another local name
17720
+ * (`renamed`). Only exports whose declaration statement overlaps an added
17721
+ * diff line count, and only consumers outside the diff. Absent when no
17722
+ * such consumer exists.
17723
+ */
17724
+ search_gap?: (SearchGapFacts | null)
16880
17725
  }
16881
17726
  /**
16882
17727
  * One directory of the blast radius and how many affected files it holds.
@@ -16917,23 +17762,115 @@ consumed_symbols: string[]
16917
17762
  note: string
16918
17763
  }
16919
17764
  /**
16920
- * The weighted focus map: the ranked `review-here` units plus the FULL
16921
- * `deprioritized` escape-hatch list, so nothing is hidden.
16922
- *
16923
- * Completeness invariant (the escape-hatch done-condition): the two lists
16924
- * partition the unit set, so `review_here.len() + deprioritized.len()` equals
16925
- * the total unit count by construction.
17765
+ * One co-change gap: `changed_file` is in the diff, `partner_file` is not,
17766
+ * and history shows that the two files usually change together.
16926
17767
  */
16927
- export interface FocusMap {
17768
+ export interface CoChangeGapFact {
16928
17769
  /**
16929
- * Units labeled `review-here`, ranked by composite score (descending), ties
16930
- * broken by path for determinism.
17770
+ * Root-relative path of the changed file.
16931
17771
  */
16932
- review_here: FocusUnit[]
17772
+ changed_file: string
16933
17773
  /**
16934
- * EVERY de-prioritized unit (`not-prioritized`, plus runtime-backed `skip`
16935
- * units on the paid path) -- the escape hatch. Always present and fully
16936
- * enumerated so a reviewer can always "show me what you de-prioritized"; the
17774
+ * Root-relative path of the hidden partner that the diff does not touch.
17775
+ */
17776
+ partner_file: string
17777
+ /**
17778
+ * Commits in the history window that changed both files.
17779
+ */
17780
+ shared_revisions: number
17781
+ /**
17782
+ * Coupling degree from 0 to 1.
17783
+ */
17784
+ degree: number
17785
+ /**
17786
+ * Scope note: history evidence, not a proof that the partner must change.
17787
+ */
17788
+ note: string
17789
+ }
17790
+ /**
17791
+ * The literal-search gap of the changed exports: the consumers that a text
17792
+ * search for the export name does not find or finds only under another name.
17793
+ */
17794
+ export interface SearchGapFacts {
17795
+ /**
17796
+ * Sum of the per-export totals, before the per-export cap. A consumer of
17797
+ * two changed exports counts once for each export.
17798
+ */
17799
+ total: number
17800
+ /**
17801
+ * One entry per changed export with at least one such consumer, sorted
17802
+ * by file and line.
17803
+ */
17804
+ exports: ExportSearchGapFact[]
17805
+ }
17806
+ /**
17807
+ * The `missed` and `renamed` consumers of one changed export.
17808
+ */
17809
+ export interface ExportSearchGapFact {
17810
+ /**
17811
+ * Root-relative path of the changed file that declares the export.
17812
+ */
17813
+ file: string
17814
+ /**
17815
+ * The export name, `default` for a default export.
17816
+ */
17817
+ export_name: string
17818
+ /**
17819
+ * 1-based line of the export.
17820
+ */
17821
+ line: number
17822
+ /**
17823
+ * Number of `missed` and `renamed` consumers of this export, before the
17824
+ * cap.
17825
+ */
17826
+ total: number
17827
+ /**
17828
+ * At most [`SEARCH_GAP_CONSUMER_CAP`] consumers, `missed` first, then by
17829
+ * path.
17830
+ */
17831
+ consumers: SearchGapConsumerFact[]
17832
+ }
17833
+ /**
17834
+ * One consumer that a text search for the export name does not find, or
17835
+ * finds only under another local name.
17836
+ */
17837
+ export interface SearchGapConsumerFact {
17838
+ /**
17839
+ * Root-relative path of the consumer.
17840
+ */
17841
+ consumer_file: string
17842
+ /**
17843
+ * 1-based line of the import statement in the consumer, when known.
17844
+ */
17845
+ line?: (number | null)
17846
+ search_visibility: SearchVisibility
17847
+ /**
17848
+ * Why the text search does not find the uses.
17849
+ */
17850
+ reason?: (SearchGapReason | null)
17851
+ /**
17852
+ * The name to search for in this consumer instead.
17853
+ */
17854
+ search_as?: (string | null)
17855
+ }
17856
+ /**
17857
+ * The weighted focus map: the ranked `review-here` units plus the FULL
17858
+ * `deprioritized` escape-hatch list, so nothing is hidden.
17859
+ *
17860
+ * Completeness invariant (the escape-hatch done-condition): the two lists
17861
+ * partition the unit set, so `review_here.len() + deprioritized.len()` equals
17862
+ * the total unit count by construction.
17863
+ */
17864
+ export interface FocusMap {
17865
+ /**
17866
+ * Units labeled `review-here`, ranked by composite score (descending), ties
17867
+ * broken by path for determinism.
17868
+ */
17869
+ review_here: FocusUnit[]
17870
+ /**
17871
+ * EVERY de-prioritized unit (`not-prioritized`, plus runtime-backed `skip`
17872
+ * units on the paid path) -- the escape hatch. Always present and fully
17873
+ * enumerated so a reviewer can always "show me what you de-prioritized"; the
16937
17874
  * human brief collapses it by default and re-expands under
16938
17875
  * `--show-deprioritized`. Nothing is ever hidden, including a `skip`.
16939
17876
  */
@@ -17370,6 +18307,111 @@ branch_points_delta: number
17370
18307
  */
17371
18308
  functions_delta: number
17372
18309
  }
18310
+ /**
18311
+ * How tests reach the value exports that the diff changes.
18312
+ *
18313
+ * A changed export is a value export whose declaring statement overlaps an
18314
+ * added line. The section is advisory: it never changes the verdict or the
18315
+ * exit code.
18316
+ */
18317
+ export interface TestReachFacts {
18318
+ status: TestReachStatus
18319
+ masking: TestReachMasking
18320
+ /**
18321
+ * Number of changed value exports.
18322
+ */
18323
+ total: number
18324
+ counts: TestReachCounts
18325
+ /**
18326
+ * The exports that need attention (`mocked-only`, `none`, `none-file`,
18327
+ * `transitive`), at most [`TEST_REACH_EXPORT_CAP`]. The order is reach
18328
+ * class, then `modified` before `new`, then file, line and name. Empty
18329
+ * for `no-tests`.
18330
+ */
18331
+ exports: ExportTestReachFact[]
18332
+ /**
18333
+ * Number of attention rows left out by the cap.
18334
+ */
18335
+ exports_omitted: number
18336
+ /**
18337
+ * True when the project uses an end-to-end test runner (Playwright or
18338
+ * Cypress). End-to-end tests drive the running app and do not import
18339
+ * source files, so the reach classes do not count them. Absent when no
18340
+ * such runner is present.
18341
+ */
18342
+ e2e_runner?: boolean
18343
+ }
18344
+ /**
18345
+ * Number of changed exports per reach class. The keys are exactly the
18346
+ * [`TestReachClass`] values.
18347
+ */
18348
+ export interface TestReachCounts {
18349
+ /**
18350
+ * Exports that a test file references.
18351
+ */
18352
+ direct: number
18353
+ /**
18354
+ * Exports that tests reach only through other modules.
18355
+ */
18356
+ transitive: number
18357
+ /**
18358
+ * Exports that only mocking tests reference.
18359
+ */
18360
+ "mocked-only": number
18361
+ /**
18362
+ * Exports in a test-reached file without a test-reachable reference.
18363
+ */
18364
+ none: number
18365
+ /**
18366
+ * Exports in a file that no test loads.
18367
+ */
18368
+ "none-file": number
18369
+ /**
18370
+ * Framework configuration exports.
18371
+ */
18372
+ framework: number
18373
+ }
18374
+ /**
18375
+ * One changed export that needs attention.
18376
+ */
18377
+ export interface ExportTestReachFact {
18378
+ /**
18379
+ * Root-relative path of the file that declares the export.
18380
+ */
18381
+ file: string
18382
+ /**
18383
+ * The export name, `default` for a default export.
18384
+ */
18385
+ export_name: string
18386
+ /**
18387
+ * 1-based line of the export.
18388
+ */
18389
+ line: number
18390
+ reach: TestReachClass
18391
+ change: ExportChange
18392
+ /**
18393
+ * Test files that name the export, sorted, at most
18394
+ * [`TEST_REACH_FILE_CAP`]. On a `mocked-only` row these are the mocking
18395
+ * tests. Absent when no test file names the export.
18396
+ */
18397
+ tests?: (string[] | null)
18398
+ /**
18399
+ * Number of test files that name the export, before the cap. Present with
18400
+ * `tests`.
18401
+ */
18402
+ tests_total?: (number | null)
18403
+ /**
18404
+ * True when one of the test files that name the export changed in this
18405
+ * diff. Present with `tests`.
18406
+ */
18407
+ test_changed?: (boolean | null)
18408
+ /**
18409
+ * The mocked modules on the import paths, sorted, at most
18410
+ * [`TEST_REACH_FILE_CAP`]. A mocked module can be a barrel in front of
18411
+ * the declaring file. Present only on `mocked-only` rows.
18412
+ */
18413
+ mocked_targets?: (string[] | null)
18414
+ }
17373
18415
  /**
17374
18416
  * The separable `decision-surface` envelope: the single call that puts taste-
17375
18417
  * decisions in front of a human, callable WITHOUT the full pipeline (the
@@ -17569,6 +18611,12 @@ decisions: DecisionSurface
17569
18611
  * never had a base snapshot.
17570
18612
  */
17571
18613
  branching?: (BranchingReport | null)
18614
+ /**
18615
+ * How tests reach the value exports that the diff changes. Advisory,
18616
+ * never gates. Absent when the diff changes no value export or no diff
18617
+ * is known.
18618
+ */
18619
+ test_reach?: (TestReachFacts | null)
17572
18620
  }
17573
18621
  /**
17574
18622
  * The review direction artifact: the order to review in, the coherent units,
@@ -18656,6 +19704,770 @@ removed: boolean
18656
19704
  */
18657
19705
  model_removed: boolean
18658
19706
  }
19707
+ /**
19708
+ * The envelope of `fallow mutation`.
19709
+ */
19710
+ export interface MutationReport {
19711
+ schema_version: MutationSchemaVersion
19712
+ version: ToolVersion
19713
+ elapsed_ms: ElapsedMs
19714
+ completion: MutationCompletion
19715
+ scope: MutationScopeOutput
19716
+ /**
19717
+ * The runner. Absent when no companion started, for example when no
19718
+ * test file reaches a mutant.
19719
+ */
19720
+ runner?: (MutationRunnerOutput | null)
19721
+ /**
19722
+ * The result cache. Absent with `--no-cache`, and when no companion
19723
+ * started.
19724
+ */
19725
+ cache?: (MutationCacheOutput | null)
19726
+ summary: MutationSummary
19727
+ /**
19728
+ * Each mutant, ranked mutants first.
19729
+ */
19730
+ mutants: MutantResult[]
19731
+ /**
19732
+ * The results per enclosing function, by file and line.
19733
+ */
19734
+ functions: MutationFunctionResult[]
19735
+ /**
19736
+ * True when the project has no test files.
19737
+ */
19738
+ no_test_files: boolean
19739
+ /**
19740
+ * The tests and test files that failed with no active mutant.
19741
+ */
19742
+ baseline_failures: MutationBaselineFailure[]
19743
+ /**
19744
+ * The selected files that the plan did not instrument.
19745
+ */
19746
+ skipped_files: MutationSkippedFile[]
19747
+ /**
19748
+ * The paths of a `paths` scope that select no file.
19749
+ */
19750
+ unmatched_paths: string[]
19751
+ /**
19752
+ * The instrumented files that the runner never loaded.
19753
+ */
19754
+ unloaded_paths: string[]
19755
+ worktree: MutationWorktreeCheck
19756
+ /**
19757
+ * The errors that did not stop the run.
19758
+ */
19759
+ errors: MutationRunIssue[]
19760
+ timings: MutationTimings
19761
+ /**
19762
+ * The mutated files with their SHA-256 digest at plan time, sorted by
19763
+ * path. `fallow mutation inspect` compares the digest with the current
19764
+ * file.
19765
+ */
19766
+ files: MutationPlanFile[]
19767
+ /**
19768
+ * The join with a verdict document. Absent when the run read no verdict
19769
+ * document (`--verdicts` not set).
19770
+ */
19771
+ verdicts?: (MutationVerdictJoin | null)
19772
+ /**
19773
+ * The type check of the survivors. Absent when the run did not check
19774
+ * them (`--typecheck` not set).
19775
+ */
19776
+ typecheck?: (MutationTypecheckOutput | null)
19777
+ }
19778
+ /**
19779
+ * The completion status of a run.
19780
+ */
19781
+ export interface MutationCompletion {
19782
+ status: MutationCompletionStatus
19783
+ /**
19784
+ * Why the run is partial, sorted. Empty for a complete run.
19785
+ */
19786
+ reasons: MutationIncompleteReason[]
19787
+ }
19788
+ /**
19789
+ * The scope of a plan or a run.
19790
+ */
19791
+ export interface MutationScopeOutput {
19792
+ kind: MutationScopeKind
19793
+ /**
19794
+ * The base ref of a `changed` scope.
19795
+ */
19796
+ base_ref?: (string | null)
19797
+ }
19798
+ /**
19799
+ * The test runner of a run.
19800
+ */
19801
+ export interface MutationRunnerOutput {
19802
+ /**
19803
+ * The runner name, for example `vitest`.
19804
+ */
19805
+ name: string
19806
+ /**
19807
+ * The runner version from the project.
19808
+ */
19809
+ version: string
19810
+ /**
19811
+ * The wire protocol version of the companion.
19812
+ */
19813
+ protocol_version: number
19814
+ runtime: MutationRuntimeOutput
19815
+ /**
19816
+ * The number of companion processes that ran mutants.
19817
+ */
19818
+ concurrency: number
19819
+ /**
19820
+ * Facts of the runner setup that limit the result, kebab-case.
19821
+ * `typecheck-not-run`: the project config enables the Vitest type-check
19822
+ * pass, and the run did not execute it, so a type-level kill is not
19823
+ * counted. Absent when the runner states no fact.
19824
+ */
19825
+ notes?: string[]
19826
+ }
19827
+ /**
19828
+ * The JavaScript runtime that ran the companion.
19829
+ */
19830
+ export interface MutationRuntimeOutput {
19831
+ /**
19832
+ * `node` or `bun`.
19833
+ */
19834
+ name: string
19835
+ /**
19836
+ * The version that the runtime reports.
19837
+ */
19838
+ version: string
19839
+ }
19840
+ /**
19841
+ * The result cache facts of a run.
19842
+ */
19843
+ export interface MutationCacheOutput {
19844
+ /**
19845
+ * The mutants whose status came from the cache. They did not run.
19846
+ */
19847
+ hits: number
19848
+ /**
19849
+ * The results that this run added to the cache.
19850
+ */
19851
+ stored: number
19852
+ /**
19853
+ * The test inputs that the cache key does not cover: modules that a
19854
+ * test loads through a dynamic import that the module graph does not
19855
+ * resolve (`dynamic-imports`), and files that a test reads
19856
+ * (`file-reads`). A change to them does not invalidate a cached result.
19857
+ */
19858
+ not_keyed: string[]
19859
+ }
19860
+ /**
19861
+ * The totals of a run.
19862
+ */
19863
+ export interface MutationSummary {
19864
+ counts: MutationStatusCounts
19865
+ /**
19866
+ * The mutation score over the executed mutants, a fraction from 0 to 1:
19867
+ * `(killed + timeout) / (killed + timeout + survived)`. `null` when no
19868
+ * mutant ran to a tested result. `--min-score` and `mutation.minScore`
19869
+ * compare this value in percent.
19870
+ */
19871
+ score?: (number | null)
19872
+ /**
19873
+ * The share of mutants that a test reaches, a fraction from 0 to 1:
19874
+ * `covered / (covered + no_coverage)` over the whole plan. `covered`
19875
+ * counts each executed mutant with a covering test and each `pending`
19876
+ * mutant that a passing dry-run test covers. A `pending` mutant that no
19877
+ * dry-run test covers is `no_coverage`, so a run that `--max-mutants`
19878
+ * caps reports the coverage of the full run. `equivalent` and `pruned`
19879
+ * mutants never count. `null` when no mutant is covered or unreached.
19880
+ */
19881
+ coverage?: (number | null)
19882
+ }
19883
+ /**
19884
+ * One mutant of a run.
19885
+ */
19886
+ export interface MutantResult {
19887
+ /**
19888
+ * The stable mutant id.
19889
+ */
19890
+ mutant_id: string
19891
+ /**
19892
+ * The root-relative path, with forward slashes.
19893
+ */
19894
+ file: string
19895
+ /**
19896
+ * The 1-based line.
19897
+ */
19898
+ line: number
19899
+ /**
19900
+ * The 1-based column.
19901
+ */
19902
+ column: number
19903
+ /**
19904
+ * The byte span in the original file.
19905
+ *
19906
+ * @minItems 2
19907
+ * @maxItems 2
19908
+ */
19909
+ span: [number, number]
19910
+ /**
19911
+ * The operator name, kebab-case.
19912
+ */
19913
+ operator: string
19914
+ /**
19915
+ * The name of the enclosing function.
19916
+ */
19917
+ function?: (string | null)
19918
+ /**
19919
+ * The 1-based first line of the enclosing function.
19920
+ */
19921
+ function_line?: (number | null)
19922
+ /**
19923
+ * The 1-based execution rank of a planned mutant.
19924
+ */
19925
+ rank?: (number | null)
19926
+ status: MutantStatus
19927
+ /**
19928
+ * The static rule of a `pruned` mutant, kebab-case.
19929
+ */
19930
+ prune_reason?: (string | null)
19931
+ /**
19932
+ * The test that killed the mutant in this run. Absent for a kill by an
19933
+ * error outside a test.
19934
+ *
19935
+ * This is evidence of one run, not a stable fact. A run stops at the
19936
+ * first failing test, and it runs the fastest covering test first, so a
19937
+ * second run on the same code can name another covering test. No
19938
+ * fingerprint or baseline comparison uses this field.
19939
+ */
19940
+ killed_by?: (string | null)
19941
+ /**
19942
+ * The tests that reached the mutant in the dry run, sorted by test id.
19943
+ */
19944
+ covering_tests?: string[]
19945
+ /**
19946
+ * True when the mutant runs while a module loads, outside each test.
19947
+ */
19948
+ static_mutant?: boolean
19949
+ /**
19950
+ * The duration of one run in milliseconds. A `killed` mutant after a
19951
+ * retry reports the retry. Each other status reports the first run.
19952
+ */
19953
+ duration_ms?: (number | null)
19954
+ /**
19955
+ * How tests reach the code of the mutant in the module graph. Only a
19956
+ * `no_coverage` mutant has this field.
19957
+ */
19958
+ test_reach?: (MutantTestReach | null)
19959
+ /**
19960
+ * True when the status comes from a first run and a retry in a new
19961
+ * companion. A `survived` or `timeout` mutant without this field got no
19962
+ * retry, because the time budget ended first.
19963
+ */
19964
+ retried?: boolean
19965
+ /**
19966
+ * True when the status comes from the result cache of an earlier run.
19967
+ * The mutant did not run in this run. `--no-cache` runs each mutant.
19968
+ */
19969
+ cached?: boolean
19970
+ /**
19971
+ * The TypeScript diagnostic codes of the new errors of a
19972
+ * `compile_error` mutant, sorted, at most 8.
19973
+ */
19974
+ type_error_codes?: number[]
19975
+ }
19976
+ /**
19977
+ * How tests reach the code of one mutant in the module graph. The class
19978
+ * gives a static reason why no test covers the mutant.
19979
+ *
19980
+ * A mutant in the top-level statement that declares a value export gets the
19981
+ * class of that export. A mutant outside each such statement gets the class
19982
+ * of its file: `none-file` when no test loads the file, `mocked-only` when no
19983
+ * test loads the file and a mock explains an export of the file, and `none`
19984
+ * when a test loads the file.
19985
+ */
19986
+ export interface MutantTestReach {
19987
+ reach: TestReachClass
19988
+ /**
19989
+ * The export whose declaration holds the mutant. Absent for a mutant
19990
+ * outside each value export declaration.
19991
+ */
19992
+ export_name?: (string | null)
19993
+ /**
19994
+ * For `mocked-only`: the test files whose references a mock removed,
19995
+ * sorted.
19996
+ */
19997
+ tests?: string[]
19998
+ /**
19999
+ * For `mocked-only`: the mocked modules on the reference paths, sorted.
20000
+ * A mocked module can be a barrel in front of the file of the mutant.
20001
+ */
20002
+ mocked_targets?: string[]
20003
+ }
20004
+ /**
20005
+ * The results of the mutants of one function.
20006
+ */
20007
+ export interface MutationFunctionResult {
20008
+ /**
20009
+ * The root-relative path, with forward slashes.
20010
+ */
20011
+ file: string
20012
+ /**
20013
+ * The function name. `null` for code outside each function, and for an
20014
+ * anonymous function.
20015
+ */
20016
+ name?: (string | null)
20017
+ /**
20018
+ * The 1-based first line. `null` for code outside each function.
20019
+ */
20020
+ line?: (number | null)
20021
+ /**
20022
+ * The 1-based last line. `null` for code outside each function.
20023
+ */
20024
+ end_line?: (number | null)
20025
+ /**
20026
+ * True when an added line of the diff is in the function.
20027
+ */
20028
+ in_diff: boolean
20029
+ /**
20030
+ * The cyclomatic complexity, when the analysis measured the function.
20031
+ */
20032
+ cyclomatic?: (number | null)
20033
+ counts: MutationStatusCounts
20034
+ /**
20035
+ * The mutation score of the function.
20036
+ */
20037
+ score?: (number | null)
20038
+ /**
20039
+ * The ids of the survived mutants, in rank order.
20040
+ */
20041
+ survived?: string[]
20042
+ }
20043
+ /**
20044
+ * A test or a test file that failed with no active mutant. Its tests do not
20045
+ * decide a mutant status.
20046
+ */
20047
+ export interface MutationBaselineFailure {
20048
+ /**
20049
+ * The test file, root-relative. `null` for an error outside each test
20050
+ * file.
20051
+ */
20052
+ file?: (string | null)
20053
+ /**
20054
+ * The test id, for a failed test.
20055
+ */
20056
+ test_id?: (string | null)
20057
+ /**
20058
+ * The error message, for an error outside a test, or the reason for a
20059
+ * test that did not pass in the dry run of a restarted companion.
20060
+ */
20061
+ message?: (string | null)
20062
+ /**
20063
+ * The mutants that ran without this test, because the test did not pass
20064
+ * in the dry run of a restarted companion. Each of them ran with its
20065
+ * other covering tests. Absent for a failure of the first dry run.
20066
+ */
20067
+ mutant_ids?: string[]
20068
+ }
20069
+ /**
20070
+ * A selected file that the plan did not instrument.
20071
+ */
20072
+ export interface MutationSkippedFile {
20073
+ /**
20074
+ * The root-relative path, with forward slashes.
20075
+ */
20076
+ path: string
20077
+ /**
20078
+ * Why the plan skipped the file, kebab-case.
20079
+ */
20080
+ reason: string
20081
+ }
20082
+ /**
20083
+ * The git worktree check of a run: a run refuses a dirty worktree unless
20084
+ * `--allow-dirty` is set, and it compares the worktree after the run.
20085
+ */
20086
+ export interface MutationWorktreeCheck {
20087
+ /**
20088
+ * False when the root is not in a git worktree, so no check ran.
20089
+ */
20090
+ checked: boolean
20091
+ /**
20092
+ * True when the caller allowed a dirty worktree.
20093
+ */
20094
+ allow_dirty: boolean
20095
+ /**
20096
+ * The paths that were dirty before the run, sorted.
20097
+ */
20098
+ dirty_at_start?: string[]
20099
+ /**
20100
+ * The paths that the run changed, sorted. A non-empty list is an error.
20101
+ */
20102
+ changed_paths: string[]
20103
+ }
20104
+ /**
20105
+ * An error of a run that did not stop the run.
20106
+ */
20107
+ export interface MutationRunIssue {
20108
+ /**
20109
+ * A stable kebab-case code: `runtime-error`, `static-map-miss`,
20110
+ * `test-files-not-discovered`, `typecheck-failed`, `worktree-changed`
20111
+ * or `worktree-check-failed`.
20112
+ */
20113
+ code: string
20114
+ /**
20115
+ * A description.
20116
+ */
20117
+ message: string
20118
+ /**
20119
+ * The mutant of the issue.
20120
+ */
20121
+ mutant_id?: (string | null)
20122
+ /**
20123
+ * The last part of the companion stderr.
20124
+ */
20125
+ stderr_tail?: (string | null)
20126
+ }
20127
+ /**
20128
+ * The wall time of each phase, in milliseconds.
20129
+ */
20130
+ export interface MutationTimings {
20131
+ /**
20132
+ * The analysis and the plan.
20133
+ */
20134
+ plan_ms: number
20135
+ /**
20136
+ * The companion install, the run directory, and the first `init`.
20137
+ */
20138
+ setup_ms: number
20139
+ /**
20140
+ * The dry run.
20141
+ */
20142
+ dry_run_ms: number
20143
+ /**
20144
+ * The mutant runs.
20145
+ */
20146
+ mutants_ms: number
20147
+ /**
20148
+ * The second runs of survived and timed-out mutants.
20149
+ */
20150
+ retry_ms: number
20151
+ /**
20152
+ * The type check of the survivors. Zero when the run did not check
20153
+ * them.
20154
+ */
20155
+ typecheck_ms: number
20156
+ }
20157
+ /**
20158
+ * One instrumented file of a plan.
20159
+ */
20160
+ export interface MutationPlanFile {
20161
+ /**
20162
+ * The root-relative path, with forward slashes.
20163
+ */
20164
+ path: string
20165
+ /**
20166
+ * The SHA-256 digest of the file, lowercase hex.
20167
+ */
20168
+ source_sha256: string
20169
+ /**
20170
+ * The test files that reach the file in the module graph, sorted.
20171
+ */
20172
+ static_test_files: string[]
20173
+ }
20174
+ /**
20175
+ * The result of the join of a run with a verdict document.
20176
+ */
20177
+ export interface MutationVerdictJoin {
20178
+ /**
20179
+ * The SHA-256 digest of the verdict document, lowercase hex.
20180
+ */
20181
+ verdicts_sha256: string
20182
+ /**
20183
+ * The mutants that got the status `equivalent`, sorted.
20184
+ */
20185
+ applied: string[]
20186
+ /**
20187
+ * The verdicts that a test contradicts, sorted: the mutant was killed or
20188
+ * timed out, so it is not equivalent. The status stays.
20189
+ */
20190
+ contradicted: string[]
20191
+ /**
20192
+ * The verdicts for mutants with no tested result (`pending`,
20193
+ * `runtime_error` or `pruned`), sorted. The status stays.
20194
+ */
20195
+ deferred: string[]
20196
+ /**
20197
+ * The verdicts that match no mutant of this run, sorted. A verdict
20198
+ * document can hold keys for code outside the scope of the run, and an
20199
+ * edit of a function gives its mutants new keys.
20200
+ */
20201
+ unmatched: string[]
20202
+ }
20203
+ /**
20204
+ * The type check of the survivors (`--typecheck`).
20205
+ */
20206
+ export interface MutationTypecheckOutput {
20207
+ /**
20208
+ * True when the type check gave a result for each survivor that it
20209
+ * received. False when the companion failed; the survivors then keep
20210
+ * the status `survived`.
20211
+ */
20212
+ completed: boolean
20213
+ /**
20214
+ * The survivors that the type check received.
20215
+ */
20216
+ survivors: number
20217
+ /**
20218
+ * The survivors that the checker checked.
20219
+ */
20220
+ checked: number
20221
+ /**
20222
+ * The checked survivors that do not type-check. They have the status
20223
+ * `compile_error`.
20224
+ */
20225
+ compile_errors: number
20226
+ /**
20227
+ * The survivors that the checker did not check, by reason.
20228
+ */
20229
+ skipped?: MutationTypecheckSkip[]
20230
+ }
20231
+ /**
20232
+ * The number of survivors with one skip reason.
20233
+ */
20234
+ export interface MutationTypecheckSkip {
20235
+ reason: MutationTypecheckSkipReason
20236
+ /**
20237
+ * The number of survivors.
20238
+ */
20239
+ count: number
20240
+ }
20241
+ /**
20242
+ * The envelope of `fallow mutation --plan`. It runs no user code.
20243
+ */
20244
+ export interface MutationPlanOutput {
20245
+ schema_version: MutationPlanSchemaVersion
20246
+ version: ToolVersion
20247
+ elapsed_ms: ElapsedMs
20248
+ scope: MutationScopeOutput
20249
+ counts: MutationPlanCountsOutput
20250
+ /**
20251
+ * Each mutant, ranked mutants first.
20252
+ */
20253
+ mutants: MutationPlanMutant[]
20254
+ /**
20255
+ * The instrumented files.
20256
+ */
20257
+ files: MutationPlanFile[]
20258
+ /**
20259
+ * The union of the static test files, sorted.
20260
+ */
20261
+ test_files: string[]
20262
+ /**
20263
+ * True when the project has no test files.
20264
+ */
20265
+ no_test_files: boolean
20266
+ /**
20267
+ * True when the plan applied the `framework-config` prune rule.
20268
+ */
20269
+ framework_config_checked: boolean
20270
+ /**
20271
+ * The selected files that the plan did not instrument.
20272
+ */
20273
+ skipped_files: MutationSkippedFile[]
20274
+ /**
20275
+ * The paths of a `paths` scope that select no file.
20276
+ */
20277
+ unmatched_paths: string[]
20278
+ }
20279
+ /**
20280
+ * The totals of a plan.
20281
+ */
20282
+ export interface MutationPlanCountsOutput {
20283
+ /**
20284
+ * Each mutant.
20285
+ */
20286
+ total: number
20287
+ /**
20288
+ * Planned mutants.
20289
+ */
20290
+ planned: number
20291
+ /**
20292
+ * Mutants after the mutant limit.
20293
+ */
20294
+ pending: number
20295
+ /**
20296
+ * Mutants that no test file reaches.
20297
+ */
20298
+ no_coverage: number
20299
+ /**
20300
+ * Mutants in unused files.
20301
+ */
20302
+ pruned_dead_code: number
20303
+ /**
20304
+ * Mutants in generated files.
20305
+ */
20306
+ pruned_generated: number
20307
+ /**
20308
+ * Mutants near a file system, process, network or database sink.
20309
+ */
20310
+ pruned_side_effect_sink: number
20311
+ /**
20312
+ * Mutants in framework config exports.
20313
+ */
20314
+ pruned_framework_config: number
20315
+ }
20316
+ /**
20317
+ * One mutant of a plan.
20318
+ */
20319
+ export interface MutationPlanMutant {
20320
+ /**
20321
+ * The stable mutant id.
20322
+ */
20323
+ mutant_id: string
20324
+ /**
20325
+ * The root-relative path, with forward slashes.
20326
+ */
20327
+ file: string
20328
+ /**
20329
+ * The 1-based line.
20330
+ */
20331
+ line: number
20332
+ /**
20333
+ * The 1-based column.
20334
+ */
20335
+ column: number
20336
+ /**
20337
+ * The byte span in the original file.
20338
+ *
20339
+ * @minItems 2
20340
+ * @maxItems 2
20341
+ */
20342
+ span: [number, number]
20343
+ /**
20344
+ * The operator name, kebab-case.
20345
+ */
20346
+ operator: string
20347
+ /**
20348
+ * The name of the enclosing function.
20349
+ */
20350
+ function?: (string | null)
20351
+ /**
20352
+ * The 1-based first line of the enclosing function.
20353
+ */
20354
+ function_line?: (number | null)
20355
+ /**
20356
+ * The 1-based execution rank of a planned mutant.
20357
+ */
20358
+ rank?: (number | null)
20359
+ disposition: MutationPlanDisposition
20360
+ /**
20361
+ * The static rule of a `pruned` mutant, kebab-case.
20362
+ */
20363
+ prune_reason?: (string | null)
20364
+ /**
20365
+ * How tests reach the code of the mutant in the module graph. Only a
20366
+ * `no_coverage` mutant has this field.
20367
+ */
20368
+ test_reach?: (MutantTestReach | null)
20369
+ }
20370
+ /**
20371
+ * The envelope of `fallow mutation inspect`. It runs no user code.
20372
+ */
20373
+ export interface MutationInspectOutput {
20374
+ schema_version: MutationInspectSchemaVersion
20375
+ version: ToolVersion
20376
+ status: MutationInspectStatus
20377
+ /**
20378
+ * Why the packet is stale. Absent for a fresh packet.
20379
+ */
20380
+ stale_reason?: (MutationStaleReason | null)
20381
+ /**
20382
+ * The stable mutant id.
20383
+ */
20384
+ mutant_id: string
20385
+ /**
20386
+ * The root-relative path, with forward slashes.
20387
+ */
20388
+ file: string
20389
+ /**
20390
+ * The 1-based line.
20391
+ */
20392
+ line: number
20393
+ /**
20394
+ * The 1-based column.
20395
+ */
20396
+ column: number
20397
+ /**
20398
+ * The byte span in the original file.
20399
+ *
20400
+ * @minItems 2
20401
+ * @maxItems 2
20402
+ */
20403
+ span: [number, number]
20404
+ /**
20405
+ * The operator name, kebab-case.
20406
+ */
20407
+ operator: string
20408
+ /**
20409
+ * The name of the enclosing function.
20410
+ */
20411
+ function?: (string | null)
20412
+ /**
20413
+ * The 1-based first line of the enclosing function.
20414
+ */
20415
+ function_line?: (number | null)
20416
+ /**
20417
+ * The 1-based execution rank of a planned mutant.
20418
+ */
20419
+ rank?: (number | null)
20420
+ /**
20421
+ * The status of the mutant in the report. Absent for a plan.
20422
+ */
20423
+ report_status?: (MutantStatus | null)
20424
+ /**
20425
+ * The SHA-256 digest of the file in the report.
20426
+ */
20427
+ report_sha256?: (string | null)
20428
+ /**
20429
+ * The SHA-256 digest of the current file. `null` when the file is
20430
+ * missing.
20431
+ */
20432
+ current_sha256?: (string | null)
20433
+ /**
20434
+ * The original and mutated code. `null` for a stale packet.
20435
+ */
20436
+ code?: (MutationInspectCode | null)
20437
+ /**
20438
+ * The tests that reached the mutant in the dry run, sorted.
20439
+ */
20440
+ covering_tests: string[]
20441
+ /**
20442
+ * The test files that reach the file in the module graph, sorted.
20443
+ */
20444
+ static_test_files: string[]
20445
+ /**
20446
+ * The test that killed the mutant in the run of the report.
20447
+ */
20448
+ killed_by?: (string | null)
20449
+ }
20450
+ /**
20451
+ * The code of one mutant, from the current file.
20452
+ */
20453
+ export interface MutationInspectCode {
20454
+ /**
20455
+ * The original text of the span.
20456
+ */
20457
+ original: string
20458
+ /**
20459
+ * The text that replaces the span.
20460
+ */
20461
+ replacement: string
20462
+ /**
20463
+ * The source lines that contain the span, before the mutation.
20464
+ */
20465
+ original_lines: string
20466
+ /**
20467
+ * The same lines with the replacement applied.
20468
+ */
20469
+ mutated_lines: string
20470
+ }
18659
20471
  /**
18660
20472
  * Single CodeClimate-compatible issue inside [`CodeClimateOutput`].
18661
20473
  */