fallow 3.1.0 → 3.3.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 (for example `dead-code`, `dead-code-grouped`, `health`, `dupes`, `combined`, `audit`, `explain`, `inspect_target`, `impact`, `security`, `coverage-setup`, `coverage-analyze`, `list-boundaries`, `review-envelope`, and `review-reconcile`). 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.
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`, `review-envelope`, `review-reconcile`, `coverage-setup`, `coverage-analyze`, `list-boundaries`, `list-workspaces`, `health`, `dupes`, `dead-code-grouped`, `impact`, `impact-cross-repo`, `security`, `security-survivors`, `security-blind-spots`, `dead-code`, `combined`, `feature-flags`, `audit-brief`, `decision-surface`, `review-walkthrough-guide`, `review-walkthrough-validation`. 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.
28
28
  */
29
29
  export type FallowJsonOutput = (FallowOutput | CodeClimateOutput)
30
30
  /**
@@ -50,6 +50,8 @@ kind: "audit"
50
50
  kind: "explain"
51
51
  }) | (InspectOutput & {
52
52
  kind: "inspect_target"
53
+ }) | (SymbolChainTrace & {
54
+ kind: "trace"
53
55
  }) | (ReviewEnvelopeOutput & {
54
56
  kind: "review-envelope"
55
57
  }) | (ReviewReconcileOutput & {
@@ -82,8 +84,12 @@ kind: "security-blind-spots"
82
84
  kind: "dead-code"
83
85
  }) | (CombinedOutput & {
84
86
  kind: "combined"
87
+ }) | (FeatureFlagsOutput & {
88
+ kind: "feature-flags"
85
89
  }) | (ReviewBriefOutput & {
86
90
  kind: "audit-brief"
91
+ }) | (DecisionSurfaceOutput & {
92
+ kind: "decision-surface"
87
93
  }) | (WalkthroughGuide & {
88
94
  kind: "review-walkthrough-guide"
89
95
  }) | (WalkthroughValidation & {
@@ -639,6 +645,10 @@ type: "symbol"
639
645
  export type InspectIdentity = (InspectFileIdentity | InspectSymbolIdentity)
640
646
  export type InspectSectionStatus = ("ok" | "error")
641
647
  export type InspectEvidenceScope = ("symbol" | "file" | "project_filtered_to_file")
648
+ /**
649
+ * Best-effort classification of why a callee did not resolve to an edge.
650
+ */
651
+ export type UnresolvedReason = ("local-or-global" | "member-or-dynamic")
642
652
  /**
643
653
  * Singleton GitHub review-event marker.
644
654
  */
@@ -800,6 +810,18 @@ export type SecurityVerifierVerdictStatus = ("survivor" | "dismissed" | "needs-h
800
810
  * The `fallow security blind-spots --format json` schema version.
801
811
  */
802
812
  export type SecurityBlindSpotsSchemaVersion = "1"
813
+ /**
814
+ * Feature flag kind values emitted in JSON.
815
+ */
816
+ export type FeatureFlagKind = ("environment_variable" | "sdk_call" | "config_object")
817
+ /**
818
+ * Feature flag confidence values emitted in JSON.
819
+ */
820
+ export type FeatureFlagConfidence = ("high" | "medium" | "low")
821
+ /**
822
+ * Feature flag action discriminants.
823
+ */
824
+ export type FeatureFlagActionType = ("investigate-flag" | "suppress-line")
803
825
  /**
804
826
  * Independently-versioned wire-version newtype for the brief envelope.
805
827
  * Serializes as the integer `REVIEW_BRIEF_SCHEMA_VERSION`.
@@ -840,6 +862,15 @@ export type WeakeningKind = ("test-weakened" | "threshold-lowered" | "suppressio
840
862
  * enum is the structural guarantee that confirmed-noise categories never ship.
841
863
  */
842
864
  export type DecisionCategory = ("coupling-boundary" | "public-api-contract" | "dependency")
865
+ /**
866
+ * Independently-versioned wire-version newtype. Serializes as the integer
867
+ * [`DECISION_SURFACE_SCHEMA_VERSION`].
868
+ */
869
+ export type DecisionSurfaceSchemaVersion = number
870
+ /**
871
+ * The discriminated action kinds a decision can carry.
872
+ */
873
+ export type DecisionActionType = ("ask-expert" | "suppress")
843
874
  /**
844
875
  * Discriminator value for [`CodeClimateIssue::kind`].
845
876
  */
@@ -3721,8 +3752,9 @@ stats: DuplicationStats
3721
3752
  /**
3722
3753
  * Wire-shape envelope for a [`CloneGroup`] finding. Flattens the bare
3723
3754
  * group via `#[serde(flatten)]` and carries a typed `actions` array plus
