fallow 3.26.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 +11 -11
- package/schema.json +1 -1
- package/skills/fallow/references/cli-reference.md +14 -12
- package/types/output-contract.d.ts +683 -48
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",
|
|
@@ -85,17 +85,17 @@
|
|
|
85
85
|
"detect-libc": "2.1.2"
|
|
86
86
|
},
|
|
87
87
|
"devDependencies": {
|
|
88
|
-
"@tanstack/intent": "0.
|
|
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
|
|
@@ -135,6 +135,16 @@ export type ElapsedMs = number
|
|
|
135
135
|
* Value of `audit.gate`: which findings drive the `fallow audit` verdict.
|
|
136
136
|
*/
|
|
137
137
|
export type AuditGate = ("new-only" | "all")
|
|
138
|
+
/**
|
|
139
|
+
* What a gate concluded on this run.
|
|
140
|
+
*
|
|
141
|
+
* Four-valued rather than a boolean because audit's verdict has a warn tier
|
|
142
|
+
* (`crates/cli/src/cli_report.rs` maps it onto three conclusions) and because
|
|
143
|
+
* a gate can stand down without passing. Widening a published boolean later
|
|
144
|
+
* would retype a required field and bump every carrying envelope, so the width
|
|
145
|
+
* is decided here.
|
|
146
|
+
*/
|
|
147
|
+
export type GateStatus = ("pass" | "warn" | "fail" | "skipped")
|
|
138
148
|
/**
|
|
139
149
|
* Analysis mode stored with baselines, snapshots, audit sides, and impact data.
|
|
140
150
|
*/
|
|
@@ -402,6 +412,30 @@ export type DependencyOverrideSource = ("pnpm-workspace.yaml" | "package.json")
|
|
|
402
412
|
* surfacing them statically catches the issue first.
|
|
403
413
|
*/
|
|
404
414
|
export type DependencyOverrideMisconfigReason = ("unparsable-key" | "empty-value")
|
|
415
|
+
/**
|
|
416
|
+
* Which advisory a loaded baseline earned on this run.
|
|
417
|
+
*
|
|
418
|
+
* Mirrors `fallow_engine::baseline::BaselineStalenessWarning` so a consumer can
|
|
419
|
+
* render the same distinction the stderr warning makes, instead of inferring it
|
|
420
|
+
* from counts.
|
|
421
|
+
*/
|
|
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")
|
|
405
439
|
/**
|
|
406
440
|
* Status of a regression-check pass.
|
|
407
441
|
*/
|
|
@@ -410,6 +444,29 @@ export type RegressionStatus = ("pass" | "exceeded" | "skipped")
|
|
|
410
444
|
* Interpretation of [`RegressionResult::tolerance`].
|
|
411
445
|
*/
|
|
412
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")
|
|
413
470
|
/**
|
|
414
471
|
* A diagnostic about a workspace-discovery candidate.
|
|
415
472
|
*
|
|
@@ -428,6 +485,25 @@ path: string
|
|
|
428
485
|
* with a next-step hint.
|
|
429
486
|
*/
|
|
430
487
|
message: string
|
|
488
|
+
/**
|
|
489
|
+
* True when this diagnostic reports a run whose RESULTS are degraded:
|
|
490
|
+
* something the user installed, wrote, or expected did not reach the
|
|
491
|
+
* analysis. Projected from [`WorkspaceDiagnosticKind::warns_on_stderr`],
|
|
492
|
+
* which is the same classification that decides whether the CLI prints a
|
|
493
|
+
* stderr line, so a CI log built from this field and a local non-quiet run
|
|
494
|
+
* say the same thing.
|
|
495
|
+
*
|
|
496
|
+
* Omitted when false, which is what keeps every clean run byte-identical.
|
|
497
|
+
* The two unconfigured-check kinds answer false on purpose: they fire in
|
|
498
|
+
* the product's default state on every project that never opted into
|
|
499
|
+
* boundaries or rule packs, so warning on them would warn forever. So does
|
|
500
|
+
* `excluded-by-default-ignore`, which is designed behavior on generated
|
|
501
|
+
* output; the alarm for that case is `no-source-files-analyzed`.
|
|
502
|
+
*
|
|
503
|
+
* Read this instead of hardcoding a kind allowlist: a degrading kind added
|
|
504
|
+
* in a later release then reaches an unchanged consumer.
|
|
505
|
+
*/
|
|
506
|
+
degrades_analysis?: boolean
|
|
431
507
|
} & WorkspaceDiagnostic1)
|
|
432
508
|
export type WorkspaceDiagnostic1 = ({
|
|
433
509
|
kind: "undeclared-workspace"
|
|
@@ -525,6 +601,105 @@ file_count: number
|
|
|
525
601
|
*/
|
|
526
602
|
directory_count: number
|
|
527
603
|
kind: "excluded-by-default-ignore"
|
|
604
|
+
} | {
|
|
605
|
+
/**
|
|
606
|
+
* Candidate source files the built-in ignore patterns removed from
|
|
607
|
+
* this walk, summed across every pattern. `0` when the walk found no
|
|
608
|
+
* candidate to exclude in the first place.
|
|
609
|
+
*/
|
|
610
|
+
excluded_file_count: number
|
|
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"
|
|
528
703
|
})
|
|
529
704
|
/**
|
|
530
705
|
* Discriminant for [`CloneGroupAction::kind`]. Mirrors the action types
|
|
@@ -1311,6 +1486,16 @@ elapsed_ms: ElapsedMs
|
|
|
1311
1486
|
base_snapshot_skipped?: (boolean | null)
|
|
1312
1487
|
summary: AuditSummary
|
|
1313
1488
|
attribution: AuditAttribution
|
|
1489
|
+
/**
|
|
1490
|
+
* Every gate this run ARMED, keyed by name, absent when it armed none.
|
|
1491
|
+
* Each entry is the same rule that decides the exit code, so a CI
|
|
1492
|
+
* integration reads the verdict instead of guessing from a process status
|
|
1493
|
+
* it usually cannot see. A gate fails the build when `status` is `fail`
|
|
1494
|
+
* AND `enforced` is true. Armed, not evaluated: fallow's default severity
|
|
1495
|
+
* rules fail a run with no flag at all, so an absent object means "no gate
|
|
1496
|
+
* was asked for", never "nothing failed". See [`crate::GateOutcomes`].
|
|
1497
|
+
*/
|
|
1498
|
+
gate_outcomes?: (GateOutcomes | null)
|
|
1314
1499
|
/**
|
|
1315
1500
|
* `_meta` block with metric / rule definitions, when `--explain` was
|
|
1316
1501
|
* passed.
|
|
@@ -1393,6 +1578,78 @@ styling_introduced: number
|
|
|
1393
1578
|
styling_inherited: number
|
|
1394
1579
|
duplication_demoted: number
|
|
1395
1580
|
}
|
|
1581
|
+
/**
|
|
1582
|
+
* Every gate a run ARMED, keyed by name.
|
|
1583
|
+
*
|
|
1584
|
+
* Armed, not evaluated: a gate is armed by a flag or by config, never merely
|
|
1585
|
+
* because the rule behind it exists. Fallow's default severity rules fail a
|
|
1586
|
+
* run with no flag at all, so a `dead-code` run can exit 1 carrying no object
|
|
1587
|
+
* whatsoever. Read an absent object as "no gate was asked for", never as
|
|
1588
|
+
* "nothing failed".
|
|
1589
|
+
*
|
|
1590
|
+
* Absent from an envelope whenever it is empty, so a run that armed no gate is
|
|
1591
|
+
* byte-identical to one produced before this object existed. An empty object
|
|
1592
|
+
* is never emitted: it would assert that gates were armed and none tripped,
|
|
1593
|
+
* which is a different and false claim.
|
|
1594
|
+
*
|
|
1595
|
+
* The names this build can emit are `error-severity-findings`, `regression`,
|
|
1596
|
+
* `stale-baseline`, `duplication-threshold`, `health-min-score`,
|
|
1597
|
+
* `health-min-severity`, `health-findings`, `health-coverage-gaps`,
|
|
1598
|
+
* `health-runtime-coverage`, `security`, `security-advisory`, `audit-verdict`
|
|
1599
|
+
* and `type-aware-require`. The set is OPEN: a name a consumer does not
|
|
1600
|
+
* recognise means "some gate", not an error.
|
|
1601
|
+
*/
|
|
1602
|
+
export interface GateOutcomes {
|
|
1603
|
+
[k: string]: GateOutcome
|
|
1604
|
+
}
|
|
1605
|
+
/**
|
|
1606
|
+
* One gate's verdict on one run.
|
|
1607
|
+
*
|
|
1608
|
+
* `status` and `enforced` answer different questions and legitimately
|
|
1609
|
+
* disagree. `status` is what the rule concluded; `enforced` is whether a
|
|
1610
|
+
* `fail` from this gate would make the run exit non-zero. A
|
|
1611
|
+
* `health --report-only` run is an explicit request never to fail, so a
|
|
1612
|
+
* failing gate there reports `status: fail` with `enforced: false`, and a
|
|
1613
|
+
* stale-baseline verdict published without `--fail-on-stale-baseline` reports
|
|
1614
|
+
* the same pair.
|
|
1615
|
+
*
|
|
1616
|
+
* **A gate fails the build when `status` is `fail` AND `enforced` is true.**
|
|
1617
|
+
* Neither member decides it alone: `enforced` is true on every armed gate,
|
|
1618
|
+
* including the ones that passed, so gating on it by itself fails every run
|
|
1619
|
+
* that armed anything. Read `status` on its own to decide what to say, and
|
|
1620
|
+
* remember that `warn` and `skipped` are neither a pass nor a failure.
|
|
1621
|
+
*/
|
|
1622
|
+
export interface GateOutcome {
|
|
1623
|
+
status: GateStatus
|
|
1624
|
+
/**
|
|
1625
|
+
* True when a `fail` from this gate makes the run exit non-zero. False
|
|
1626
|
+
* when the verdict is published for information only, because the gate was
|
|
1627
|
+
* never armed or because the run was told never to fail.
|
|
1628
|
+
*/
|
|
1629
|
+
enforced: boolean
|
|
1630
|
+
/**
|
|
1631
|
+
* The measured value the gate compared, when there is one: the duplication
|
|
1632
|
+
* percentage, the health score, or the number of findings at or above the
|
|
1633
|
+
* severity floor. Whole numbers are carried as JSON numbers, so a count of
|
|
1634
|
+
* three reads as `3.0`. Absent for gates that compare no number.
|
|
1635
|
+
*/
|
|
1636
|
+
observed?: (number | null)
|
|
1637
|
+
/**
|
|
1638
|
+
* The configured limit `observed` was compared against, when there is one.
|
|
1639
|
+
* Absent for gates that compare no number.
|
|
1640
|
+
*/
|
|
1641
|
+
threshold?: (number | null)
|
|
1642
|
+
/**
|
|
1643
|
+
* How the limit was spelled, for a gate whose `threshold` number does not
|
|
1644
|
+
* carry its own unit. `health-min-severity` sets it to the severity floor
|
|
1645
|
+
* (`moderate`, `high` or `critical`); `regression` sets it to the
|
|
1646
|
+
* tolerance as the user wrote it (`"50%"` or `"5"`), because `threshold`
|
|
1647
|
+
* there is the allowance in issues and the percentage would otherwise be
|
|
1648
|
+
* unrecoverable on the grouped envelope, which carries no `regression`
|
|
1649
|
+
* object. Absent for gates whose numbers speak for themselves.
|
|
1650
|
+
*/
|
|
1651
|
+
threshold_label?: (string | null)
|
|
1652
|
+
}
|
|
1396
1653
|
/**
|
|
1397
1654
|
* Metric and rule definitions emitted under `_meta` when `--explain` is
|
|
1398
1655
|
* passed (always present in MCP responses). Helps AI agents and CI systems
|
|
@@ -2670,10 +2927,39 @@ baseline_deltas?: (BaselineDeltas | null)
|
|
|
2670
2927
|
* Which baseline snapshot was matched, in baseline runs.
|
|
2671
2928
|
*/
|
|
2672
2929
|
baseline?: (BaselineMatch | null)
|
|
2930
|
+
/**
|
|
2931
|
+
* This run's view of the loaded baseline, present only in baseline runs.
|
|
2932
|
+
* Carries the staleness counts, the advisory verdict and `gate_trips`, the
|
|
2933
|
+
* same boolean `--fail-on-stale-baseline` exits on, so a CI integration
|
|
2934
|
+
* reads one field instead of restating the rule. Read `change_scoped`
|
|
2935
|
+
* before dividing `matched_entries` by `baseline_entries`: a narrowed run
|
|
2936
|
+
* can report `matched_entries: 0` on a healthy baseline.
|
|
2937
|
+
*/
|
|
2938
|
+
baseline_staleness?: (BaselineStaleness | null)
|
|
2673
2939
|
/**
|
|
2674
2940
|
* Regression verdict against the baseline, in `--fail-on-regression` runs.
|
|
2675
2941
|
*/
|
|
2676
2942
|
regression?: (RegressionResult | null)
|
|
2943
|
+
/**
|
|
2944
|
+
* Every gate this run ARMED, keyed by name, absent when it armed none.
|
|
2945
|
+
* Each entry is the same rule that decides the exit code, so a CI
|
|
2946
|
+
* integration reads the verdict instead of guessing from a process status
|
|
2947
|
+
* it usually cannot see. A gate fails the build when `status` is `fail`
|
|
2948
|
+
* AND `enforced` is true. Armed, not evaluated: fallow's default severity
|
|
2949
|
+
* rules fail a run with no flag at all, so an absent object means "no gate
|
|
2950
|
+
* was asked for", never "nothing failed". See [`crate::GateOutcomes`].
|
|
2951
|
+
*/
|
|
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)
|
|
2677
2963
|
/**
|
|
2678
2964
|
* `_meta` block with docs and rule definitions, when `--explain` was
|
|
2679
2965
|
* passed.
|
|
@@ -2692,10 +2978,12 @@ _meta?: (Meta | null)
|
|
|
2692
2978
|
* `source-parse-degraded`;
|
|
2693
2979
|
* - dead-code analysis, from the dependency-catalog and override
|
|
2694
2980
|
* detectors: `malformed-pnpm-workspace-yaml`,
|
|
2695
|
-
* `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`.
|
|
2696
2984
|
*
|
|
2697
|
-
* Analysis-stage kinds therefore reach only the envelopes
|
|
2698
|
-
* 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
|
|
2699
2987
|
* `fallow dupes --format json`. `path` is project-root-relative with
|
|
2700
2988
|
* forward slashes; the array is omitted when empty. The same list is
|
|
2701
2989
|
* repeated on each top-level command's envelope so single-command
|
|
@@ -5092,6 +5380,126 @@ entries: number
|
|
|
5092
5380
|
*/
|
|
5093
5381
|
matched: number
|
|
5094
5382
|
}
|
|
5383
|
+
/**
|
|
5384
|
+
* One run's machine-readable view of a loaded baseline.
|
|
5385
|
+
*
|
|
5386
|
+
* `stale` and `gate_trips` answer different questions and legitimately
|
|
5387
|
+
* disagree. `stale` mirrors the unasked-for stderr advisory, which stays silent
|
|
5388
|
+
* below a quarter of the baseline and on a run that produced no findings at
|
|
5389
|
+
* all, because a cleaned project and a rotted baseline look identical from
|
|
5390
|
+
* there. `gate_trips` mirrors the opt-in `--fail-on-stale-baseline` rule, which
|
|
5391
|
+
* a repository asks for precisely to catch those cases, so it fires on any
|
|
5392
|
+
* stale entry. A rotted baseline on a cleaned project reports
|
|
5393
|
+
* `stale: false` with `gate_trips: true`; that is the contract, not a defect.
|
|
5394
|
+
*
|
|
5395
|
+
* `change_scoped` is the member a consumer must read before dividing
|
|
5396
|
+
* `matched_entries` by `baseline_entries`. A run narrowed to part of the
|
|
5397
|
+
* project compares a whole-project baseline against a slice of it and can
|
|
5398
|
+
* report `matched_entries: 0` while the baseline is perfectly healthy, so both
|
|
5399
|
+
* `stale` and `gate_trips` are false there by construction. The remedy for a
|
|
5400
|
+
* tripped gate is always the same: re-save the baseline from a whole-project
|
|
5401
|
+
* run with `--save-baseline`.
|
|
5402
|
+
*/
|
|
5403
|
+
export interface BaselineStaleness {
|
|
5404
|
+
/**
|
|
5405
|
+
* Entries carried by the loaded baseline file. On health these are the
|
|
5406
|
+
* complexity and CRAP finding entries; runtime-coverage suppressions and
|
|
5407
|
+
* refactoring target keys carried by the same file are not counted.
|
|
5408
|
+
*/
|
|
5409
|
+
baseline_entries: number
|
|
5410
|
+
/**
|
|
5411
|
+
* Entries that matched a current finding on this run and were filtered out
|
|
5412
|
+
* of the report. On health this includes entries matched through a
|
|
5413
|
+
* followed file move.
|
|
5414
|
+
*/
|
|
5415
|
+
matched_entries: number
|
|
5416
|
+
/**
|
|
5417
|
+
* Entries that matched no current finding on this run:
|
|
5418
|
+
* `baseline_entries - matched_entries`.
|
|
5419
|
+
*/
|
|
5420
|
+
stale_entries: number
|
|
5421
|
+
/**
|
|
5422
|
+
* Findings this run produced before the baseline filtered them. Zero means
|
|
5423
|
+
* there was nothing to compare, either because the project is clean or
|
|
5424
|
+
* because the scope was empty, which is why `stale` stays false there even
|
|
5425
|
+
* when every entry went unmatched.
|
|
5426
|
+
*/
|
|
5427
|
+
current_findings: number
|
|
5428
|
+
/**
|
|
5429
|
+
* True when this run analyzed only part of the project, so a whole-project
|
|
5430
|
+
* baseline matches less of it for reasons that are not rot. The channels
|
|
5431
|
+
* differ per command and include a diff, a base ref, `--changed-since`,
|
|
5432
|
+
* `--workspace`, `--changed-workspaces`, `--scope`, `--file`, an
|
|
5433
|
+
* issue-type filter, and production mode. Both `stale` and `gate_trips`
|
|
5434
|
+
* are false whenever this is true. `scope_reasons` names the channels
|
|
5435
|
+
* that fired.
|
|
5436
|
+
*/
|
|
5437
|
+
change_scoped: boolean
|
|
5438
|
+
/**
|
|
5439
|
+
* True exactly when the advisory stderr warning fired: not change-scoped,
|
|
5440
|
+
* at least one current finding before baseline filtering, and either
|
|
5441
|
+
* nothing matched or `stale_entries` reached a quarter of
|
|
5442
|
+
* `baseline_entries`.
|
|
5443
|
+
*/
|
|
5444
|
+
stale: boolean
|
|
5445
|
+
warning: BaselineStalenessAdvisory
|
|
5446
|
+
/**
|
|
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`.
|
|
5462
|
+
*/
|
|
5463
|
+
gate_trips: boolean
|
|
5464
|
+
/**
|
|
5465
|
+
* Entries that matched only by following a file move. Only `health` can
|
|
5466
|
+
* follow one, in its identity baseline mode; `dead-code` and `dupes` match
|
|
5467
|
+
* entries by fingerprint and never classify one as moved, so they report
|
|
5468
|
+
* `0`. Always `0` in health's count mode too.
|
|
5469
|
+
*/
|
|
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[]
|
|
5502
|
+
}
|
|
5095
5503
|
/**
|
|
5096
5504
|
* Result of regression detection (`--fail-on-regression`). Compares current
|
|
5097
5505
|
* issue counts against a baseline from config or an explicit file.
|
|
@@ -5128,6 +5536,102 @@ exceeded: boolean
|
|
|
5128
5536
|
*/
|
|
5129
5537
|
reason?: (string | null)
|
|
5130
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
|
+
}
|
|
5131
5635
|
/**
|
|
5132
5636
|
* A read-only follow-up command fallow surfaces from the current findings,
|
|
5133
5637
|
* emitted as the top-level `next_steps` array on each command's JSON envelope.
|
|
@@ -6040,51 +6544,7 @@ severity_moderate_count: number
|
|
|
6040
6544
|
/**
|
|
6041
6545
|
* Baseline staleness data, present only when a baseline was loaded.
|
|
6042
6546
|
*/
|
|
6043
|
-
baseline_staleness?: (
|
|
6044
|
-
}
|
|
6045
|
-
/**
|
|
6046
|
-
* Staleness of a loaded health baseline.
|
|
6047
|
-
*
|
|
6048
|
-
* Reports how many saved complexity and CRAP finding entries still matched a
|
|
6049
|
-
* current finding on this run, so consumers can see a rotting baseline before
|
|
6050
|
-
* it degrades to zero overlap. Runtime-coverage suppressions and refactoring
|
|
6051
|
-
* target keys carried by the same baseline are not counted here. Present in
|
|
6052
|
-
* the summary only when a baseline was loaded.
|
|
6053
|
-
*/
|
|
6054
|
-
export interface HealthBaselineStaleness {
|
|
6055
|
-
/**
|
|
6056
|
-
* Complexity and CRAP finding entries carried by the loaded baseline.
|
|
6057
|
-
*/
|
|
6058
|
-
baseline_entries: number
|
|
6059
|
-
/**
|
|
6060
|
-
* Entries that matched a current finding in the active baseline mode,
|
|
6061
|
-
* including entries matched through a followed file move.
|
|
6062
|
-
*/
|
|
6063
|
-
matched_entries: number
|
|
6064
|
-
/**
|
|
6065
|
-
* Entries that matched no current finding on this run.
|
|
6066
|
-
*/
|
|
6067
|
-
stale_entries: number
|
|
6068
|
-
/**
|
|
6069
|
-
* Entries that matched only by following a file move in identity mode.
|
|
6070
|
-
* Always zero in count mode.
|
|
6071
|
-
*/
|
|
6072
|
-
moved_entries: number
|
|
6073
|
-
/**
|
|
6074
|
-
* True when this run analyzed a subset of the project (changed-file,
|
|
6075
|
-
* diff, or workspace scoping, or production mode, which drops test, story
|
|
6076
|
-
* and dev files), so the baseline was compared against a narrowed finding
|
|
6077
|
-
* set and staleness cannot be judged. `stale` is always false on scoped
|
|
6078
|
-
* runs.
|
|
6079
|
-
*/
|
|
6080
|
-
change_scoped: boolean
|
|
6081
|
-
/**
|
|
6082
|
-
* True exactly when the run was not change-scoped, at least one current
|
|
6083
|
-
* finding existed before baseline filtering, and `stale_entries` reached
|
|
6084
|
-
* a quarter of `baseline_entries`. Mirrors the human warning so machine
|
|
6085
|
-
* consumers do not have to reimplement the threshold.
|
|
6086
|
-
*/
|
|
6087
|
-
stale: boolean
|
|
6547
|
+
baseline_staleness?: (BaselineStaleness | null)
|
|
6088
6548
|
}
|
|
6089
6549
|
/**
|
|
6090
6550
|
* Report entry describing whether a threshold override is active, stale, or
|
|
@@ -10835,6 +11295,26 @@ grouped_by?: (GroupByMode | null)
|
|
|
10835
11295
|
* Per-bucket recomputed metrics; present only in grouped output.
|
|
10836
11296
|
*/
|
|
10837
11297
|
groups?: (HealthGroup[] | null)
|
|
11298
|
+
/**
|
|
11299
|
+
* Every gate this run ARMED, keyed by name, absent when it armed none.
|
|
11300
|
+
* Each entry is the same rule that decides the exit code, so a CI
|
|
11301
|
+
* integration reads the verdict instead of guessing from a process status
|
|
11302
|
+
* it usually cannot see. A gate fails the build when `status` is `fail`
|
|
11303
|
+
* AND `enforced` is true. Armed, not evaluated: fallow's default severity
|
|
11304
|
+
* rules fail a run with no flag at all, so an absent object means "no gate
|
|
11305
|
+
* was asked for", never "nothing failed". See [`crate::GateOutcomes`].
|
|
11306
|
+
*/
|
|
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)
|
|
10838
11318
|
/**
|
|
10839
11319
|
* `_meta` block with metric definitions, when `--explain` was passed.
|
|
10840
11320
|
*/
|
|
@@ -11009,6 +11489,35 @@ total_issues?: (number | null)
|
|
|
11009
11489
|
* Grouped findings; present only in grouped output.
|
|
11010
11490
|
*/
|
|
11011
11491
|
groups?: (DuplicationGroup[] | null)
|
|
11492
|
+
/**
|
|
11493
|
+
* This run's view of the loaded baseline, present only in baseline runs.
|
|
11494
|
+
* Carries the staleness counts, the advisory verdict and `gate_trips`, the
|
|
11495
|
+
* same boolean `--fail-on-stale-baseline` exits on, so a CI integration
|
|
11496
|
+
* reads one field instead of restating the rule. Read `change_scoped`
|
|
11497
|
+
* before dividing `matched_entries` by `baseline_entries`: a narrowed run
|
|
11498
|
+
* can report `matched_entries: 0` on a healthy baseline.
|
|
11499
|
+
*/
|
|
11500
|
+
baseline_staleness?: (BaselineStaleness | null)
|
|
11501
|
+
/**
|
|
11502
|
+
* Every gate this run ARMED, keyed by name, absent when it armed none.
|
|
11503
|
+
* Each entry is the same rule that decides the exit code, so a CI
|
|
11504
|
+
* integration reads the verdict instead of guessing from a process status
|
|
11505
|
+
* it usually cannot see. A gate fails the build when `status` is `fail`
|
|
11506
|
+
* AND `enforced` is true. Armed, not evaluated: fallow's default severity
|
|
11507
|
+
* rules fail a run with no flag at all, so an absent object means "no gate
|
|
11508
|
+
* was asked for", never "nothing failed". See [`crate::GateOutcomes`].
|
|
11509
|
+
*/
|
|
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)
|
|
11012
11521
|
/**
|
|
11013
11522
|
* `_meta` block with metric / rule definitions, emitted when `--explain`
|
|
11014
11523
|
* is passed (always present in MCP responses).
|
|
@@ -11167,6 +11676,35 @@ total_issues: number
|
|
|
11167
11676
|
* One bucket per resolver key.
|
|
11168
11677
|
*/
|
|
11169
11678
|
groups: CheckGroupedEntry[]
|
|
11679
|
+
/**
|
|
11680
|
+
* This run's view of the loaded baseline, present only in baseline runs.
|
|
11681
|
+
* Carries the staleness counts, the advisory verdict and `gate_trips`, the
|
|
11682
|
+
* same boolean `--fail-on-stale-baseline` exits on, so a CI integration
|
|
11683
|
+
* reads one field instead of restating the rule. Read `change_scoped`
|
|
11684
|
+
* before dividing `matched_entries` by `baseline_entries`: a narrowed run
|
|
11685
|
+
* can report `matched_entries: 0` on a healthy baseline.
|
|
11686
|
+
*/
|
|
11687
|
+
baseline_staleness?: (BaselineStaleness | null)
|
|
11688
|
+
/**
|
|
11689
|
+
* Every gate this run ARMED, keyed by name, absent when it armed none.
|
|
11690
|
+
* Each entry is the same rule that decides the exit code, so a CI
|
|
11691
|
+
* integration reads the verdict instead of guessing from a process status
|
|
11692
|
+
* it usually cannot see. A gate fails the build when `status` is `fail`
|
|
11693
|
+
* AND `enforced` is true. Armed, not evaluated: fallow's default severity
|
|
11694
|
+
* rules fail a run with no flag at all, so an absent object means "no gate
|
|
11695
|
+
* was asked for", never "nothing failed". See [`crate::GateOutcomes`].
|
|
11696
|
+
*/
|
|
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)
|
|
11170
11708
|
/**
|
|
11171
11709
|
* `_meta` block with docs and rule definitions, when `--explain` was
|
|
11172
11710
|
* passed.
|
|
@@ -11836,6 +12374,26 @@ schema_version: SecuritySchemaVersion
|
|
|
11836
12374
|
version: ToolVersion
|
|
11837
12375
|
elapsed_ms: ElapsedMs
|
|
11838
12376
|
config: SecurityOutputConfig
|
|
12377
|
+
/**
|
|
12378
|
+
* Every gate this run ARMED, keyed by name, absent when it armed none.
|
|
12379
|
+
* Each entry is the same rule that decides the exit code, so a CI
|
|
12380
|
+
* integration reads the verdict instead of guessing from a process status
|
|
12381
|
+
* it usually cannot see. A gate fails the build when `status` is `fail`
|
|
12382
|
+
* AND `enforced` is true. Armed, not evaluated: fallow's default severity
|
|
12383
|
+
* rules fail a run with no flag at all, so an absent object means "no gate
|
|
12384
|
+
* was asked for", never "nothing failed". See [`crate::GateOutcomes`].
|
|
12385
|
+
*/
|
|
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)
|
|
11839
12397
|
/**
|
|
11840
12398
|
* Security-specific rule and field metadata, emitted with `--explain`.
|
|
11841
12399
|
*/
|
|
@@ -12459,6 +13017,26 @@ schema_version: SecuritySchemaVersion
|
|
|
12459
13017
|
version: ToolVersion
|
|
12460
13018
|
elapsed_ms: ElapsedMs
|
|
12461
13019
|
config: SecurityOutputConfig
|
|
13020
|
+
/**
|
|
13021
|
+
* Every gate this run ARMED, keyed by name, absent when it armed none.
|
|
13022
|
+
* Each entry is the same rule that decides the exit code, so a CI
|
|
13023
|
+
* integration reads the verdict instead of guessing from a process status
|
|
13024
|
+
* it usually cannot see. A gate fails the build when `status` is `fail`
|
|
13025
|
+
* AND `enforced` is true. Armed, not evaluated: fallow's default severity
|
|
13026
|
+
* rules fail a run with no flag at all, so an absent object means "no gate
|
|
13027
|
+
* was asked for", never "nothing failed". See [`crate::GateOutcomes`].
|
|
13028
|
+
*/
|
|
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)
|
|
12462
13040
|
/**
|
|
12463
13041
|
* Security-specific rule and field metadata, emitted with `--explain`.
|
|
12464
13042
|
*/
|
|
@@ -12742,6 +13320,26 @@ export interface CombinedOutput {
|
|
|
12742
13320
|
schema_version: CombinedSchemaVersion
|
|
12743
13321
|
version: ToolVersion
|
|
12744
13322
|
elapsed_ms: ElapsedMs
|
|
13323
|
+
/**
|
|
13324
|
+
* Every gate this run ARMED, keyed by name, absent when it armed none.
|
|
13325
|
+
* Each entry is the same rule that decides the exit code, so a CI
|
|
13326
|
+
* integration reads the verdict instead of guessing from a process status
|
|
13327
|
+
* it usually cannot see. A gate fails the build when `status` is `fail`
|
|
13328
|
+
* AND `enforced` is true. Armed, not evaluated: fallow's default severity
|
|
13329
|
+
* rules fail a run with no flag at all, so an absent object means "no gate
|
|
13330
|
+
* was asked for", never "nothing failed". See [`crate::GateOutcomes`].
|
|
13331
|
+
*/
|
|
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)
|
|
12745
13343
|
/**
|
|
12746
13344
|
* Per-section `_meta` blocks, when `--explain` was passed.
|
|
12747
13345
|
*/
|
|
@@ -12801,6 +13399,22 @@ export interface FeatureFlagsOutput {
|
|
|
12801
13399
|
schema_version: FeatureFlagsSchemaVersion
|
|
12802
13400
|
version: ToolVersion
|
|
12803
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)
|
|
12804
13418
|
/**
|
|
12805
13419
|
* Detected feature-flag findings.
|
|
12806
13420
|
*/
|
|
@@ -14137,6 +14751,22 @@ invalid_value?: (string | null)
|
|
|
14137
14751
|
*/
|
|
14138
14752
|
export interface SuppressionInventoryOutput {
|
|
14139
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)
|
|
14140
14770
|
summary: SuppressionInventorySummary
|
|
14141
14771
|
/**
|
|
14142
14772
|
* Per-file suppression listings, sorted by path then line.
|
|
@@ -15283,3 +15913,8 @@ export type UnusedDependency = UnusedDependencyFinding | UnusedDevDependencyFind
|
|
|
15283
15913
|
* this alias; new code should narrow on the specific wrapper variant.
|
|
15284
15914
|
*/
|
|
15285
15915
|
export type UnusedMember = UnusedClassMemberFinding | UnusedEnumMemberFinding | UnusedStoreMemberFinding;
|
|
15916
|
+
|
|
15917
|
+
/**
|
|
15918
|
+
* @deprecated Renamed to BaselineStaleness in 3.27.0, when dead-code and dupes started carrying the same shape. The members are unchanged.
|
|
15919
|
+
*/
|
|
15920
|
+
export type HealthBaselineStaleness = BaselineStaleness;
|