fallow 3.18.0 → 3.19.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 +139 -4
- package/package.json +11 -10
- package/schema.json +39 -0
- package/scripts/lazy-verify.js +4 -5
- package/scripts/lazy-verify.test.js +9 -5
- package/scripts/verify-binary.js +10 -9
- package/scripts/verify-binary.test.js +6 -6
- package/skills/fallow/SKILL.md +12 -8
- package/skills/fallow/references/cli-reference.md +69 -1
- package/skills/fallow/references/gotchas.md +1 -1
- package/skills/fallow/references/mcp.md +23 -4
- package/skills/fallow/references/node-bindings.md +3 -2
- package/skills/fallow/references/similar-code.md +47 -0
- package/types/output-contract.d.ts +647 -26
package/README.md
CHANGED
|
@@ -89,7 +89,7 @@ The bundled `fallow-mcp` server lives in `node_modules/.bin/` when installed as
|
|
|
89
89
|
}
|
|
90
90
|
```
|
|
91
91
|
|
|
92
|
-
Swap `npx` for `pnpm exec` or `yarn` to match your package manager; a globally installed `fallow-mcp` works as `"command": "fallow-mcp"` directly. See the [MCP integration guide](https://docs.fallow.tools/integrations/mcp).
|
|
92
|
+
Swap `npx` for `pnpm exec` or `yarn` to match your package manager; a globally installed `fallow-mcp` works as `"command": "fallow-mcp"` directly. See the [MCP integration guide](https://docs.fallow.tools/integrations/mcp). `npx fallow agent install` writes this registration for you, together with the skill, an `AGENTS.md` task map, and the commit/push gate, for every harness it detects (Claude Code, Codex, Cursor); `--dry-run` shows the plan first.
|
|
93
93
|
|
|
94
94
|
The package also ships a version-matched agent skill under `skills/fallow`, and `fallow/capabilities.json` mirrors `fallow schema` for tools that need CLI and issue-surface metadata without spawning the binary. TanStack Intent discovers both from `node_modules`:
|
|
95
95
|
|
package/capabilities.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "fallow",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.19.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": [
|
|
@@ -906,6 +906,36 @@
|
|
|
906
906
|
"description": "Inspect the optional TypeScript semantic companion",
|
|
907
907
|
"flags": []
|
|
908
908
|
},
|
|
909
|
+
{
|
|
910
|
+
"name": "similar-code",
|
|
911
|
+
"description": "Find semantically similar functions with a pinned local model (opt-in)",
|
|
912
|
+
"flags": [
|
|
913
|
+
{
|
|
914
|
+
"name": "--threshold",
|
|
915
|
+
"type": "string",
|
|
916
|
+
"required": false,
|
|
917
|
+
"description": "Minimum cosine similarity retained as an unverified candidate"
|
|
918
|
+
},
|
|
919
|
+
{
|
|
920
|
+
"name": "--min-lines",
|
|
921
|
+
"type": "string",
|
|
922
|
+
"required": false,
|
|
923
|
+
"description": "Minimum source lines per extracted function"
|
|
924
|
+
},
|
|
925
|
+
{
|
|
926
|
+
"name": "--top",
|
|
927
|
+
"type": "string",
|
|
928
|
+
"required": false,
|
|
929
|
+
"description": "Cap displayed candidates after bounded full-corpus comparison"
|
|
930
|
+
},
|
|
931
|
+
{
|
|
932
|
+
"name": "--file",
|
|
933
|
+
"type": "string",
|
|
934
|
+
"required": false,
|
|
935
|
+
"description": "Report pairs touching one of these project-relative files"
|
|
936
|
+
}
|
|
937
|
+
]
|
|
938
|
+
},
|
|
909
939
|
{
|
|
910
940
|
"name": "inspect",
|
|
911
941
|
"description": "Inspect one file or exported symbol as a bundled evidence query",
|
|
@@ -1075,6 +1105,11 @@
|
|
|
1075
1105
|
"description": "Install or remove fallow-managed Git and agent hooks",
|
|
1076
1106
|
"flags": []
|
|
1077
1107
|
},
|
|
1108
|
+
{
|
|
1109
|
+
"name": "agent",
|
|
1110
|
+
"description": "Wire fallow into the coding-agent harnesses used by this project in one pass (AGENTS.md task map, skill, MCP server, commit/push gate), or show and remove what was installed. `fallow init --agents` and `fallow hooks install --target agent` remain the single-piece commands underneath",
|
|
1111
|
+
"flags": []
|
|
1112
|
+
},
|
|
1078
1113
|
{
|
|
1079
1114
|
"name": "ci",
|
|
1080
1115
|
"description": "CI helpers for PR/MR feedback envelopes",
|
|
@@ -6475,7 +6510,7 @@
|
|
|
6475
6510
|
},
|
|
6476
6511
|
"mcp_tools": {
|
|
6477
6512
|
"server": "fallow-mcp",
|
|
6478
|
-
"note": "key_params is a curated subset; the live MCP input schemas (
|
|
6513
|
+
"note": "key_params is a curated subset; the live MCP input schemas (tools/list) are authoritative for the full parameter list. cli_command is the nearest CLI fallback, not a full MCP input-schema projection",
|
|
6479
6514
|
"tools": [
|
|
6480
6515
|
{
|
|
6481
6516
|
"name": "code_execute",
|
|
@@ -6537,6 +6572,35 @@
|
|
|
6537
6572
|
"license_note": null,
|
|
6538
6573
|
"read_only": true
|
|
6539
6574
|
},
|
|
6575
|
+
{
|
|
6576
|
+
"name": "find_similar_code",
|
|
6577
|
+
"kind": "analysis",
|
|
6578
|
+
"description": "Find unverified semantically similar function candidates with the exact pinned local model",
|
|
6579
|
+
"cli_command": "fallow similar-code --format json --quiet",
|
|
6580
|
+
"key_params": [
|
|
6581
|
+
"threshold",
|
|
6582
|
+
"min_lines",
|
|
6583
|
+
"top",
|
|
6584
|
+
"changed_since",
|
|
6585
|
+
"paths"
|
|
6586
|
+
],
|
|
6587
|
+
"license": "free",
|
|
6588
|
+
"license_note": null,
|
|
6589
|
+
"read_only": true
|
|
6590
|
+
},
|
|
6591
|
+
{
|
|
6592
|
+
"name": "inspect_similar_code",
|
|
6593
|
+
"kind": "trace",
|
|
6594
|
+
"description": "Inspect one exact candidate snapshot without rerunning retrieval or global ranking",
|
|
6595
|
+
"cli_command": "fallow similar-code inspect <candidate-id> --candidates <report.json> --format json --quiet",
|
|
6596
|
+
"key_params": [
|
|
6597
|
+
"candidate_id",
|
|
6598
|
+
"snapshot"
|
|
6599
|
+
],
|
|
6600
|
+
"license": "free",
|
|
6601
|
+
"license_note": null,
|
|
6602
|
+
"read_only": true
|
|
6603
|
+
},
|
|
6540
6604
|
{
|
|
6541
6605
|
"name": "inspect_target",
|
|
6542
6606
|
"kind": "analysis",
|
|
@@ -6672,7 +6736,7 @@
|
|
|
6672
6736
|
{
|
|
6673
6737
|
"name": "get_token_blast_radius",
|
|
6674
6738
|
"kind": "analysis",
|
|
6675
|
-
"description": "Design-token blast radius for Tailwind v4 @theme tokens AND CSS-in-JS defineVars/createTheme-family token definitions: per token, a consumer_count (static lower bound) and a capped located consumers[] sample tagged theme-var/css-var/utility/apply (Tailwind)
|
|
6739
|
+
"description": "Design-token blast radius for Tailwind v4 @theme tokens AND CSS-in-JS defineVars/createTheme-family token definitions: per token, a consumer_count (static lower bound) and a capped located consumers[] sample tagged theme-var/css-var/utility/apply (Tailwind), js-member (CSS-in-JS member access), or js-call (StyleX theme-group and Panda token calls); descriptive context for sizing a token change, never a deletion gate",
|
|
6676
6740
|
"cli_command": "fallow health --css --format json --quiet",
|
|
6677
6741
|
"key_params": [],
|
|
6678
6742
|
"license": "free",
|
|
@@ -6934,8 +6998,78 @@
|
|
|
6934
6998
|
}
|
|
6935
6999
|
]
|
|
6936
7000
|
},
|
|
7001
|
+
"mcp_resources": {
|
|
7002
|
+
"server": "fallow-mcp",
|
|
7003
|
+
"note": "Read-only reference material served in-process by fallow-mcp; every JSON payload carries fallow_version. Rows with template: true are RFC 6570 URI templates listed under resources/templates/list; the catalogue is static, so the server declares neither subscribe nor listChanged",
|
|
7004
|
+
"resources": [
|
|
7005
|
+
{
|
|
7006
|
+
"uri": "fallow://tools",
|
|
7007
|
+
"name": "tools",
|
|
7008
|
+
"title": "Tool manifest",
|
|
7009
|
+
"description": "MCP tool manifest: name, kind, one-line description, nearest CLI fallback, key params, license, and read-only flag for every tool",
|
|
7010
|
+
"mime_type": "application/json",
|
|
7011
|
+
"template": false
|
|
7012
|
+
},
|
|
7013
|
+
{
|
|
7014
|
+
"uri": "fallow://issue-types",
|
|
7015
|
+
"name": "issue-types",
|
|
7016
|
+
"title": "Issue type registry",
|
|
7017
|
+
"description": "Every issue type with its command, category, config key, zero-config default severity, opt-in flag, fixable flag, docs URL, and explain resource URI",
|
|
7018
|
+
"mime_type": "application/json",
|
|
7019
|
+
"template": false
|
|
7020
|
+
},
|
|
7021
|
+
{
|
|
7022
|
+
"uri": "fallow://explain",
|
|
7023
|
+
"name": "explain",
|
|
7024
|
+
"title": "Explain index",
|
|
7025
|
+
"description": "Index of every explainable issue type with its one-line summary and the fallow://explain/{issue_type} URI to read",
|
|
7026
|
+
"mime_type": "application/json",
|
|
7027
|
+
"template": false
|
|
7028
|
+
},
|
|
7029
|
+
{
|
|
7030
|
+
"uri": "fallow://task-matrix",
|
|
7031
|
+
"name": "task-matrix",
|
|
7032
|
+
"title": "Agent task matrix",
|
|
7033
|
+
"description": "Agent task-to-command matrix: which read-only fallow command to run before deleting, refactoring, committing, or scoping work",
|
|
7034
|
+
"mime_type": "application/json",
|
|
7035
|
+
"template": false
|
|
7036
|
+
},
|
|
7037
|
+
{
|
|
7038
|
+
"uri": "fallow://schema/config",
|
|
7039
|
+
"name": "schema-config",
|
|
7040
|
+
"title": "Config JSON Schema",
|
|
7041
|
+
"description": "JSON Schema of the fallow config file (same document as fallow config-schema)",
|
|
7042
|
+
"mime_type": "application/json",
|
|
7043
|
+
"template": false
|
|
7044
|
+
},
|
|
7045
|
+
{
|
|
7046
|
+
"uri": "fallow://schema/plugin",
|
|
7047
|
+
"name": "schema-plugin",
|
|
7048
|
+
"title": "Plugin JSON Schema",
|
|
7049
|
+
"description": "JSON Schema of a user-authored external plugin (same document as fallow plugin-schema)",
|
|
7050
|
+
"mime_type": "application/json",
|
|
7051
|
+
"template": false
|
|
7052
|
+
},
|
|
7053
|
+
{
|
|
7054
|
+
"uri": "fallow://schema/rule-pack",
|
|
7055
|
+
"name": "schema-rule-pack",
|
|
7056
|
+
"title": "Rule pack JSON Schema",
|
|
7057
|
+
"description": "JSON Schema of a declarative rule pack (same document as fallow rule-pack-schema)",
|
|
7058
|
+
"mime_type": "application/json",
|
|
7059
|
+
"template": false
|
|
7060
|
+
},
|
|
7061
|
+
{
|
|
7062
|
+
"uri": "fallow://explain/{issue_type}",
|
|
7063
|
+
"name": "explain-issue-type",
|
|
7064
|
+
"title": "Explain one issue type",
|
|
7065
|
+
"description": "Explain document for one issue type (same payload as fallow explain <issue-type> --format json): name, summary, rationale, example, fix guidance, docs URL. issue_type accepts the bare id (unused-export), the namespaced id (fallow/unused-export), or the CLI filter spelling; see fallow://explain for the index",
|
|
7066
|
+
"mime_type": "application/json",
|
|
7067
|
+
"template": true
|
|
7068
|
+
}
|
|
7069
|
+
]
|
|
7070
|
+
},
|
|
6937
7071
|
"plugins": {
|
|
6938
|
-
"count":
|
|
7072
|
+
"count": 124,
|
|
6939
7073
|
"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",
|
|
6940
7074
|
"names": [
|
|
6941
7075
|
"nextjs",
|
|
@@ -7043,6 +7177,7 @@
|
|
|
7043
7177
|
"lint-staged",
|
|
7044
7178
|
"lefthook",
|
|
7045
7179
|
"simple-git-hooks",
|
|
7180
|
+
"size-limit",
|
|
7046
7181
|
"svgo",
|
|
7047
7182
|
"svgr",
|
|
7048
7183
|
"graphql-codegen",
|
package/package.json
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "fallow",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.19.0",
|
|
4
|
+
"mcpName": "io.github.fallow-rs/fallow",
|
|
4
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.",
|
|
5
6
|
"license": "MIT",
|
|
6
7
|
"repository": {
|
|
@@ -87,14 +88,14 @@
|
|
|
87
88
|
"@tanstack/intent": "0.3.6"
|
|
88
89
|
},
|
|
89
90
|
"optionalDependencies": {
|
|
90
|
-
"@fallow-cli/darwin-arm64": "3.
|
|
91
|
-
"@fallow-cli/darwin-x64": "3.
|
|
92
|
-
"@fallow-cli/linux-x64-gnu": "3.
|
|
93
|
-
"@fallow-cli/linux-arm64-gnu": "3.
|
|
94
|
-
"@fallow-cli/linux-x64-musl": "3.
|
|
95
|
-
"@fallow-cli/linux-arm64-musl": "3.
|
|
96
|
-
"@fallow-cli/win32-arm64-msvc": "3.
|
|
97
|
-
"@fallow-cli/win32-x64-msvc": "3.
|
|
98
|
-
"fallow-type-aware": "3.
|
|
91
|
+
"@fallow-cli/darwin-arm64": "3.19.0",
|
|
92
|
+
"@fallow-cli/darwin-x64": "3.19.0",
|
|
93
|
+
"@fallow-cli/linux-x64-gnu": "3.19.0",
|
|
94
|
+
"@fallow-cli/linux-arm64-gnu": "3.19.0",
|
|
95
|
+
"@fallow-cli/linux-x64-musl": "3.19.0",
|
|
96
|
+
"@fallow-cli/linux-arm64-musl": "3.19.0",
|
|
97
|
+
"@fallow-cli/win32-arm64-msvc": "3.19.0",
|
|
98
|
+
"@fallow-cli/win32-x64-msvc": "3.19.0",
|
|
99
|
+
"fallow-type-aware": "3.19.0"
|
|
99
100
|
}
|
|
100
101
|
}
|
package/schema.json
CHANGED
|
@@ -143,6 +143,15 @@
|
|
|
143
143
|
"minCorpusSizeForTokenCache": 5000
|
|
144
144
|
}
|
|
145
145
|
},
|
|
146
|
+
"similarCode": {
|
|
147
|
+
"description": "Configures the explicit local `similar-code` candidate workflow:\n`threshold` (0.80, model-specific cosine floor), `minLines` (3), and\nadditional `ignore` globs. Provider identity, setup, executables,\nendpoints, credentials, and consent cannot be set by project config.",
|
|
148
|
+
"$ref": "#/$defs/SimilarCodeConfig",
|
|
149
|
+
"default": {
|
|
150
|
+
"threshold": 0.8,
|
|
151
|
+
"minLines": 3,
|
|
152
|
+
"ignore": []
|
|
153
|
+
}
|
|
154
|
+
},
|
|
146
155
|
"health": {
|
|
147
156
|
"description": "Sets complexity and health thresholds for `fallow health` (also applied in combined `fallow` and `fallow audit`): `maxCyclomatic` (20), `maxCognitive` (15), `maxCrap` (30.0, findings at or above this are reported), `crapRefactorBand` (5, cyclomatic band below `maxCyclomatic` where a secondary refactor action is added), `maxUnitSize` (max function lines before a large-function finding, 60), `coverage`/`coverageRoot` (Istanbul coverage path and path-prefix strip for accurate CRAP), `ignore` globs (remove files from findings AND the health score), `thresholdOverrides` (per-file/per-function ceilings via `files`/`functions`/`maxCyclomatic`/`maxCognitive`/`maxCrap`/`maxUnitSize`/`reason`), `ownership` (`botPatterns` and `emailMode` for `--ownership`), and `suggestInlineSuppression` (true, emit `suppress-line` action hints in JSON). Raise thresholds to relax which functions are flagged, wire `coverage` for real CRAP scores, or exempt generated/test files via `ignore` (drops them from the score too) or `thresholdOverrides` (keeps them visible under a higher ceiling). The four `max*` thresholds govern findings only and never move `health_score`: its penalties use fixed calibration so grades stay comparable across projects, and `ignore` is the lever that removes files from the score.",
|
|
148
157
|
"$ref": "#/$defs/HealthConfig",
|
|
@@ -986,6 +995,36 @@
|
|
|
986
995
|
}
|
|
987
996
|
}
|
|
988
997
|
},
|
|
998
|
+
"SimilarCodeConfig": {
|
|
999
|
+
"description": "Project-owned tuning for the explicit `fallow similar-code` workflow.\n\nProvider identity, executable discovery, model setup, credentials, and\nconsent are intentionally absent. Project configuration cannot select code\ndestinations or authorize model downloads.",
|
|
1000
|
+
"type": "object",
|
|
1001
|
+
"properties": {
|
|
1002
|
+
"threshold": {
|
|
1003
|
+
"description": "Minimum model-specific cosine similarity retained as an unverified\ncandidate. It is not a probability or refactor-safety verdict.",
|
|
1004
|
+
"type": "number",
|
|
1005
|
+
"format": "double",
|
|
1006
|
+
"minimum": 0.0,
|
|
1007
|
+
"maximum": 1.0,
|
|
1008
|
+
"default": 0.8
|
|
1009
|
+
},
|
|
1010
|
+
"minLines": {
|
|
1011
|
+
"description": "Minimum source line count for a function to enter model inference.",
|
|
1012
|
+
"type": "integer",
|
|
1013
|
+
"format": "uint",
|
|
1014
|
+
"minimum": 1,
|
|
1015
|
+
"default": 3
|
|
1016
|
+
},
|
|
1017
|
+
"ignore": {
|
|
1018
|
+
"description": "Additional project-root-relative globs excluded only from similar-code\nextraction. Global `ignorePatterns` remain authoritative first.",
|
|
1019
|
+
"type": "array",
|
|
1020
|
+
"items": {
|
|
1021
|
+
"type": "string"
|
|
1022
|
+
},
|
|
1023
|
+
"default": []
|
|
1024
|
+
}
|
|
1025
|
+
},
|
|
1026
|
+
"additionalProperties": false
|
|
1027
|
+
},
|
|
989
1028
|
"HealthConfig": {
|
|
990
1029
|
"description": "Configuration for complexity health metrics (`fallow health`).",
|
|
991
1030
|
"type": "object",
|
package/scripts/lazy-verify.js
CHANGED
|
@@ -29,7 +29,7 @@ const { verifyInstalledSync, SKIP_ENV } = require("./verify-binary");
|
|
|
29
29
|
// Bumped to 2 when SHA-256 + platformPkgDir binding landed (closes the
|
|
30
30
|
// cross-install reuse gap in the shared $XDG fallback cache). v1 sentinels
|
|
31
31
|
// without these fields are invalidated automatically.
|
|
32
|
-
const SENTINEL_SCHEMA_VERSION =
|
|
32
|
+
const SENTINEL_SCHEMA_VERSION = 3;
|
|
33
33
|
const VERIFY_LOG_ENV = "FALLOW_VERIFY_LOG";
|
|
34
34
|
|
|
35
35
|
// One-shot warning state: each warning class fires once per process,
|
|
@@ -66,11 +66,10 @@ function emitVerifyLog(env, payload) {
|
|
|
66
66
|
}
|
|
67
67
|
|
|
68
68
|
function binaryTargetsForPlatform(platform) {
|
|
69
|
-
//
|
|
70
|
-
//
|
|
71
|
-
// is only one binary to sentinel-track and verify.
|
|
69
|
+
// Track every executable the multicall CLI may launch without another
|
|
70
|
+
// wrapper verification boundary.
|
|
72
71
|
const ext = platform === "win32" ? ".exe" : "";
|
|
73
|
-
return [`fallow${ext}`];
|
|
72
|
+
return [`fallow${ext}`, `fallow-similar-code${ext}`];
|
|
74
73
|
}
|
|
75
74
|
|
|
76
75
|
function statMtimeMs(absPath) {
|
|
@@ -31,8 +31,8 @@ function packageNameForPlatform(platform) {
|
|
|
31
31
|
}
|
|
32
32
|
|
|
33
33
|
function binaryNames(platform) {
|
|
34
|
-
|
|
35
|
-
return [
|
|
34
|
+
const ext = platform === "win32" ? ".exe" : "";
|
|
35
|
+
return [`fallow${ext}`, `fallow-similar-code${ext}`];
|
|
36
36
|
}
|
|
37
37
|
|
|
38
38
|
function computeDigestsForDir(dir, platform) {
|
|
@@ -123,7 +123,7 @@ test("ensureVerified verifies on cache miss and writes the sentinel", (t) => {
|
|
|
123
123
|
assert.equal(sentinel.schemaVersion, SENTINEL_SCHEMA_VERSION);
|
|
124
124
|
assert.equal(sentinel.packageVersion, "2.81.0");
|
|
125
125
|
assert.equal(sentinel.packageName, "@fallow-cli/test-platform");
|
|
126
|
-
assert.equal(Object.keys(sentinel.binaries).length,
|
|
126
|
+
assert.equal(Object.keys(sentinel.binaries).length, 2);
|
|
127
127
|
});
|
|
128
128
|
|
|
129
129
|
test("ensureVerified verifies and caches a win32 executable on any host", (t) => {
|
|
@@ -139,7 +139,7 @@ test("ensureVerified verifies and caches a win32 executable on any host", (t) =>
|
|
|
139
139
|
assert.equal(verified.ok, true);
|
|
140
140
|
assert.equal(verified.cached, false);
|
|
141
141
|
const sentinel = JSON.parse(fs.readFileSync(verified.sentinelPath, "utf8"));
|
|
142
|
-
assert.deepEqual(Object.keys(sentinel.binaries), ["fallow.exe"]);
|
|
142
|
+
assert.deepEqual(Object.keys(sentinel.binaries), ["fallow.exe", "fallow-similar-code.exe"]);
|
|
143
143
|
|
|
144
144
|
const cached = ensureVerified({
|
|
145
145
|
...input,
|
|
@@ -194,7 +194,11 @@ test("ensureVerified invalidates sentinel on mtime drift", (t) => {
|
|
|
194
194
|
);
|
|
195
195
|
assert.equal(result.ok, true);
|
|
196
196
|
assert.equal(result.cached, false);
|
|
197
|
-
assert.equal(
|
|
197
|
+
assert.equal(
|
|
198
|
+
verifyCallCount,
|
|
199
|
+
binaryNames(DEFAULT_PLATFORM).length,
|
|
200
|
+
"verify should rerun for every shipped binary",
|
|
201
|
+
);
|
|
198
202
|
});
|
|
199
203
|
|
|
200
204
|
test("ensureVerified invalidates sentinel on packageVersion drift", (t) => {
|
package/scripts/verify-binary.js
CHANGED
|
@@ -293,15 +293,16 @@ function binaryTargetsForPlatform(platformId) {
|
|
|
293
293
|
// and tests can synthesize a Windows verify without running on Windows.
|
|
294
294
|
const isWindows = typeof platformId === "string" && platformId.startsWith("win32");
|
|
295
295
|
const ext = isWindows ? ".exe" : "";
|
|
296
|
-
//
|
|
297
|
-
//
|
|
298
|
-
//
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
296
|
+
// The platform package ships the multicall CLI plus the local-only
|
|
297
|
+
// similar-code provider. Both are signed and digest-pinned. Verifying them
|
|
298
|
+
// together keeps the Rust sibling lookup free of project or PATH overrides.
|
|
299
|
+
return [
|
|
300
|
+
{ binary: `fallow${ext}`, asset: `fallow-${platformId}${ext}` },
|
|
301
|
+
{
|
|
302
|
+
binary: `fallow-similar-code${ext}`,
|
|
303
|
+
asset: `fallow-similar-code-${platformId}${ext}`,
|
|
304
|
+
},
|
|
305
|
+
];
|
|
305
306
|
}
|
|
306
307
|
|
|
307
308
|
function isSkipRequested() {
|
|
@@ -253,7 +253,7 @@ function makePlatformDir(privateKey, options) {
|
|
|
253
253
|
const opts = options || {};
|
|
254
254
|
const dir = fs.mkdtempSync(path.join(os.tmpdir(), "fallow-vbtest-"));
|
|
255
255
|
const ext = extForPlatformId(opts.platformId);
|
|
256
|
-
for (const base of ["fallow"]) {
|
|
256
|
+
for (const base of ["fallow", "fallow-similar-code"]) {
|
|
257
257
|
const binaryPath = path.join(dir, `${base}${ext}`);
|
|
258
258
|
const content = Buffer.from(`mock ${base} contents`);
|
|
259
259
|
fs.writeFileSync(binaryPath, content);
|
|
@@ -395,7 +395,7 @@ test("verifyInstalled resolves a global npm install from the fallow package dire
|
|
|
395
395
|
);
|
|
396
396
|
|
|
397
397
|
const ext = process.platform === "win32" ? ".exe" : "";
|
|
398
|
-
for (const base of ["fallow"]) {
|
|
398
|
+
for (const base of ["fallow", "fallow-similar-code"]) {
|
|
399
399
|
const binaryPath = path.join(platformDir, `${base}${ext}`);
|
|
400
400
|
const content = Buffer.from(`global install ${base}`);
|
|
401
401
|
fs.writeFileSync(binaryPath, content);
|
|
@@ -509,7 +509,7 @@ test("verifyInstalled honors FALLOW_SKIP_BINARY_VERIFY", async (t) => {
|
|
|
509
509
|
function computeDigestsForDir(dir, platformId) {
|
|
510
510
|
const ext = extForPlatformId(platformId);
|
|
511
511
|
const out = {};
|
|
512
|
-
for (const base of ["fallow"]) {
|
|
512
|
+
for (const base of ["fallow", "fallow-similar-code"]) {
|
|
513
513
|
const fileName = `${base}${ext}`;
|
|
514
514
|
const full = path.join(dir, fileName);
|
|
515
515
|
out[fileName] =
|
|
@@ -595,7 +595,7 @@ test("verifyInstalled falls back to the provider when the embedded digest is mis
|
|
|
595
595
|
},
|
|
596
596
|
});
|
|
597
597
|
assert.equal(result.ok, true);
|
|
598
|
-
assert.equal(providerCalls,
|
|
598
|
+
assert.equal(providerCalls, 2);
|
|
599
599
|
});
|
|
600
600
|
|
|
601
601
|
test("verifyInstalled falls back to the provider when fallowDigests is partial / malformed", async (t) => {
|
|
@@ -619,8 +619,8 @@ test("verifyInstalled falls back to the provider when fallowDigests is partial /
|
|
|
619
619
|
},
|
|
620
620
|
});
|
|
621
621
|
assert.equal(result.ok, true);
|
|
622
|
-
//
|
|
623
|
-
assert.equal(providerCalls,
|
|
622
|
+
// Both shipped binaries fall back because their embedded entries are absent or malformed.
|
|
623
|
+
assert.equal(providerCalls, 2);
|
|
624
624
|
});
|
|
625
625
|
|
|
626
626
|
test("verifyInstalled returns digest-mismatch when the embedded digest disagrees with the binary", async (t) => {
|
package/skills/fallow/SKILL.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: fallow
|
|
3
|
-
description: Codebase intelligence for TypeScript and JavaScript. Static analysis
|
|
3
|
+
description: Codebase intelligence for TypeScript and JavaScript. Static analysis reports changed-code risk, cleanup opportunities, duplication, circular dependencies, complexity hotspots, architecture boundaries, design-system drift, feature flags, and opt-in security candidates. Optional local similar-code discovery finds functions that may implement the same intent despite different syntax. Runtime coverage can merge production execution data. Use when asked to audit PR risk, find unused code or dependencies, compare semantically similar functions, detect duplicates, inspect architecture boundaries, merge runtime coverage, auto-fix supported issues, or run fallow.
|
|
4
4
|
license: MIT
|
|
5
5
|
---
|
|
6
6
|
|
|
@@ -11,6 +11,7 @@ Codebase intelligence for TypeScript and JavaScript. The static layer analyzes c
|
|
|
11
11
|
## When to Use
|
|
12
12
|
- Find cleanup opportunities: unused files, exports, types, members, dependencies, or stale flags.
|
|
13
13
|
- Detect code duplication, circular dependencies, architecture boundary issues, and complexity hotspots.
|
|
14
|
+
- Find functions that may implement the same intent despite different names, syntax, or control flow (`fallow similar-code`).
|
|
14
15
|
- Check styling consistency, CSS dead surface, and design-token drift.
|
|
15
16
|
- Audit changed code before a commit, PR, release, or refactor.
|
|
16
17
|
- Set up CI quality gates, duplication thresholds, and regression baselines.
|
|
@@ -31,7 +32,6 @@ Codebase intelligence for TypeScript and JavaScript. The static layer analyzes c
|
|
|
31
32
|
- Projects that are not JavaScript or TypeScript
|
|
32
33
|
|
|
33
34
|
## Prerequisites
|
|
34
|
-
|
|
35
35
|
Fallow must be installed. If not available, install it:
|
|
36
36
|
|
|
37
37
|
```bash
|
|
@@ -41,7 +41,6 @@ cargo install fallow-cli # build from source
|
|
|
41
41
|
```
|
|
42
42
|
|
|
43
43
|
## Agent Rules
|
|
44
|
-
|
|
45
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`.
|
|
46
45
|
2. **Preserve and interpret the exit status.** Codes 0 and 1 are successful analysis outcomes: 0 is clean and 1 means findings. 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.
|
|
47
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.
|
|
@@ -55,6 +54,8 @@ cargo install fallow-cli # build from source
|
|
|
55
54
|
11. **Never enable telemetry on the user's behalf**. Fallow's product telemetry is opt-in and off by default; only the user may run `fallow telemetry enable`. You MAY set `FALLOW_AGENT_SOURCE=<allowlisted-value>` (for example `claude_code`, `codex`, `cursor`, `windsurf`, `gemini`, `cline`) so that, IF the user has already enabled telemetry, your integration is correctly attributed. Setting `FALLOW_AGENT_SOURCE` never enables telemetry by itself and uploads no codebase content.
|
|
56
55
|
12. **Use type-aware analysis only for Fallow-owned project questions**. Reach for `--type-aware` to prove exact symbol use, preserve TypeScript class contracts, guard class-member cleanup, find cross-file private type leaks, suggest targeted tests, or inspect public-signature coupling. Keep `tsc --noEmit` responsible for compiler correctness and Oxlint responsible for local typed lint rules. Treat partial or unavailable semantic results as retained findings, never as deletion proof. Unknown external consumers of a published library remain outside checker-visible evidence, so preserve declared public API unless every relevant consumer project is explicitly in scope.
|
|
57
56
|
13. **Use `fallow impact statusline` only for a user-facing status surface**. It intentionally emits one plain-text, path-free line and ignores `--format`. It starts no analysis, never enables Impact, and compares only whole-project scans. Do not parse this line as JSON.
|
|
57
|
+
14. **Treat similar-code output as discovery only**. Never describe its score as a probability, finding, proof of equivalent behavior, or safe-refactor decision. Agents must not authorize setup. Inspect a candidate before judging it: save discovery as `similar-code.json`, inspect with `--candidates similar-code.json`, and pass the unchanged file to `fallow similar-code review`. Over MCP use `find_similar_code` with `paths:` and `inspect_similar_code` with a typed `snapshot`; it fails closed on stale source. Keep `candidate_worthy`, `behaviorally_equivalent`, and `refactor_safe` separate, use `needs-human-review`, and abstain when evidence is incomplete. Only `completion.status: "complete"` makes an empty result conclusive. Follow [the complete workflow to compare semantically similar functions](references/similar-code.md).
|
|
58
|
+
|
|
58
59
|
## Onboarding And Insight
|
|
59
60
|
Offer setup only after a human-requested analysis shows findings and all signals match: `fallow config --path` exits 3, not CI, not a pipeline format, `fallow impact --format json --quiet` has `onboarding_declined: false`, and no offer happened this session. Ask after showing value. Choices: guard commits and PRs, baseline the existing backlog and clean by category, add AGENTS.md guidance, or keep as-is. On decline, run `fallow init --decline --quiet` and stay silent for this project. Mutate only after consent. For guards, inspect `fallow hooks status --format json --quiet`, then use `fallow hooks install --target agent` and `fallow hooks install --target git`; for large backlogs, pair the gate with `--save-baseline` / new-only guidance. Offer `fallow impact enable` as local-only value tracking, never as telemetry; also offer it once on already-configured projects when `fallow impact status --format json` has `enabled: false` and `explicit_decision: false`, and record a no with `fallow impact disable --quiet`. Surface value on clear events: if the agent gate blocked a commit or push and a later retry succeeded, mention what was contained; when `next_steps` carries id `impact-report`, run its command and relay the non-zero numbers to the user in one line. On request, summarize non-zero Impact counts. Ask about telemetry only after such a win, only if `fallow telemetry status --format json` has `explicit_decision: false`, and never run `fallow telemetry enable`.
|
|
60
61
|
## Task Cheat Sheet
|
|
@@ -79,7 +80,6 @@ Route by intent before reaching for the big analysis commands. Same matrix as `f
|
|
|
79
80
|
<!-- generated:task-matrix:end -->
|
|
80
81
|
|
|
81
82
|
## Commands
|
|
82
|
-
|
|
83
83
|
<!-- generated:commands:start -->
|
|
84
84
|
| Command | Purpose | Key Flags |
|
|
85
85
|
|---|---|---|
|
|
@@ -87,11 +87,13 @@ Route by intent before reaching for the big analysis commands. Same matrix as `f
|
|
|
87
87
|
| `dead-code` | Dead code analysis (`check` is an alias) | `--unused-exports`, `--changed-since`, `--changed-workspaces`, `--production`, `--file`, `--include-entry-exports`, `--stale-suppressions`, `--ci`, `--group-by`, `--summary`, `--fail-on-regression`, `--tolerance`, `--regression-baseline`, `--save-regression-baseline` |
|
|
88
88
|
| `watch` | Watch for changes and re-run analysis | `--no-clear` |
|
|
89
89
|
| `type-aware` | Inspect the optional TypeScript semantic companion | |
|
|
90
|
+
| `similar-code` | Find semantically similar functions with a pinned local model (opt-in) | `--threshold`, `--min-lines`, `--top`, `--file` |
|
|
90
91
|
| `inspect` | Compose one evidence bundle for a file or exported symbol | `--file <path>`, `--symbol <file>:<export>` |
|
|
91
92
|
| `trace` | Trace a symbol's call chain (best-effort, syntactic; OFF the ranked path) | `symbol`, `--callers`, `--callees`, `--depth` |
|
|
92
93
|
| `fix` | Auto-remove unused exports/deps | `--dry-run`, `--yes` (required in non-TTY) |
|
|
93
94
|
| `init` | Generate config file, AGENTS.md agent guide, or pre-commit hook | `--toml`, `--agents`, `--hooks`, `--branch` |
|
|
94
95
|
| `hooks` | Inspect, install, or remove fallow-managed Git and agent hooks | `status`, `install --target git`, `install --target agent`, `uninstall --target git`, `uninstall --target agent` |
|
|
96
|
+
| `agent` | Wire fallow into Claude Code, Codex, or Cursor in one pass: AGENTS.md task map, skill, MCP server, commit/push gate; `status` and `uninstall` cover the same surfaces | `install --harness auto\|claude\|codex\|cursor`, `install --dry-run`, `install --approve`, `install --without <guide\|skill\|mcp\|hooks>`, `status`, `uninstall` |
|
|
95
97
|
| `ci` | CI helpers for PR/MR feedback envelopes | |
|
|
96
98
|
| `ci reconcile-review` | Resolve stale review threads on a PR/MR by joining a typed review envelope (`--format review-github` / `review-gitlab`) against the provider's existing comments + threads. Posts an idempotent "Resolved in `<sha>`" follow-up per stale fingerprint, marker keyed on (fingerprint, short-sha) so re-runs on the same commit don't duplicate. Provider mutations are fail-fast; JSON can include `apply_hint`, `failed_fingerprints`, and `unapplied_fingerprints` when `apply_errors` is non-empty. | `--provider`, `--pr` (GH) / `--mr` (GL), `--repo` / `--project-id`, `--api-url`, `--envelope`, `--dry-run` |
|
|
97
99
|
| `config-schema` | Print the JSON Schema for fallow configuration files | |
|
|
@@ -122,14 +124,13 @@ Route by intent before reaching for the big analysis commands. Same matrix as `f
|
|
|
122
124
|
| `telemetry` | Manage opt-in, off-by-default product telemetry (never collects code, paths, or names). Agents must not enable it; only the user may | `status`, `enable`, `disable`, `inspect --example` |
|
|
123
125
|
| `coverage` | Runtime coverage setup, focused analysis, and cloud inventory workflow helper | `setup`, `setup --yes`, `setup --non-interactive`, `analyze --runtime-coverage <path>`, `analyze --cloud --repo owner/repo`, `upload-inventory` |
|
|
124
126
|
| `coverage upload-source-maps` | Upload build source maps from CI so bundled runtime coverage resolves to original source paths. Retries 429 `Retry-After` and transient gateway failures. Use `FALLOW_CA_BUNDLE` for complete custom PEM trust bundles. | `--dir dist`, `--git-sha <sha>`, `--repo <name>`, `--strip-path=false`, `--dry-run` |
|
|
125
|
-
| `setup-hooks` |
|
|
127
|
+
| `setup-hooks` | Deprecated (removed in the next major): use `agent install` or `hooks install --target agent`; still installs the Claude Code PreToolUse gate with a stderr warning | `--agent`, `--dry-run`, `--force`, `--user`, `--gitignore-claude`, `--uninstall` |
|
|
126
128
|
| `viz` | Render the codebase as a self-contained interactive HTML map (treemap + import graph, four lenses: dead code, duplication, boundaries, complexity, with click-through detail panels), or emit the import graph as text. Read-only. | `--out <path>`, `--no-open`, `--viz-format html\|dot\|mermaid`, `--root`, `--config`, `--production`, `--no-cache` |
|
|
127
129
|
|
|
128
130
|
Run `fallow <command> --help` for the full flag list per command (see also references/cli-reference.md).
|
|
129
131
|
<!-- generated:commands:end -->
|
|
130
132
|
|
|
131
133
|
## Issue Types
|
|
132
|
-
|
|
133
134
|
<!-- generated:issue-types:start -->
|
|
134
135
|
| Type | Filter flag | Fixable | Suppress comment | Description |
|
|
135
136
|
|---|---|---|---|---|
|
|
@@ -204,13 +205,16 @@ Runtime-coverage verdicts and the full security sink catalogue are listed by `fa
|
|
|
204
205
|
|
|
205
206
|
Fallow ships an MCP server (`fallow-mcp`) that exposes these same analyses as agent tools. When the server is connected, its tools are already in your context with typed params and structured JSON returns, and each maps to a CLI fallback command. Prefer them when you want JSON without shelling out, or `code_execute` (Code Mode) to compose several read-only analyses in one sandboxed snippet (no single-call CLI equivalent). Otherwise use the CLI.
|
|
206
207
|
|
|
207
|
-
|
|
208
|
+
The server also serves read-only reference resources (no subprocess, no analysis run, cacheable by URI; your client reads them through its own resource tool): `fallow://tools`, `fallow://issue-types`, `fallow://explain/{issue_type}`, `fallow://task-matrix`, and the config, plugin, and rule-pack JSON Schemas. Every payload is JSON and carries `fallow_version`.
|
|
209
|
+
|
|
210
|
+
Full tool catalogue, resource catalogue, key params, runtime source-map confidence tiers, shared timeouts, and the `next_steps` dispatch mapping: **[references/mcp.md](references/mcp.md)**.
|
|
208
211
|
|
|
209
212
|
## References
|
|
210
213
|
- [CLI Reference](references/cli-reference.md): complete command and flag specifications, plus configuration field details
|
|
211
|
-
- [MCP Tools](references/mcp.md): MCP server tool
|
|
214
|
+
- [MCP Tools](references/mcp.md): MCP server tool and resource catalogues, CLI fallbacks, params, and agent dispatch guidance
|
|
212
215
|
- [Gotchas](references/gotchas.md): common pitfalls, edge cases, and correct usage patterns
|
|
213
216
|
- [Patterns](references/patterns.md): workflow recipes for CI, monorepos, migration, and incremental adoption
|
|
217
|
+
- [Similar Code](references/similar-code.md): snapshot-stable discovery, inspection, and verdict workflow
|
|
214
218
|
- [Node Bindings](references/node-bindings.md): embed the analysis engine in a Node.js process via NAPI
|
|
215
219
|
|
|
216
220
|
## Common Workflows
|