fallow 3.36.0 → 3.37.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/README.md +1 -1
- package/capabilities.json +21 -7
- package/issue-registry.json +8 -4
- package/package.json +14 -11
- package/rule-pack-schema.json +264 -0
- package/schema.json +7 -0
- package/skills/fallow/SKILL.md +2 -2
- package/skills/fallow/references/cli-reference.md +11 -10
- package/skills/fallow/references/gotchas.md +2 -0
- package/types/output-contract.d.ts +59 -11
- package/scripts/lazy-verify.test.js +0 -564
- package/scripts/platform-package.test.js +0 -26
- package/scripts/run-binary.test.js +0 -293
- package/scripts/sentinel-path.test.js +0 -240
- package/scripts/verify-binary.test.js +0 -809
package/README.md
CHANGED
|
@@ -28,7 +28,7 @@ npx fallow fix --dry-run # Preview automatic cleanup
|
|
|
28
28
|
|
|
29
29
|
## Output and exit codes
|
|
30
30
|
|
|
31
|
-
Add `--format json --quiet` to any command for one typed JSON document on stdout. Exit code 1 means findings, not failure; 0
|
|
31
|
+
Add `--format json --quiet` to any command for one typed JSON document on stdout. Exit code 1 means findings, not failure; 0 means no enforced gate failed (or an audit pass or warn verdict). Bare `fallow` in a machine format exits 0 on findings unless you pass `--fail-on-issues`; 2 is a validation or runtime error, reported as a JSON error envelope rather than a stack trace. License, coverage setup, network, and security-gate workflows use additional documented codes; read `fallow schema.exit_codes` instead of suppressing the process status.
|
|
32
32
|
|
|
33
33
|
Parsing the output in TypeScript? Import the typed shapes, version-pinned to the CLI you install:
|
|
34
34
|
|
package/capabilities.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "fallow",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.37.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": [
|
|
@@ -1289,6 +1289,16 @@
|
|
|
1289
1289
|
"false"
|
|
1290
1290
|
]
|
|
1291
1291
|
},
|
|
1292
|
+
{
|
|
1293
|
+
"name": "--resume",
|
|
1294
|
+
"type": "bool",
|
|
1295
|
+
"required": false,
|
|
1296
|
+
"description": "Continue an interrupted or partial run: reuse the killed and confirmed survived mutants in its journal and run only the others. A journal of other inputs exits 2",
|
|
1297
|
+
"possible_values": [
|
|
1298
|
+
"true",
|
|
1299
|
+
"false"
|
|
1300
|
+
]
|
|
1301
|
+
},
|
|
1292
1302
|
{
|
|
1293
1303
|
"name": "paths",
|
|
1294
1304
|
"type": "string",
|
|
@@ -4536,9 +4546,11 @@
|
|
|
4536
4546
|
"sarif_rule_ids": [
|
|
4537
4547
|
"fallow/thin-wrapper"
|
|
4538
4548
|
],
|
|
4539
|
-
"codeclimate_check_names":
|
|
4549
|
+
"codeclimate_check_names": [
|
|
4550
|
+
"fallow/thin-wrapper"
|
|
4551
|
+
],
|
|
4540
4552
|
"ts_alias": null,
|
|
4541
|
-
"counts_in_total":
|
|
4553
|
+
"counts_in_total": true,
|
|
4542
4554
|
"fixable": false,
|
|
4543
4555
|
"suppressible": true,
|
|
4544
4556
|
"suppress_comment": "// fallow-ignore-next-line thin-wrapper",
|
|
@@ -4570,9 +4582,11 @@
|
|
|
4570
4582
|
"sarif_rule_ids": [
|
|
4571
4583
|
"fallow/duplicate-prop-shape"
|
|
4572
4584
|
],
|
|
4573
|
-
"codeclimate_check_names":
|
|
4585
|
+
"codeclimate_check_names": [
|
|
4586
|
+
"fallow/duplicate-prop-shape"
|
|
4587
|
+
],
|
|
4574
4588
|
"ts_alias": null,
|
|
4575
|
-
"counts_in_total":
|
|
4589
|
+
"counts_in_total": true,
|
|
4576
4590
|
"fixable": false,
|
|
4577
4591
|
"suppressible": true,
|
|
4578
4592
|
"suppress_comment": "// fallow-ignore-next-line duplicate-prop-shape",
|
|
@@ -6995,8 +7009,8 @@
|
|
|
6995
7009
|
"github-summary"
|
|
6996
7010
|
],
|
|
6997
7011
|
"exit_codes": {
|
|
6998
|
-
"0": "Success
|
|
6999
|
-
"1": "
|
|
7012
|
+
"0": "Success: no enforced gate failed. Bare fallow in a machine format (json, sarif, codeclimate, the GitHub formats, the comment and review formats) does not enforce findings without --fail-on-issues, so it exits 0 on findings. Read gate_outcomes: status \"fail\" with enforced false is a failing gate that did not set the exit code",
|
|
7013
|
+
"1": "An enforced gate failed, for example error-severity findings (per rules config, or --fail-on-issues promotes warn to error). This is an analysis result, not a tool failure",
|
|
7000
7014
|
"2": "Error (invalid config, invalid input, etc.). When --format json is active, errors are emitted as structured JSON on stdout: {\"error\": true, \"message\": \"...\", \"exit_code\": 2}",
|
|
7001
7015
|
"3": "Requested resource unavailable: config --path found no config, or a license is missing, invalid, or beyond its offline hard-fail window",
|
|
7002
7016
|
"4": "Runtime coverage sidecar is unavailable, unverifiable, protocol-incompatible, or terminated unexpectedly",
|
package/issue-registry.json
CHANGED
|
@@ -1939,9 +1939,11 @@
|
|
|
1939
1939
|
"sarif_rule_ids": [
|
|
1940
1940
|
"fallow/thin-wrapper"
|
|
1941
1941
|
],
|
|
1942
|
-
"codeclimate_check_names":
|
|
1942
|
+
"codeclimate_check_names": [
|
|
1943
|
+
"fallow/thin-wrapper"
|
|
1944
|
+
],
|
|
1943
1945
|
"ts_alias": null,
|
|
1944
|
-
"counts_in_total":
|
|
1946
|
+
"counts_in_total": true,
|
|
1945
1947
|
"fixable": false,
|
|
1946
1948
|
"suppressible": true,
|
|
1947
1949
|
"suppress_comment": "// fallow-ignore-next-line thin-wrapper",
|
|
@@ -1973,9 +1975,11 @@
|
|
|
1973
1975
|
"sarif_rule_ids": [
|
|
1974
1976
|
"fallow/duplicate-prop-shape"
|
|
1975
1977
|
],
|
|
1976
|
-
"codeclimate_check_names":
|
|
1978
|
+
"codeclimate_check_names": [
|
|
1979
|
+
"fallow/duplicate-prop-shape"
|
|
1980
|
+
],
|
|
1977
1981
|
"ts_alias": null,
|
|
1978
|
-
"counts_in_total":
|
|
1982
|
+
"counts_in_total": true,
|
|
1979
1983
|
"fixable": false,
|
|
1980
1984
|
"suppressible": true,
|
|
1981
1985
|
"suppress_comment": "// fallow-ignore-next-line duplicate-prop-shape",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "fallow",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.37.0",
|
|
4
4
|
"mcpName": "io.github.fallow-rs/fallow",
|
|
5
5
|
"description": "Codebase intelligence for TypeScript and JavaScript: health, complexity, duplication, architecture, styling drift, and unused code from one graph. CLI, LSP, and MCP server. Zero config for over 100 frameworks.",
|
|
6
6
|
"license": "MIT",
|
|
@@ -54,6 +54,7 @@
|
|
|
54
54
|
"./scripts/*": "./scripts/*",
|
|
55
55
|
"./skills/*": "./skills/*",
|
|
56
56
|
"./schema.json": "./schema.json",
|
|
57
|
+
"./rule-pack-schema.json": "./rule-pack-schema.json",
|
|
57
58
|
"./capabilities.json": "./capabilities.json",
|
|
58
59
|
"./issue-registry.json": "./issue-registry.json"
|
|
59
60
|
},
|
|
@@ -67,11 +68,13 @@
|
|
|
67
68
|
"files": [
|
|
68
69
|
"bin",
|
|
69
70
|
"scripts",
|
|
71
|
+
"!scripts/*.test.js",
|
|
70
72
|
"skills",
|
|
71
73
|
"!skills/_artifacts",
|
|
72
74
|
"types",
|
|
73
75
|
"README.md",
|
|
74
76
|
"schema.json",
|
|
77
|
+
"rule-pack-schema.json",
|
|
75
78
|
"capabilities.json",
|
|
76
79
|
"issue-registry.json"
|
|
77
80
|
],
|
|
@@ -86,17 +89,17 @@
|
|
|
86
89
|
"detect-libc": "2.1.2"
|
|
87
90
|
},
|
|
88
91
|
"devDependencies": {
|
|
89
|
-
"@tanstack/intent": "0.5.
|
|
92
|
+
"@tanstack/intent": "0.5.6"
|
|
90
93
|
},
|
|
91
94
|
"optionalDependencies": {
|
|
92
|
-
"@fallow-cli/darwin-arm64": "3.
|
|
93
|
-
"@fallow-cli/darwin-x64": "3.
|
|
94
|
-
"@fallow-cli/linux-x64-gnu": "3.
|
|
95
|
-
"@fallow-cli/linux-arm64-gnu": "3.
|
|
96
|
-
"@fallow-cli/linux-x64-musl": "3.
|
|
97
|
-
"@fallow-cli/linux-arm64-musl": "3.
|
|
98
|
-
"@fallow-cli/win32-arm64-msvc": "3.
|
|
99
|
-
"@fallow-cli/win32-x64-msvc": "3.
|
|
100
|
-
"fallow-type-aware": "3.
|
|
95
|
+
"@fallow-cli/darwin-arm64": "3.37.0",
|
|
96
|
+
"@fallow-cli/darwin-x64": "3.37.0",
|
|
97
|
+
"@fallow-cli/linux-x64-gnu": "3.37.0",
|
|
98
|
+
"@fallow-cli/linux-arm64-gnu": "3.37.0",
|
|
99
|
+
"@fallow-cli/linux-x64-musl": "3.37.0",
|
|
100
|
+
"@fallow-cli/linux-arm64-musl": "3.37.0",
|
|
101
|
+
"@fallow-cli/win32-arm64-msvc": "3.37.0",
|
|
102
|
+
"@fallow-cli/win32-x64-msvc": "3.37.0",
|
|
103
|
+
"fallow-type-aware": "3.37.0"
|
|
101
104
|
}
|
|
102
105
|
}
|
|
@@ -0,0 +1,264 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
+
"title": "RulePackDef",
|
|
4
|
+
"description": "A declarative rule pack loaded from a standalone JSON or JSONC file listed\nin the `rulePacks` config key.\n\nRule packs are pure data: loading a pack never executes project code. They\nencode project-specific policy (banned calls, banned imports, and\ncatalogue-backed banned effects) evaluated over fallow's static extraction\ndata, reporting as `policy-violation`\nfindings.\n\n```jsonc\n{\n \"$schema\": \"https://raw.githubusercontent.com/fallow-rs/fallow/main/rule-pack-schema.json\",\n \"version\": 1,\n \"name\": \"team-policy\",\n \"description\": \"House rules for the platform team\",\n \"rules\": [\n {\n \"id\": \"no-child-process\",\n \"kind\": \"banned-call\",\n \"callees\": [\"child_process.*\"],\n \"message\": \"Use the sandboxed runner instead.\",\n \"severity\": \"error\"\n },\n {\n \"id\": \"no-network\",\n \"kind\": \"banned-effect\",\n \"effects\": [\"network\"],\n \"message\": \"Keep this package side-effect free.\"\n },\n {\n \"id\": \"no-moment\",\n \"kind\": \"banned-import\",\n \"specifiers\": [\"moment\"],\n \"message\": \"Use date-fns.\"\n }\n ]\n}\n```",
|
|
5
|
+
"type": "object",
|
|
6
|
+
"properties": {
|
|
7
|
+
"version": {
|
|
8
|
+
"description": "Pack format version. Must be `1`; the field exists so future rule\nkinds can be added without breaking older fallow builds silently.",
|
|
9
|
+
"type": "integer",
|
|
10
|
+
"format": "uint32",
|
|
11
|
+
"minimum": 0
|
|
12
|
+
},
|
|
13
|
+
"name": {
|
|
14
|
+
"description": "Pack name, unique across all loaded packs. Must use only ASCII\nletters, digits, `.`, `_`, and `-` so `\"<pack>/<id>\"` is unambiguous in\noutput, baselines, and scoped suppression comments.",
|
|
15
|
+
"type": "string"
|
|
16
|
+
},
|
|
17
|
+
"description": {
|
|
18
|
+
"description": "Optional human description of the pack's intent.",
|
|
19
|
+
"type": [
|
|
20
|
+
"string",
|
|
21
|
+
"null"
|
|
22
|
+
]
|
|
23
|
+
},
|
|
24
|
+
"rules": {
|
|
25
|
+
"description": "The policy rules this pack enforces. Must be non-empty: an empty pack\nwould silently enforce nothing.",
|
|
26
|
+
"type": "array",
|
|
27
|
+
"items": {
|
|
28
|
+
"$ref": "#/$defs/RulePackRule"
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
},
|
|
32
|
+
"additionalProperties": false,
|
|
33
|
+
"required": [
|
|
34
|
+
"version",
|
|
35
|
+
"name",
|
|
36
|
+
"rules"
|
|
37
|
+
],
|
|
38
|
+
"$defs": {
|
|
39
|
+
"RulePackRule": {
|
|
40
|
+
"description": "One declarative policy rule inside a rule pack.\n\n`callees` applies only to `banned-call` rules; `specifiers` and\n`ignoreTypeOnly` apply only to `banned-import` rules; `effects` applies\nonly to `banned-effect` rules; `exports` applies only to `banned-export`\nrules. `allowedFiles` and `proofKinds` apply only to `gdp-proof-producer`\nrules. `zones` can scope any rule kind to files classified into one of the\nnamed boundary zones. Setting a field on the wrong kind is a load error\n(fail loud, never silently ignore policy).",
|
|
41
|
+
"type": "object",
|
|
42
|
+
"properties": {
|
|
43
|
+
"id": {
|
|
44
|
+
"description": "Rule id, unique within the pack. Must use only ASCII letters, digits,\n`.`, `_`, and `-` so `\"<pack>/<id>\"` is unambiguous in output,\nbaselines, and scoped suppression comments.",
|
|
45
|
+
"type": "string"
|
|
46
|
+
},
|
|
47
|
+
"kind": {
|
|
48
|
+
"description": "Which check this rule performs.",
|
|
49
|
+
"$ref": "#/$defs/RulePackRuleKind"
|
|
50
|
+
},
|
|
51
|
+
"callees": {
|
|
52
|
+
"description": "Callee patterns to ban (`banned-call` only). Matching is segment-aware\nand import-resolved, identical to `boundaries.calls.forbidden`:\n`child_process.*` covers `import { exec } from \"node:child_process\"`,\nthe bare specifier, and namespace/default imports; `fetch` matches only\nthe global `fetch`; a leading `*.member` matches any object.",
|
|
53
|
+
"type": "array",
|
|
54
|
+
"items": {
|
|
55
|
+
"type": "string"
|
|
56
|
+
}
|
|
57
|
+
},
|
|
58
|
+
"specifiers": {
|
|
59
|
+
"description": "Import specifiers to ban (`banned-import` only). Matched segment-aware\nagainst the RAW specifier: `moment` covers `moment` and\n`moment/locale/nl` but not `moment-timezone`. A trailing `/*` form,\nsuch as `@org/ui/*`, matches subpaths only (`@org/ui/internal`) and\nnot the package root (`@org/ui`). Aliased or rewritten specifiers\n(e.g. `npm:moment`) are not matched.",
|
|
60
|
+
"type": "array",
|
|
61
|
+
"items": {
|
|
62
|
+
"type": "string"
|
|
63
|
+
}
|
|
64
|
+
},
|
|
65
|
+
"effects": {
|
|
66
|
+
"description": "Effect classes to ban (`banned-effect` only). Effects are derived from\n`security_matchers.toml` catalogue rows and matched against captured\ncall sites after import-resolution canonicalization.",
|
|
67
|
+
"type": "array",
|
|
68
|
+
"items": {
|
|
69
|
+
"$ref": "#/$defs/EffectKind"
|
|
70
|
+
}
|
|
71
|
+
},
|
|
72
|
+
"exports": {
|
|
73
|
+
"description": "Export names to ban (`banned-export` only). `\"default\"` matches the\ndefault export; any other entry matches an exported name exactly; a\nsingle trailing `*` makes it a prefix match (`internal*`). No other\nglob syntax is supported. Re-exports are out of scope for this rule.",
|
|
74
|
+
"type": "array",
|
|
75
|
+
"items": {
|
|
76
|
+
"type": "string"
|
|
77
|
+
}
|
|
78
|
+
},
|
|
79
|
+
"allowedFiles": {
|
|
80
|
+
"description": "Project-root-relative globs allowed to call `@gdp-ts/core.defineProof`\n(`gdp-proof-producer` only). At least one pattern is required.\nA single `*` stays within one path segment; use `**` to match across directories.",
|
|
81
|
+
"type": "array",
|
|
82
|
+
"items": {
|
|
83
|
+
"type": "string"
|
|
84
|
+
}
|
|
85
|
+
},
|
|
86
|
+
"proofKinds": {
|
|
87
|
+
"description": "Exact literal proof labels checked by a `gdp-proof-producer` rule.\nEmpty or absent checks every recognized factory call, including calls\nwith dynamic labels. A nonempty list checks only static string labels.",
|
|
88
|
+
"type": "array",
|
|
89
|
+
"items": {
|
|
90
|
+
"type": "string"
|
|
91
|
+
}
|
|
92
|
+
},
|
|
93
|
+
"ignoreTypeOnly": {
|
|
94
|
+
"description": "When `true`, type-only imports (`import type ...` and type-only\nre-exports) are ignored by `banned-import`; type-only exports are\nignored by `banned-export`. Defaults to `false`: type-only sites are\nflagged too.",
|
|
95
|
+
"type": "boolean"
|
|
96
|
+
},
|
|
97
|
+
"files": {
|
|
98
|
+
"description": "Optional include globs (project-root-relative). Empty or absent means\nthe rule applies to every analyzed file.\nA single `*` stays within one path segment; use `**` to match across directories.",
|
|
99
|
+
"type": "array",
|
|
100
|
+
"items": {
|
|
101
|
+
"type": "string"
|
|
102
|
+
}
|
|
103
|
+
},
|
|
104
|
+
"exclude": {
|
|
105
|
+
"description": "Optional exclude globs (project-root-relative), applied after `files`.\nA single `*` stays within one path segment; use `**` to match across directories.",
|
|
106
|
+
"type": "array",
|
|
107
|
+
"items": {
|
|
108
|
+
"type": "string"
|
|
109
|
+
}
|
|
110
|
+
},
|
|
111
|
+
"zones": {
|
|
112
|
+
"description": "Optional boundary zones this rule applies to. Empty or absent means the\nrule applies regardless of zone; non-empty values require matching\nconfigured boundaries and combine with `files`/`exclude` as AND.",
|
|
113
|
+
"type": "array",
|
|
114
|
+
"items": {
|
|
115
|
+
"type": "string"
|
|
116
|
+
}
|
|
117
|
+
},
|
|
118
|
+
"message": {
|
|
119
|
+
"description": "Author-provided message naming the sanctioned alternative. Rendered\nnext to each finding.",
|
|
120
|
+
"type": [
|
|
121
|
+
"string",
|
|
122
|
+
"null"
|
|
123
|
+
]
|
|
124
|
+
},
|
|
125
|
+
"severity": {
|
|
126
|
+
"description": "Per-rule severity overriding the `rules.\"policy-violation\"` master.\n`off` disables this rule. When the master itself is `off`, the whole\nevaluator is disabled and per-rule severity cannot resurrect it.",
|
|
127
|
+
"anyOf": [
|
|
128
|
+
{
|
|
129
|
+
"$ref": "#/$defs/Severity"
|
|
130
|
+
},
|
|
131
|
+
{
|
|
132
|
+
"type": "null"
|
|
133
|
+
}
|
|
134
|
+
]
|
|
135
|
+
}
|
|
136
|
+
},
|
|
137
|
+
"additionalProperties": false,
|
|
138
|
+
"required": [
|
|
139
|
+
"id",
|
|
140
|
+
"kind"
|
|
141
|
+
]
|
|
142
|
+
},
|
|
143
|
+
"RulePackRuleKind": {
|
|
144
|
+
"description": "Which check a rule-pack rule performs.",
|
|
145
|
+
"oneOf": [
|
|
146
|
+
{
|
|
147
|
+
"description": "Ban call sites whose callee path matches one of `callees`.",
|
|
148
|
+
"type": "string",
|
|
149
|
+
"const": "banned-call"
|
|
150
|
+
},
|
|
151
|
+
{
|
|
152
|
+
"description": "Ban imports and re-exports whose raw specifier matches one of\n`specifiers`.",
|
|
153
|
+
"type": "string",
|
|
154
|
+
"const": "banned-import"
|
|
155
|
+
},
|
|
156
|
+
{
|
|
157
|
+
"description": "Ban call sites whose catalogue-derived effect matches one of `effects`.",
|
|
158
|
+
"type": "string",
|
|
159
|
+
"const": "banned-effect"
|
|
160
|
+
},
|
|
161
|
+
{
|
|
162
|
+
"description": "Ban exported names that match one of `exports`.",
|
|
163
|
+
"type": "string",
|
|
164
|
+
"const": "banned-export"
|
|
165
|
+
},
|
|
166
|
+
{
|
|
167
|
+
"description": "Restrict gdp-ts proof factory calls to explicitly allowed modules.",
|
|
168
|
+
"type": "string",
|
|
169
|
+
"const": "gdp-proof-producer"
|
|
170
|
+
}
|
|
171
|
+
]
|
|
172
|
+
},
|
|
173
|
+
"EffectKind": {
|
|
174
|
+
"description": "Internal side-effect taxonomy derived from security catalogue rows.",
|
|
175
|
+
"oneOf": [
|
|
176
|
+
{
|
|
177
|
+
"description": "No observable side effect.",
|
|
178
|
+
"type": "string",
|
|
179
|
+
"const": "pure"
|
|
180
|
+
},
|
|
181
|
+
{
|
|
182
|
+
"description": "Structured-data read/query evaluation (XML external entities, XPath).",
|
|
183
|
+
"type": "string",
|
|
184
|
+
"const": "read"
|
|
185
|
+
},
|
|
186
|
+
{
|
|
187
|
+
"description": "In-memory state mutation (mass assignment, prototype pollution).",
|
|
188
|
+
"type": "string",
|
|
189
|
+
"const": "write"
|
|
190
|
+
},
|
|
191
|
+
{
|
|
192
|
+
"description": "Network I/O (HTTP clients, request-forgery sinks).",
|
|
193
|
+
"type": "string",
|
|
194
|
+
"const": "network"
|
|
195
|
+
},
|
|
196
|
+
{
|
|
197
|
+
"description": "Filesystem access (path traversal, file permission changes).",
|
|
198
|
+
"type": "string",
|
|
199
|
+
"const": "storage"
|
|
200
|
+
},
|
|
201
|
+
{
|
|
202
|
+
"description": "In-process code evaluation (`eval`, `Function`, string timers).",
|
|
203
|
+
"type": "string",
|
|
204
|
+
"const": "process"
|
|
205
|
+
},
|
|
206
|
+
{
|
|
207
|
+
"description": "OS shell command execution.",
|
|
208
|
+
"type": "string",
|
|
209
|
+
"const": "shell"
|
|
210
|
+
},
|
|
211
|
+
{
|
|
212
|
+
"description": "Cryptographic primitives (weak algorithm or key usage).",
|
|
213
|
+
"type": "string",
|
|
214
|
+
"const": "crypto"
|
|
215
|
+
},
|
|
216
|
+
{
|
|
217
|
+
"description": "Random-number generation in security-sensitive contexts.",
|
|
218
|
+
"type": "string",
|
|
219
|
+
"const": "randomness"
|
|
220
|
+
},
|
|
221
|
+
{
|
|
222
|
+
"description": "DOM injection (`innerHTML`-style XSS sinks).",
|
|
223
|
+
"type": "string",
|
|
224
|
+
"const": "dom"
|
|
225
|
+
},
|
|
226
|
+
{
|
|
227
|
+
"description": "Database query execution (SQL/NoSQL injection sinks).",
|
|
228
|
+
"type": "string",
|
|
229
|
+
"const": "database"
|
|
230
|
+
},
|
|
231
|
+
{
|
|
232
|
+
"description": "Callback invoked by a framework rather than a direct effect.",
|
|
233
|
+
"type": "string",
|
|
234
|
+
"const": "framework-callback"
|
|
235
|
+
},
|
|
236
|
+
{
|
|
237
|
+
"description": "Effect the catalogue cannot classify.",
|
|
238
|
+
"type": "string",
|
|
239
|
+
"const": "unknown"
|
|
240
|
+
}
|
|
241
|
+
]
|
|
242
|
+
},
|
|
243
|
+
"Severity": {
|
|
244
|
+
"description": "Severity level for rules.\n\nControls whether an issue type sets a non-zero exit code (`error`), is\nreported without an effect on the exit code (`warn`), or is suppressed\nentirely (`off`). `--fail-on-issues` promotes `warn` to `error`. The\ndead-code count gate of the GitHub Action counts `warn` findings unless its\n`fail-on-issues` input is `false`.",
|
|
245
|
+
"oneOf": [
|
|
246
|
+
{
|
|
247
|
+
"description": "Report and set a non-zero exit code.",
|
|
248
|
+
"type": "string",
|
|
249
|
+
"const": "error"
|
|
250
|
+
},
|
|
251
|
+
{
|
|
252
|
+
"description": "Report without an effect on the exit code.",
|
|
253
|
+
"type": "string",
|
|
254
|
+
"const": "warn"
|
|
255
|
+
},
|
|
256
|
+
{
|
|
257
|
+
"description": "Don't detect or report.",
|
|
258
|
+
"type": "string",
|
|
259
|
+
"const": "off"
|
|
260
|
+
}
|
|
261
|
+
]
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
}
|
package/schema.json
CHANGED
|
@@ -357,6 +357,13 @@
|
|
|
357
357
|
},
|
|
358
358
|
"default": []
|
|
359
359
|
},
|
|
360
|
+
"markupExtensions": {
|
|
361
|
+
"description": "An array of file extensions, without the leading dot, for server-side template files whose text counts as CSS class references for the `unreferenced-css-class` finding of `fallow health --css`. These files are read as text only: they do not join source discovery or the module graph, so they never become unused files and their imports are not followed. Templates are more lenient than Markdown: the whole text of a template file counts as a dynamic class reference, so any class-like word in it counts as used, also a common word such as `hidden` or `title` in prose or a template tag. A Markdown file joins the reference text only when it has dynamic class syntax. The extensions `liquid`, `njk`, `hbs`, `handlebars`, `twig`, and `blade.php` are always read; set this (e.g. `[\"tpl\", \"erb\"]`) for other template languages. An extension matches the end of a file name, ignoring case, so `blade.php` matches `welcome.blade.php`. Values may contain only letters, digits, `.`, `-`, and `_`. A value whose last segment is a script, stylesheet, data or asset extension (`js`, `ts`, `css`, `json`, `svg`, `xml`, `map`, and similar, so also `module.css` or `d.ts`), or a compound value that ends in a markup extension that fallow already reads (`page.html`), is a config error. The walk uses the ignore files of source discovery (`.gitignore`, `.ignore`), skips `ignorePatterns`, `health.ignore`, `node_modules`, `vendor`, and build output directories, reads only regular files, and skips files over the `--max-file-size` limit. In `extends`, a child list replaces the parent list.",
|
|
362
|
+
"type": "array",
|
|
363
|
+
"items": {
|
|
364
|
+
"type": "string"
|
|
365
|
+
}
|
|
366
|
+
},
|
|
360
367
|
"overrides": {
|
|
361
368
|
"description": "An ordered list of per-file rule-severity overrides: each entry re-severities specific analysis rules for files its globs match, layered on top of the top-level `rules` defaults. Set to relax or tighten rules for a subset of paths (e.g. downgrade unused-exports to warn under a generated directory); each entry has `files` (glob-pattern array) and `rules` (a partial per-rule severity map of error/warn/off). Entries apply in list order and a file matched by several entries takes every matching entry's overrides (later entries win on conflict); inter-file rules (duplicate-exports, circular-dependencies, re-export-cycle) have no effect in an override (fallow warns during analysis and points to the right mechanism: top-level `ignoreExports` for duplicate-exports, a file-level `// fallow-ignore-file` comment for the others). A single `*` stays within one path segment; use `**` to match across directories.",
|
|
362
369
|
"type": "array",
|
package/skills/fallow/SKILL.md
CHANGED
|
@@ -42,7 +42,7 @@ cargo install fallow-cli # build from source
|
|
|
42
42
|
|
|
43
43
|
## Agent Rules
|
|
44
44
|
1. **Always use `--format json --quiet`** for machine-readable output and parse stdout as JSON. Compact JSON is the default; never depend on whitespace or add `--pretty` in agent pipelines. Keep stderr separate so diagnostics remain visible; never merge it into the JSON stream with `2>&1`.
|
|
45
|
-
2. **Preserve and interpret the exit status.** Codes 0 and 1 are successful analysis outcomes
|
|
45
|
+
2. **Preserve and interpret the exit status.** Codes 0 and 1 are successful analysis outcomes. 0 means no enforced gate failed, and 1 means an enforced gate failed: findings, not a tool failure. Bare `fallow` in a machine format exits 0 on findings unless you pass `--fail-on-issues`. To gate, pass `--fail-on-issues`, run `fallow dead-code` or `fallow audit`, or read `gate_outcomes`: `status: "fail"` with `enforced: false` is a failing gate that did not set the exit code. Treat every other code according to `fallow schema.exit_codes`. Do not force a successful status, because that hides validation, license, setup, network, and security-gate outcomes.
|
|
46
46
|
3. **Use `--explain`** to include a `_meta` object in JSON output with metric definitions, ranges, and interpretation hints. In human format, `--explain` prints a `Description:` line under each section header.
|
|
47
47
|
4. **Use the root `kind` field** to identify typed JSON envelopes (`dead-code`, `dead-code-grouped`, `architecture`, `architecture-grouped`, `health`, `dupes`, `combined`, `audit`, etc.).
|
|
48
48
|
5. **Use issue type filters** (`--unused-exports`, `--unused-files`, etc.) to limit output scope
|
|
@@ -375,7 +375,7 @@ fallow hooks install --target git # pre-commit gate; --branch <ref> sets the f
|
|
|
375
375
|
|
|
376
376
|
## Exit Codes
|
|
377
377
|
|
|
378
|
-
Codes 0 and 1 are successful analysis outcomes
|
|
378
|
+
Codes 0 and 1 are successful analysis outcomes. 0 means no enforced gate failed, and 1 means an enforced gate failed: findings, not a tool failure. Bare `fallow` in a machine format exits 0 on findings unless you pass `--fail-on-issues`. To gate, pass `--fail-on-issues`, run `fallow dead-code` or `fallow audit`, or read `gate_outcomes`: `status: "fail"` with `enforced: false` is a failing gate that did not set the exit code. Read `fallow schema.exit_codes` for validation, resource, runtime, network, security-gate, and upload failures instead of maintaining another copied table.
|
|
379
379
|
|
|
380
380
|
When `--format json` is active and exit code is 2, errors are emitted as JSON on stdout:
|
|
381
381
|
```json
|
|
@@ -526,7 +526,7 @@ Human output groups paths under "Shared with your team (commit these)" and "Loca
|
|
|
526
526
|
{
|
|
527
527
|
"kind": "agent-install",
|
|
528
528
|
"schema_version": 1,
|
|
529
|
-
"fallow_version": "3.
|
|
529
|
+
"fallow_version": "3.37.0",
|
|
530
530
|
"root": "/abs/path",
|
|
531
531
|
"mode": "install",
|
|
532
532
|
"dry_run": false,
|
|
@@ -737,7 +737,7 @@ fallow health --format json --quiet --trend
|
|
|
737
737
|
{
|
|
738
738
|
"kind": "health",
|
|
739
739
|
"schema_version": 7,
|
|
740
|
-
"version": "3.
|
|
740
|
+
"version": "3.37.0",
|
|
741
741
|
"elapsed_ms": 32,
|
|
742
742
|
"summary": {
|
|
743
743
|
"files_analyzed": 482,
|
|
@@ -1212,7 +1212,7 @@ fallow audit \
|
|
|
1212
1212
|
{
|
|
1213
1213
|
"kind": "audit",
|
|
1214
1214
|
"schema_version": 7,
|
|
1215
|
-
"version": "3.
|
|
1215
|
+
"version": "3.37.0",
|
|
1216
1216
|
"command": "audit",
|
|
1217
1217
|
"verdict": "fail",
|
|
1218
1218
|
"changed_files_count": 12,
|
|
@@ -1300,7 +1300,7 @@ fallow flags --format json --quiet --workspace my-package
|
|
|
1300
1300
|
```json
|
|
1301
1301
|
{
|
|
1302
1302
|
"schema_version": 7,
|
|
1303
|
-
"version": "3.
|
|
1303
|
+
"version": "3.37.0",
|
|
1304
1304
|
"elapsed_ms": 116,
|
|
1305
1305
|
"feature_flags": [],
|
|
1306
1306
|
"total_flags": 0
|
|
@@ -1401,7 +1401,7 @@ fallow security --gate newly-reachable --changed-since origin/main
|
|
|
1401
1401
|
{
|
|
1402
1402
|
"kind": "security",
|
|
1403
1403
|
"schema_version": "4",
|
|
1404
|
-
"version": "3.
|
|
1404
|
+
"version": "3.37.0",
|
|
1405
1405
|
"elapsed_ms": 42,
|
|
1406
1406
|
"config": {
|
|
1407
1407
|
"rules": {
|
|
@@ -1430,7 +1430,7 @@ fallow security --gate newly-reachable --changed-since origin/main
|
|
|
1430
1430
|
{
|
|
1431
1431
|
"kind": "security",
|
|
1432
1432
|
"schema_version": "4",
|
|
1433
|
-
"version": "3.
|
|
1433
|
+
"version": "3.37.0",
|
|
1434
1434
|
"elapsed_ms": 42,
|
|
1435
1435
|
"config": {
|
|
1436
1436
|
"rules": {
|
|
@@ -2245,7 +2245,7 @@ The HTTP layer mirrors the bash `gh_api_retry` / `curl_retry` helpers: `FALLOW_A
|
|
|
2245
2245
|
{
|
|
2246
2246
|
"kind": "dead-code",
|
|
2247
2247
|
"schema_version": 7,
|
|
2248
|
-
"version": "3.
|
|
2248
|
+
"version": "3.37.0",
|
|
2249
2249
|
"elapsed_ms": 45,
|
|
2250
2250
|
"total_issues": 12,
|
|
2251
2251
|
"entry_points": {
|
|
@@ -2405,7 +2405,7 @@ When `--baseline` is used in combined output, the JSON includes a `baseline_delt
|
|
|
2405
2405
|
{
|
|
2406
2406
|
"kind": "dupes",
|
|
2407
2407
|
"schema_version": 7,
|
|
2408
|
-
"version": "3.
|
|
2408
|
+
"version": "3.37.0",
|
|
2409
2409
|
"elapsed_ms": 82,
|
|
2410
2410
|
"total_clones": 15,
|
|
2411
2411
|
"total_lines_duplicated": 230,
|
|
@@ -2449,11 +2449,11 @@ When running `fallow` with no subcommand (all analyses), the JSON output combine
|
|
|
2449
2449
|
{
|
|
2450
2450
|
"kind": "combined",
|
|
2451
2451
|
"schema_version": 7,
|
|
2452
|
-
"version": "3.
|
|
2452
|
+
"version": "3.37.0",
|
|
2453
2453
|
"elapsed_ms": 159,
|
|
2454
2454
|
"check": {
|
|
2455
2455
|
"schema_version": 7,
|
|
2456
|
-
"version": "3.
|
|
2456
|
+
"version": "3.37.0",
|
|
2457
2457
|
"elapsed_ms": 45,
|
|
2458
2458
|
"total_issues": 12,
|
|
2459
2459
|
"unused_files": [],
|
|
@@ -2664,6 +2664,7 @@ preset = "bulletproof"
|
|
|
2664
2664
|
- `publicPackages`: workspace packages that are public libraries; exported API surface from these packages is not flagged as unused
|
|
2665
2665
|
- `entry`: glob patterns for files that are manual entry points. A single `*` stays within one path segment; use `**` to match across directories
|
|
2666
2666
|
- `dynamicallyLoaded`: glob patterns for files loaded at runtime (plugin dirs, locale files); treated as always-used. A single `*` stays within one path segment; use `**` to match across directories
|
|
2667
|
+
- `markupExtensions`: file extensions without the dot (for example `["tpl", "erb"]`) of server-side template files whose text counts as CSS class references for `unreferenced-css-class` in `fallow health --css`. `liquid`, `njk`, `hbs`, `handlebars`, `twig`, and `blade.php` are always read. Any class-like word in a template counts as used, so templates are more lenient than Markdown. These files never join discovery or the module graph. A value that ends in a script, stylesheet, data or asset extension (also `module.css` or `d.ts`) is a config error
|
|
2667
2668
|
- Path globs in other fields (`ignorePatterns`, `ignoreFindings`, `overrides[].files`, `ignoreExports[].file`, `duplicates.ignore`, `health.ignore`, boundary zones, rule-pack and `framework[]` globs) use the same rule: a single `*` stays within one path segment. Write `**/*.test.ts` to match test files at any depth
|
|
2668
2669
|
- `cache.dir`: override the persistent extraction cache directory. `FALLOW_CACHE_DIR` wins over this config field, and `--no-cache` disables caching entirely
|
|
2669
2670
|
- `cache.maxSizeMb`: cap the serialized extraction cache size in megabytes. `FALLOW_CACHE_MAX_SIZE` wins over this config field
|
|
@@ -181,6 +181,8 @@ Error-severity findings can trigger exit code 1. Default severity varies by rule
|
|
|
181
181
|
|
|
182
182
|
Exit code 1 always means that an enforced gate failed. A load warning or a workspace diagnostic (for example `node-modules-missing` or a tsconfig `extends` that does not resolve) never changes the exit code. The only exceptions are `source-parse-degraded` and `source-nesting-too-deep` with `--fail-on-parse-error`. To find the gate, read `gate_outcomes` in the JSON output and look for an entry with `status: "fail"` and `enforced: true`. Under `--quiet` and in every machine format, fallow also prints one stderr line that names the failed gates, for example `[X] Exit code 1: gate health-findings (3 at or above error) failed.` On `health`, the `complexity-*` rules default to `error`, so each complexity finding fails the run. Set them to `warn` or pass `--report-only` to report without a failure.
|
|
183
183
|
|
|
184
|
+
Bare `fallow` in a machine format (`json`, `sarif`, `codeclimate`, the GitHub formats, and the comment and review formats) exits 0 on findings. `fallow dead-code --format json` exits 1 on the same findings. The bare machine run reports only, because the GitHub Action and the GitLab template read its JSON output and not its exit code. Its `gate_outcomes` entries then have `status: "fail"` and `enforced: false`, and stderr has one line, also under `--quiet`, for example `[W] Exit code 0: gate error-severity-findings (2 at or above error) failed, but bare fallow does not enforce it in --format json. To exit 1 on it, pass --fail-on-issues.` To gate on a bare machine run, pass `--fail-on-issues` or `--ci`.
|
|
185
|
+
|
|
184
186
|
---
|
|
185
187
|
|
|
186
188
|
## `--fail-on-issues` Promotes Warn to Error
|