fallow 3.27.0 → 3.28.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/capabilities.json +3 -2
- package/package.json +10 -10
- package/schema.json +1 -1
- package/skills/fallow/references/cli-reference.md +14 -12
- package/types/output-contract.d.ts +381 -11
package/capabilities.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "fallow",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.28.0",
|
|
4
4
|
"manifest_version": "1",
|
|
5
5
|
"description": "Codebase analyzer for TypeScript/JavaScript: unused code, circular dependencies, code duplication, complexity hotspots, and architecture boundary violations",
|
|
6
6
|
"global_flags": [
|
|
@@ -7262,7 +7262,7 @@
|
|
|
7262
7262
|
]
|
|
7263
7263
|
},
|
|
7264
7264
|
"plugins": {
|
|
7265
|
-
"count":
|
|
7265
|
+
"count": 127,
|
|
7266
7266
|
"note": "Built-in framework plugins, auto-activated when their enabler dependency is present; run fallow list --plugins for the set active in a specific project",
|
|
7267
7267
|
"names": [
|
|
7268
7268
|
"nextjs",
|
|
@@ -7314,6 +7314,7 @@
|
|
|
7314
7314
|
"rolldown",
|
|
7315
7315
|
"rspack",
|
|
7316
7316
|
"rsbuild",
|
|
7317
|
+
"module-federation",
|
|
7317
7318
|
"tsup",
|
|
7318
7319
|
"tsdown",
|
|
7319
7320
|
"pkg-utils",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "fallow",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.28.0",
|
|
4
4
|
"mcpName": "io.github.fallow-rs/fallow",
|
|
5
5
|
"description": "Codebase intelligence for TypeScript and JavaScript. Free static analysis of code and styles, optional paid runtime intelligence (Fallow Runtime). Quality, risk, architecture, dependencies, duplication, and design-system drift for humans, CI, and the agents writing your code. Zero-config framework support.",
|
|
6
6
|
"license": "MIT",
|
|
@@ -88,14 +88,14 @@
|
|
|
88
88
|
"@tanstack/intent": "0.4.0"
|
|
89
89
|
},
|
|
90
90
|
"optionalDependencies": {
|
|
91
|
-
"@fallow-cli/darwin-arm64": "3.
|
|
92
|
-
"@fallow-cli/darwin-x64": "3.
|
|
93
|
-
"@fallow-cli/linux-x64-gnu": "3.
|
|
94
|
-
"@fallow-cli/linux-arm64-gnu": "3.
|
|
95
|
-
"@fallow-cli/linux-x64-musl": "3.
|
|
96
|
-
"@fallow-cli/linux-arm64-musl": "3.
|
|
97
|
-
"@fallow-cli/win32-arm64-msvc": "3.
|
|
98
|
-
"@fallow-cli/win32-x64-msvc": "3.
|
|
99
|
-
"fallow-type-aware": "3.
|
|
91
|
+
"@fallow-cli/darwin-arm64": "3.28.0",
|
|
92
|
+
"@fallow-cli/darwin-x64": "3.28.0",
|
|
93
|
+
"@fallow-cli/linux-x64-gnu": "3.28.0",
|
|
94
|
+
"@fallow-cli/linux-arm64-gnu": "3.28.0",
|
|
95
|
+
"@fallow-cli/linux-x64-musl": "3.28.0",
|
|
96
|
+
"@fallow-cli/linux-arm64-musl": "3.28.0",
|
|
97
|
+
"@fallow-cli/win32-arm64-msvc": "3.28.0",
|
|
98
|
+
"@fallow-cli/win32-x64-msvc": "3.28.0",
|
|
99
|
+
"fallow-type-aware": "3.28.0"
|
|
100
100
|
}
|
|
101
101
|
}
|
package/schema.json
CHANGED
|
@@ -363,7 +363,7 @@
|
|
|
363
363
|
"default": false
|
|
364
364
|
},
|
|
365
365
|
"autoImports": {
|
|
366
|
-
"description": "When true, drops Nuxt convention-based entry-pattern fallbacks
|
|
366
|
+
"description": "When true, drops Nuxt convention-based entry-pattern fallbacks so genuinely-unreferenced convention files surface as unused-file. Component fallbacks are kept when nuxt.config customizes components: in a way fallow does not model, and composable/util fallbacks are kept when it customizes imports:; a config that scans no more than the Nuxt defaults (components: false, components: [], components: { dirs: [] }, components: true, imports: { scan: false }, imports: {}, imports: { dirs: [] }) is treated like the default and its fallbacks are dropped; imports: { autoImport: false } on its own is not, because it only switches the injection off while the same directories stay registered behind #imports. A nuxt.config that carries any top-level key fallow cannot read statically, a computed key, an accessor, or a spread such as { ...base, devtools: {} }, keeps both surfaces' fallbacks for that root, because the spread may hold the keys that decide. Each root is classified on its own config, so one custom nuxt.config in a monorepo does not keep every other workspace's fallbacks. Component names follow Nuxt: a component under components/global or components/islands is named after its own directory (components/global/Foo.vue is `<Foo>`), and .client, .server, .global and .island suffixes are stripped. A name imported or re-exported by hand from #components or #imports credits its convention file just like a template tag or a bare call; a namespace import names nothing and credits nothing. Boolean, defaults to false; set it for a Nuxt project that has explicitly configured its auto-import directories. Synthesis of auto-import graph edges (resolving `<Card />` or `useUserStore()` to their convention files) happens regardless of this flag.",
|
|
367
367
|
"type": "boolean",
|
|
368
368
|
"default": false
|
|
369
369
|
},
|
|
@@ -446,7 +446,7 @@ Human output groups paths under "Shared with your team (commit these)" and "Loca
|
|
|
446
446
|
{
|
|
447
447
|
"kind": "agent-install",
|
|
448
448
|
"schema_version": 1,
|
|
449
|
-
"fallow_version": "3.
|
|
449
|
+
"fallow_version": "3.28.0",
|
|
450
450
|
"root": "/abs/path",
|
|
451
451
|
"mode": "install",
|
|
452
452
|
"dry_run": false,
|
|
@@ -650,7 +650,7 @@ fallow health --format json --quiet --trend
|
|
|
650
650
|
{
|
|
651
651
|
"kind": "health",
|
|
652
652
|
"schema_version": 7,
|
|
653
|
-
"version": "3.
|
|
653
|
+
"version": "3.28.0",
|
|
654
654
|
"elapsed_ms": 32,
|
|
655
655
|
"summary": {
|
|
656
656
|
"files_analyzed": 482,
|
|
@@ -1053,7 +1053,7 @@ fallow audit \
|
|
|
1053
1053
|
{
|
|
1054
1054
|
"kind": "audit",
|
|
1055
1055
|
"schema_version": 7,
|
|
1056
|
-
"version": "3.
|
|
1056
|
+
"version": "3.28.0",
|
|
1057
1057
|
"command": "audit",
|
|
1058
1058
|
"verdict": "fail",
|
|
1059
1059
|
"changed_files_count": 12,
|
|
@@ -1130,7 +1130,7 @@ fallow flags --format json --quiet --workspace my-package
|
|
|
1130
1130
|
```json
|
|
1131
1131
|
{
|
|
1132
1132
|
"schema_version": 7,
|
|
1133
|
-
"version": "3.
|
|
1133
|
+
"version": "3.28.0",
|
|
1134
1134
|
"elapsed_ms": 116,
|
|
1135
1135
|
"feature_flags": [],
|
|
1136
1136
|
"total_flags": 0
|
|
@@ -1231,7 +1231,7 @@ fallow security --gate newly-reachable --changed-since origin/main
|
|
|
1231
1231
|
{
|
|
1232
1232
|
"kind": "security",
|
|
1233
1233
|
"schema_version": "4",
|
|
1234
|
-
"version": "3.
|
|
1234
|
+
"version": "3.28.0",
|
|
1235
1235
|
"elapsed_ms": 42,
|
|
1236
1236
|
"config": {
|
|
1237
1237
|
"rules": {
|
|
@@ -1260,7 +1260,7 @@ fallow security --gate newly-reachable --changed-since origin/main
|
|
|
1260
1260
|
{
|
|
1261
1261
|
"kind": "security",
|
|
1262
1262
|
"schema_version": "4",
|
|
1263
|
-
"version": "3.
|
|
1263
|
+
"version": "3.28.0",
|
|
1264
1264
|
"elapsed_ms": 42,
|
|
1265
1265
|
"config": {
|
|
1266
1266
|
"rules": {
|
|
@@ -2030,7 +2030,7 @@ The HTTP layer mirrors the bash `gh_api_retry` / `curl_retry` helpers: `FALLOW_A
|
|
|
2030
2030
|
{
|
|
2031
2031
|
"kind": "dead-code",
|
|
2032
2032
|
"schema_version": 7,
|
|
2033
|
-
"version": "3.
|
|
2033
|
+
"version": "3.28.0",
|
|
2034
2034
|
"elapsed_ms": 45,
|
|
2035
2035
|
"total_issues": 12,
|
|
2036
2036
|
"entry_points": {
|
|
@@ -2190,7 +2190,7 @@ When `--baseline` is used in combined output, the JSON includes a `baseline_delt
|
|
|
2190
2190
|
{
|
|
2191
2191
|
"kind": "dupes",
|
|
2192
2192
|
"schema_version": 7,
|
|
2193
|
-
"version": "3.
|
|
2193
|
+
"version": "3.28.0",
|
|
2194
2194
|
"elapsed_ms": 82,
|
|
2195
2195
|
"total_clones": 15,
|
|
2196
2196
|
"total_lines_duplicated": 230,
|
|
@@ -2234,11 +2234,11 @@ When running `fallow` with no subcommand (all analyses), the JSON output combine
|
|
|
2234
2234
|
{
|
|
2235
2235
|
"kind": "combined",
|
|
2236
2236
|
"schema_version": 7,
|
|
2237
|
-
"version": "3.
|
|
2237
|
+
"version": "3.28.0",
|
|
2238
2238
|
"elapsed_ms": 159,
|
|
2239
2239
|
"check": {
|
|
2240
2240
|
"schema_version": 7,
|
|
2241
|
-
"version": "3.
|
|
2241
|
+
"version": "3.28.0",
|
|
2242
2242
|
"elapsed_ms": 45,
|
|
2243
2243
|
"total_issues": 12,
|
|
2244
2244
|
"unused_files": [],
|
|
@@ -2376,8 +2376,10 @@ Config files are searched in priority order: `.fallowrc.json` > `.fallowrc.jsonc
|
|
|
2376
2376
|
// Resolve framework convention auto-imports (Nuxt components) as graph edges.
|
|
2377
2377
|
// Edges for `<Card001 />`-style template tags are always synthesized; setting
|
|
2378
2378
|
// this to true also drops the Nuxt component entry patterns so an
|
|
2379
|
-
// unreferenced component is reported as unused-file. Kept conservative:
|
|
2380
|
-
// `components:`
|
|
2379
|
+
// unreferenced component is reported as unused-file. Kept conservative: an
|
|
2380
|
+
// unmodelled `components:` or `imports:` config keeps the entry patterns, but
|
|
2381
|
+
// a config that switches the scan off (`components: { dirs: [] }`,
|
|
2382
|
+
// `imports: { scan: false }`) is treated like the default. Default false.
|
|
2381
2383
|
"autoImports": false,
|
|
2382
2384
|
|
|
2383
2385
|
// Production mode
|
|
@@ -420,6 +420,22 @@ export type DependencyOverrideMisconfigReason = ("unparsable-key" | "empty-value
|
|
|
420
420
|
* from counts.
|
|
421
421
|
*/
|
|
422
422
|
export type BaselineStalenessAdvisory = ("none" | "zero-overlap" | "partial")
|
|
423
|
+
/**
|
|
424
|
+
* One channel that narrowed a run to part of the project.
|
|
425
|
+
*
|
|
426
|
+
* Serialized as kebab-case inside `scope_reasons` and published as an OPEN
|
|
427
|
+
* set, the same tolerate-unknown contract `gate_outcomes` keys carry: a name
|
|
428
|
+
* this build does not emit means "some narrowing", not an error.
|
|
429
|
+
*
|
|
430
|
+
* Which names a command can emit differs per command, because the three
|
|
431
|
+
* narrowing predicates see different state. `dead-code` reads the flags
|
|
432
|
+
* themselves and can name every channel. `dupes` and `health` see an already
|
|
433
|
+
* resolved changed-file set and report `changed-files`, because at that point
|
|
434
|
+
* the flag that produced it is gone. `health` reports `workspace` for both
|
|
435
|
+
* `--workspace` and `--changed-workspaces` for the same reason. A consumer
|
|
436
|
+
* must therefore not assume a given command emits a given name.
|
|
437
|
+
*/
|
|
438
|
+
export type ScopeReason = ("diff" | "changed-since" | "changed-files" | "workspace" | "changed-workspaces" | "scope" | "file" | "issue-type-filter" | "production")
|
|
423
439
|
/**
|
|
424
440
|
* Status of a regression-check pass.
|
|
425
441
|
*/
|
|
@@ -428,6 +444,29 @@ export type RegressionStatus = ("pass" | "exceeded" | "skipped")
|
|
|
428
444
|
* Interpretation of [`RegressionResult::tolerance`].
|
|
429
445
|
*/
|
|
430
446
|
export type RegressionToleranceKind = ("absolute" | "percentage")
|
|
447
|
+
/**
|
|
448
|
+
* What became of one request on this run.
|
|
449
|
+
*
|
|
450
|
+
* Two-valued today. The value set is OPEN so a later `partial` needs no bump,
|
|
451
|
+
* and it is deliberately not added now: nothing emits it, and a permanently
|
|
452
|
+
* unused value reads as a measurement nobody takes.
|
|
453
|
+
*/
|
|
454
|
+
export type RequestStatus = ("applied" | "not-applied")
|
|
455
|
+
/**
|
|
456
|
+
* What a request governs, and therefore what its failure means.
|
|
457
|
+
*
|
|
458
|
+
* Published on every entry so a consumer selects on the class rather than on
|
|
459
|
+
* a name list. Without it the one sentence a consumer can write for the whole
|
|
460
|
+
* object ("the report is wider than requested") is false for any request that
|
|
461
|
+
* does not narrow, which is how a failed `--sarif-file` write came to be
|
|
462
|
+
* reported as an unscoped run. A request name added later carries its own
|
|
463
|
+
* class, so a consumer written today keeps saying the right thing about it.
|
|
464
|
+
*
|
|
465
|
+
* The value set is OPEN, like the names and the statuses: read a class this
|
|
466
|
+
* build does not recognise as "some request", not as an error, and do not read
|
|
467
|
+
* it as `scope`.
|
|
468
|
+
*/
|
|
469
|
+
export type RequestEffect = ("scope" | "artifact")
|
|
431
470
|
/**
|
|
432
471
|
* A diagnostic about a workspace-discovery candidate.
|
|
433
472
|
*
|
|
@@ -570,6 +609,97 @@ kind: "excluded-by-default-ignore"
|
|
|
570
609
|
*/
|
|
571
610
|
excluded_file_count: number
|
|
572
611
|
kind: "no-source-files-analyzed"
|
|
612
|
+
} | {
|
|
613
|
+
/**
|
|
614
|
+
* Scoring error text.
|
|
615
|
+
*/
|
|
616
|
+
error: string
|
|
617
|
+
kind: "file-scores-unavailable"
|
|
618
|
+
} | {
|
|
619
|
+
/**
|
|
620
|
+
* Which input stopped it, as a kebab-case token: `not-a-repository`,
|
|
621
|
+
* `invalid-since` or `churn-file-unreadable`. The set is open.
|
|
622
|
+
*
|
|
623
|
+
* The cause decides the remedy, which is why it is on the wire: a run
|
|
624
|
+
* outside a repository is fixed by running fallow inside one, a
|
|
625
|
+
* malformed `--since` by respelling the flag, and a churn file that
|
|
626
|
+
* changed under the run by rerunning it. A consumer reading only the
|
|
627
|
+
* kind would offer the first remedy for all three.
|
|
628
|
+
*/
|
|
629
|
+
cause: string
|
|
630
|
+
kind: "hotspots-skipped"
|
|
631
|
+
} | {
|
|
632
|
+
/**
|
|
633
|
+
* `true` when the run also asked for ownership attribution, which a
|
|
634
|
+
* shallow clone skews further by inflating single-author dominance.
|
|
635
|
+
*/
|
|
636
|
+
ownership_requested: boolean
|
|
637
|
+
kind: "shallow-clone"
|
|
638
|
+
} | {
|
|
639
|
+
kind: "unpinned-clock"
|
|
640
|
+
} | {
|
|
641
|
+
/**
|
|
642
|
+
* Which input failed, as a kebab-case token: `invalid-bot-pattern` or
|
|
643
|
+
* `codeowners-parse-failed`. The set is open.
|
|
644
|
+
*/
|
|
645
|
+
cause: string
|
|
646
|
+
/**
|
|
647
|
+
* Underlying error text.
|
|
648
|
+
*/
|
|
649
|
+
error: string
|
|
650
|
+
kind: "ownership-unavailable"
|
|
651
|
+
} | {
|
|
652
|
+
/**
|
|
653
|
+
* Filesystem or JSON error text.
|
|
654
|
+
*/
|
|
655
|
+
error: string
|
|
656
|
+
kind: "trend-snapshot-unreadable"
|
|
657
|
+
} | {
|
|
658
|
+
/**
|
|
659
|
+
* The plugin that read the config, as it labels itself:
|
|
660
|
+
* `module-federation` for a standalone `module-federation.config.*`,
|
|
661
|
+
* or the bundler plugin (`webpack`, `rspack`, `rsbuild`, `vite`) that
|
|
662
|
+
* read the same options inline from its own config.
|
|
663
|
+
*/
|
|
664
|
+
plugin: string
|
|
665
|
+
/**
|
|
666
|
+
* The config key that was present and not fully readable (`exposes`,
|
|
667
|
+
* `remotes`). The set is open.
|
|
668
|
+
*/
|
|
669
|
+
key: string
|
|
670
|
+
/**
|
|
671
|
+
* Why it could not be read, as a kebab-case token:
|
|
672
|
+
* `not-object-literal`, `array-form`, `spread` or
|
|
673
|
+
* `unreadable-entries`. The set is open.
|
|
674
|
+
*
|
|
675
|
+
* The reason decides the remedy, which is why it is on the wire: a
|
|
676
|
+
* value that is not an object literal is fixed by writing one, while
|
|
677
|
+
* unreadable entries are fixed by naming those entries in the config
|
|
678
|
+
* option the message points at.
|
|
679
|
+
*/
|
|
680
|
+
reason: string
|
|
681
|
+
kind: "plugin-config-unreadable"
|
|
682
|
+
} | {
|
|
683
|
+
/**
|
|
684
|
+
* The plugin that read the config, as it labels itself (`nuxt`).
|
|
685
|
+
*/
|
|
686
|
+
plugin: string
|
|
687
|
+
/**
|
|
688
|
+
* The config key whose effect is not modeled (`components`,
|
|
689
|
+
* `imports`). The set is open.
|
|
690
|
+
*/
|
|
691
|
+
key: string
|
|
692
|
+
/**
|
|
693
|
+
* Why the effect is not modeled, as a kebab-case token:
|
|
694
|
+
* `key-effect-not-modeled` when the key's own value is the reason,
|
|
695
|
+
* `config-property-unreadable` when a top-level property of the same
|
|
696
|
+
* config file could not be read statically, so no surface in it can
|
|
697
|
+
* be classified at all. The set is open.
|
|
698
|
+
*/
|
|
699
|
+
reason: string
|
|
700
|
+
kind: "plugin-effect-not-modeled"
|
|
701
|
+
} | {
|
|
702
|
+
kind: "coverage-auto-detected"
|
|
573
703
|
})
|
|
574
704
|
/**
|
|
575
705
|
* Discriminant for [`CloneGroupAction::kind`]. Mirrors the action types
|
|
@@ -2820,6 +2950,16 @@ regression?: (RegressionResult | null)
|
|
|
2820
2950
|
* was asked for", never "nothing failed". See [`crate::GateOutcomes`].
|
|
2821
2951
|
*/
|
|
2822
2952
|
gate_outcomes?: (GateOutcomes | null)
|
|
2953
|
+
/**
|
|
2954
|
+
* Every narrowing or shaping request this run RECEIVED, keyed by name,
|
|
2955
|
+
* absent when it was asked for nothing. An entry whose `status` is not
|
|
2956
|
+
* `applied` means the run could not do what it was asked and reported
|
|
2957
|
+
* something WIDER instead, so what follows is a valid report of a scope
|
|
2958
|
+
* nobody requested. Honoured requests are published too, with
|
|
2959
|
+
* `status: "applied"`, so an absent object means "nothing was asked for",
|
|
2960
|
+
* never "nothing failed". See [`crate::RequestOutcomes`].
|
|
2961
|
+
*/
|
|
2962
|
+
request_outcomes?: (RequestOutcomes | null)
|
|
2823
2963
|
/**
|
|
2824
2964
|
* `_meta` block with docs and rule definitions, when `--explain` was
|
|
2825
2965
|
* passed.
|
|
@@ -2838,10 +2978,12 @@ _meta?: (Meta | null)
|
|
|
2838
2978
|
* `source-parse-degraded`;
|
|
2839
2979
|
* - dead-code analysis, from the dependency-catalog and override
|
|
2840
2980
|
* detectors: `malformed-pnpm-workspace-yaml`,
|
|
2841
|
-
* `bun-lockb-override-resolution-skipped
|
|
2981
|
+
* `bun-lockb-override-resolution-skipped`;
|
|
2982
|
+
* - framework plugins, while they read their own build configs:
|
|
2983
|
+
* `plugin-config-unreadable`, `plugin-effect-not-modeled`.
|
|
2842
2984
|
*
|
|
2843
|
-
* Analysis-stage kinds therefore reach only the envelopes
|
|
2844
|
-
* includes a dead-code analyze pass, never a standalone
|
|
2985
|
+
* Analysis-stage and plugin-stage kinds therefore reach only the envelopes
|
|
2986
|
+
* whose run includes a dead-code analyze pass, never a standalone
|
|
2845
2987
|
* `fallow dupes --format json`. `path` is project-root-relative with
|
|
2846
2988
|
* forward slashes; the array is omitted when empty. The same list is
|
|
2847
2989
|
* repeated on each top-level command's envelope so single-command
|
|
@@ -5289,7 +5431,8 @@ current_findings: number
|
|
|
5289
5431
|
* differ per command and include a diff, a base ref, `--changed-since`,
|
|
5290
5432
|
* `--workspace`, `--changed-workspaces`, `--scope`, `--file`, an
|
|
5291
5433
|
* issue-type filter, and production mode. Both `stale` and `gate_trips`
|
|
5292
|
-
* are false whenever this is true.
|
|
5434
|
+
* are false whenever this is true. `scope_reasons` names the channels
|
|
5435
|
+
* that fired.
|
|
5293
5436
|
*/
|
|
5294
5437
|
change_scoped: boolean
|
|
5295
5438
|
/**
|
|
@@ -5301,13 +5444,21 @@ change_scoped: boolean
|
|
|
5301
5444
|
stale: boolean
|
|
5302
5445
|
warning: BaselineStalenessAdvisory
|
|
5303
5446
|
/**
|
|
5304
|
-
* True exactly when
|
|
5305
|
-
* `!change_scoped && baseline_entries > 0 && matched_entries < baseline_entries
|
|
5306
|
-
*
|
|
5307
|
-
* stricter than `stale`: any unmatched entry counts
|
|
5308
|
-
*
|
|
5309
|
-
*
|
|
5310
|
-
*
|
|
5447
|
+
* True exactly when `unrecognised_format` is true, or
|
|
5448
|
+
* `!change_scoped && baseline_entries > 0 && matched_entries < baseline_entries`.
|
|
5449
|
+
* That is the rule `--fail-on-stale-baseline` applies. Deliberately
|
|
5450
|
+
* stricter than `stale`: any unmatched entry counts, and so does a file
|
|
5451
|
+
* this command could not read as its own, which protects nothing at all.
|
|
5452
|
+
* The second half is suppressed by `change_scoped` and the first is not:
|
|
5453
|
+
* which command wrote a file does not depend on how much of the project
|
|
5454
|
+
* the run looked at.
|
|
5455
|
+
*
|
|
5456
|
+
* It describes the baseline, not the run's exit code: `health
|
|
5457
|
+
* --report-only` is an explicit request never to fail, so that run exits 0
|
|
5458
|
+
* and says so on stderr while still reporting `gate_trips: true` here, and
|
|
5459
|
+
* `fallow audit` never judges a baseline at all, so its
|
|
5460
|
+
* `gate_outcomes["stale-baseline"]` stands down beside a section that
|
|
5461
|
+
* reports `true`.
|
|
5311
5462
|
*/
|
|
5312
5463
|
gate_trips: boolean
|
|
5313
5464
|
/**
|
|
@@ -5317,6 +5468,37 @@ gate_trips: boolean
|
|
|
5317
5468
|
* `0`. Always `0` in health's count mode too.
|
|
5318
5469
|
*/
|
|
5319
5470
|
moved_entries: number
|
|
5471
|
+
/**
|
|
5472
|
+
* True when the loaded file is not a baseline of the command that read it:
|
|
5473
|
+
* it names another command in its top-level `kind`, or it names none and
|
|
5474
|
+
* carries no key this command's own format writes. Read this, not
|
|
5475
|
+
* `baseline_entries == 0`, before telling anyone their baseline is the
|
|
5476
|
+
* wrong file: a baseline saved from a project that had nothing to record
|
|
5477
|
+
* is legitimately empty and is not a mistake.
|
|
5478
|
+
*
|
|
5479
|
+
* Present only when true, so an envelope from a run that loaded its own
|
|
5480
|
+
* baseline is unchanged. All three commands set it, including `dead-code`,
|
|
5481
|
+
* which classifies the file before its required fields could reject it.
|
|
5482
|
+
* A file with no `kind` is the reading a baseline saved before that member
|
|
5483
|
+
* existed gets, which is why the keys remain the fallback.
|
|
5484
|
+
*/
|
|
5485
|
+
unrecognised_format?: boolean
|
|
5486
|
+
/**
|
|
5487
|
+
* Which channels narrowed this run, present and non-empty exactly when
|
|
5488
|
+
* `change_scoped` is true. Both members are derived from one function, so
|
|
5489
|
+
* the boolean and the array cannot disagree.
|
|
5490
|
+
*
|
|
5491
|
+
* Read it to decide whether the narrowing is removable: a run narrowed
|
|
5492
|
+
* only by `diff`, `changed-since`, `changed-files`, `scope`, `file` or
|
|
5493
|
+
* `issue-type-filter` can be repeated unscoped to judge the baseline,
|
|
5494
|
+
* while `production`, `workspace` and `changed-workspaces` are the
|
|
5495
|
+
* caller's own choice about what to analyze and an unscoped repeat would
|
|
5496
|
+
* contradict it.
|
|
5497
|
+
*
|
|
5498
|
+
* The name set is OPEN and the names a command can emit differ per
|
|
5499
|
+
* command; see [`ScopeReason`].
|
|
5500
|
+
*/
|
|
5501
|
+
scope_reasons?: ScopeReason[]
|
|
5320
5502
|
}
|
|
5321
5503
|
/**
|
|
5322
5504
|
* Result of regression detection (`--fail-on-regression`). Compares current
|
|
@@ -5354,6 +5536,102 @@ exceeded: boolean
|
|
|
5354
5536
|
*/
|
|
5355
5537
|
reason?: (string | null)
|
|
5356
5538
|
}
|
|
5539
|
+
/**
|
|
5540
|
+
* Every narrowing or shaping request a run RECEIVED, keyed by name.
|
|
5541
|
+
*
|
|
5542
|
+
* Received, not failed: a request the run honoured is published with
|
|
5543
|
+
* `status: "applied"`, so a consumer can say "scoped to the change"
|
|
5544
|
+
* positively. Read an absent object as "nothing was asked for", never as
|
|
5545
|
+
* "nothing failed".
|
|
5546
|
+
*
|
|
5547
|
+
* Absent from an envelope whenever it is empty, so a run that was asked for
|
|
5548
|
+
* nothing is byte-identical to one produced before this object existed. An
|
|
5549
|
+
* empty object is never emitted: it would assert that something was asked and
|
|
5550
|
+
* all of it applied, which is a different and false claim.
|
|
5551
|
+
*
|
|
5552
|
+
* The names this build can emit are `changed-since`, `diff-filter` and
|
|
5553
|
+
* `sarif-file`. The reasons are `git-missing`, `not-a-repository`,
|
|
5554
|
+
* `git-failed` and `invalid-ref` for `changed-since`, `oversize`,
|
|
5555
|
+
* `unreadable`, `not-utf8`, `foreign-namespace` and `ambiguous-base` for
|
|
5556
|
+
* `diff-filter`, and `directory-create-failed`, `write-failed` and
|
|
5557
|
+
* `serialize-failed` for `sarif-file`. Every set is OPEN: a name a consumer
|
|
5558
|
+
* does not recognise means "some request", not an error.
|
|
5559
|
+
*
|
|
5560
|
+
* `sarif-file` reports a SECONDARY artifact rather than the scope of the
|
|
5561
|
+
* report it travels in, and it is in the same object for the same reason the
|
|
5562
|
+
* others are: the run was asked to do something and did something else, and
|
|
5563
|
+
* nothing in the primary report says so. Which of the two an entry is, every
|
|
5564
|
+
* entry says for itself: `affects` is `scope` for the narrowing requests and
|
|
5565
|
+
* `artifact` for this one. Select on it. A consumer that instead assumes the
|
|
5566
|
+
* whole object narrows the report tells its reader an unwritten SARIF file
|
|
5567
|
+
* widened the analysis, which is what `affects` exists to prevent.
|
|
5568
|
+
*
|
|
5569
|
+
* `scope_size` is emitted for `diff-filter` only today, in added lines. A
|
|
5570
|
+
* consumer reads the unit off the name, so a name that starts measuring its
|
|
5571
|
+
* own scope in a later release needs no change here.
|
|
5572
|
+
*
|
|
5573
|
+
* `invalid-ref` is reachable only through the programmatic API. The
|
|
5574
|
+
* `--changed-since` flag validates its value before a run starts and fails
|
|
5575
|
+
* with exit 2 and an error document, which is the right side to err on: a
|
|
5576
|
+
* malformed ref is invalid input rather than a report of the wrong scope.
|
|
5577
|
+
*/
|
|
5578
|
+
export interface RequestOutcomes {
|
|
5579
|
+
[k: string]: RequestOutcome
|
|
5580
|
+
}
|
|
5581
|
+
/**
|
|
5582
|
+
* One request's fate on one run.
|
|
5583
|
+
*
|
|
5584
|
+
* `reason` and `message` are present exactly when `status` is not `applied`,
|
|
5585
|
+
* and absent otherwise, so a consumer that only wants to know whether a
|
|
5586
|
+
* report is scoped reads `status` alone.
|
|
5587
|
+
*/
|
|
5588
|
+
export interface RequestOutcome {
|
|
5589
|
+
status: RequestStatus
|
|
5590
|
+
affects: RequestEffect
|
|
5591
|
+
/**
|
|
5592
|
+
* What was asked, as the user spelled it: the git ref for
|
|
5593
|
+
* `changed-since`, the diff source label (`--diff-file pr.diff`,
|
|
5594
|
+
* `--diff-stdin`, `$FALLOW_DIFF_FILE build/pr.diff`) for `diff-filter`,
|
|
5595
|
+
* the target path for `sarif-file`. Echoed rather than normalised, so a
|
|
5596
|
+
* consumer must not join it to the project root the way it joins every
|
|
5597
|
+
* other path-shaped field.
|
|
5598
|
+
*/
|
|
5599
|
+
requested: string
|
|
5600
|
+
/**
|
|
5601
|
+
* How much this request left in scope, in the request's own unit, when the
|
|
5602
|
+
* run applied it AND measured that scope. Absent otherwise, including on
|
|
5603
|
+
* every unapplied entry: a request that stood down narrowed nothing, so a
|
|
5604
|
+
* number there would describe a scope nobody applied.
|
|
5605
|
+
*
|
|
5606
|
+
* The unit belongs to the name. `diff-filter` counts added lines, which is
|
|
5607
|
+
* what its filter keeps a finding for. Read the unit off the name the entry
|
|
5608
|
+
* is keyed under, never across names, and read an absent member as "not
|
|
5609
|
+
* measured" rather than as zero.
|
|
5610
|
+
*
|
|
5611
|
+
* The count is what the run INDEXED rather than the true total:
|
|
5612
|
+
* `diff-filter` indexes at most one million added lines and reports that
|
|
5613
|
+
* cap for a larger diff, so read any non-zero value as a lower bound.
|
|
5614
|
+
*
|
|
5615
|
+
* `0` is the case this member exists for: a request that applied over an
|
|
5616
|
+
* EMPTY scope. Every finding then filters out and the report reads clean,
|
|
5617
|
+
* so a consumer that sees no findings beside `scope_size: 0` learns that
|
|
5618
|
+
* nothing was analyzable rather than that the code is clean.
|
|
5619
|
+
*/
|
|
5620
|
+
scope_size?: (number | null)
|
|
5621
|
+
/**
|
|
5622
|
+
* Why the request was not applied, as a kebab-case token. Present exactly
|
|
5623
|
+
* when `status` is not `applied`. The set is open per request name; the
|
|
5624
|
+
* names this build can emit are listed on [`RequestOutcomes`].
|
|
5625
|
+
*/
|
|
5626
|
+
reason?: (string | null)
|
|
5627
|
+
/**
|
|
5628
|
+
* One sentence naming what was asked, what happened instead, and the next
|
|
5629
|
+
* step. Byte-identical to the stderr line for the same case, so a
|
|
5630
|
+
* consumer that renders this never contradicts a log a human read.
|
|
5631
|
+
* Present exactly when `status` is not `applied`.
|
|
5632
|
+
*/
|
|
5633
|
+
message?: (string | null)
|
|
5634
|
+
}
|
|
5357
5635
|
/**
|
|
5358
5636
|
* A read-only follow-up command fallow surfaces from the current findings,
|
|
5359
5637
|
* emitted as the top-level `next_steps` array on each command's JSON envelope.
|
|
@@ -11027,6 +11305,16 @@ groups?: (HealthGroup[] | null)
|
|
|
11027
11305
|
* was asked for", never "nothing failed". See [`crate::GateOutcomes`].
|
|
11028
11306
|
*/
|
|
11029
11307
|
gate_outcomes?: (GateOutcomes | null)
|
|
11308
|
+
/**
|
|
11309
|
+
* Every narrowing or shaping request this run RECEIVED, keyed by name,
|
|
11310
|
+
* absent when it was asked for nothing. An entry whose `status` is not
|
|
11311
|
+
* `applied` means the run could not do what it was asked and reported
|
|
11312
|
+
* something WIDER instead, so what follows is a valid report of a scope
|
|
11313
|
+
* nobody requested. Honoured requests are published too, with
|
|
11314
|
+
* `status: "applied"`, so an absent object means "nothing was asked for",
|
|
11315
|
+
* never "nothing failed". See [`crate::RequestOutcomes`].
|
|
11316
|
+
*/
|
|
11317
|
+
request_outcomes?: (RequestOutcomes | null)
|
|
11030
11318
|
/**
|
|
11031
11319
|
* `_meta` block with metric definitions, when `--explain` was passed.
|
|
11032
11320
|
*/
|
|
@@ -11220,6 +11508,16 @@ baseline_staleness?: (BaselineStaleness | null)
|
|
|
11220
11508
|
* was asked for", never "nothing failed". See [`crate::GateOutcomes`].
|
|
11221
11509
|
*/
|
|
11222
11510
|
gate_outcomes?: (GateOutcomes | null)
|
|
11511
|
+
/**
|
|
11512
|
+
* Every narrowing or shaping request this run RECEIVED, keyed by name,
|
|
11513
|
+
* absent when it was asked for nothing. An entry whose `status` is not
|
|
11514
|
+
* `applied` means the run could not do what it was asked and reported
|
|
11515
|
+
* something WIDER instead, so what follows is a valid report of a scope
|
|
11516
|
+
* nobody requested. Honoured requests are published too, with
|
|
11517
|
+
* `status: "applied"`, so an absent object means "nothing was asked for",
|
|
11518
|
+
* never "nothing failed". See [`crate::RequestOutcomes`].
|
|
11519
|
+
*/
|
|
11520
|
+
request_outcomes?: (RequestOutcomes | null)
|
|
11223
11521
|
/**
|
|
11224
11522
|
* `_meta` block with metric / rule definitions, emitted when `--explain`
|
|
11225
11523
|
* is passed (always present in MCP responses).
|
|
@@ -11397,6 +11695,16 @@ baseline_staleness?: (BaselineStaleness | null)
|
|
|
11397
11695
|
* was asked for", never "nothing failed". See [`crate::GateOutcomes`].
|
|
11398
11696
|
*/
|
|
11399
11697
|
gate_outcomes?: (GateOutcomes | null)
|
|
11698
|
+
/**
|
|
11699
|
+
* Every narrowing or shaping request this run RECEIVED, keyed by name,
|
|
11700
|
+
* absent when it was asked for nothing. An entry whose `status` is not
|
|
11701
|
+
* `applied` means the run could not do what it was asked and reported
|
|
11702
|
+
* something WIDER instead, so what follows is a valid report of a scope
|
|
11703
|
+
* nobody requested. Honoured requests are published too, with
|
|
11704
|
+
* `status: "applied"`, so an absent object means "nothing was asked for",
|
|
11705
|
+
* never "nothing failed". See [`crate::RequestOutcomes`].
|
|
11706
|
+
*/
|
|
11707
|
+
request_outcomes?: (RequestOutcomes | null)
|
|
11400
11708
|
/**
|
|
11401
11709
|
* `_meta` block with docs and rule definitions, when `--explain` was
|
|
11402
11710
|
* passed.
|
|
@@ -12076,6 +12384,16 @@ config: SecurityOutputConfig
|
|
|
12076
12384
|
* was asked for", never "nothing failed". See [`crate::GateOutcomes`].
|
|
12077
12385
|
*/
|
|
12078
12386
|
gate_outcomes?: (GateOutcomes | null)
|
|
12387
|
+
/**
|
|
12388
|
+
* Every narrowing or shaping request this run RECEIVED, keyed by name,
|
|
12389
|
+
* absent when it was asked for nothing. An entry whose `status` is not
|
|
12390
|
+
* `applied` means the run could not do what it was asked and reported
|
|
12391
|
+
* something WIDER instead, so what follows is a valid report of a scope
|
|
12392
|
+
* nobody requested. Honoured requests are published too, with
|
|
12393
|
+
* `status: "applied"`, so an absent object means "nothing was asked for",
|
|
12394
|
+
* never "nothing failed". See [`crate::RequestOutcomes`].
|
|
12395
|
+
*/
|
|
12396
|
+
request_outcomes?: (RequestOutcomes | null)
|
|
12079
12397
|
/**
|
|
12080
12398
|
* Security-specific rule and field metadata, emitted with `--explain`.
|
|
12081
12399
|
*/
|
|
@@ -12709,6 +13027,16 @@ config: SecurityOutputConfig
|
|
|
12709
13027
|
* was asked for", never "nothing failed". See [`crate::GateOutcomes`].
|
|
12710
13028
|
*/
|
|
12711
13029
|
gate_outcomes?: (GateOutcomes | null)
|
|
13030
|
+
/**
|
|
13031
|
+
* Every narrowing or shaping request this run RECEIVED, keyed by name,
|
|
13032
|
+
* absent when it was asked for nothing. An entry whose `status` is not
|
|
13033
|
+
* `applied` means the run could not do what it was asked and reported
|
|
13034
|
+
* something WIDER instead, so what follows is a valid report of a scope
|
|
13035
|
+
* nobody requested. Honoured requests are published too, with
|
|
13036
|
+
* `status: "applied"`, so an absent object means "nothing was asked for",
|
|
13037
|
+
* never "nothing failed". See [`crate::RequestOutcomes`].
|
|
13038
|
+
*/
|
|
13039
|
+
request_outcomes?: (RequestOutcomes | null)
|
|
12712
13040
|
/**
|
|
12713
13041
|
* Security-specific rule and field metadata, emitted with `--explain`.
|
|
12714
13042
|
*/
|
|
@@ -13002,6 +13330,16 @@ elapsed_ms: ElapsedMs
|
|
|
13002
13330
|
* was asked for", never "nothing failed". See [`crate::GateOutcomes`].
|
|
13003
13331
|
*/
|
|
13004
13332
|
gate_outcomes?: (GateOutcomes | null)
|
|
13333
|
+
/**
|
|
13334
|
+
* Every narrowing or shaping request this run RECEIVED, keyed by name,
|
|
13335
|
+
* absent when it was asked for nothing. An entry whose `status` is not
|
|
13336
|
+
* `applied` means the run could not do what it was asked and reported
|
|
13337
|
+
* something WIDER instead, so what follows is a valid report of a scope
|
|
13338
|
+
* nobody requested. Honoured requests are published too, with
|
|
13339
|
+
* `status: "applied"`, so an absent object means "nothing was asked for",
|
|
13340
|
+
* never "nothing failed". See [`crate::RequestOutcomes`].
|
|
13341
|
+
*/
|
|
13342
|
+
request_outcomes?: (RequestOutcomes | null)
|
|
13005
13343
|
/**
|
|
13006
13344
|
* Per-section `_meta` blocks, when `--explain` was passed.
|
|
13007
13345
|
*/
|
|
@@ -13061,6 +13399,22 @@ export interface FeatureFlagsOutput {
|
|
|
13061
13399
|
schema_version: FeatureFlagsSchemaVersion
|
|
13062
13400
|
version: ToolVersion
|
|
13063
13401
|
elapsed_ms: ElapsedMs
|
|
13402
|
+
/**
|
|
13403
|
+
* What the run was asked to narrow and whether it did. See
|
|
13404
|
+
* [`crate::RequestOutcomes`] for the full contract.
|
|
13405
|
+
*
|
|
13406
|
+
* `fallow flags` accepts `--changed-since`, and an unresolvable ref widens
|
|
13407
|
+
* the scan to the whole project rather than failing the run. Until this
|
|
13408
|
+
* member existed the only account of that was a stderr line, which `--quiet`
|
|
13409
|
+
* removes, so a flag inventory read as scoped to the change could silently
|
|
13410
|
+
* be the whole project's (issue #2734).
|
|
13411
|
+
*
|
|
13412
|
+
* The command applies no diff filter, so the object carries the
|
|
13413
|
+
* `changed-since` entry only. Omitted when the run was asked for nothing,
|
|
13414
|
+
* which keeps a scan that passed no narrowing flag byte-identical and moves
|
|
13415
|
+
* no `schema_version`.
|
|
13416
|
+
*/
|
|
13417
|
+
request_outcomes?: (RequestOutcomes | null)
|
|
13064
13418
|
/**
|
|
13065
13419
|
* Detected feature-flag findings.
|
|
13066
13420
|
*/
|
|
@@ -14397,6 +14751,22 @@ invalid_value?: (string | null)
|
|
|
14397
14751
|
*/
|
|
14398
14752
|
export interface SuppressionInventoryOutput {
|
|
14399
14753
|
schema_version: SuppressionInventorySchemaVersion
|
|
14754
|
+
/**
|
|
14755
|
+
* What the run was asked to narrow and whether it did. See
|
|
14756
|
+
* [`crate::RequestOutcomes`] for the full contract.
|
|
14757
|
+
*
|
|
14758
|
+
* `fallow suppressions` accepts `--changed-since`, and an unresolvable ref
|
|
14759
|
+
* widens the inventory to the whole project rather than failing the run.
|
|
14760
|
+
* Until this member existed the only account of that was a stderr line,
|
|
14761
|
+
* which `--quiet` removes, so an inventory read as scoped to the change
|
|
14762
|
+
* could silently be the whole project's (issue #2734).
|
|
14763
|
+
*
|
|
14764
|
+
* The command applies no diff filter, so the object carries the
|
|
14765
|
+
* `changed-since` entry only. Omitted when the run was asked for nothing,
|
|
14766
|
+
* which keeps an inventory that passed no narrowing flag byte-identical and
|
|
14767
|
+
* leaves `schema_version` at `1`.
|
|
14768
|
+
*/
|
|
14769
|
+
request_outcomes?: (RequestOutcomes | null)
|
|
14400
14770
|
summary: SuppressionInventorySummary
|
|
14401
14771
|
/**
|
|
14402
14772
|
* Per-file suppression listings, sorted by path then line.
|