3724
- * the optional audit-mode `introduced` flag. Replaces the legacy
3725
- * post-pass injection in `crates/cli/src/report/json.rs::inject_dupes_actions`.
3755
+ * the optional audit-mode `introduced` flag. The typed envelope replaced
3756
+ * the legacy JSON post-pass injection; a guard test in
3757
+ * `crates/cli/src/report/json.rs` rejects any reintroduced post-pass.
3726
3758
  */
3727
3759
  export interface CloneGroupFinding {
3728
3760
  /**
@@ -3796,9 +3828,9 @@ fragment: string
3796
3828
  }
3797
3829
  /**
3798
3830
  * Per-action wire shape attached to each `CloneGroupFinding` and
3799
- * `AttributedCloneGroupFinding`. Mirrors the action types previously
3800
- * emitted by `inject_dupes_actions::build_clone_group_actions` in
3801
- * `crates/cli/src/report/json.rs`: `extract-shared` plus `suppress-line`.
3831
+ * `AttributedCloneGroupFinding` (see `crates/api/src/dupes_output.rs`):
3832
+ * `extract-shared` plus `suppress-line`. The typed wrappers replaced the
3833
+ * legacy JSON post-pass injection that used to live in the CLI report layer.
3802
3834
  */
3803
3835
  export interface CloneGroupAction {
3804
3836
  type: CloneGroupActionType
@@ -4267,6 +4299,12 @@ export interface HealthEffectiveThresholds {
4267
4299
  max_cyclomatic: number
4268
4300
  max_cognitive: number
4269
4301
  max_crap: number
4302
+ /**
4303
+ * Effective unit-size ceiling (maximum function length in lines) for the
4304
+ * matched file, after applying any `thresholdOverrides` on top of the
4305
+ * global `health.maxUnitSize` default.
4306
+ */
4307
+ max_unit_size: number
4270
4308
  }
4271
4309
  /**
4272
4310
  * Suggested action attached to a [`ComplexityViolation`].
@@ -4340,6 +4378,14 @@ functions_above_threshold: number
4340
4378
  max_cyclomatic_threshold: number
4341
4379
  max_cognitive_threshold: number
4342
4380
  max_crap_threshold: number
4381
+ /**
4382
+ * Effective global unit-size ceiling (`health.maxUnitSize`, maximum
4383
+ * function length in lines) for this run. Sits alongside the other three
4384
+ * `max_*_threshold` siblings so a consumer reading the summary sees every
4385
+ * configured threshold. Per-file `thresholdOverrides` are not reflected
4386
+ * here; this is the global default.
4387
+ */
4388
+ max_unit_size_threshold: number
4343
4389
  files_scored?: (number | null)
4344
4390
  average_maintainability?: (number | null)
4345
4391
  coverage_model?: (CoverageModel | null)
@@ -4371,6 +4417,7 @@ export interface HealthConfiguredThresholds {
4371
4417
  max_cyclomatic?: (number | null)
4372
4418
  max_cognitive?: (number | null)
4373
4419
  max_crap?: (number | null)
4420
+ max_unit_size?: (number | null)
4374
4421
  }
4375
4422
  /**
4376
4423
  * Current complexity metrics for a matched threshold override entry.
@@ -5998,6 +6045,13 @@ unused_theme_tokens?: UnusedThemeToken[]
5998
6045
  * candidates because they need whole-project token context.
5999
6046
  */
6000
6047
  near_duplicate_theme_tokens?: NearDuplicateThemeToken[]
6048
+ /**
6049
+ * CSS-in-JS design tokens whose comparable values are close to another
6050
+ * token from the same project. Covers StyleX, vanilla-extract, PandaCSS,
6051
+ * styled-components, and Emotion token definitions. These are opt-in
6052
+ * `--css-deep` candidates because they need whole-project token context.
6053
+ */
6054
+ near_duplicate_css_in_js_tokens?: NearDuplicateThemeToken[]
6001
6055
  /**
6002
6056
  * A location-aware reverse index of Tailwind v4 `@theme` token consumers:
6003
6057
  * per token, where it is consumed (`var()` reads, `@apply` bodies, generated
@@ -6374,6 +6428,12 @@ unused_theme_tokens: number
6374
6428
  * `near_duplicate_theme_tokens`.
6375
6429
  */
6376
6430
  near_duplicate_theme_tokens: number
6431
+ /**
6432
+ * CSS-in-JS design tokens whose comparable values are close to another
6433
+ * token from the same project. Located in
6434
+ * `near_duplicate_css_in_js_tokens`.
6435
+ */
6436
+ near_duplicate_css_in_js_tokens: number
6377
6437
  /**
6378
6438
  * Number of distinct `font-size` units (`px` / `rem` / `em` / `%`) authored
6379
6439
  * across the codebase. Mixing units is a type-scale consistency smell,
@@ -7139,6 +7199,93 @@ scope: InspectEvidenceScope
7139
7199
  message?: (string | null)
7140
7200
  data?: unknown
7141
7201
  }
7202
+ /**
7203
+ * The result of a symbol-level call-chain trace. Its own surface (`kind:
7204
+ * "trace"`), NOT folded into the ranked brief.
7205
+ */
7206
+ export interface SymbolChainTrace {
7207
+ /**
7208
+ * The file containing the traced symbol (project-root-relative).
7209
+ */
7210
+ file: string
7211
+ /**
7212
+ * The traced symbol name.
7213
+ */
7214
+ symbol: string
7215
+ /**
7216
+ * Whether the symbol's defining export was found in the graph. When
7217
+ * `false`, the chains are empty and `reason` explains why.
7218
+ */
7219
+ symbol_found: boolean
7220
+ /**
7221
+ * The chain depth applied to both directions.
7222
+ */
7223
+ depth: number
7224
+ /**
7225
+ * Whether this trace is best-effort (always `true`: symbol-level chains are
7226
+ * labeled best-effort, syntactic per ADR-001).
7227
+ */
7228
+ best_effort: boolean
7229
+ /**
7230
+ * Caller chain hops (UP). Present only when `--callers` was requested.
7231
+ */
7232
+ callers?: (ChainHop[] | null)
7233
+ /**
7234
+ * Callee chain hops (DOWN) resolved to an import-symbol edge. Present only
7235
+ * when `--callees` was requested.
7236
+ */
7237
+ callees?: (ChainHop[] | null)
7238
+ /**
7239
+ * Callees referenced at a call site in the symbol's module that the
7240
+ * syntactic walk could NOT resolve to an import-symbol edge (locals,
7241
+ * globals, dynamic dispatch, re-bound callees). Reported, never dropped.
7242
+ * Present only when `--callees` was requested.
7243
+ */
7244
+ unresolved_callees?: (UnresolvedCallee[] | null)
7245
+ /**
7246
+ * A human-readable summary of the trace outcome.
7247
+ */
7248
+ reason: string
7249
+ }
7250
+ /**
7251
+ * One hop in a caller / callee chain.
7252
+ */
7253
+ export interface ChainHop {
7254
+ /**
7255
+ * The file at this hop (project-root-relative). For a caller hop this is
7256
+ * the importing module; for a callee hop the imported module.
7257
+ */
7258
+ file: string
7259
+ /**
7260
+ * The symbol name as imported across the edge (`default`, `*` for namespace,
7261
+ * the imported name otherwise).
7262
+ */
7263
+ imported_as: string
7264
+ /**
7265
+ * The local binding name in the file at this hop.
7266
+ */
7267
+ local_name: string
7268
+ /**
7269
+ * Whether the import edge is type-only (`import type { ... }`).
7270
+ */
7271
+ type_only: boolean
7272
+ /**
7273
+ * The hop's depth (1 = direct caller/callee of the symbol).
7274
+ */
7275
+ depth: number
7276
+ }
7277
+ /**
7278
+ * A callee referenced at a call site that did not resolve to an import-symbol
7279
+ * edge. Surfaced so a missing callee is never silently dropped.
7280
+ */
7281
+ export interface UnresolvedCallee {
7282
+ /**
7283
+ * The callee path as written at the call site (e.g. `helper`,
7284
+ * `obj.method`).
7285
+ */
7286
+ callee: string
7287
+ reason: UnresolvedReason
7288
+ }
7142
7289
  /**
7143
7290
  * Envelope emitted by `fallow --format review-github` / `review-gitlab`.
7144
7291
  */
@@ -9131,6 +9278,79 @@ dupes?: (Meta | null)
9131
9278
  health?: (Meta | null)
9132
9279
  telemetry?: (TelemetryMeta | null)
9133
9280
  }
9281
+ /**
9282
+ * Envelope emitted by `fallow flags --format json`.
9283
+ */
9284
+ export interface FeatureFlagsOutput {
9285
+ schema_version: SchemaVersion
9286
+ version: ToolVersion
9287
+ elapsed_ms: ElapsedMs
9288
+ feature_flags: FeatureFlagFinding[]
9289
+ total_flags: number
9290
+ _meta?: (FeatureFlagsMeta | null)
9291
+ }
9292
+ /**
9293
+ * One feature flag finding in JSON output.
9294
+ */
9295
+ export interface FeatureFlagFinding {
9296
+ path: string
9297
+ flag_name: string
9298
+ kind: FeatureFlagKind
9299
+ confidence: FeatureFlagConfidence
9300
+ line: number
9301
+ col: number
9302
+ actions: FeatureFlagAction[]
9303
+ sdk_name?: (string | null)
9304
+ dead_code_overlap?: (FeatureFlagDeadCodeOverlap | null)
9305
+ }
9306
+ /**
9307
+ * Per-finding action emitted for feature flag findings.
9308
+ */
9309
+ export interface FeatureFlagAction {
9310
+ type: FeatureFlagActionType
9311
+ auto_fixable: boolean
9312
+ description: string
9313
+ comment?: (string | null)
9314
+ }
9315
+ /**
9316
+ * Dead-code overlap block attached when a flag guards unused exports.
9317
+ */
9318
+ export interface FeatureFlagDeadCodeOverlap {
9319
+ guarded_lines: number
9320
+ dead_export_count: number
9321
+ dead_exports: string[]
9322
+ }
9323
+ /**
9324
+ * `_meta.feature_flags` details emitted with `--explain`.
9325
+ */
9326
+ export interface FeatureFlagsMeta {
9327
+ feature_flags: FeatureFlagsMetaDetails
9328
+ }
9329
+ /**
9330
+ * Feature flag explanatory metadata.
9331
+ */
9332
+ export interface FeatureFlagsMetaDetails {
9333
+ description: string
9334
+ kinds: FeatureFlagsKindMeta
9335
+ confidence: FeatureFlagsConfidenceMeta
9336
+ docs: string
9337
+ }
9338
+ /**
9339
+ * Feature flag kind explanations.
9340
+ */
9341
+ export interface FeatureFlagsKindMeta {
9342
+ environment_variable: string
9343
+ sdk_call: string
9344
+ config_object: string
9345
+ }
9346
+ /**
9347
+ * Feature flag confidence explanations.
9348
+ */
9349
+ export interface FeatureFlagsConfidenceMeta {
9350
+ high: string
9351
+ medium: string
9352
+ low: string
9353
+ }
9134
9354
  /**
9135
9355
  * The full `fallow audit --brief --format json` envelope. Carries the
9136
9356
  * informational verdict, the triage and graph-facts orientation stages, plus
@@ -9552,6 +9772,127 @@ collapsed: number
9552
9772
  */
9553
9773
  reason: string
9554
9774
  }
