pi-lens 3.3.1 → 3.6.1
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 +83 -0
- package/README.md +75 -196
- package/clients/biome-client.js +28 -0
- package/clients/biome-client.ts +32 -0
- package/clients/cache/rule-cache.js +72 -0
- package/clients/cache/rule-cache.ts +104 -0
- package/clients/dispatch/integration.js +48 -1
- package/clients/dispatch/integration.ts +60 -2
- package/clients/dispatch/plan.js +5 -2
- package/clients/dispatch/plan.ts +5 -2
- package/clients/dispatch/runners/ast-grep-napi.js +175 -56
- package/clients/dispatch/runners/ast-grep-napi.test.js +2 -1
- package/clients/dispatch/runners/ast-grep-napi.test.ts +2 -1
- package/clients/dispatch/runners/ast-grep-napi.ts +191 -79
- package/clients/dispatch/runners/biome.js +1 -2
- package/clients/dispatch/runners/biome.ts +1 -2
- package/clients/dispatch/runners/similarity.js +1 -1
- package/clients/dispatch/runners/similarity.ts +2 -2
- package/clients/dispatch/runners/tree-sitter.js +137 -10
- package/clients/dispatch/runners/tree-sitter.ts +168 -13
- package/clients/dispatch/runners/ts-lsp.js +3 -2
- package/clients/dispatch/runners/ts-lsp.ts +3 -2
- package/clients/dispatch/runners/yaml-rule-parser.js +70 -2
- package/clients/dispatch/runners/yaml-rule-parser.ts +71 -2
- package/clients/dispatch/types.js +1 -1
- package/clients/dispatch/types.ts +1 -1
- package/clients/installer/index.js +0 -21
- package/clients/installer/index.ts +0 -22
- package/clients/lsp/__tests__/service.test.js +3 -0
- package/clients/lsp/__tests__/service.test.ts +3 -0
- package/clients/lsp/client.js +42 -0
- package/clients/lsp/client.ts +79 -0
- package/clients/lsp/index.js +27 -0
- package/clients/lsp/index.ts +35 -0
- package/clients/lsp/server.js +68 -5
- package/clients/lsp/server.ts +75 -7
- package/clients/metrics-client.js +3 -160
- package/clients/metrics-client.test.js +30 -43
- package/clients/metrics-client.test.ts +30 -54
- package/clients/metrics-client.ts +5 -219
- package/clients/metrics-history.js +33 -7
- package/clients/metrics-history.ts +47 -10
- package/clients/pipeline.js +272 -0
- package/clients/pipeline.ts +371 -0
- package/clients/sg-runner.js +21 -3
- package/clients/sg-runner.ts +22 -3
- package/clients/tree-sitter-client.js +23 -2
- package/clients/tree-sitter-client.ts +27 -2
- package/index.ts +604 -824
- package/package.json +2 -2
- package/rules/ast-grep-rules/rules/no-architecture-violation.yml +7 -4
- package/rules/ast-grep-rules/rules/no-single-char-var.yml +3 -3
- package/rules/ast-grep-rules/slop-patterns.yml +85 -62
- package/skills/ast-grep/SKILL.md +42 -1
- package/skills/lsp-navigation/SKILL.md +62 -0
- package/tsconfig.json +1 -1
- package/rules/ast-grep-rules/rules/no-console-log.yml +0 -10
- package/rules/ast-grep-rules/rules/no-default-export.yml +0 -19
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,89 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to pi-lens will be documented in this file.
|
|
4
4
|
|
|
5
|
+
## [3.6.0] - 2026-04-02
|
|
6
|
+
|
|
7
|
+
### Added
|
|
8
|
+
- **LSP Call Hierarchy Support** — Added 3 new operations to `lsp_navigation` tool:
|
|
9
|
+
- `prepareCallHierarchy` — Get callable item at position
|
|
10
|
+
- `incomingCalls` — Find all functions/methods that CALL this function
|
|
11
|
+
- `outgoingCalls` — Find all functions/methods CALLED by this function
|
|
12
|
+
- Use case: "Who calls this function?" and "What does this function depend on?"
|
|
13
|
+
- **LSP Navigation Skill** — New built-in skill (`skills/lsp-navigation/SKILL.md`) that guides LLM on when to use LSP for code intelligence vs other tools
|
|
14
|
+
- **AST-Grep Skill Improvements** — Enhanced `skills/ast-grep/SKILL.md` with:
|
|
15
|
+
- Testing Tips section (Search → Dry-run → Apply workflow)
|
|
16
|
+
- Metavariable selection guide ($ vs $$$)
|
|
17
|
+
- Specific guidance for "Multiple AST nodes" error
|
|
18
|
+
- **Skills Registration** — Extension now registers `skills/` directory via `resources_discover` event, exposing both `ast-grep` and `lsp-navigation` skills to pi
|
|
19
|
+
- **Enhanced TDI (Technical Debt Index) with 5-factor formula** — Now captures "worst offender" functions and code unpredictability:
|
|
20
|
+
- **Max Cyclomatic (10%)**: Catches worst function complexity (avg hides bad apples)
|
|
21
|
+
- **Entropy (5%)**: Measures code unpredictability/vocabulary richness in bits
|
|
22
|
+
- Rebalanced weights: MI (45%), Cognitive (30%), Nesting (10%), MaxCyc (10%), Entropy (5%)
|
|
23
|
+
- New thresholds: MaxCyc >10 bad, >30 critical; Entropy >4.0 bits risky, >7.0 critical
|
|
24
|
+
|
|
25
|
+
### Removed
|
|
26
|
+
- **TDR (Technical Debt Ratio)** — Removed orphaned metric tracking system:
|
|
27
|
+
- Deleted `TDREntry`, `TDRCategory` types, `tdrFindings` Map, `updateTDR()` method
|
|
28
|
+
- Removed `convertDiagnosticsToTDREntries()` helper and all `tdrCategory` assignments
|
|
29
|
+
- Deleted TDR test file
|
|
30
|
+
- TDI is sufficient for code health tracking; inline diagnostics provide immediate feedback
|
|
31
|
+
|
|
32
|
+
### Changed
|
|
33
|
+
- **Updated `/lens-tdi` display** — Shows 5 category breakdown with descriptions:
|
|
34
|
+
```
|
|
35
|
+
Debt breakdown:
|
|
36
|
+
Maintainability: 45% (MI-based)
|
|
37
|
+
Cognitive: 30%
|
|
38
|
+
Nesting: 10%
|
|
39
|
+
Max Cyclomatic: 10% (worst function)
|
|
40
|
+
Entropy: 5% (code unpredictability)
|
|
41
|
+
```
|
|
42
|
+
- **Extended MetricSnapshot** — Added `maxCyclomatic` and `entropy` fields for historical tracking
|
|
43
|
+
|
|
44
|
+
---
|
|
45
|
+
|
|
46
|
+
## [3.5.0] - 2026-04-02
|
|
47
|
+
|
|
48
|
+
### Added
|
|
49
|
+
- **Tree-sitter query compilation cache** — 10× performance improvement for structural analysis. Query files (`.yml`) are compiled to binary `.wasm-cache` format once and cached to disk. Subsequent loads use the compiled cache directly, reducing tree-sitter startup from ~50ms to ~5ms per query. Cache uses mtime-based invalidation — automatically recompiles when source `.yml` changes.
|
|
50
|
+
- **Rule cache infrastructure** (`clients/cache/`) — New disk-backed cache system with:
|
|
51
|
+
- `RuleCache` class for storing compiled artifacts
|
|
52
|
+
- mtime-based invalidation (auto-refresh when source files change)
|
|
53
|
+
- JSON metadata tracking for cache entries
|
|
54
|
+
- TTL and integrity validation
|
|
55
|
+
|
|
56
|
+
### Fixed
|
|
57
|
+
- **YAML parser colon truncation** — Fixed regex-based parser that incorrectly truncated values containing colons. Changed from `split(':', 2)` to `indexOf(':')` for proper value extraction.
|
|
58
|
+
- **Tree-sitter rules directory resolution** — Fixed path resolution to use `ctx.cwd` instead of hardcoded `.pi-lens/rules/` path. Rules now load correctly from the actual project root regardless of where pi is invoked.
|
|
59
|
+
- **Tree-sitter post_filter support** — Implemented missing `post_filter` functionality for tree-sitter queries. Rules with post-filters (e.g., semantic validation for `bare-except` vs specific exception handlers) now work correctly instead of being silently skipped.
|
|
60
|
+
- **Event handler silent crashes** — Wrapped all event handlers in try/catch to prevent unhandled exceptions from crashing the extension silently. Errors are now logged to stderr instead of terminating the process.
|
|
61
|
+
- **Latency logging restored** — Fixed missing latency logging in `tool_result` handler. Runner timing data now correctly flows to `~/.pi-lens/latency.log` again.
|
|
62
|
+
|
|
63
|
+
### Removed
|
|
64
|
+
- **Broken ast-grep rules** — Removed overlapping rules that were causing false positives or conflicts with tree-sitter coverage.
|
|
65
|
+
|
|
66
|
+
---
|
|
67
|
+
|
|
68
|
+
## [3.4.0] - 2026-04-02
|
|
69
|
+
|
|
70
|
+
### Fixed
|
|
71
|
+
- **Delta mode was broken** — `dispatchLint()` created a fresh empty baseline store on every call, making delta filtering a complete no-op. Every issue looked "new" every time. Now uses a persistent session-level baseline store. First write captures baseline, subsequent writes only show NEW issues.
|
|
72
|
+
- **Duplicate type-checking with `--lens-lsp`** — Both the `lsp` runner (priority 4) and `ts-lsp` runner (priority 5) were calling the same LSP service for TypeScript files. `ts-lsp` now skips when `--lens-lsp` is active.
|
|
73
|
+
|
|
74
|
+
### Added
|
|
75
|
+
- **Inline security rules via ast-grep-napi** — Re-enabled the ast-grep-napi runner for real-time blocking on security violations (`no-eval`, `jwt-no-verify`, `no-hardcoded-secrets`, `weak-rsa-key`, `no-open-redirect`, etc.). Only error-severity rules fire inline; warnings remain in `/lens-booboo`. Skips 5 rules already covered by tree-sitter to avoid duplicates. ~9ms execution time.
|
|
76
|
+
- **Pre-write duplicate detection (two layers):**
|
|
77
|
+
- **Exact name match** — Checks exported names in new content against the session’s cached export index. If a function/class/type already exists in another file, blocks the write: `🔴 STOP — function X already exists in utils.ts. Import instead.`
|
|
78
|
+
- **Structural similarity** — Parses new functions, builds AST state matrices, compares against the project index (built at session start). Functions with ≥80% structural similarity trigger a warning with the match location. Non-blocking.
|
|
79
|
+
- **Project similarity index at session start** — Builds 57×72 state matrices for all TS functions at session start (cached to `.pi-lens/index.json`). Makes pre-write similarity checks ~50ms instead of seconds.
|
|
80
|
+
|
|
81
|
+
### Changed
|
|
82
|
+
- **Extracted post-write pipeline** — Moved the entire post-write pipeline (secrets, format, autofix, dispatch, tests, cascade diagnostics) from `index.ts` into `clients/pipeline.ts`. `index.ts` reduced from 1764 to 1439 lines.
|
|
83
|
+
- **Removed inline complexity warnings** — `⚠️ Complexity increased: +4 cognitive` no longer shown on every write. No agent acts on this mid-task. Complexity data still captured for `/lens-booboo` and `/lens-tdi`.
|
|
84
|
+
- **Simplified pre-write handler** — Removed pre-write TypeScript and LSP diagnostics checks (checked old content before write landed — post-write catches everything). Kept only complexity baseline capture and duplicate detection.
|
|
85
|
+
|
|
86
|
+
---
|
|
87
|
+
|
|
5
88
|
## [3.3.1] - 2026-04-02
|
|
6
89
|
|
|
7
90
|
### Fixed
|
package/README.md
CHANGED
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
3. **Scans for secrets** — Blocks on hardcoded API keys, tokens, passwords
|
|
11
11
|
4. **Runs linters** — Biome (TS/JS), Ruff (Python), plus structural analysis
|
|
12
12
|
5. **Tree-sitter analysis** — Deep structural patterns (empty catch, eval, deep nesting, mixed async styles)
|
|
13
|
-
6. **Auto-installs** — TypeScript, Python, Biome, Ruff tools install
|
|
13
|
+
6. **Auto-installs** — TypeScript, Python, Biome, Ruff, and analysis tools auto-install on first use
|
|
14
14
|
7. **Only shows NEW issues** — Delta-mode tracks baselines and filters pre-existing problems
|
|
15
15
|
|
|
16
16
|
**🔴 Blockers** (type errors, secrets, empty catches) appear inline and stop the agent until fixed.
|
|
@@ -28,10 +28,7 @@ pi
|
|
|
28
28
|
# Disable auto-formatting if needed
|
|
29
29
|
pi --no-autoformat
|
|
30
30
|
|
|
31
|
-
# Full LSP mode (31 language servers)
|
|
32
|
-
pi --lens-lsp
|
|
33
|
-
|
|
34
|
-
# LSP mode (recommended for large projects)
|
|
31
|
+
# Full LSP mode (31 language servers) — recommended for large/multi-language projects
|
|
35
32
|
pi --lens-lsp
|
|
36
33
|
```
|
|
37
34
|
|
|
@@ -131,7 +128,7 @@ Enable full Language Server Protocol support with `--lens-lsp`:
|
|
|
131
128
|
| **Config** | YAML, JSON, Prisma |
|
|
132
129
|
| **Web** | Vue, Svelte, CSS/SCSS/Sass/Less |
|
|
133
130
|
|
|
134
|
-
**Auto-installation (
|
|
131
|
+
**Auto-installation (8 tools):** TypeScript, Python, Biome, Ruff, and analysis tools (Madge, jscpd, ast-grep, Knip) auto-install on first use to `.pi-lens/tools/`. Other LSP servers are launched via `npx` when available or require manual installation.
|
|
135
132
|
|
|
136
133
|
**Usage:**
|
|
137
134
|
```bash
|
|
@@ -156,14 +153,6 @@ See [docs/LSP_CONFIG.md](docs/LSP_CONFIG.md) for configuration options.
|
|
|
156
153
|
|
|
157
154
|
---
|
|
158
155
|
|
|
159
|
-
### Execution Modes
|
|
160
|
-
|
|
161
|
-
| Mode | Flag | Description |
|
|
162
|
-
|------|------|-------------|
|
|
163
|
-
| **Sequential** | (default) | Runners execute one at a time |
|
|
164
|
-
|
|
165
|
-
---
|
|
166
|
-
|
|
167
156
|
### On every write / edit
|
|
168
157
|
|
|
169
158
|
Every file write/edit triggers multiple analysis phases:
|
|
@@ -202,12 +191,12 @@ pi-lens uses a **dispatcher-runner architecture** for extensible multi-language
|
|
|
202
191
|
| **ruff** | Python | 10 | Warning | Python linting (delta-tracked) |
|
|
203
192
|
| **oxlint** | TS/JS | 12 | Warning | Fast Rust-based JS/TS linter |
|
|
204
193
|
| **tree-sitter** | TS/JS, Python | 14 | Mixed | AST-based structural analysis (21 patterns) — **singleton WASM client** |
|
|
205
|
-
| **ast-grep-napi** | TS/JS | 15 |
|
|
194
|
+
| **ast-grep-napi** | TS/JS | 15 | Blocking | Security rules inline (no-eval, jwt-no-verify, no-hardcoded-secrets, etc.) |
|
|
206
195
|
| **type-safety** | TS | 20 | Mixed | Switch exhaustiveness (blocking), other (warning) |
|
|
207
196
|
| **shellcheck** | Shell | 20 | Warning | Bash/sh/zsh/fish linting |
|
|
208
197
|
| **python-slop** | Python | 25 | Warning | AI slop detection (~40 patterns) |
|
|
209
198
|
| **spellcheck** | Markdown | 30 | Warning | Typo detection in docs |
|
|
210
|
-
| **similarity** | TS | 35 |
|
|
199
|
+
| **similarity** | TS | 35 | Warning | Semantic duplicate detection (structural similarity) |
|
|
211
200
|
| **architect** | All | 40 | Warning | Architectural rule violations |
|
|
212
201
|
| **go-vet** | Go | 50 | Warning | Go static analysis |
|
|
213
202
|
| **rust-clippy** | Rust | 50 | Warning | Rust linting |
|
|
@@ -224,7 +213,7 @@ pi-lens uses a **dispatcher-runner architecture** for extensible multi-language
|
|
|
224
213
|
- **Warning** — Shown in `/lens-booboo`, not inline (noise reduction)
|
|
225
214
|
- **Silent** — Tracked in metrics only, never shown
|
|
226
215
|
|
|
227
|
-
**Consolidated runners:** `ts-slop` merged into `ast-grep-napi`
|
|
216
|
+
**Consolidated runners:** `ts-slop` merged into `ast-grep-napi` — CLI ast-grep used for full linter via `/lens-booboo`
|
|
228
217
|
|
|
229
218
|
**Tree-sitter runner patterns** (priority 14, AST-based structural analysis):
|
|
230
219
|
|
|
@@ -244,7 +233,7 @@ Python (6 patterns):
|
|
|
244
233
|
|
|
245
234
|
**AI Slop Detection:**
|
|
246
235
|
- `python-slop` runner (priority 25): ~40 patterns for Python code quality
|
|
247
|
-
- `ast-grep-napi` runner (priority 15):
|
|
236
|
+
- `ast-grep-napi` runner (priority 15): Security rules fire inline (blocking); slop/architecture warnings via `/lens-booboo` only. Skips 5 rules already covered by tree-sitter.
|
|
248
237
|
|
|
249
238
|
---
|
|
250
239
|
|
|
@@ -294,7 +283,7 @@ message: "Remove console statements before production"
|
|
|
294
283
|
severity: warning
|
|
295
284
|
```
|
|
296
285
|
|
|
297
|
-
See [
|
|
286
|
+
See [AST_GREP_RULES.md](AST_GREP_RULES.md) for full guide.
|
|
298
287
|
|
|
299
288
|
---
|
|
300
289
|
|
|
@@ -393,26 +382,20 @@ Running the full suite on every edit would be too slow. Targeted testing gives i
|
|
|
393
382
|
|
|
394
383
|
### Complexity Metrics
|
|
395
384
|
|
|
396
|
-
pi-lens
|
|
385
|
+
pi-lens tracks code quality metrics for every file:
|
|
397
386
|
|
|
398
|
-
| Metric |
|
|
399
|
-
|
|
400
|
-
| **Maintainability Index
|
|
401
|
-
| **Cognitive Complexity** |
|
|
402
|
-
| **Cyclomatic Complexity** |
|
|
403
|
-
| **
|
|
404
|
-
| **Nesting Depth** | 0+ | Maximum block nesting level | >4: 🟡 Deep nesting, >6: 🔴 Excessive |
|
|
405
|
-
| **Code Entropy** | 0-8+ bits | Shannon entropy — unpredictability of code patterns | >3.5: 🟡 Risky AI-induced complexity |
|
|
406
|
-
| **Halstead Volume** | 0+ | Vocabulary × length — unique ops/operands | High = many different operations |
|
|
387
|
+
| Metric | Description | Threshold |
|
|
388
|
+
|--------|-------------|-----------|
|
|
389
|
+
| **Maintainability Index** | 0-100 composite score | >60 ✅ <20 🔴 |
|
|
390
|
+
| **Cognitive Complexity** | Mental effort to understand | >20 🟡 >50 🔴 |
|
|
391
|
+
| **Cyclomatic Complexity** | Independent code paths | >10 🟡 >20 🔴 |
|
|
392
|
+
| **Code Entropy** | Shannon entropy in bits | >4.0 🟡 >7.0 🔴 |
|
|
407
393
|
|
|
408
|
-
**
|
|
409
|
-
-
|
|
410
|
-
-
|
|
411
|
-
- Single-use helpers with high entropy = over-abstraction
|
|
394
|
+
**Commands:**
|
|
395
|
+
- `/lens-tdi` — Technical Debt Index (0-100) with grades A-F
|
|
396
|
+
- `/lens-booboo` — Full complexity table for all files
|
|
412
397
|
|
|
413
|
-
|
|
414
|
-
- `/lens-booboo` — Shows complexity table for all files
|
|
415
|
-
- `tool_result` — Complexity tracked per file, AI slop warnings inline
|
|
398
|
+
See [docs/COMPLEXITY_METRICS.md](docs/COMPLEXITY_METRICS.md) for formulas and detailed calculations.
|
|
416
399
|
|
|
417
400
|
---
|
|
418
401
|
|
|
@@ -429,7 +412,7 @@ pi-lens works out of the box for TypeScript/JavaScript. For full language suppor
|
|
|
429
412
|
| `knip` | `npm i -D knip` | Dead code / unused exports |
|
|
430
413
|
| `jscpd` | `npm i -D jscpd` | Copy-paste detection |
|
|
431
414
|
| `type-coverage` | `npm i -D type-coverage` | TypeScript `any` coverage % |
|
|
432
|
-
| `@ast-grep/napi` | `npm i -D @ast-grep/napi` | Fast structural analysis (TS/JS) —
|
|
415
|
+
| `@ast-grep/napi` | `npm i -D @ast-grep/napi` | Fast structural analysis (TS/JS) — security rules inline, slop in booboo |
|
|
433
416
|
| `@ast-grep/cli` | `npm i -D @ast-grep/cli` | Structural pattern matching (all languages) |
|
|
434
417
|
| `typos-cli` | `cargo install typos-cli` | Spellcheck for Markdown |
|
|
435
418
|
|
|
@@ -465,7 +448,6 @@ pi-lens works out of the box for TypeScript/JavaScript. For full language suppor
|
|
|
465
448
|
| Command | Description |
|
|
466
449
|
|---------|-------------|
|
|
467
450
|
| `/lens-booboo` | Full codebase review (10 analysis runners) |
|
|
468
|
-
| `/lens-format` | Apply Biome formatting |
|
|
469
451
|
| `/lens-tdi` | Technical Debt Index and trends |
|
|
470
452
|
|
|
471
453
|
---
|
|
@@ -476,7 +458,6 @@ pi-lens works out of the box for TypeScript/JavaScript. For full language suppor
|
|
|
476
458
|
|------|---------|--------------|
|
|
477
459
|
| **Standard** (default) | `pi` | Auto-formatting, TS/Python type-checking, sequential execution |
|
|
478
460
|
| **Full LSP** | `pi --lens-lsp` | Real LSP servers (31 languages), sequential execution |
|
|
479
|
-
| **Fastest** | `pi --lens-lsp` | Real LSP + full runner suite |
|
|
480
461
|
|
|
481
462
|
|
|
482
463
|
### Flag Reference
|
|
@@ -502,193 +483,90 @@ pi-lens works out of the box for TypeScript/JavaScript. For full language suppor
|
|
|
502
483
|
```bash
|
|
503
484
|
pi # Default: auto-format, auto-fix, built-in type-checking
|
|
504
485
|
pi --lens-lsp # LSP type-checking (31 languages)
|
|
505
|
-
pi --lens-lsp # LSP mode (recommended)
|
|
506
486
|
```
|
|
507
487
|
|
|
508
488
|
---
|
|
509
489
|
|
|
510
490
|
## TypeScript LSP — tsconfig detection
|
|
511
491
|
|
|
512
|
-
The LSP walks up from
|
|
513
|
-
|
|
514
|
-
- `target: ES2020`
|
|
515
|
-
- `lib: ["es2020", "dom", "dom.iterable"]`
|
|
516
|
-
- `moduleResolution: bundler`
|
|
517
|
-
- `strict: true`
|
|
518
|
-
|
|
519
|
-
The compiler options are refreshed automatically when you switch between projects within a session.
|
|
492
|
+
The LSP walks up from edited files to find `tsconfig.json`, using its `compilerOptions` (paths, strict settings, etc.). Falls back to sensible defaults if not found.
|
|
520
493
|
|
|
521
494
|
---
|
|
522
495
|
|
|
523
|
-
##
|
|
524
|
-
|
|
525
|
-
pi-lens automatically excludes certain files from analysis to reduce noise and focus on production code.
|
|
526
|
-
|
|
527
|
-
### Test Files
|
|
528
|
-
|
|
529
|
-
All runners respect test file exclusions — both in the dispatch system (`skipTestFiles: true`) and the `/lens-booboo` command.
|
|
530
|
-
|
|
531
|
-
**Excluded patterns:**
|
|
532
|
-
```
|
|
533
|
-
**/*.test.ts **/*.test.tsx **/*.test.js **/*.test.jsx
|
|
534
|
-
**/*.spec.ts **/*.spec.tsx **/*.spec.js **/*.spec.jsx
|
|
535
|
-
**/*.poc.test.ts **/*.poc.test.tsx
|
|
536
|
-
**/test-utils.ts **/test-*.ts
|
|
537
|
-
**/__tests__/** **/tests/** **/test/**
|
|
538
|
-
```
|
|
539
|
-
|
|
540
|
-
**Why:** Test files intentionally duplicate patterns (test fixtures, mock setups) and have different complexity standards. Including them creates false positives.
|
|
541
|
-
|
|
542
|
-
### Build Artifacts (TypeScript Projects)
|
|
543
|
-
|
|
544
|
-
In TypeScript projects (detected by `tsconfig.json` presence), compiled `.js` files are excluded:
|
|
496
|
+
## Project Structure
|
|
545
497
|
|
|
546
498
|
```
|
|
547
|
-
|
|
499
|
+
pi-lens/
|
|
500
|
+
├── clients/ # Lint tools, LSP clients, formatters
|
|
501
|
+
├── commands/ # /lens-booboo, /lens-format commands
|
|
502
|
+
├── docs/ # Documentation
|
|
503
|
+
├── rules/ # AST-grep rules
|
|
504
|
+
├── skills/ # Built-in pi skills
|
|
505
|
+
├── index.ts # Main extension entry point
|
|
506
|
+
└── package.json
|
|
548
507
|
```
|
|
549
508
|
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
**Note:** In pure JavaScript projects (no `tsconfig.json`), `.js` files are **included** as they are the source files.
|
|
553
|
-
|
|
554
|
-
### Excluded Directories
|
|
555
|
-
|
|
556
|
-
| Directory | Reason |
|
|
557
|
-
|-----------|--------|
|
|
558
|
-
| `node_modules/` | Third-party dependencies |
|
|
559
|
-
| `.git/` | Version control metadata |
|
|
560
|
-
| `dist/`, `build/` | Build outputs |
|
|
561
|
-
| `.pi-lens/`, `.pi/` | pi agent internal files |
|
|
562
|
-
| `.next/`, `.ruff_cache/` | Framework/build caches |
|
|
563
|
-
| `coverage/` | Test coverage reports |
|
|
564
|
-
|
|
565
|
-
### Per-Runner Exclusion Summary
|
|
566
|
-
|
|
567
|
-
| Runner | Test Files | Build Artifacts | Directories |
|
|
568
|
-
|--------|-----------|-----------------|-------------|
|
|
569
|
-
| **dispatch runners** | ✅ `skipTestFiles` | ✅ `.js` excluded in TS | ✅ `EXCLUDED_DIRS` |
|
|
570
|
-
| **booboo /lens-booboo** | ✅ `shouldIncludeFile()` | ✅ `isTsProject` check | ✅ `EXCLUDED_DIRS` |
|
|
571
|
-
| **Secrets scan** | ❌ No exclusion (security) | ❌ No exclusion | ✅ Dirs excluded |
|
|
509
|
+
See source for detailed structure.
|
|
572
510
|
|
|
573
511
|
---
|
|
574
512
|
|
|
575
|
-
##
|
|
513
|
+
## Skills
|
|
576
514
|
|
|
577
|
-
pi-lens
|
|
515
|
+
pi-lens includes two built-in skills that guide the LLM on when to use specific tools:
|
|
578
516
|
|
|
579
|
-
###
|
|
517
|
+
### ast-grep
|
|
580
518
|
|
|
581
|
-
**
|
|
519
|
+
**Purpose:** Guide AST-aware pattern matching for semantic code search/replace.
|
|
582
520
|
|
|
583
|
-
|
|
584
|
-
┌─────────────────────────────────────────┐
|
|
585
|
-
│ TOOL AVAILABILITY CACHE │
|
|
586
|
-
│ Map<toolName, {available, version}> │
|
|
587
|
-
│ • Persisted for session lifetime │
|
|
588
|
-
│ • Refreshed on extension restart │
|
|
589
|
-
└─────────────────────────────────────────┘
|
|
590
|
-
```
|
|
591
|
-
|
|
592
|
-
Avoids repeated `which`/`where` calls to check if `biome`, `ruff`, `pyright`, etc. are installed.
|
|
521
|
+
**When to load:** Use `/skill:ast-grep` when performing structural code searches (finding function calls, class methods, imports) or replacements across files.
|
|
593
522
|
|
|
594
|
-
|
|
523
|
+
**Key guidance:**
|
|
524
|
+
- Use `$VAR` for single nodes, `$$$` for multiple
|
|
525
|
+
- Patterns must be **complete valid code** (not fragments)
|
|
526
|
+
- **Workflow:** Search → Dry-run (`apply: false`) → Apply (`apply: true`)
|
|
527
|
+
- **Error "Multiple AST nodes":** Use metavariables like `it($TEST)` not raw text like `it"test"`
|
|
595
528
|
|
|
596
|
-
|
|
529
|
+
```typescript
|
|
530
|
+
// ✅ GOOD: Complete code with metavariables
|
|
531
|
+
ast_grep_search
|
|
532
|
+
pattern: "console.log($MSG)"
|
|
533
|
+
lang: typescript
|
|
534
|
+
paths: ["src/"]
|
|
597
535
|
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
│ DISPATCH BASELINES │
|
|
601
|
-
│ Map<filePath, Diagnostic[]> │
|
|
602
|
-
│ • Cleared at turn start │
|
|
603
|
-
│ • Updated after each runner execution │
|
|
604
|
-
│ • Filters: only NEW issues shown │
|
|
605
|
-
└─────────────────────────────────────────┘
|
|
536
|
+
// ❌ BAD: Incomplete pattern
|
|
537
|
+
pattern: "console.log(" // Missing args/body
|
|
606
538
|
```
|
|
607
539
|
|
|
608
|
-
|
|
540
|
+
### lsp-navigation
|
|
609
541
|
|
|
610
|
-
|
|
542
|
+
**Purpose:** Guide code intelligence via Language Server Protocol.
|
|
611
543
|
|
|
612
|
-
|
|
613
|
-
|--------|-------|-----|---------|
|
|
614
|
-
| **Knip** | `clients/cache-manager.ts` | 5 min | Dead code analysis (slow) |
|
|
615
|
-
| **jscpd** | `clients/cache-manager.ts` | 5 min | Duplicate detection (slow) |
|
|
616
|
-
| **Type Coverage** | In-memory | Session | `any` type percentage |
|
|
617
|
-
| **Complexity** | In-memory | File-level | MI, cognitive complexity per file |
|
|
544
|
+
**When to load:** Use `/skill:lsp-navigation` for understanding code structure — definitions, references, types, call hierarchy.
|
|
618
545
|
|
|
619
|
-
|
|
546
|
+
**Key guidance:**
|
|
547
|
+
- **LSP is PRIMARY** for code intelligence — NOT grep/glob/ast-grep
|
|
548
|
+
- Requires `--lens-lsp` flag
|
|
549
|
+
- Call hierarchy: `prepareCallHierarchy` → `incomingCalls`/`outgoingCalls`
|
|
620
550
|
|
|
621
|
-
|
|
551
|
+
| Task | Use LSP | Use Other |
|
|
552
|
+
|------|---------|-----------|
|
|
553
|
+
| "Where is this defined?" | `definition` | — |
|
|
554
|
+
| "Find all usages" | `references` | — |
|
|
555
|
+
| "What type is this?" | `hover` | — |
|
|
556
|
+
| "Who calls this function?" | `prepareCallHierarchy` → `incomingCalls` | — |
|
|
557
|
+
| Find patterns (console.log) | — | `ast_grep_search` |
|
|
558
|
+
| Find TODO comments | — | `grep` |
|
|
622
559
|
|
|
623
|
-
```
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
└─────────────────────────────────────────┘
|
|
631
|
-
```
|
|
560
|
+
```typescript
|
|
561
|
+
// ✅ Code intelligence → LSP
|
|
562
|
+
lsp_navigation
|
|
563
|
+
operation: "references"
|
|
564
|
+
filePath: "src/utils.ts"
|
|
565
|
+
line: 42
|
|
566
|
+
character: 10
|
|
632
567
|
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
- Madge: Only check deps if imports changed
|
|
636
|
-
- Cycle detection: Prevents infinite fix loops
|
|
637
|
-
|
|
638
|
-
### 5. Runner Internal Caches
|
|
639
|
-
|
|
640
|
-
| Runner | Cache | Notes |
|
|
641
|
-
|--------|-------|-------|
|
|
642
|
-
| `ast-grep-napi` | Rule descriptions | Loaded once per session (disabled by default) |
|
|
643
|
-
| `biome` | Tool availability | Checked once, cached |
|
|
644
|
-
| `pyright` | Command path | Venv lookup cached |
|
|
645
|
-
| `ruff` | Command path | Venv lookup cached |
|
|
646
|
-
|
|
647
|
-
---
|
|
648
|
-
|
|
649
|
-
## Project Structure
|
|
650
|
-
|
|
651
|
-
```
|
|
652
|
-
pi-lens/
|
|
653
|
-
├── clients/ # Lint tool wrappers and utilities
|
|
654
|
-
│ ├── bus/ # Event bus system (Phase 1)
|
|
655
|
-
│ │ ├── bus.ts
|
|
656
|
-
│ │ ├── events.ts
|
|
657
|
-
│ │ └── integration.ts
|
|
658
|
-
│ ├── dispatch/ # Dispatcher and runners
|
|
659
|
-
│ │ ├── dispatcher.ts
|
|
660
|
-
│ │ └── runners/ # Individual runners
|
|
661
|
-
│ │ ├── ast-grep-napi.ts # Fast TS/JS runner (disabled by default)
|
|
662
|
-
│ │ ├── python-slop.ts # Python slop detection
|
|
663
|
-
│ │ ├── ts-lsp.ts # TS type checking
|
|
664
|
-
│ │ ├── biome.ts
|
|
665
|
-
│ │ ├── ruff.ts
|
|
666
|
-
│ │ ├── pyright.ts
|
|
667
|
-
│ │ ├── go-vet.ts
|
|
668
|
-
│ │ └── rust-clippy.ts
|
|
669
|
-
│ ├── lsp/ # LSP client system (Phase 3)
|
|
670
|
-
│ │ ├── client.ts
|
|
671
|
-
│ │ ├── server.ts # 31 LSP server definitions
|
|
672
|
-
│ │ ├── language.ts
|
|
673
|
-
│ │ ├── launch.ts
|
|
674
|
-
│ │ └── config.ts # Custom LSP configuration
|
|
675
|
-
│ ├── installer/ # Auto-installation (Phase 4)
|
|
676
|
-
│ │ └── index.ts
|
|
677
|
-
│ ├── services/ # Effect-TS services (Phase 2)
|
|
678
|
-
│ │ ├── runner-service.ts
|
|
679
|
-
│ │ └── effect-integration.ts
|
|
680
|
-
│ ├── complexity-client.ts
|
|
681
|
-
│ ├── type-safety-client.ts
|
|
682
|
-
│ └── secrets-scanner.ts
|
|
683
|
-
├── commands/ # pi commands
|
|
684
|
-
│ ├── booboo.ts
|
|
685
|
-
│ └── fix-simplified.ts
|
|
686
|
-
├── docs/ # Documentation
|
|
687
|
-
│ └── LSP_CONFIG.md # LSP configuration guide
|
|
688
|
-
├── rules/ # AST-grep rules
|
|
689
|
-
│ └── ast-grep-rules/ # General structural rules
|
|
690
|
-
├── index.ts # Main entry point
|
|
691
|
-
└── package.json
|
|
568
|
+
// ❌ Don't use LSP for text patterns
|
|
569
|
+
pattern: "TODO" // Use grep instead
|
|
692
570
|
```
|
|
693
571
|
|
|
694
572
|
---
|
|
@@ -699,8 +577,9 @@ See [CHANGELOG.md](CHANGELOG.md) for full history.
|
|
|
699
577
|
|
|
700
578
|
### Latest Highlights
|
|
701
579
|
|
|
580
|
+
- **Tree-sitter Query Cache:** Compiled query cache with mtime-based invalidation — 10× faster structural analysis startup
|
|
702
581
|
- **LSP Support:** 31 Language Server Protocol clients (4 core auto-installed, others via npx or manual)
|
|
703
|
-
- **NAPI Runner:** 100x faster TypeScript/JavaScript structural analysis (~9ms vs ~1200ms) —
|
|
582
|
+
- **NAPI Runner:** 100x faster TypeScript/JavaScript structural analysis (~9ms vs ~1200ms) — security rules fire inline
|
|
704
583
|
- **Slop Detection:** 33+ TypeScript and 40+ Python patterns for AI-generated code quality issues
|
|
705
584
|
|
|
706
585
|
---
|
package/clients/biome-client.js
CHANGED
|
@@ -73,6 +73,34 @@ export class BiomeClient {
|
|
|
73
73
|
}
|
|
74
74
|
return this.biomeAvailable;
|
|
75
75
|
}
|
|
76
|
+
/**
|
|
77
|
+
* Ensure Biome is available, auto-installing if necessary.
|
|
78
|
+
* Prefer this over isAvailable() for auto-install behavior.
|
|
79
|
+
*/
|
|
80
|
+
async ensureAvailable() {
|
|
81
|
+
if (this.biomeAvailable !== null)
|
|
82
|
+
return this.biomeAvailable;
|
|
83
|
+
// Check if already available
|
|
84
|
+
const result = this.spawnBiome(["--version"], 10000);
|
|
85
|
+
if (!result.error && result.status === 0) {
|
|
86
|
+
this.biomeAvailable = true;
|
|
87
|
+
return true;
|
|
88
|
+
}
|
|
89
|
+
// Auto-install via pi-lens installer
|
|
90
|
+
this.log("Biome not found, attempting auto-install...");
|
|
91
|
+
const { ensureTool } = await import("./installer/index.js");
|
|
92
|
+
const installedPath = await ensureTool("biome");
|
|
93
|
+
if (installedPath) {
|
|
94
|
+
this.log(`Biome auto-installed: ${installedPath}`);
|
|
95
|
+
// Set the installed path as local binary to avoid npx overhead
|
|
96
|
+
this.localBinaryPath = installedPath;
|
|
97
|
+
this.biomeAvailable = true;
|
|
98
|
+
return true;
|
|
99
|
+
}
|
|
100
|
+
this.log("Biome auto-install failed");
|
|
101
|
+
this.biomeAvailable = false;
|
|
102
|
+
return false;
|
|
103
|
+
}
|
|
76
104
|
/**
|
|
77
105
|
* Check if a file is supported by Biome
|
|
78
106
|
*/
|
package/clients/biome-client.ts
CHANGED
|
@@ -110,6 +110,38 @@ export class BiomeClient {
|
|
|
110
110
|
return this.biomeAvailable;
|
|
111
111
|
}
|
|
112
112
|
|
|
113
|
+
/**
|
|
114
|
+
* Ensure Biome is available, auto-installing if necessary.
|
|
115
|
+
* Prefer this over isAvailable() for auto-install behavior.
|
|
116
|
+
*/
|
|
117
|
+
async ensureAvailable(): Promise<boolean> {
|
|
118
|
+
if (this.biomeAvailable !== null) return this.biomeAvailable;
|
|
119
|
+
|
|
120
|
+
// Check if already available
|
|
121
|
+
const result = this.spawnBiome(["--version"], 10000);
|
|
122
|
+
if (!result.error && result.status === 0) {
|
|
123
|
+
this.biomeAvailable = true;
|
|
124
|
+
return true;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
// Auto-install via pi-lens installer
|
|
128
|
+
this.log("Biome not found, attempting auto-install...");
|
|
129
|
+
const { ensureTool } = await import("./installer/index.js");
|
|
130
|
+
const installedPath = await ensureTool("biome");
|
|
131
|
+
|
|
132
|
+
if (installedPath) {
|
|
133
|
+
this.log(`Biome auto-installed: ${installedPath}`);
|
|
134
|
+
// Set the installed path as local binary to avoid npx overhead
|
|
135
|
+
this.localBinaryPath = installedPath;
|
|
136
|
+
this.biomeAvailable = true;
|
|
137
|
+
return true;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
this.log("Biome auto-install failed");
|
|
141
|
+
this.biomeAvailable = false;
|
|
142
|
+
return false;
|
|
143
|
+
}
|
|
144
|
+
|
|
113
145
|
/**
|
|
114
146
|
* Check if a file is supported by Biome
|
|
115
147
|
*/
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Rule Cache for pi-lens
|
|
3
|
+
*
|
|
4
|
+
* Provides disk-based caching for parsed tree-sitter rules with
|
|
5
|
+
* automatic invalidation based on rule file modification times.
|
|
6
|
+
*/
|
|
7
|
+
import * as crypto from "node:crypto";
|
|
8
|
+
import * as fs from "node:fs";
|
|
9
|
+
import * as path from "node:path";
|
|
10
|
+
const CACHE_DIR = path.join(process.cwd(), ".pi-lens", "cache");
|
|
11
|
+
const CACHE_VERSION = "v1";
|
|
12
|
+
export class RuleCache {
|
|
13
|
+
constructor(language) {
|
|
14
|
+
this.cacheFile = path.join(CACHE_DIR, `${language}-rules-${CACHE_VERSION}.json`);
|
|
15
|
+
}
|
|
16
|
+
ensureCacheDir() {
|
|
17
|
+
if (!fs.existsSync(CACHE_DIR)) {
|
|
18
|
+
fs.mkdirSync(CACHE_DIR, { recursive: true });
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
computeRuleHash(ruleFiles) {
|
|
22
|
+
const hash = crypto.createHash("sha256");
|
|
23
|
+
for (const file of ruleFiles.sort()) {
|
|
24
|
+
if (fs.existsSync(file)) {
|
|
25
|
+
const stat = fs.statSync(file);
|
|
26
|
+
hash.update(`${file}:${stat.mtimeMs}:${stat.size}`);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
return hash.digest("hex").slice(0, 16);
|
|
30
|
+
}
|
|
31
|
+
get(ruleFiles) {
|
|
32
|
+
try {
|
|
33
|
+
this.ensureCacheDir();
|
|
34
|
+
if (!fs.existsSync(this.cacheFile))
|
|
35
|
+
return null;
|
|
36
|
+
const cached = JSON.parse(fs.readFileSync(this.cacheFile, "utf-8"));
|
|
37
|
+
const currentHash = this.computeRuleHash(ruleFiles);
|
|
38
|
+
if (cached.version !== CACHE_VERSION || cached.ruleHash !== currentHash) {
|
|
39
|
+
return null; // Cache invalid
|
|
40
|
+
}
|
|
41
|
+
return cached;
|
|
42
|
+
}
|
|
43
|
+
catch {
|
|
44
|
+
return null;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
set(ruleFiles, queries) {
|
|
48
|
+
try {
|
|
49
|
+
this.ensureCacheDir();
|
|
50
|
+
const entry = {
|
|
51
|
+
version: CACHE_VERSION,
|
|
52
|
+
timestamp: Date.now(),
|
|
53
|
+
ruleHash: this.computeRuleHash(ruleFiles),
|
|
54
|
+
queries,
|
|
55
|
+
};
|
|
56
|
+
fs.writeFileSync(this.cacheFile, JSON.stringify(entry, null, 2));
|
|
57
|
+
}
|
|
58
|
+
catch {
|
|
59
|
+
// Cache write failure is non-fatal
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
clear() {
|
|
63
|
+
try {
|
|
64
|
+
if (fs.existsSync(this.cacheFile)) {
|
|
65
|
+
fs.unlinkSync(this.cacheFile);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
catch {
|
|
69
|
+
// Ignore
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
}
|