pi-lens 3.8.73 → 3.8.74
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/CHANGELOG.md +1116 -0
- package/README.md +37 -21
- package/dist/clients/atomic-write.js +3 -3
- package/dist/clients/bus-events-logger.js +5 -1
- package/dist/clients/cache/rule-cache.js +43 -2
- package/dist/clients/cache-observability.js +211 -0
- package/dist/clients/call-graph.js +20 -0
- package/dist/clients/cascade-logger.js +5 -1
- package/dist/clients/complexity-client.js +4 -7
- package/dist/clients/dependency-checker.js +151 -20
- package/dist/clients/diagnostic-dispositions.js +22 -2
- package/dist/clients/dispatch/auxiliary-lsp.js +34 -0
- package/dist/clients/dispatch/dispatcher.js +16 -1
- package/dist/clients/dispatch/fact-store.js +11 -0
- package/dist/clients/dispatch/facts/function-facts.js +14 -0
- package/dist/clients/dispatch/facts/import-facts.js +100 -101
- package/dist/clients/dispatch/facts/tree-sitter-facts.js +5 -8
- package/dist/clients/dispatch/facts/try-catch-facts.js +13 -0
- package/dist/clients/dispatch/integration.js +94 -15
- package/dist/clients/dispatch/rules/async-noise.js +1 -0
- package/dist/clients/dispatch/rules/unsafe-boundary.js +7 -0
- package/dist/clients/dispatch/runners/ast-grep-napi.js +24 -1
- package/dist/clients/dispatch/runners/psscriptanalyzer.js +10 -1
- package/dist/clients/dispatch/runners/tree-sitter.js +153 -166
- package/dist/clients/dispatch/runners/utils/runner-helpers.js +17 -18
- package/dist/clients/feature-hints.js +53 -7
- package/dist/clients/file-kinds.js +86 -31
- package/dist/clients/fix-worklog.js +14 -2
- package/dist/clients/generated-artifacts.js +21 -0
- package/dist/clients/gzip-stage-write.js +84 -0
- package/dist/clients/installer/index.js +358 -129
- package/dist/clients/knip-client.js +64 -1
- package/dist/clients/language-profile.js +61 -72
- package/dist/clients/latency-logger.js +6 -16
- package/dist/clients/lens-config.js +128 -165
- package/dist/clients/lens-engine.js +39 -5
- package/dist/clients/lens-flag-registry.js +285 -0
- package/dist/clients/lens-map.js +2 -7
- package/dist/clients/log-cleanup.js +6 -17
- package/dist/clients/lsp/cascade-tier.js +22 -2
- package/dist/clients/lsp/client.js +74 -10
- package/dist/clients/lsp/config.js +62 -9
- package/dist/clients/lsp/index.js +34 -24
- package/dist/clients/lsp/language.js +4 -1
- package/dist/clients/lsp/launch.js +8 -6
- package/dist/clients/lsp/server.js +84 -29
- package/dist/clients/lsp-document-symbols.js +112 -0
- package/dist/clients/mcp/analyze.js +5 -4
- package/dist/clients/mcp/review.js +36 -3
- package/dist/clients/module-report.js +100 -80
- package/dist/clients/ndjson-logger.js +51 -21
- package/dist/clients/path-keyed-map.js +76 -0
- package/dist/clients/path-utils.js +35 -0
- package/dist/clients/performance-report.js +327 -0
- package/dist/clients/pipeline.js +7 -0
- package/dist/clients/project-changes.js +77 -4
- package/dist/clients/project-diagnostics/extractors.js +26 -115
- package/dist/clients/project-diagnostics/fresh-fetch.js +149 -19
- package/dist/clients/project-diagnostics/runner-adapters/call-graph-impact.js +109 -0
- package/dist/clients/project-diagnostics/runner-adapters/runner-findings.js +37 -5
- package/dist/clients/project-diagnostics/scanner.js +247 -127
- package/dist/clients/project-lens-config.js +53 -26
- package/dist/clients/project-report.js +39 -14
- package/dist/clients/project-scale.js +8 -10
- package/dist/clients/project-snapshot-persist-worker.js +6 -0
- package/dist/clients/project-snapshot.js +611 -7
- package/dist/clients/quiet-window.js +9 -1
- package/dist/clients/read-expansion.js +22 -12
- package/dist/clients/read-guard.js +78 -0
- package/dist/clients/redact/secrets.js +449 -0
- package/dist/clients/resource-sampler.js +133 -14
- package/dist/clients/reverse-deps.js +48 -0
- package/dist/clients/review-graph/builder.js +1522 -179
- package/dist/clients/review-graph/persist-worker.js +10 -0
- package/dist/clients/review-graph/query.js +5 -0
- package/dist/clients/review-graph/shared-extraction-ir.js +90 -0
- package/dist/clients/review-graph-logger.js +24 -0
- package/dist/clients/runtime-agent-end.js +4 -2
- package/dist/clients/runtime-coordinator.js +2 -2
- package/dist/clients/runtime-session.js +433 -59
- package/dist/clients/runtime-tool-call.js +46 -14
- package/dist/clients/runtime-turn.js +97 -26
- package/dist/clients/safe-spawn.js +102 -15
- package/dist/clients/session-start-observability.js +15 -0
- package/dist/clients/session-state-store.js +2 -1
- package/dist/clients/sessionstart-logger.js +18 -0
- package/dist/clients/sg-runner.js +48 -33
- package/dist/clients/source-filter.js +49 -25
- package/dist/clients/startup-marker.js +6 -0
- package/dist/clients/startup-timing.js +9 -0
- package/dist/clients/todo-scanner.js +30 -3
- package/dist/clients/tree-sitter-cache.js +147 -139
- package/dist/clients/tree-sitter-client.js +1340 -67
- package/dist/clients/tree-sitter-logger.js +43 -1
- package/dist/clients/tree-sitter-query-loader.js +110 -11
- package/dist/clients/tree-sitter-shared.js +43 -19
- package/dist/clients/tree-sitter-symbol-extractor.js +71 -4
- package/dist/clients/widget-state.js +50 -14
- package/dist/clients/word-index-logger.js +44 -0
- package/dist/clients/word-index.js +252 -35
- package/dist/clients/workspace-topology.js +11 -1
- package/dist/index.js +45544 -39255
- package/dist/mcp/analyze-cli.js +3 -0
- package/dist/mcp/cli.js +110 -0
- package/dist/mcp/server.js +63 -8
- package/dist/tools/lens-diagnostics.js +47 -5
- package/dist/tools/lsp-navigation.js +5 -28
- package/dist/tools/symbol-search.js +21 -2
- package/docs/agent-guide.md +247 -0
- package/docs/astplayground.md +3 -4
- package/docs/audit1.md +5 -5
- package/docs/environment-variables.md +153 -11
- package/docs/features.md +4 -3
- package/docs/globalconfig.md +56 -4
- package/docs/language-coverage.md +2 -2
- package/docs/mcp.md +17 -16
- package/docs/servercapabilities.md +5 -2
- package/docs/settings.md +181 -0
- package/docs/tools.md +14 -0
- package/docs/tree-sitter_rules_catalog.md +11 -31
- package/docs/usage.md +13 -0
- package/package.json +139 -138
- package/rules/ast-grep-rules/rule-tests/hardcoded-url-js-test.yml +1 -0
- package/rules/ast-grep-rules/rule-tests/hardcoded-url-test.yml +2 -0
- package/rules/ast-grep-rules/rule-tests/no-case-declarations-js-test.yml +10 -0
- package/rules/ast-grep-rules/rule-tests/no-case-declarations-test.yml +10 -0
- package/rules/ast-grep-rules/rule-tests/no-javascript-url-js-test.yml +10 -0
- package/rules/ast-grep-rules/rule-tests/no-javascript-url-test.yml +10 -0
- package/rules/ast-grep-rules/rule-tests/strict-equality-js-test.yml +3 -0
- package/rules/ast-grep-rules/rule-tests/strict-equality-test.yml +3 -0
- package/rules/ast-grep-rules/rule-tests/strict-inequality-js-test.yml +3 -0
- package/rules/ast-grep-rules/rule-tests/strict-inequality-test.yml +4 -0
- package/rules/ast-grep-rules/rules/hardcoded-url-js.yml +22 -4
- package/rules/ast-grep-rules/rules/hardcoded-url.yml +22 -4
- package/rules/ast-grep-rules/rules/no-case-declarations-js.yml +4 -3
- package/rules/ast-grep-rules/rules/no-case-declarations.yml +4 -3
- package/rules/ast-grep-rules/rules/no-console-except-error-js.yml +10 -0
- package/rules/ast-grep-rules/rules/no-console-except-error.yml +10 -0
- package/rules/ast-grep-rules/rules/no-javascript-url-js.yml +42 -6
- package/rules/ast-grep-rules/rules/no-javascript-url.yml +42 -6
- package/rules/ast-grep-rules/rules/strict-equality-js.yml +14 -1
- package/rules/ast-grep-rules/rules/strict-equality.yml +14 -1
- package/rules/ast-grep-rules/rules/strict-inequality-js.yml +14 -1
- package/rules/ast-grep-rules/rules/strict-inequality.yml +14 -1
- package/rules/tree-sitter-queries/cpp/no-memset-sensitive-data.yml +9 -3
- package/rules/tree-sitter-queries/cpp/no-scoped-lock-without-args.yml +6 -6
- package/rules/tree-sitter-queries/css/calc-spacing.yml +8 -6
- package/rules/tree-sitter-queries/go/go-mutex-copy.yml +21 -18
- package/rules/tree-sitter-queries/go/go-shared-map-write-goroutine.yml +3 -3
- package/rules/tree-sitter-queries/java/infinite-loop-java.yml +3 -3
- package/rules/tree-sitter-queries/java/junit-call-super.yml +6 -4
- package/rules/tree-sitter-queries/java/no-double-checked-locking.yml +10 -8
- package/rules/tree-sitter-queries/java/no-field-shadowing.yml +1 -1
- package/rules/tree-sitter-queries/java/prepared-statement-valid-indices.yml +2 -3
- package/rules/tree-sitter-queries/java/resources-closed.yml +2 -2
- package/rules/tree-sitter-queries/java/springboot-default-package.yml +6 -3
- package/rules/tree-sitter-queries/java/switch-fall-through.yml +6 -4
- package/rules/tree-sitter-queries/java/switch-non-case-labels.yml +4 -3
- package/rules/tree-sitter-queries/java/tests-include-assertions.yml +6 -5
- package/rules/tree-sitter-queries/javascript/switch-case-termination-js.yml +5 -8
- package/rules/tree-sitter-queries/javascript/switch-non-case-labels.yml +3 -2
- package/rules/tree-sitter-queries/kotlin/prepared-statement-indices.yml +9 -5
- package/rules/tree-sitter-queries/php/this-in-static-context.yml +5 -5
- package/rules/tree-sitter-queries/python/exit-signature-check.yml +2 -9
- package/rules/tree-sitter-queries/python/in-operator-unsupported.yml +3 -4
- package/rules/tree-sitter-queries/python/no-super-torchscript.yml +4 -8
- package/rules/tree-sitter-queries/python/notimplemented-boolean-context.yml +1 -5
- package/rules/tree-sitter-queries/python/python-empty-except.yml +1 -1
- package/rules/tree-sitter-queries/python/return-in-init.yml +0 -2
- package/rules/tree-sitter-queries/python/yield-return-outside-function.yml +0 -3
- package/rules/tree-sitter-queries/ruby/ruby-command-injection.yml +1 -12
- package/rules/tree-sitter-queries/ruby/ruby-eval.yml +1 -1
- package/rules/tree-sitter-queries/ruby/ruby-insecure-deserialization.yml +4 -4
- package/rules/tree-sitter-queries/ruby/ruby-insecure-random.yml +4 -11
- package/rules/tree-sitter-queries/ruby/ruby-open-struct.yml +1 -1
- package/rules/tree-sitter-queries/ruby/ruby-string-eval.yml +2 -3
- package/rules/tree-sitter-queries/ruby/ruby-weak-hash.yml +4 -4
- package/rules/tree-sitter-queries/rust/rust-lock-held-across-await.yml +4 -3
- package/rules/tree-sitter-queries/typescript/console-statement.yml +11 -0
- package/rules/tree-sitter-queries/typescript/duplicate-function-arg.yml +4 -9
- package/rules/tree-sitter-queries/typescript/empty-switch-case.yml +13 -9
- package/rules/tree-sitter-queries/typescript/infinite-loop.yml +2 -2
- package/rules/tree-sitter-queries/typescript/mixed-async-styles.yml +10 -1
- package/rules/tree-sitter-queries/typescript/switch-case-termination.yml +5 -8
- package/rules/tree-sitter-queries/typescript/ts-insecure-random.yml +7 -10
- package/rules/tree-sitter-queries/typescript/unsafe-regex.yml +4 -2
- package/rules/typos/_typos.toml +17 -0
- package/skills/pi-lens-write-tree-sitter-rule/SKILL.md +5 -0
- package/dist/clients/config-enabled-shape.js +0 -39
- package/docs/env_variables.md +0 -10
- package/rules/tree-sitter-queries/abap-disabled/delete-where.yml +0 -46
- package/rules/tree-sitter-queries/cpp/no-confused-move-forward.yml +0 -59
- package/rules/tree-sitter-queries/cpp/noexcept-functions.yml +0 -58
- package/rules/tree-sitter-queries/java/mockito-initialized.yml +0 -66
- package/rules/tree-sitter-queries/java/no-wait-notify-on-thread.yml +0 -58
- package/rules/tree-sitter-queries/java/short-circuit-logic.yml +0 -57
- package/rules/tree-sitter-queries/java/spring-session-attributes-setcomplete.yml +0 -75
- package/rules/tree-sitter-queries/plsql-disabled/delete-update-where.yml +0 -56
- package/rules/tree-sitter-queries/plsql-disabled/end-loop-semicolon.yml +0 -51
- package/rules/tree-sitter-queries/plsql-disabled/fetch-bulk-collect-limit.yml +0 -47
- package/rules/tree-sitter-queries/plsql-disabled/forallsave-exceptions.yml +0 -51
- package/rules/tree-sitter-queries/plsql-disabled/nchar-nvarchar2-bytes.yml +0 -54
- package/rules/tree-sitter-queries/plsql-disabled/not-null-initialization.yml +0 -59
- package/rules/tree-sitter-queries/plsql-disabled/raise-application-error-codes.yml +0 -50
- package/rules/tree-sitter-queries/typescript-disabled/ts-path-traversal.yml +0 -71
package/package.json
CHANGED
|
@@ -1,140 +1,141 @@
|
|
|
1
1
|
{
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
2
|
+
"name": "pi-lens",
|
|
3
|
+
"version": "3.8.74",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"description": "Real-time code feedback for pi — LSP, linters, formatters, type-checking, structural analysis & booboo",
|
|
6
|
+
"repository": {
|
|
7
|
+
"type": "git",
|
|
8
|
+
"url": "git+https://github.com/apmantza/pi-lens.git"
|
|
9
|
+
},
|
|
10
|
+
"main": "./dist/index.js",
|
|
11
|
+
"bin": {
|
|
12
|
+
"pi-lens": "dist/mcp/cli.js",
|
|
13
|
+
"pi-lens-mcp": "dist/mcp/server.js",
|
|
14
|
+
"pi-lens-analyze": "dist/mcp/analyze-cli.js"
|
|
15
|
+
},
|
|
16
|
+
"scripts": {
|
|
17
|
+
"build": "tsc --project tsconfig.build.json",
|
|
18
|
+
"build:dist": "node -e \"require('fs').rmSync('dist',{recursive:true,force:true})\" && npx --yes -p typescript@7.0.2 tsc --project tsconfig.dist.json --noCheck && npm run bundle:dist",
|
|
19
|
+
"bundle:dist": "node scripts/bundle-dist.mjs",
|
|
20
|
+
"prepare": "npm run build:dist && node scripts/download-grammars.js --core --dest grammars",
|
|
21
|
+
"lint": "tsc --project tsconfig.json",
|
|
22
|
+
"watch": "tsc --watch",
|
|
23
|
+
"test": "vitest run",
|
|
24
|
+
"test:unit": "vitest run --ignore tests/index-integration.test.ts --ignore tests/clients/lsp/integration.test.ts",
|
|
25
|
+
"test:integration": "vitest run tests/index-integration.test.ts tests/clients/lsp/integration.test.ts",
|
|
26
|
+
"test:watch": "vitest",
|
|
27
|
+
"check": "node scripts/check-extensions.mjs",
|
|
28
|
+
"selftest:install": "node scripts/install-selftest.mjs",
|
|
29
|
+
"check:lockfile": "node scripts/check-lockfile-sync.mjs",
|
|
30
|
+
"check:grammars": "node scripts/check-grammar-provenance.mjs",
|
|
31
|
+
"check:grammar-load": "node scripts/check-grammar-load.mjs",
|
|
32
|
+
"audit:tree-sitter": "node scripts/audit-tree-sitter-rules.mjs",
|
|
33
|
+
"audit:rule-catalog": "node scripts/validate-rule-catalog.mjs",
|
|
34
|
+
"audit:astgrep-rule-pairs": "node scripts/audit-astgrep-rule-pairs.mjs",
|
|
35
|
+
"audit:playground": "node scripts/playground-verify-rule.mjs",
|
|
36
|
+
"logs:smells": "node scripts/analyze-pi-lens-logs.mjs",
|
|
37
|
+
"changelog:check": "node scripts/changelog-release.mjs --check",
|
|
38
|
+
"changelog:release": "node scripts/changelog-release.mjs",
|
|
39
|
+
"changelog:extract": "node scripts/changelog-extract.mjs",
|
|
40
|
+
"release:backfill-notes": "node scripts/backfill-github-releases.mjs",
|
|
41
|
+
"release:backfill-thanks": "node scripts/backfill-release-thanks.mjs",
|
|
42
|
+
"docs:rule-catalogs": "node scripts/gen-rule-catalogs.mjs",
|
|
43
|
+
"banner": "npx -y sharp-cli --input banner.svg --output banner.png resize 2200 620",
|
|
44
|
+
"download-grammars": "node scripts/download-grammars.js",
|
|
45
|
+
"harness:poc": "node scripts/run-harness.mjs cases/ts/pipeline-dispatch-poc --pi-bin \"C:\\Users\\R3LiC\\AppData\\Roaming\\npm\\pi.cmd\"",
|
|
46
|
+
"harness:python-poc": "node scripts/run-harness.mjs cases/python/pipeline-dispatch-poc --pi-bin \"C:\\Users\\R3LiC\\AppData\\Roaming\\npm\\pi.cmd\"",
|
|
47
|
+
"harness:ts-format-poc": "node scripts/run-harness.mjs cases/ts/format-default-poc --pi-bin \"C:\\Users\\R3LiC\\AppData\\Roaming\\npm\\pi.cmd\"",
|
|
48
|
+
"harness:python-autofix-poc": "node scripts/run-harness.mjs cases/python/autofix-default-poc --pi-bin \"C:\\Users\\R3LiC\\AppData\\Roaming\\npm\\pi.cmd\"",
|
|
49
|
+
"harness:go-poc": "node scripts/run-harness.mjs cases/go/pipeline-dispatch-poc --pi-bin \"C:\\Users\\R3LiC\\AppData\\Roaming\\npm\\pi.cmd\""
|
|
50
|
+
},
|
|
51
|
+
"keywords": [
|
|
52
|
+
"pi",
|
|
53
|
+
"pi-extension",
|
|
54
|
+
"pi-package",
|
|
55
|
+
"linter",
|
|
56
|
+
"biome",
|
|
57
|
+
"ast-grep",
|
|
58
|
+
"ruff",
|
|
59
|
+
"typescript",
|
|
60
|
+
"code-quality",
|
|
61
|
+
"feedback",
|
|
62
|
+
"type-coverage",
|
|
63
|
+
"jscpd",
|
|
64
|
+
"knip"
|
|
65
|
+
],
|
|
66
|
+
"author": "Apostolos Mantzaris",
|
|
67
|
+
"license": "MIT",
|
|
68
|
+
"files": [
|
|
69
|
+
"dist/",
|
|
70
|
+
"docs/",
|
|
71
|
+
"grammars/",
|
|
72
|
+
"config/",
|
|
73
|
+
"rules/",
|
|
74
|
+
"skills/",
|
|
75
|
+
"scripts/download-grammars.js",
|
|
76
|
+
"scripts/grammars.lock.json",
|
|
77
|
+
"scripts/analyze-pi-lens-logs.mjs",
|
|
78
|
+
"scripts/install-selftest.mjs",
|
|
79
|
+
"scripts/rpc-load-check.mjs",
|
|
80
|
+
"README.md",
|
|
81
|
+
"CHANGELOG.md",
|
|
82
|
+
"banner.svg",
|
|
83
|
+
"banner.png"
|
|
84
|
+
],
|
|
85
|
+
"dependencies": {
|
|
86
|
+
"@ast-grep/cli": "^0.45.0",
|
|
87
|
+
"@ast-grep/napi": "^0.45.0",
|
|
88
|
+
"@earendil-works/pi-tui": "^0.82.1",
|
|
89
|
+
"js-yaml": "^5.2.2",
|
|
90
|
+
"minimatch": "^10.2.5",
|
|
91
|
+
"pidusage": "^4.0.1",
|
|
92
|
+
"typebox": "^1.0.0",
|
|
93
|
+
"vscode-jsonrpc": "^9.0.0"
|
|
94
|
+
},
|
|
95
|
+
"peerDependencies": {
|
|
96
|
+
"@earendil-works/pi-coding-agent": "*"
|
|
97
|
+
},
|
|
98
|
+
"peerDependenciesMeta": {
|
|
99
|
+
"@earendil-works/pi-coding-agent": {
|
|
100
|
+
"optional": true
|
|
101
|
+
}
|
|
102
|
+
},
|
|
103
|
+
"optionalDependencies": {
|
|
104
|
+
"web-tree-sitter": "0.25.10"
|
|
105
|
+
},
|
|
106
|
+
"devDependencies": {
|
|
107
|
+
"@biomejs/biome": "^2.4.10",
|
|
108
|
+
"@earendil-works/pi-coding-agent": "^0.82.1",
|
|
109
|
+
"@types/node": "^26.0.0",
|
|
110
|
+
"@types/pidusage": "^2.0.5",
|
|
111
|
+
"@vitest/coverage-v8": "^4.1.5",
|
|
112
|
+
"typescript": "^7.0.2",
|
|
113
|
+
"typescript-language-server": "^5.1.3",
|
|
114
|
+
"vitest": "^4.1.1"
|
|
115
|
+
},
|
|
116
|
+
"pi": {
|
|
117
|
+
"extensions": [
|
|
118
|
+
"./dist/index.js"
|
|
119
|
+
],
|
|
120
|
+
"skills": [
|
|
121
|
+
"../../skills"
|
|
122
|
+
]
|
|
123
|
+
},
|
|
124
|
+
"knip": {
|
|
125
|
+
"entry": [
|
|
126
|
+
"index.ts"
|
|
127
|
+
],
|
|
128
|
+
"project": [
|
|
129
|
+
"**/*.ts",
|
|
130
|
+
"!**/*.test.ts"
|
|
131
|
+
],
|
|
132
|
+
"ignore": [
|
|
133
|
+
"**/*.test.ts"
|
|
134
|
+
]
|
|
135
|
+
},
|
|
136
|
+
"allowScripts": {
|
|
137
|
+
"@ast-grep/cli@0.44.1": true,
|
|
138
|
+
"@google/genai@1.52.0": true,
|
|
139
|
+
"protobufjs@7.6.4": true
|
|
140
|
+
}
|
|
140
141
|
}
|
|
@@ -2,6 +2,8 @@ id: hardcoded-url
|
|
|
2
2
|
valid:
|
|
3
3
|
- 'const url = process.env.API_URL'
|
|
4
4
|
- 'const x = "hello"'
|
|
5
|
+
- 'export const BASE_URL_CLINE = "https://api.cline.bot";'
|
|
6
|
+
- 'export const URL_KILO_TOS = "https://kilo.dev/tos";'
|
|
5
7
|
invalid:
|
|
6
8
|
- 'const url = "https://api.example.com"'
|
|
7
9
|
- 'const endpoint = "http://localhost:3000"'
|
|
@@ -8,7 +8,17 @@ valid:
|
|
|
8
8
|
it("rejects javascript: urls", () => {
|
|
9
9
|
expect(openBrowser("javascript:alert(1)")).toBe(false);
|
|
10
10
|
});
|
|
11
|
+
- 'const links = arr.filter((l) => !l.startsWith("javascript:"))'
|
|
12
|
+
- 'if (url.includes("javascript:")) return null;'
|
|
13
|
+
- 'const isBlocked = url === "javascript:alert(1)"'
|
|
14
|
+
- 'const safe = url !== "javascript:alert(1)"'
|
|
15
|
+
- 'url?.startsWith("javascript:")'
|
|
11
16
|
invalid:
|
|
12
17
|
- 'a.href = "javascript:alert(1)"'
|
|
13
18
|
- 'a.href = "javascript:void(0)"'
|
|
14
19
|
- 'const u = "javascript:alert(1)"'
|
|
20
|
+
- 'a.href = str.replace("http:", "javascript:alert(1)")'
|
|
21
|
+
- 'if (candidates.includes(link.href = "javascript:alert(1)")) { doThing(); }'
|
|
22
|
+
- 'someArray.includes((a.href = "javascript:alert(1)", true));'
|
|
23
|
+
- 'if ((a.href = "javascript:alert(1)") === expected) { doThing(); }'
|
|
24
|
+
- 'const ok = (typeof (a.href = "javascript:alert(1)")) === "string";'
|
|
@@ -12,7 +12,17 @@ valid:
|
|
|
12
12
|
test.each(["javascript:alert(1)"])("rejects %s", (url) => {
|
|
13
13
|
expect(openBrowser(url)).toBe(false);
|
|
14
14
|
});
|
|
15
|
+
- 'const links = arr.filter((l) => !l.startsWith("javascript:"))'
|
|
16
|
+
- 'if (url.includes("javascript:")) return null;'
|
|
17
|
+
- 'const isBlocked = url === "javascript:alert(1)"'
|
|
18
|
+
- 'const safe = url !== "javascript:alert(1)"'
|
|
19
|
+
- 'url?.startsWith("javascript:")'
|
|
15
20
|
invalid:
|
|
16
21
|
- 'a.href = "javascript:alert(1)"'
|
|
17
22
|
- 'a.href = "javascript:void(0)"'
|
|
18
23
|
- 'const u = "javascript:alert(1)"'
|
|
24
|
+
- 'a.href = str.replace("http:", "javascript:alert(1)")'
|
|
25
|
+
- 'if (candidates.includes(link.href = "javascript:alert(1)")) { doThing(); }'
|
|
26
|
+
- 'someArray.includes((a.href = "javascript:alert(1)", true));'
|
|
27
|
+
- 'if ((a.href = "javascript:alert(1)") === expected) { doThing(); }'
|
|
28
|
+
- 'const ok = (typeof (a.href = "javascript:alert(1)")) === "string";'
|
|
@@ -9,9 +9,27 @@ note: |
|
|
|
9
9
|
level for some shapes; using a regex on `variable_declarator` (the
|
|
10
10
|
inner `name = value` node) catches all const/let/var URL assignments
|
|
11
11
|
regardless of the surrounding keyword.
|
|
12
|
+
A `SCREAMING_SNAKE_CASE` name is the project-wide convention for a
|
|
13
|
+
deliberate, named constant (see e.g. `check_secret_pattern` in
|
|
14
|
+
tree-sitter-client.ts, which trusts the same convention for secrets).
|
|
15
|
+
Provider/integration endpoint constants (`BASE_URL_CLINE`, `URL_KILO_TOS`,
|
|
16
|
+
…) are declared this way on purpose — they are configuration, just
|
|
17
|
+
expressed as a JS constant instead of an env var — so exempting that
|
|
18
|
+
naming shape removes the low-signal noise while still catching a URL
|
|
19
|
+
hardcoded under an ordinary lower/camelCase name (#964).
|
|
12
20
|
rule:
|
|
13
21
|
any:
|
|
14
|
-
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
22
|
+
- all:
|
|
23
|
+
- kind: variable_declarator
|
|
24
|
+
regex: '"https?://'
|
|
25
|
+
- not:
|
|
26
|
+
has:
|
|
27
|
+
field: name
|
|
28
|
+
regex: "^[A-Z][A-Z0-9_]*$"
|
|
29
|
+
- all:
|
|
30
|
+
- kind: assignment_expression
|
|
31
|
+
regex: '"https?://'
|
|
32
|
+
- not:
|
|
33
|
+
has:
|
|
34
|
+
field: left
|
|
35
|
+
regex: "^[A-Z][A-Z0-9_]*$"
|
|
@@ -9,9 +9,27 @@ note: |
|
|
|
9
9
|
level for some shapes; using a regex on `variable_declarator` (the
|
|
10
10
|
inner `name = value` node) catches all const/let/var URL assignments
|
|
11
11
|
regardless of the surrounding keyword.
|
|
12
|
+
A `SCREAMING_SNAKE_CASE` name is the project-wide convention for a
|
|
13
|
+
deliberate, named constant (see e.g. `check_secret_pattern` in
|
|
14
|
+
tree-sitter-client.ts, which trusts the same convention for secrets).
|
|
15
|
+
Provider/integration endpoint constants (`BASE_URL_CLINE`, `URL_KILO_TOS`,
|
|
16
|
+
…) are declared this way on purpose — they are configuration, just
|
|
17
|
+
expressed as a TS constant instead of an env var — so exempting that
|
|
18
|
+
naming shape removes the low-signal noise while still catching a URL
|
|
19
|
+
hardcoded under an ordinary lower/camelCase name (#964).
|
|
12
20
|
rule:
|
|
13
21
|
any:
|
|
14
|
-
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
22
|
+
- all:
|
|
23
|
+
- kind: variable_declarator
|
|
24
|
+
regex: '"https?://'
|
|
25
|
+
- not:
|
|
26
|
+
has:
|
|
27
|
+
field: name
|
|
28
|
+
regex: "^[A-Z][A-Z0-9_]*$"
|
|
29
|
+
- all:
|
|
30
|
+
- kind: assignment_expression
|
|
31
|
+
regex: '"https?://'
|
|
32
|
+
- not:
|
|
33
|
+
has:
|
|
34
|
+
field: left
|
|
35
|
+
regex: "^[A-Z][A-Z0-9_]*$"
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
id: no-case-declarations-js
|
|
2
2
|
language: JavaScript
|
|
3
|
-
message:
|
|
3
|
+
message: >-
|
|
4
|
+
Unexpected lexical declaration in case block — wrap in braces to restrict
|
|
5
|
+
scope
|
|
4
6
|
severity: error
|
|
5
7
|
note: |
|
|
6
8
|
Variables declared with let/const in a case clause are accessible to the
|
|
@@ -17,5 +19,4 @@ rule:
|
|
|
17
19
|
- not:
|
|
18
20
|
inside:
|
|
19
21
|
kind: statement_block
|
|
20
|
-
|
|
21
|
-
kind: switch_case
|
|
22
|
+
stopBy: end
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
id: no-case-declarations
|
|
2
2
|
language: TypeScript
|
|
3
|
-
message:
|
|
3
|
+
message: >-
|
|
4
|
+
Unexpected lexical declaration in case block — wrap in braces to restrict
|
|
5
|
+
scope
|
|
4
6
|
severity: error
|
|
5
7
|
note: |
|
|
6
8
|
Variables declared with let/const in a case clause are accessible to the
|
|
@@ -17,5 +19,4 @@ rule:
|
|
|
17
19
|
- not:
|
|
18
20
|
inside:
|
|
19
21
|
kind: statement_block
|
|
20
|
-
|
|
21
|
-
kind: switch_case
|
|
22
|
+
stopBy: end
|
|
@@ -6,6 +6,16 @@ note: |
|
|
|
6
6
|
console.log/debug/warn usually indicate leftover debug output shipped to
|
|
7
7
|
production. Allow console.error ONLY inside catch blocks (logging the
|
|
8
8
|
error there is useful for production triage).
|
|
9
|
+
Console output IS the point in a CLI script's own stdout contract and in
|
|
10
|
+
a logging implementation's console fallback/sink — flagging it there
|
|
11
|
+
just trains users to ignore the rule; `ignores` below carves those paths
|
|
12
|
+
out while application/library code elsewhere still gets flagged (#965).
|
|
13
|
+
ignores:
|
|
14
|
+
- "scripts/**"
|
|
15
|
+
- "bin/**"
|
|
16
|
+
- "**/logger.ts"
|
|
17
|
+
- "**/logger.js"
|
|
18
|
+
- "**/logger.mjs"
|
|
9
19
|
rule:
|
|
10
20
|
any:
|
|
11
21
|
- pattern: console.error($$$)
|
|
@@ -6,6 +6,16 @@ note: |
|
|
|
6
6
|
console.log/debug/warn usually indicate leftover debug output shipped to
|
|
7
7
|
production. Allow console.error ONLY inside catch blocks (logging the
|
|
8
8
|
error there is useful for production triage).
|
|
9
|
+
Console output IS the point in a CLI script's own stdout contract and in
|
|
10
|
+
a logging implementation's console fallback/sink — flagging it there
|
|
11
|
+
just trains users to ignore the rule; `ignores` below carves those paths
|
|
12
|
+
out while application/library code elsewhere still gets flagged (#965).
|
|
13
|
+
ignores:
|
|
14
|
+
- "scripts/**"
|
|
15
|
+
- "bin/**"
|
|
16
|
+
- "**/logger.ts"
|
|
17
|
+
- "**/logger.js"
|
|
18
|
+
- "**/logger.mjs"
|
|
9
19
|
rule:
|
|
10
20
|
any:
|
|
11
21
|
- pattern: console.error($$$)
|
|
@@ -15,13 +15,49 @@ note: |
|
|
|
15
15
|
`.only`/`.skip`/`.each` variants): a test asserting that a guard REJECTS a
|
|
16
16
|
`javascript:` URL — e.g. `expect(openBrowser("javascript:...")).toBe(false)`
|
|
17
17
|
— is the adversarial input the code is meant to reject, not a real sink.
|
|
18
|
+
|
|
19
|
+
Also excludes literals used as the needle in a defensive string check —
|
|
20
|
+
`url.startsWith("javascript:")`, `.endsWith(...)`, `.includes(...)`,
|
|
21
|
+
`.indexOf(...)`, `.search(...)`, `.match(...)` — or as one side of an
|
|
22
|
+
equality/inequality comparison (`url === "javascript:..."`). These are the
|
|
23
|
+
code detecting/rejecting a javascript: URL, not introducing one (refs
|
|
24
|
+
#533). Deliberately NOT excluded: `.replace(...)`/`.replaceAll(...)`,
|
|
25
|
+
since the literal there could be the replacement (second) argument —
|
|
26
|
+
i.e. the malicious payload being substituted IN — and excluding the
|
|
27
|
+
whole call would hide that true positive.
|
|
28
|
+
|
|
29
|
+
IMPORTANT: unlike the expect/it/test/describe exclusion above, these two
|
|
30
|
+
new exclusions deliberately do NOT use `stopBy: end`. `inside` without
|
|
31
|
+
`stopBy` only checks the immediate parent, so the literal must be a
|
|
32
|
+
DIRECT argument/operand of the defensive call/comparison — not merely
|
|
33
|
+
somewhere in its subtree. Without this constraint, a real sink smuggled
|
|
34
|
+
inside the call/comparison would go unflagged, e.g.
|
|
35
|
+
`candidates.includes(link.href = "javascript:alert(1)")` (assignment
|
|
36
|
+
nested in `.includes()`'s argument), `arr.includes((a.href =
|
|
37
|
+
"javascript:...", true))` (comma operator), or `(a.href =
|
|
38
|
+
"javascript:...") === expected` (assignment nested in a `===` operand) —
|
|
39
|
+
in all three the literal's immediate parent is the assignment
|
|
40
|
+
expression, not the `arguments`/`binary_expression` node, so it stays
|
|
41
|
+
flagged.
|
|
18
42
|
rule:
|
|
19
43
|
kind: string
|
|
20
44
|
regex: '^"javascript:'
|
|
21
45
|
not:
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
46
|
+
any:
|
|
47
|
+
- inside:
|
|
48
|
+
stopBy: end
|
|
49
|
+
kind: call_expression
|
|
50
|
+
has:
|
|
51
|
+
field: function
|
|
52
|
+
regex: "^(expect|it|test|describe)(\\.\\w+)?$"
|
|
53
|
+
- inside:
|
|
54
|
+
kind: arguments
|
|
55
|
+
inside:
|
|
56
|
+
kind: call_expression
|
|
57
|
+
has:
|
|
58
|
+
field: function
|
|
59
|
+
regex: "\\.(startsWith|endsWith|includes|indexOf|search|match)$"
|
|
60
|
+
- inside:
|
|
61
|
+
kind: binary_expression
|
|
62
|
+
has:
|
|
63
|
+
regex: "^(===|!==|==|!=)$"
|