@kevinrabun/judges 3.1.0 → 3.2.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 CHANGED
@@ -1,6 +1,6 @@
1
1
  # Judges Panel
2
2
 
3
- An MCP (Model Context Protocol) server that provides a panel of **35 specialized judges** to evaluate AI-generated code — acting as an independent quality gate regardless of which project is being reviewed. Includes **built-in AST analysis** powered by the TypeScript Compiler API no separate parser server needed.
3
+ An MCP (Model Context Protocol) server that provides a panel of **35 specialized judges** to evaluate AI-generated code — acting as an independent quality gate regardless of which project is being reviewed. Combines **deterministic pattern matching & AST analysis** (instant, offline, zero LLM calls) with **LLM-powered deep-review prompts** that let your AI assistant perform expert-persona analysis across all 35 domains.
4
4
 
5
5
  **Highlights:**
6
6
  - Includes an **App Builder Workflow (3-step)** demo for release decisions, plain-language risk summaries, and prioritized fixes — see [Try the Demo](#2-try-the-demo).
@@ -9,12 +9,100 @@ An MCP (Model Context Protocol) server that provides a panel of **35 specialized
9
9
 
10
10
  [![CI](https://github.com/KevinRabun/judges/actions/workflows/ci.yml/badge.svg)](https://github.com/KevinRabun/judges/actions/workflows/ci.yml)
11
11
  [![npm](https://img.shields.io/npm/v/@kevinrabun/judges)](https://www.npmjs.com/package/@kevinrabun/judges)
12
+ [![npm downloads](https://img.shields.io/npm/dw/@kevinrabun/judges)](https://www.npmjs.com/package/@kevinrabun/judges)
12
13
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
14
+ [![Tests](https://img.shields.io/badge/tests-702-brightgreen)](https://github.com/KevinRabun/judges/actions)
15
+
16
+ ---
17
+
18
+ ## Why Judges?
19
+
20
+ AI code generators (Copilot, Cursor, Claude, ChatGPT, etc.) write code fast — but they routinely produce **insecure defaults, missing auth, hardcoded secrets, and poor error handling**. Human reviewers catch some of this, but nobody reviews 35 dimensions consistently.
21
+
22
+ | | ESLint / Biome | SonarQube | Semgrep / CodeQL | **Judges** |
23
+ |---|---|---|---|---|
24
+ | **Scope** | Style + some bugs | Bugs + code smells | Security patterns | **35 domains**: security, cost, compliance, a11y, API design, cloud, UX, … |
25
+ | **AI-generated code focus** | No | No | Partial | **Purpose-built** for AI output failure modes |
26
+ | **Setup** | Config per project | Server + scanner | Cloud or local | **One command**: `npx @kevinrabun/judges eval file.ts` |
27
+ | **Auto-fix patches** | Some | No | No | **47 deterministic patches** — instant, offline |
28
+ | **Non-technical output** | No | Dashboard | No | **Plain-language findings** with What/Why/Next |
29
+ | **MCP native** | No | No | No | **Yes** — works inside Copilot, Claude, Cursor |
30
+ | **SARIF output** | No | Yes | Yes | **Yes** — upload to GitHub Code Scanning |
31
+ | **Cost** | Free | $$$$ | Free/paid | **Free / MIT** |
32
+
33
+ **Judges doesn't replace linters** — it covers the dimensions linters don't: authentication strategy, data sovereignty, cost patterns, accessibility, framework-specific anti-patterns, and architectural issues across multiple files.
13
34
 
14
35
  ---
15
36
 
16
37
  ## Quick Start
17
38
 
39
+ ### Try it now (no clone needed)
40
+
41
+ ```bash
42
+ # Install globally
43
+ npm install -g @kevinrabun/judges
44
+
45
+ # Evaluate any file
46
+ judges eval src/app.ts
47
+
48
+ # Pipe from stdin
49
+ cat api.py | judges eval --language python
50
+
51
+ # Single judge
52
+ judges eval --judge cybersecurity server.ts
53
+
54
+ # SARIF output for CI
55
+ judges eval --file app.ts --format sarif > results.sarif
56
+
57
+ # List all 35 judges
58
+ judges list
59
+ ```
60
+
61
+ ### Use in GitHub Actions
62
+
63
+ Add Judges to your CI pipeline with zero configuration:
64
+
65
+ ```yaml
66
+ # .github/workflows/judges.yml
67
+ name: Judges Code Review
68
+ on: [pull_request]
69
+
70
+ jobs:
71
+ judges:
72
+ runs-on: ubuntu-latest
73
+ permissions:
74
+ contents: read
75
+ security-events: write # only if using upload-sarif
76
+ steps:
77
+ - uses: actions/checkout@v4
78
+ - uses: KevinRabun/judges@main
79
+ with:
80
+ path: src/api.ts # file or directory
81
+ format: text # text | json | sarif | markdown
82
+ upload-sarif: true # upload to GitHub Code Scanning
83
+ fail-on-findings: true # fail CI on critical/high findings
84
+ ```
85
+
86
+ **Outputs** available for downstream steps: `verdict`, `score`, `findings`, `critical`, `high`, `sarif-file`.
87
+
88
+ ### Use with Docker (no Node.js required)
89
+
90
+ ```bash
91
+ # Build the image
92
+ docker build -t judges .
93
+
94
+ # Evaluate a local file
95
+ docker run --rm -v $(pwd):/code judges eval --file /code/app.ts
96
+
97
+ # Pipe from stdin
98
+ cat api.py | docker run --rm -i judges eval --language python
99
+
100
+ # List judges
101
+ docker run --rm judges list
102
+ ```
103
+
104
+ ### Or use as an MCP server
105
+
18
106
  ### 1. Install and Build
19
107
 
20
108
  ```bash
@@ -279,24 +367,24 @@ This helps keep Copilot feedback aligned with Judges findings.
279
367
 
280
368
  The tribunal operates in three layers:
281
369
 
282
- 1. **Pattern-Based Analysis** — All tools (`evaluate_code`, `evaluate_code_single_judge`, `evaluate_project`, `evaluate_diff`) perform heuristic analysis using regex pattern matching to catch common anti-patterns. This works entirely offline with zero external API calls.
370
+ 1. **Pattern-Based Analysis** — All tools (`evaluate_code`, `evaluate_code_single_judge`, `evaluate_project`, `evaluate_diff`) perform heuristic analysis using regex pattern matching to catch common anti-patterns. This layer is instant, deterministic, and runs entirely offline with zero external API calls.
283
371
 
284
- 2. **AST-Based Structural Analysis** — The Code Structure judge (`STRUCT-*` rules) uses real Abstract Syntax Tree parsing to measure cyclomatic complexity, nesting depth, function length, parameter count, dead code, and type safety with precision that regex cannot achieve. JavaScript/TypeScript files are parsed via the TypeScript Compiler API; Python, Rust, Go, Java, and C# use a scope-tracking structural parser. No external AST server required.
372
+ 2. **AST-Based Structural Analysis** — The Code Structure judge (`STRUCT-*` rules) uses real Abstract Syntax Tree parsing to measure cyclomatic complexity, nesting depth, function length, parameter count, dead code, and type safety with precision that regex cannot achieve. JavaScript/TypeScript files are parsed via the TypeScript Compiler API. Python, Rust, Go, Java, and C# are parsed via **tree-sitter WASM grammars** — real syntax trees compiled to WebAssembly that run in-process with zero native dependencies. A scope-tracking structural parser is kept as a fallback when WASM grammars are unavailable. No external AST server required.
285
373
 
286
- 3. **LLM-Powered Deep Analysis (Prompts)** — The server exposes MCP prompts (e.g., `judge-data-security`, `full-tribunal`) that provide each judge's expert persona as a system prompt. When used by an LLM-based client, this enables deeper, context-aware analysis beyond what static analysis can detect.
374
+ 3. **LLM-Powered Deep Analysis (Prompts)** — The server exposes MCP prompts (e.g., `judge-data-security`, `full-tribunal`) that provide each judge's expert persona as a system prompt. When used by an LLM-based client (Copilot, Claude, Cursor, etc.), the host LLM performs deeper, context-aware probabilistic analysis beyond what static patterns can detect. This is where the `systemPrompt` on each judge comes alive — Judges itself makes no LLM calls, but it provides the expert criteria so your AI assistant can act as 35 specialized reviewers.
287
375
 
288
376
  ---
289
377
 
290
378
  ## Composable by Design
291
379
 
292
- Judges Panel covers **heuristic pattern detection** and **AST structural analysis** in a single server fast, offline, and self-contained. It does not try to be a CVE scanner or a linter. Those capabilities belong in dedicated MCP servers that an AI agent can orchestrate alongside Judges.
380
+ Judges Panel is a **dual-layer** review system: instant **deterministic tools** (offline, no API keys) for pattern and AST analysis, plus **35 expert-persona MCP prompts** that unlock LLM-powered deep analysis when connected to an AI client. It does not try to be a CVE scanner or a linter. Those capabilities belong in dedicated MCP servers that an AI agent can orchestrate alongside Judges.
293
381
 
294
382
  ### Built-in AST Analysis (v2.0.0)
295
383
 
296
384
  Unlike earlier versions that recommended a separate AST MCP server, Judges Panel now includes **real AST-based structural analysis** out of the box:
297
385
 
298
386
  - **JavaScript / TypeScript** — Parsed with the TypeScript Compiler API (`ts.createSourceFile`) for full-fidelity AST
299
- - **Python, Rust, Go, Java, C#** — Analyzed with a scope-tracking structural parser that counts decision points and nesting levels
387
+ - **Python, Rust, Go, Java, C#** — Parsed with **tree-sitter WASM grammars** for full syntax-tree analysis (functions, complexity, nesting, dead code, type safety). Falls back to a scope-tracking structural parser when WASM grammars are unavailable
300
388
 
301
389
  The Code Structure judge (`STRUCT-*`) uses these parsers to accurately measure:
302
390
 
@@ -723,7 +811,8 @@ judges/
723
811
  │ │ ├── index.ts # analyzeStructure() — routes to correct parser
724
812
  │ │ ├── types.ts # FunctionInfo, CodeStructure interfaces
725
813
  │ │ ├── typescript-ast.ts # TypeScript Compiler API parser (JS/TS)
726
- │ │ └── structural-parser.ts # Scope-tracking parser (Python/Rust/Go/Java/C#)
814
+ │ │ ├── tree-sitter-ast.ts # Tree-sitter WASM parser (Python/Rust/Go/Java/C#)
815
+ │ │ └── structural-parser.ts # Fallback scope-tracking parser
727
816
  │ ├── evaluators/ # Analysis engine for each judge
728
817
  │ │ ├── index.ts # evaluateWithJudge(), evaluateWithTribunal(), evaluateProject(), etc.
729
818
  │ │ ├── shared.ts # Scoring, verdict logic, markdown formatters
@@ -741,6 +830,12 @@ judges/
741
830
  │ └── demo.ts # Run: npm run demo
742
831
  ├── tests/
743
832
  │ └── judges.test.ts # Run: npm test
833
+ ├── grammars/ # Tree-sitter WASM grammar files
834
+ │ ├── tree-sitter-python.wasm
835
+ │ ├── tree-sitter-go.wasm
836
+ │ ├── tree-sitter-rust.wasm
837
+ │ ├── tree-sitter-java.wasm
838
+ │ └── tree-sitter-c_sharp.wasm
744
839
  ├── server.json # MCP Registry manifest
745
840
  ├── package.json
746
841
  ├── tsconfig.json
package/dist/api.d.ts CHANGED
@@ -19,6 +19,7 @@ export { LRUCache, contentHash } from "./cache.js";
19
19
  export { clearProjectCache } from "./evaluators/project.js";
20
20
  export { findingsToSarif, evaluationToSarif, verdictToSarif, validateSarifLog } from "./formatters/sarif.js";
21
21
  export type { SarifValidationError } from "./formatters/sarif.js";
22
+ export { runCli } from "./cli.js";
22
23
  import type { EvaluationOptions } from "./evaluators/index.js";
23
24
  import type { JudgeEvaluation, TribunalVerdict } from "./types.js";
24
25
  /**
package/dist/api.d.ts.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"api.d.ts","sourceRoot":"","sources":["../src/api.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAGH,YAAY,EACV,QAAQ,EACR,OAAO,EACP,OAAO,EACP,KAAK,EACL,UAAU,EACV,YAAY,EACZ,YAAY,EACZ,WAAW,EACX,cAAc,EACd,WAAW,EACX,eAAe,EACf,iBAAiB,EACjB,eAAe,EACf,eAAe,EACf,eAAe,EACf,mBAAmB,EACnB,gBAAgB,EAChB,oBAAoB,EACpB,iBAAiB,EACjB,kBAAkB,EAClB,iBAAiB,EACjB,wBAAwB,EACxB,oBAAoB,EACpB,YAAY,EACZ,aAAa,GACd,MAAM,YAAY,CAAC;AAGpB,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,eAAe,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAGpF,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAGzD,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAIxE,OAAO,EACL,iBAAiB,EACjB,oBAAoB,EACpB,eAAe,EACf,YAAY,EACZ,mBAAmB,EACnB,iBAAiB,EACjB,mBAAmB,EACnB,uBAAuB,EACvB,qBAAqB,EACrB,uBAAuB,EACvB,0BAA0B,EAC1B,qBAAqB,GACtB,MAAM,uBAAuB,CAAC;AAG/B,OAAO,EAAE,cAAc,EAAE,iBAAiB,EAAE,0BAA0B,EAAE,MAAM,oBAAoB,CAAC;AAGnG,OAAO,EAAE,qBAAqB,EAAE,MAAM,2BAA2B,CAAC;AAGlE,OAAO,EAAE,QAAQ,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AACnD,OAAO,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAG5D,OAAO,EAAE,eAAe,EAAE,iBAAiB,EAAE,cAAc,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAC7G,YAAY,EAAE,oBAAoB,EAAE,MAAM,uBAAuB,CAAC;AAKlE,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAC/D,OAAO,KAAK,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAInE;;;;;;;GAOG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,iBAAiB,GAAG,eAAe,CAEzG;AAED;;;;;;;;GAQG;AACH,wBAAgB,uBAAuB,CACrC,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,MAAM,EAChB,OAAO,CAAC,EAAE,iBAAiB,GAC1B,eAAe,CAMjB"}
1
+ {"version":3,"file":"api.d.ts","sourceRoot":"","sources":["../src/api.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAGH,YAAY,EACV,QAAQ,EACR,OAAO,EACP,OAAO,EACP,KAAK,EACL,UAAU,EACV,YAAY,EACZ,YAAY,EACZ,WAAW,EACX,cAAc,EACd,WAAW,EACX,eAAe,EACf,iBAAiB,EACjB,eAAe,EACf,eAAe,EACf,eAAe,EACf,mBAAmB,EACnB,gBAAgB,EAChB,oBAAoB,EACpB,iBAAiB,EACjB,kBAAkB,EAClB,iBAAiB,EACjB,wBAAwB,EACxB,oBAAoB,EACpB,YAAY,EACZ,aAAa,GACd,MAAM,YAAY,CAAC;AAGpB,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,eAAe,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAGpF,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAGzD,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAIxE,OAAO,EACL,iBAAiB,EACjB,oBAAoB,EACpB,eAAe,EACf,YAAY,EACZ,mBAAmB,EACnB,iBAAiB,EACjB,mBAAmB,EACnB,uBAAuB,EACvB,qBAAqB,EACrB,uBAAuB,EACvB,0BAA0B,EAC1B,qBAAqB,GACtB,MAAM,uBAAuB,CAAC;AAG/B,OAAO,EAAE,cAAc,EAAE,iBAAiB,EAAE,0BAA0B,EAAE,MAAM,oBAAoB,CAAC;AAGnG,OAAO,EAAE,qBAAqB,EAAE,MAAM,2BAA2B,CAAC;AAGlE,OAAO,EAAE,QAAQ,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AACnD,OAAO,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAG5D,OAAO,EAAE,eAAe,EAAE,iBAAiB,EAAE,cAAc,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAC7G,YAAY,EAAE,oBAAoB,EAAE,MAAM,uBAAuB,CAAC;AAGlE,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAKlC,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAC/D,OAAO,KAAK,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAInE;;;;;;;GAOG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,iBAAiB,GAAG,eAAe,CAEzG;AAED;;;;;;;;GAQG;AACH,wBAAgB,uBAAuB,CACrC,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,MAAM,EAChB,OAAO,CAAC,EAAE,iBAAiB,GAC1B,eAAe,CAMjB"}
package/dist/api.js CHANGED
@@ -25,6 +25,8 @@ export { LRUCache, contentHash } from "./cache.js";
25
25
  export { clearProjectCache } from "./evaluators/project.js";
26
26
  // ─── Formatters ──────────────────────────────────────────────────────────────
27
27
  export { findingsToSarif, evaluationToSarif, verdictToSarif, validateSarifLog } from "./formatters/sarif.js";
28
+ // ─── CLI ─────────────────────────────────────────────────────────────────────
29
+ export { runCli } from "./cli.js";
28
30
  // ─── Convenience Aliases ─────────────────────────────────────────────────────
29
31
  import { evaluateWithTribunal, evaluateWithJudge } from "./evaluators/index.js";
30
32
  import { getJudge } from "./judges/index.js";
package/dist/api.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"api.js","sourceRoot":"","sources":["../src/api.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AA+BH,gFAAgF;AAChF,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,eAAe,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAEpF,gFAAgF;AAChF,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAEzD,gFAAgF;AAChF,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAExE,gFAAgF;AAEhF,OAAO,EACL,iBAAiB,EACjB,oBAAoB,EACpB,eAAe,EACf,YAAY,EACZ,mBAAmB,EACnB,iBAAiB,EACjB,mBAAmB,EACnB,uBAAuB,EACvB,qBAAqB,EACrB,uBAAuB,EACvB,0BAA0B,EAC1B,qBAAqB,GACtB,MAAM,uBAAuB,CAAC;AAE/B,+EAA+E;AAC/E,OAAO,EAAE,cAAc,EAAE,iBAAiB,EAAE,0BAA0B,EAAE,MAAM,oBAAoB,CAAC;AAEnG,gFAAgF;AAChF,OAAO,EAAE,qBAAqB,EAAE,MAAM,2BAA2B,CAAC;AAElE,gFAAgF;AAChF,OAAO,EAAE,QAAQ,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AACnD,OAAO,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAE5D,gFAAgF;AAChF,OAAO,EAAE,eAAe,EAAE,iBAAiB,EAAE,cAAc,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAG7G,gFAAgF;AAEhF,OAAO,EAAE,oBAAoB,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAGhF,OAAO,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAC7C,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAE9C;;;;;;;GAOG;AACH,MAAM,UAAU,YAAY,CAAC,IAAY,EAAE,QAAgB,EAAE,OAA2B;IACtF,OAAO,oBAAoB,CAAC,IAAI,EAAE,QAAQ,EAAE,SAAS,EAAE,OAAO,CAAC,CAAC;AAClE,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,uBAAuB,CACrC,OAAe,EACf,IAAY,EACZ,QAAgB,EAChB,OAA2B;IAE3B,MAAM,KAAK,GAAG,QAAQ,CAAC,OAAO,CAAC,CAAC;IAChC,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,MAAM,IAAI,eAAe,CAAC,mBAAmB,OAAO,GAAG,EAAE,OAAO,CAAC,CAAC;IACpE,CAAC;IACD,OAAO,iBAAiB,CAAC,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,SAAS,EAAE,OAAO,CAAC,CAAC;AACtE,CAAC"}
1
+ {"version":3,"file":"api.js","sourceRoot":"","sources":["../src/api.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AA+BH,gFAAgF;AAChF,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,eAAe,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAEpF,gFAAgF;AAChF,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAEzD,gFAAgF;AAChF,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAExE,gFAAgF;AAEhF,OAAO,EACL,iBAAiB,EACjB,oBAAoB,EACpB,eAAe,EACf,YAAY,EACZ,mBAAmB,EACnB,iBAAiB,EACjB,mBAAmB,EACnB,uBAAuB,EACvB,qBAAqB,EACrB,uBAAuB,EACvB,0BAA0B,EAC1B,qBAAqB,GACtB,MAAM,uBAAuB,CAAC;AAE/B,+EAA+E;AAC/E,OAAO,EAAE,cAAc,EAAE,iBAAiB,EAAE,0BAA0B,EAAE,MAAM,oBAAoB,CAAC;AAEnG,gFAAgF;AAChF,OAAO,EAAE,qBAAqB,EAAE,MAAM,2BAA2B,CAAC;AAElE,gFAAgF;AAChF,OAAO,EAAE,QAAQ,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AACnD,OAAO,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAE5D,gFAAgF;AAChF,OAAO,EAAE,eAAe,EAAE,iBAAiB,EAAE,cAAc,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAG7G,gFAAgF;AAChF,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAElC,gFAAgF;AAEhF,OAAO,EAAE,oBAAoB,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAGhF,OAAO,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAC7C,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAE9C;;;;;;;GAOG;AACH,MAAM,UAAU,YAAY,CAAC,IAAY,EAAE,QAAgB,EAAE,OAA2B;IACtF,OAAO,oBAAoB,CAAC,IAAI,EAAE,QAAQ,EAAE,SAAS,EAAE,OAAO,CAAC,CAAC;AAClE,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,uBAAuB,CACrC,OAAe,EACf,IAAY,EACZ,QAAgB,EAChB,OAA2B;IAE3B,MAAM,KAAK,GAAG,QAAQ,CAAC,OAAO,CAAC,CAAC;IAChC,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,MAAM,IAAI,eAAe,CAAC,mBAAmB,OAAO,GAAG,EAAE,OAAO,CAAC,CAAC;IACpE,CAAC;IACD,OAAO,iBAAiB,CAAC,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,SAAS,EAAE,OAAO,CAAC,CAAC;AACtE,CAAC"}
@@ -1,5 +1,6 @@
1
1
  import type { CodeStructure, FunctionInfo } from "./types.js";
2
2
  export type { CodeStructure, FunctionInfo };
3
+ export { isTreeSitterAvailable, isTreeSitterReadySync } from "./tree-sitter-ast.js";
3
4
  export { analyzeTaintFlows } from "./taint-tracker.js";
4
5
  export type { TaintFlow, TaintSourceKind, TaintSinkKind } from "./taint-tracker.js";
5
6
  export { analyzeCrossFileTaint } from "./cross-file-taint.js";
@@ -7,10 +8,20 @@ export type { CrossFileTaintFlow } from "./cross-file-taint.js";
7
8
  /**
8
9
  * Analyse source code structurally. For JavaScript/TypeScript this uses the
9
10
  * TypeScript compiler API (full AST). For Python, Rust, Go, Java, and C# it
10
- * uses a lightweight scope-tracking parser.
11
+ * uses tree-sitter (real AST via WASM) when available, falling back to the
12
+ * lightweight scope-tracking parser.
11
13
  *
12
14
  * Returns function metrics (complexity, nesting, length, params), dead code
13
15
  * locations, deep-nesting locations, and type-safety issues.
14
16
  */
15
17
  export declare function analyzeStructure(code: string, language: string): CodeStructure;
18
+ /**
19
+ * Async version of analyzeStructure that uses tree-sitter (real AST) for
20
+ * Python, Rust, Go, Java, and C# when WASM grammars are available.
21
+ * Falls back to the structural parser if tree-sitter is not available.
22
+ *
23
+ * Prefer this over analyzeStructure() for Tier 2 languages — it provides
24
+ * the same depth of analysis that the TS Compiler API gives JS/TS.
25
+ */
26
+ export declare function analyzeStructureAsync(code: string, language: string): Promise<CodeStructure>;
16
27
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/ast/index.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAE9D,YAAY,EAAE,aAAa,EAAE,YAAY,EAAE,CAAC;AAG5C,OAAO,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AACvD,YAAY,EAAE,SAAS,EAAE,eAAe,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAGpF,OAAO,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AAC9D,YAAY,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAEhE;;;;;;;GAOG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,aAAa,CA6B9E"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/ast/index.ts"],"names":[],"mappings":"AAiBA,OAAO,KAAK,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAE9D,YAAY,EAAE,aAAa,EAAE,YAAY,EAAE,CAAC;AAG5C,OAAO,EAAE,qBAAqB,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAGpF,OAAO,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AACvD,YAAY,EAAE,SAAS,EAAE,eAAe,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAGpF,OAAO,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AAC9D,YAAY,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAahE;;;;;;;;GAQG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,aAAa,CAuC9E;AAED;;;;;;;GAOG;AACH,wBAAsB,qBAAqB,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC,CAsClG"}
package/dist/ast/index.js CHANGED
@@ -1,20 +1,33 @@
1
1
  // ─────────────────────────────────────────────────────────────────────────────
2
2
  // AST Analysis — Unified Entry Point
3
3
  // ─────────────────────────────────────────────────────────────────────────────
4
- // Routes to the TypeScript compiler-based parser for JS/TS or the lightweight
5
- // structural parser for Python, Rust, Go, Java, and C#.
4
+ // Routes to the TypeScript compiler-based parser for JS/TS, the tree-sitter
5
+ // real-AST parser for Python, Rust, Go, Java, and C# (when WASM grammars are
6
+ // available), or the lightweight structural parser as a fallback.
6
7
  // ─────────────────────────────────────────────────────────────────────────────
7
8
  import { normalizeLanguage } from "../language-patterns.js";
8
9
  import { analyzeTypeScript } from "./typescript-ast.js";
9
10
  import { analyzeStructurally } from "./structural-parser.js";
11
+ import { isTreeSitterAvailable, isTreeSitterReadySync, analyzeWithTreeSitter, analyzeWithTreeSitterSync, } from "./tree-sitter-ast.js";
12
+ // Re-export tree-sitter availability checks
13
+ export { isTreeSitterAvailable, isTreeSitterReadySync } from "./tree-sitter-ast.js";
10
14
  // Re-export taint analysis
11
15
  export { analyzeTaintFlows } from "./taint-tracker.js";
12
16
  // Re-export cross-file taint analysis
13
17
  export { analyzeCrossFileTaint } from "./cross-file-taint.js";
18
+ // ─── Tree-sitter Warm-up ────────────────────────────────────────────────────
19
+ // Pre-initialize tree-sitter on module load so it's ready when needed.
20
+ // This is fire-and-forget; if it fails, analyzeStructure falls back silently.
21
+ const TREE_SITTER_LANGS = ["python", "rust", "go", "java", "csharp"];
22
+ const treeSitterReady = new Map();
23
+ for (const lang of TREE_SITTER_LANGS) {
24
+ treeSitterReady.set(lang, isTreeSitterAvailable(lang));
25
+ }
14
26
  /**
15
27
  * Analyse source code structurally. For JavaScript/TypeScript this uses the
16
28
  * TypeScript compiler API (full AST). For Python, Rust, Go, Java, and C# it
17
- * uses a lightweight scope-tracking parser.
29
+ * uses tree-sitter (real AST via WASM) when available, falling back to the
30
+ * lightweight scope-tracking parser.
18
31
  *
19
32
  * Returns function metrics (complexity, nesting, length, params), dead code
20
33
  * locations, deep-nesting locations, and type-safety issues.
@@ -30,6 +43,17 @@ export function analyzeStructure(code, language) {
30
43
  case "go":
31
44
  case "java":
32
45
  case "csharp":
46
+ // Use tree-sitter (real AST) if WASM runtime + grammar already loaded,
47
+ // otherwise fall back to the lightweight structural parser.
48
+ // parser.parse() is synchronous in web-tree-sitter once initialized.
49
+ if (isTreeSitterReadySync(lang)) {
50
+ try {
51
+ return analyzeWithTreeSitterSync(code, lang);
52
+ }
53
+ catch {
54
+ // Tree-sitter failed at runtime — fall back silently
55
+ }
56
+ }
33
57
  return analyzeStructurally(code, lang);
34
58
  default:
35
59
  // Unknown language — return a minimal structure
@@ -46,4 +70,49 @@ export function analyzeStructure(code, language) {
46
70
  };
47
71
  }
48
72
  }
73
+ /**
74
+ * Async version of analyzeStructure that uses tree-sitter (real AST) for
75
+ * Python, Rust, Go, Java, and C# when WASM grammars are available.
76
+ * Falls back to the structural parser if tree-sitter is not available.
77
+ *
78
+ * Prefer this over analyzeStructure() for Tier 2 languages — it provides
79
+ * the same depth of analysis that the TS Compiler API gives JS/TS.
80
+ */
81
+ export async function analyzeStructureAsync(code, language) {
82
+ const lang = normalizeLanguage(language);
83
+ switch (lang) {
84
+ case "javascript":
85
+ case "typescript":
86
+ return analyzeTypeScript(code, lang);
87
+ case "python":
88
+ case "rust":
89
+ case "go":
90
+ case "java":
91
+ case "csharp": {
92
+ // Try tree-sitter first (real AST), fall back to structural parser
93
+ const available = await (treeSitterReady.get(lang) ?? Promise.resolve(false));
94
+ if (available) {
95
+ try {
96
+ return await analyzeWithTreeSitter(code, lang);
97
+ }
98
+ catch {
99
+ // Tree-sitter failed at runtime — fall back silently
100
+ }
101
+ }
102
+ return analyzeStructurally(code, lang);
103
+ }
104
+ default:
105
+ return {
106
+ language: lang,
107
+ totalLines: code.split("\n").length,
108
+ functions: [],
109
+ fileCyclomaticComplexity: 1,
110
+ maxNestingDepth: 0,
111
+ deadCodeLines: [],
112
+ deepNestLines: [],
113
+ typeAnyLines: [],
114
+ imports: [],
115
+ };
116
+ }
117
+ }
49
118
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/ast/index.ts"],"names":[],"mappings":"AAAA,gFAAgF;AAChF,qCAAqC;AACrC,gFAAgF;AAChF,8EAA8E;AAC9E,wDAAwD;AACxD,gFAAgF;AAEhF,OAAO,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAC5D,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,EAAE,mBAAmB,EAAE,MAAM,wBAAwB,CAAC;AAK7D,2BAA2B;AAC3B,OAAO,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AAGvD,sCAAsC;AACtC,OAAO,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AAG9D;;;;;;;GAOG;AACH,MAAM,UAAU,gBAAgB,CAAC,IAAY,EAAE,QAAgB;IAC7D,MAAM,IAAI,GAAG,iBAAiB,CAAC,QAAQ,CAAC,CAAC;IAEzC,QAAQ,IAAI,EAAE,CAAC;QACb,KAAK,YAAY,CAAC;QAClB,KAAK,YAAY;YACf,OAAO,iBAAiB,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;QAEvC,KAAK,QAAQ,CAAC;QACd,KAAK,MAAM,CAAC;QACZ,KAAK,IAAI,CAAC;QACV,KAAK,MAAM,CAAC;QACZ,KAAK,QAAQ;YACX,OAAO,mBAAmB,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;QAEzC;YACE,gDAAgD;YAChD,OAAO;gBACL,QAAQ,EAAE,IAAI;gBACd,UAAU,EAAE,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,MAAM;gBACnC,SAAS,EAAE,EAAE;gBACb,wBAAwB,EAAE,CAAC;gBAC3B,eAAe,EAAE,CAAC;gBAClB,aAAa,EAAE,EAAE;gBACjB,aAAa,EAAE,EAAE;gBACjB,YAAY,EAAE,EAAE;gBAChB,OAAO,EAAE,EAAE;aACZ,CAAC;IACN,CAAC;AACH,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/ast/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,34 @@
1
+ import type { CodeStructure } from "./types.js";
2
+ /**
3
+ * Check whether tree-sitter analysis is available for a given language.
4
+ * Must be called (and awaited) before analyzeWithTreeSitter.
5
+ */
6
+ export declare function isTreeSitterAvailable(lang: string): Promise<boolean>;
7
+ /**
8
+ * Synchronous readiness check — returns true only if tree-sitter's WASM
9
+ * runtime AND the grammar for `lang` have already been loaded into memory.
10
+ * This is safe to call from synchronous code paths; if the async init
11
+ * hasn't finished yet, it simply returns false and the caller falls back
12
+ * to the structural parser.
13
+ */
14
+ export declare function isTreeSitterReadySync(lang: string): boolean;
15
+ /**
16
+ * Synchronous tree-sitter analysis. Can ONLY be called when
17
+ * isTreeSitterReadySync(lang) returns true (i.e. parser module and grammar
18
+ * are already loaded). parser.parse() is synchronous in web-tree-sitter
19
+ * once the WASM runtime and grammar are in memory.
20
+ *
21
+ * Returns the same CodeStructure interface as analyzeWithTreeSitter.
22
+ * Throws if preconditions are not met.
23
+ */
24
+ export declare function analyzeWithTreeSitterSync(code: string, language: string): CodeStructure;
25
+ /**
26
+ * Analyse source code using tree-sitter's real syntax tree.
27
+ * Returns the same CodeStructure interface as the TypeScript and
28
+ * structural parsers — but with much higher precision for non-JS/TS languages.
29
+ *
30
+ * IMPORTANT: Call isTreeSitterAvailable(lang) first. If it returns false,
31
+ * fall back to analyzeStructurally().
32
+ */
33
+ export declare function analyzeWithTreeSitter(code: string, language: string): Promise<CodeStructure>;
34
+ //# sourceMappingURL=tree-sitter-ast.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tree-sitter-ast.d.ts","sourceRoot":"","sources":["../../src/ast/tree-sitter-ast.ts"],"names":[],"mappings":"AAkBA,OAAO,KAAK,EAAE,aAAa,EAAgB,MAAM,YAAY,CAAC;AAkG9D;;;GAGG;AACH,wBAAsB,qBAAqB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAK1E;AAED;;;;;;GAMG;AACH,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAE3D;AAED;;;;;;;;GAQG;AACH,wBAAgB,yBAAyB,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,aAAa,CAKvF;AAED;;;;;;;GAOG;AACH,wBAAsB,qBAAqB,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC,CAKlG"}