9775
+ /**
9776
+ * The separable `decision-surface` envelope: the single call that puts taste-
9777
+ * decisions in front of a human, callable WITHOUT the full pipeline (the
9778
+ * `decision_surface` MCP tool's output). Carries `kind`/`schema_version` plus
9779
+ * structured `actions[]` per decision.
9780
+ */
9781
+ export interface DecisionSurfaceOutput {
9782
+ schema_version: DecisionSurfaceSchemaVersion
9783
+ /**
9784
+ * Fallow CLI version that produced this output.
9785
+ */
9786
+ version: string
9787
+ /**
9788
+ * Command discriminator singleton: always `"decision-surface"`.
9789
+ */
9790
+ command: string
9791
+ /**
9792
+ * The ranked, capped decisions, each with structured actions.
9793
+ */
9794
+ decisions: DecisionWithActions[]
9795
+ /**
9796
+ * Present when more than the cap were extracted.
9797
+ */
9798
+ truncated?: (TruncationNote | null)
9799
+ /**
9800
+ * Count of fallow-emitted signal_ids (the anti-hallucination allowlist size).
9801
+ */
9802
+ signal_count: number
9803
+ }
9804
+ /**
9805
+ * One decision plus its structured `actions[]`.
9806
+ */
9807
+ export interface DecisionWithActions {
9808
+ /**
9809
+ * Deterministic anchor to the fallow-emitted candidate this decision frames.
9810
+ * `accept_signal_id` rejects any id not in the emitted set.
9811
+ */
9812
+ signal_id: string
9813
+ category: DecisionCategory
9814
+ /**
9815
+ * The decision framed as a judgment question for the human.
9816
+ */
9817
+ question: string
9818
+ /**
9819
+ * Root-relative file the decision is anchored at.
9820
+ */
9821
+ anchor_file: string
9822
+ /**
9823
+ * 1-based anchor line, when the underlying signal carries one (0 = file head).
9824
+ */
9825
+ anchor_line: number
9826
+ /**
9827
+ * The raw fallow-emitted candidate key the `signal_id` hashes.
9828
+ */
9829
+ signal_key: string
9830
+ /**
9831
+ * The `signal_id` this decision WOULD have had before any rename in this
9832
+ * change (the anchor file's pre-rename path). Present only when the anchor was
9833
+ * renamed. A review-memory layer carries a dismissal across a `git mv`: if
9834
+ * `previous_signal_id` was dismissed in an earlier PR, treat this decision as
9835
+ * dismissed too. Keeps `signal_id` itself exact + deterministic.
9836
+ */
9837
+ previous_signal_id?: (string | null)
9838
+ /**
9839
+ * Blast radius: count of modules affected beyond the diff by this decision.
9840
+ */
9841
+ blast: number
9842
+ /**
9843
+ * `blast * reversibility_weight`: the rank key (sorted descending).
9844
+ */
9845
+ consequence: number
9846
+ /**
9847
+ * The routed expert(s) to ask, from ownership routing. Empty when no
9848
+ * ownership signal is available for the anchor file.
9849
+ */
9850
+ expert: string[]
9851
+ /**
9852
+ * Whether the anchor file's only qualified owner is one person.
9853
+ */
9854
+ bus_factor_one?: boolean
9855
+ /**
9856
+ * Honest per-decision count: in-repo modules OUTSIDE the diff that already
9857
+ * depend on this decision's anchor. This is the DISPLAY number (taste
9858
+ * ownership: the human reads reversibility from the count itself), distinct
9859
+ * from `blast` (the project-wide proxy used only for ranking). Never a door
9860
+ * label. Internal-only by construction, so it cannot see a published library's
9861
+ * external consumers; the public-API trade-off clause names that risk in prose.
9862
+ */
9863
+ internal_consumer_count: number
9864
+ /**
9865
+ * The named structural sacrifice this change makes, stated as a fact, never a
9866
+ * recommendation (e.g. "Couples `app` to `infra`; 4 in-repo modules already
9867
+ * depend on this anchor."). A sibling fact to `question`; it never tells the
9868
+ * human what to choose.
9869
+ */
9870
+ tradeoff: string
9871
+ /**
9872
+ * Structured actions: route to the expert, or suppress.
9873
+ */
9874
+ actions: DecisionAction[]
9875
+ }
9876
+ /**
9877
+ * A structured action attached to a surfaced decision (the agent-actionable
9878
+ * surface). Mirrors the typed-action shape the rest of fallow emits.
9879
+ */
9880
+ export interface DecisionAction {
9881
+ type: DecisionActionType
9882
+ /**
9883
+ * Human-readable description of the action.
9884
+ */
9885
+ description: string
9886
+ /**
9887
+ * Runnable command or paste-ready suppression comment.
9888
+ */
9889
+ command?: (string | null)
9890
+ /**
9891
+ * Whether fallow can carry the action out automatically. Always `false`:
9892
+ * a decision is a human judgment, never auto-applied.
9893
+ */
9894
+ auto_fixable: boolean
9895
+ }
9555
9896
  /**
9556
9897
  * The `fallow review --walkthrough-guide` envelope: the current digest + schema
9557
9898
  * the agent fetches. The tool owns this; the skill stays thin (it fetches this